Advertisement
Guest User

Untitled

a guest
Apr 25th, 2017
158
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Kotlin 22.86 KB | None | 0 0
  1. package com.magiadigital.cobranzas.flow
  2.  
  3. import co.paralleluniverse.fibers.Suspendable
  4. import com.magiadigital.cobranzas.contract.DocumentContract
  5. import com.magiadigital.cobranzas.state.DocumentState
  6. import net.corda.core.contracts.*
  7. import net.corda.core.crypto.Party
  8. import net.corda.core.crypto.SecureHash
  9. import net.corda.core.crypto.composite
  10. import net.corda.core.crypto.signWithECDSA
  11. import net.corda.core.flows.FlowLogic
  12. import net.corda.core.node.ServiceHub
  13. import net.corda.core.node.services.Vault
  14. import net.corda.core.node.services.linearHeadsOfType
  15. import net.corda.core.node.services.unconsumedStates
  16. import net.corda.core.seconds
  17. import net.corda.core.transactions.SignedTransaction
  18. import net.corda.core.utilities.ProgressTracker
  19. import net.corda.core.utilities.unwrap
  20. import net.corda.flows.FinalityFlow
  21. import net.corda.flows.NotaryFlow
  22. import java.util.EnumSet
  23. import net.corda.core.contracts.*
  24. import net.corda.core.crypto.*
  25. import net.corda.core.node.PluginServiceHub
  26. import net.corda.core.node.services.linearHeadsOfType
  27. import net.corda.core.serialization.CordaSerializable
  28. import net.corda.core.utilities.unwrap
  29. import java.security.PublicKey
  30. import java.time.Duration
  31.  
  32. /**
  33.  * This flow allows two parties (the [Initiator] and the [Acceptor]) to come to an agreement about the Document encapsulated
  34.  * within an [DocumentState].
  35.  *
  36.  * In our simple example, the [Acceptor] always accepts a valid Document.
  37.  *
  38.  * These flows have deliberately been implemented by using only the call() method for ease of understanding. In
  39.  * practice we would recommend splitting up the various stages of the flow into sub-routines.
  40.  *
  41.  * All methods called within the [FlowLogic] sub-class need to be annotated with the @Suspendable annotation.
  42.  */
  43. object DocumentFlow {
  44.  
  45.     // Helper method to locate the latest Vault version of a LinearState from a possibly out of date StateRef
  46.     inline fun <reified T : LinearState> ServiceHub.latest(ref: StateRef): StateAndRef<T> {
  47.         val linearHeads = vaultService.linearHeadsOfType<T>()
  48.         val original = toStateAndRef<T>(ref)
  49.         return linearHeads.get(original.state.data.linearId)!!
  50.     }
  51.  
  52.     class Initiator(val document: DocumentState,
  53.                     val globoKAS: Party): FlowLogic<StateAndRef<DocumentState>>() {
  54.         /**
  55.          * The progress tracker checkpoints each stage of the flow and outputs the specified messages when each
  56.          * checkpoint is reached in the code. See the 'progressTracker.currentStep' expressions within the call() function.
  57.          */
  58.         companion object {
  59.             object GENERATING_TRANSACTION : ProgressTracker.Step("Generating transaction based on new Document.")
  60.             object VERIFYING_TRANSACTION : ProgressTracker.Step("Verifying contract constraints.")
  61.             object SIGNING_TRANSACTION : ProgressTracker.Step("Signing transaction with our private key.")
  62.             object SENDING_TRANSACTION : ProgressTracker.Step("Sending proposed transaction to recipient for review.")
  63.  
  64.             fun tracker() = ProgressTracker(
  65.                     GENERATING_TRANSACTION,
  66.                     VERIFYING_TRANSACTION,
  67.                     SIGNING_TRANSACTION,
  68.                     SENDING_TRANSACTION
  69.             )
  70.         }
  71.  
  72.         override val progressTracker = tracker()
  73.  
  74.         /**
  75.          * The flow logic is encapsulated within the call() method.
  76.          */
  77.         @Suspendable
  78.         override fun call(): StateAndRef<DocumentState> {
  79.             println("Arranco FLOW Initiator")
  80.             // Prep.
  81.             // Obtain a reference to our key pair. Currently, the only key pair used is the one which is registered
  82.             // with the NetWorkMapService. In a future milestone release we'll implement HD key generation so that
  83.             // new keys can be generated for each transaction.
  84.             val keyPair = serviceHub.legalIdentityKey
  85.             // Obtain a reference to the notary we want to use.
  86.             //val notary = serviceHub.networkMapCache.notaryNodes.single().notaryIdentity
  87.             val notary = serviceHub.networkMapCache.getAnyNotary()
  88.             // Create the TransactionBuilder and populate with the new state.
  89.             val tx = TransactionType.General.Builder(notary)
  90.                     .withItems(document, Command(DocumentContract.Commands.Create(), listOf(document.company.owningKey)))
  91.             tx.setTime(serviceHub.clock.instant(), Duration.ofSeconds(60))
  92.             // We can automatically sign as there is no untrusted data.
  93.             tx.signWith(serviceHub.legalIdentityKey)
  94.             // Convert to a SignedTransaction that we can send to the notary
  95.             val signedTx = tx.toSignedTransaction(false)
  96.             // Notarise and distribute.
  97.             subFlow(FinalityFlow(signedTx, setOf(serviceHub.myInfo.legalIdentity, globoKAS)))
  98.             // Return the initial state
  99.             return signedTx.tx.outRef<DocumentState>(0)
  100.  
  101. //            // Stage 1.
  102. //            progressTracker.currentStep = GENERATING_TRANSACTION
  103. //            // Generate an unsigned transaction.
  104. //            val txCommand = Command(DocumentContract.Commands.Create(), document.participants)
  105. //            val unsignedTx = TransactionType.General.Builder(notary).withItems(document, txCommand)
  106. //
  107. //            // Stage 2.
  108. //            progressTracker.currentStep = VERIFYING_TRANSACTION
  109. //            // Verify that the transaction is valid.
  110. //            unsignedTx.toWireTransaction().toLedgerTransaction(serviceHub).verify()
  111. //
  112. //            // Stage 3.
  113. //            progressTracker.currentStep = SIGNING_TRANSACTION
  114. //            val partSignedTx = unsignedTx.signWith(keyPair).toSignedTransaction(checkSufficientSignatures = false)
  115. //
  116. //            // Stage 4.
  117. //            progressTracker.currentStep = SENDING_TRANSACTION
  118. //            // Send the state across the wire to the designated counterparty.
  119. //            // -----------------------
  120. //            // Flow jumps to Acceptor.
  121. //            // -----------------------
  122. //            send(otherParty, partSignedTx)
  123. //
  124. //            return waitForLedgerCommit(partSignedTx.id)
  125.         }
  126.     }
  127.  
  128. //    class Acceptor(val otherParty: Party) : FlowLogic<Unit>() {
  129. //        companion object {
  130. //            object RECEIVING_TRANSACTION : ProgressTracker.Step("Receiving proposed transaction from sender.")
  131. //            object VERIFYING_TRANSACTION : ProgressTracker.Step("Verifying signatures and contract constraints.")
  132. //            object SIGNING_TRANSACTION : ProgressTracker.Step("Signing proposed transaction with our private key.")
  133. //            object FINALISING_TRANSACTION : ProgressTracker.Step("Obtaining notary signature and recording transaction.")
  134. //
  135. //            fun tracker() = ProgressTracker(
  136. //                    RECEIVING_TRANSACTION,
  137. //                    VERIFYING_TRANSACTION,
  138. //                    SIGNING_TRANSACTION,
  139. //                    FINALISING_TRANSACTION
  140. //            )
  141. //        }
  142. //
  143. //        override val progressTracker = tracker()
  144. //
  145. //        @Suspendable
  146. //        override fun call() {
  147. //            println("Arranco FLOW Acceptor")
  148. //            // Prep.
  149. //            // Obtain a reference to our key pair.
  150. //            val keyPair = serviceHub.legalIdentityKey
  151. //            // Obtain a reference to the notary we want to use and its public key.
  152. //            val notary = serviceHub.networkMapCache.notaryNodes.single().notaryIdentity
  153. //            val notaryPubKey = notary.owningKey
  154. //
  155. //            // Stage 5.
  156. //            progressTracker.currentStep = RECEIVING_TRANSACTION
  157. //            // All messages come off the wire as UntrustworthyData. You need to 'unwrap' them. This is where you
  158. //            // validate what you have just received.
  159. //            val partSignedTx = receive<SignedTransaction>(otherParty).unwrap { partSignedTx ->
  160. //                // Stage 6.
  161. //                progressTracker.currentStep = VERIFYING_TRANSACTION
  162. //                // Check that the signature of the other party is valid.
  163. //                // Our signature and the notary's signature are allowed to be omitted at this stage as this is only
  164. //                // a partially signed transaction.
  165. //                val wireTx = partSignedTx.verifySignatures(keyPair.public.composite, notaryPubKey)
  166. //                // Run the contract's verify function.
  167. //                // We want to be sure that the agreed-upon Document is valid under the rules of the contract.
  168. //                // To do this we need to run the contract's verify() function.
  169. //                wireTx.toLedgerTransaction(serviceHub).verify()
  170. //                // We've verified the signed transaction and return it.
  171. //                partSignedTx
  172. //            }
  173. //
  174. //            // Stage 7.
  175. //            progressTracker.currentStep = SIGNING_TRANSACTION
  176. //            // Sign the transaction with our key pair and add it to the transaction.
  177. //            // We now have 'validation consensus'. We still require uniqueness consensus.
  178. //            // Technically validation consensus for this type of agreement implicitly provides uniqueness consensus.
  179. //            val mySig = keyPair.signWithECDSA(partSignedTx.id.bytes)
  180. //            // Add our signature to the transaction.
  181. //            val signedTx = partSignedTx + mySig
  182. //
  183. //            // Stage 8.
  184. //            progressTracker.currentStep = FINALISING_TRANSACTION
  185. //            // FinalityFlow() notarises the transaction and records it in each party's vault.
  186. //            subFlow(FinalityFlow(signedTx, setOf(serviceHub.myInfo.legalIdentity, otherParty)))
  187. //        }
  188. //    }
  189.     /**
  190.      * Esto siempre se tiene que ejecutar solo en el nodo Collector.
  191.      * Una vez finalizado el flujo se actualiza el documento de cobranza en ambos Vaults.
  192.      */
  193.     class InitCharged(val linearId: String): FlowLogic<SignedTransaction>() {
  194.  
  195.         companion object {
  196.             object RETRIEVING_DOCUMENT : ProgressTracker.Step("Retrieving the document.")
  197.             object UPDATING_DOCUMENT_FLAG_CHARGED : ProgressTracker.Step("Updating new charged state to the document.")
  198.             object CONSTRUCTING_TRANSACTION : ProgressTracker.Step("Constructing transaction to commit")
  199.             object TIMESTAMPING_TRANSACTION : ProgressTracker.Step("Timestamping transaction.")
  200.             object SIGNING_TRANSACTION : ProgressTracker.Step("Signing transaction with our private key.")
  201.             object NOTARISING_TRANSACTION : ProgressTracker.Step("Signing transaction and notarizing.")
  202.             object RECORDING_TRANSACTION : ProgressTracker.Step("Record transaction in collectors company vault.")
  203.             object SENDING_TO_COMPANY : ProgressTracker.Step("Sending transaction to company.")
  204.  
  205.             fun tracker() = ProgressTracker(
  206.                     RETRIEVING_DOCUMENT,
  207.                     UPDATING_DOCUMENT_FLAG_CHARGED,
  208.                     CONSTRUCTING_TRANSACTION,
  209.                     TIMESTAMPING_TRANSACTION,
  210.                     SIGNING_TRANSACTION,
  211.                     NOTARISING_TRANSACTION,
  212.                     RECORDING_TRANSACTION,
  213.                     SENDING_TO_COMPANY
  214.             )
  215.         }
  216.  
  217.         override val progressTracker = tracker()
  218.  
  219.         @Suspendable
  220.         override fun call() : SignedTransaction  {
  221.             println("***** Arranco FLOW InitCharge *****")
  222.             println(serviceHub.myInfo.legalIdentity.name)
  223.             // Naively, wrapped the whole flow in a try ... catch block so we can
  224.             // push the exceptions back through the web API.
  225.             val myKeyPair = serviceHub.legalIdentityKey
  226.             //val notary = serviceHub.networkMapCache.notaryNodes.single().notaryIdentity
  227.  
  228.             // Stage 1 - Retrieve the input purchaseOrderState
  229.             progressTracker.currentStep = RETRIEVING_DOCUMENT
  230.             val documentStates = serviceHub.vaultService.unconsumedStates<DocumentState>()
  231.             var docRef : StateRef = StateRef(SecureHash.zeroHash,0)
  232.             println("documentStates = " + documentStates)
  233.             for (c in documentStates) {
  234.                 println(c.ref)
  235.                 println(c.state.data.linearId)
  236.                 println(c.state.data.document.payer)
  237.                 if (c.state.data.document.payer == linearId) {
  238.                     println("Entro al IF del linearId")
  239.                     docRef = c.ref
  240.                 }
  241.             }
  242.             println("docRef = " + docRef)
  243.             val documentStateAndRef = serviceHub.latest<DocumentState>(docRef)
  244.             println("documentStateAndRef = " + documentStateAndRef)
  245.             println("***** pass documentStateAndRef *****")
  246.  
  247.             // Stage 2 - Create the updated output purchase order
  248.             progressTracker.currentStep = UPDATING_DOCUMENT_FLAG_CHARGED
  249.             val newDocumentState = documentStateAndRef.state.data.copy(flagCharged = true)
  250.             println("***** pass Stage2 *****")
  251.  
  252.             // We have to use the original notary for the new transaction
  253.             val notary = documentStateAndRef.state.notary
  254.  
  255.             // Stage 3 - Generate an unsigned transaction
  256.             progressTracker.currentStep = CONSTRUCTING_TRANSACTION
  257.             val txBuilder = TransactionType.General.Builder(notary)
  258.                     .withItems(
  259.                             // Input state.
  260.                             documentStateAndRef,
  261.                             //Output state.
  262.                             newDocumentState,
  263.                             // Command.
  264.                             Command(
  265.                                     DocumentContract.Commands.Collect(),
  266.                                     listOf(serviceHub.myInfo.legalIdentity.owningKey, documentStateAndRef.state.data.company.owningKey))
  267.                     )
  268.             println("***** pass Stage3 *****")
  269.             txBuilder.setTime(serviceHub.clock.instant(), Duration.ofSeconds(60))
  270.  
  271.             // We can sign this transaction immediately as we have already checked all the fields and the decision
  272.             // is ultimately a manual one from the caller.
  273.             txBuilder.signWith(serviceHub.legalIdentityKey)
  274.  
  275.             // Convert to SignedTransaction we can pass around certain that it cannot be modified.
  276.             val selfSignedTx = txBuilder.toSignedTransaction(false)
  277.             println("***** pass antes del sendAndReceive *****")
  278.             // Send the signed transaction to the company and await their signature to confirm
  279.             val allPartySignedTx = sendAndReceive<DigitalSignature.WithKey>(newDocumentState.company, selfSignedTx).unwrap {
  280.                 // Add their signature to our unmodified transaction. To check they signed the same tx.
  281.                 println("***** it 1 *****")
  282.                 val agreedTx = selfSignedTx + it
  283.                 // Receive back their signature and confirm that it is for an unmodified transaction
  284.                 // Also that the only missing signature is from teh Notary
  285.                 println("***** it 2 *****")
  286.                 agreedTx.verifySignatures(notary.owningKey)
  287.                 // Recheck the data of the transaction. Note we run toLedgerTransaction on the WireTransaction
  288.                 // as we do not have all the signature.
  289.                 println("***** it 3 *****")
  290.                 agreedTx.tx.toLedgerTransaction(serviceHub).verify()
  291.                 // return the SignedTransaction to notarise
  292.                 println("***** it 4 *****")
  293.                 agreedTx
  294.             }
  295.  
  296.             // Notarise and distribute the completed transaction.
  297.             println("***** subflow *****")
  298.             subFlow(FinalityFlow(allPartySignedTx, setOf(documentStateAndRef.state.data.company, documentStateAndRef.state.data.collector)))
  299.  
  300.             return(allPartySignedTx)
  301.  
  302. //            txBuilder.toWireTransaction().toLedgerTransaction(serviceHub).verify()
  303. //
  304. //            // Stage 4 - Add a timestamp, as mandated by the contract code
  305. ////            progressTracker.currentStep = TIMESTAMPING_TRANSACTION
  306. ////            val currentTime = serviceHub.clock.instant()
  307. ////            txBuilder.setTime(currentTime, 30.seconds)
  308. ////            println("***** pass Stage4 *****")
  309. //
  310. //            // Stage 5 - Sign the transaction
  311. //            progressTracker.currentStep = SIGNING_TRANSACTION
  312. //            val sigTx = txBuilder.signWith(myKeyPair).toSignedTransaction(checkSufficientSignatures = false)
  313. //            println("***** pass Stage5 *****")
  314. //
  315. //            // Stage 6 - Obtain the notary's signature
  316. ////            progressTracker.currentStep = NOTARISING_TRANSACTION
  317. ////            val notarySignature = subFlow(NotaryFlow.Client(sigTx))
  318. ////            val notTx = sigTx + notarySignature
  319. ////            println("***** pass Stage6 *****")
  320. //
  321. //            // Stage 7 - Record the transaction in our vault
  322. ////            progressTracker.currentStep = RECORDING_TRANSACTION
  323. ////            serviceHub.recordTransactions(listOf(sigTx))
  324. ////            println("***** pass Stage7 *****")
  325. //
  326. //            // Stage 8 - Send the transaction to the counterparty
  327. //            progressTracker.currentStep = SENDING_TO_COMPANY
  328. //            println("***** justo antes del send *****")
  329. //            println("company = " + documentStateAndRef.state.data.company)
  330. //            println("sigTx = " + sigTx)
  331. //            send(documentStateAndRef.state.data.company, sigTx)
  332. //            println("***** pass Stage8 *****")
  333. //
  334. //            //return  waitForLedgerCommit(sigTx.id)
  335. //            return(sigTx)
  336.         }
  337.     }
  338.  
  339.     /**
  340.      * Esto finaliza el flujo para indicar que un documento ya a sido cobrado y es guardado en el Vault de la empresa.
  341.      */
  342.     class EndCharged(val source: Party): FlowLogic<Unit>() {
  343.         companion object {
  344.             object RECEIVING_END_TRANSACTION : ProgressTracker.Step("Receiving proposed transaction from sender.")
  345.             object VERIFYING_END_TRANSACTION : ProgressTracker.Step("Verifying signatures and contract constraints.")
  346.             object SIGNING_END_TRANSACTION : ProgressTracker.Step("Signing proposed transaction with our private key.")
  347.             object FINALISING_END_TRANSACTION : ProgressTracker.Step("Obtaining notary signature and recording transaction.")
  348.  
  349.             fun tracker() = ProgressTracker(
  350.                     RECEIVING_END_TRANSACTION,
  351.                     VERIFYING_END_TRANSACTION,
  352.                     SIGNING_END_TRANSACTION,
  353.                     FINALISING_END_TRANSACTION
  354.             )
  355.         }
  356.  
  357.         override val progressTracker = tracker()
  358.  
  359.         @Suspendable
  360.         override fun call(): Unit {
  361.             println("Arranco FLOW EndCharged")
  362.             // First we receive the verdict transaction signed by their single key
  363.             val completeTx = receive<SignedTransaction>(source).unwrap {
  364.                 // Check the transaction is signed apart from our own key and the notary
  365.                 val wtx = it.verifySignatures(serviceHub.myInfo.legalIdentity.owningKey, it.tx.notary!!.owningKey)
  366.                 // Check the transaction data is correctly formed
  367.                 wtx.toLedgerTransaction(serviceHub).verify()
  368.                 // Confirm that this is the expected type of transaction
  369.                 require(wtx.commands.single().value is DocumentContract.Commands.Collect) {
  370.                     "Transaction must represent a workflow completion"
  371.                 }
  372.                 // Check the context dependent parts of the transaction as the
  373.                 // Contract verify method must not use serviceHub queries.
  374.                 val state = wtx.outRef<DocumentState>(0)
  375.                 require(state.state.data.company == serviceHub.myInfo.legalIdentity) {
  376.                     "Document for collect not one of our original proposals"
  377.                 }
  378.                 require(state.state.data.collector == source) {
  379.                     "This document charged not for send from correct collector"
  380.                 }
  381.                 it
  382.             }
  383.             // DOCEND 3
  384.             // Having verified the SignedTransaction passed to us we can sign it too
  385.             val ourSignature = serviceHub.legalIdentityKey.signWithECDSA(completeTx.tx.id)
  386.             // Send our signature to the other party.
  387.             send(source, ourSignature)
  388.             // N.B. The FinalityProtocol will be responsible for Notarising the SignedTransaction
  389.             // and broadcasting the result to us.
  390.  
  391. //            // Prep.
  392. //            // Obtain a reference to our key pair.
  393. //            val keyPair = serviceHub.legalIdentityKey
  394. //            // Obtain a reference to the notary we want to use and its public key.
  395. //            val notary = serviceHub.networkMapCache.notaryNodes.single().notaryIdentity
  396. //            val notaryPubKey = notary.owningKey
  397. //
  398. //            // Stage 5.
  399. //            progressTracker.currentStep = EndCharged.Companion.RECEIVING_END_TRANSACTION
  400. //            // All messages come off the wire as UntrustworthyData. You need to 'unwrap' them. This is where you
  401. //            // validate what you have just received.
  402. //            val partSignedTx = receive<SignedTransaction>(company).unwrap { partSignedTx ->
  403. //                // Stage 6.
  404. //                progressTracker.currentStep = EndCharged.Companion.VERIFYING_END_TRANSACTION
  405. //                // Check that the signature of the other party is valid.
  406. //                // Our signature and the notary's signature are allowed to be omitted at this stage as this is only
  407. //                // a partially signed transaction.
  408. //                val wireTx = partSignedTx.verifySignatures(keyPair.public.composite, notaryPubKey)
  409. //                // Run the contract's verify function.
  410. //                // We want to be sure that the agreed-upon Document is valid under the rules of the contract.
  411. //                // To do this we need to run the contract's verify() function.
  412. //                wireTx.toLedgerTransaction(serviceHub).verify()
  413. //                // We've verified the signed transaction and return it.
  414. //                partSignedTx
  415. //            }
  416. //
  417. //            // Stage 7.
  418. //            progressTracker.currentStep = EndCharged.Companion.SIGNING_END_TRANSACTION
  419. //            // Sign the transaction with our key pair and add it to the transaction.
  420. //            // We now have 'validation consensus'. We still require uniqueness consensus.
  421. //            // Technically validation consensus for this type of agreement implicitly provides uniqueness consensus.
  422. //            val mySig = keyPair.signWithECDSA(partSignedTx.id.bytes)
  423. //            // Add our signature to the transaction.
  424. //            val signedTx = partSignedTx + mySig
  425. //
  426. //            // Stage 8.
  427. //            progressTracker.currentStep = EndCharged.Companion.FINALISING_END_TRANSACTION
  428. //            // FinalityFlow() notarises the transaction and records it in each party's vault.
  429. //            subFlow(FinalityFlow(signedTx, setOf(serviceHub.myInfo.legalIdentity, company)))
  430.         }
  431.     }
  432. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement