@@ -20,10 +20,13 @@ import co.paralleluniverse.fibers.Suspendable
2020import net.corda.core.contracts.StateAndRef
2121import net.corda.core.contracts.StateRef
2222import net.corda.core.crypto.SecureHash
23- import net.corda.core.flows.FlowException
24- import net.corda.core.flows.FlowLogic
23+ import net.corda.core.flows.*
24+ import net.corda.core.identity.Party
25+ import net.corda.core.node.StatesToRecord
2526import net.corda.core.transactions.SignedTransaction
27+ import net.corda.core.transactions.TransactionBuilder
2628import net.corda.core.utilities.ProgressTracker.Step
29+ import net.corda.core.utilities.unwrap
2730
2831/* *
2932 * Sets the current progress tracker step.
@@ -84,3 +87,136 @@ fun FlowLogic<*>.findTransaction(stateRef: StateRef): SignedTransaction {
8487fun FlowLogic <* >.findTransaction (stateAndRef : StateAndRef <* >): SignedTransaction {
8588 return findTransaction(stateAndRef.ref)
8689}
90+
91+ /* *
92+ * Provides a DSL-like transaction builder.
93+ * To use this function, [BuildingTransactionStep] will need to be evident in your progress tracker.
94+ *
95+ * @param notary The notary which will be applied to the transaction.
96+ * @param action The action which will be used to build the transaction.
97+ * @return Returns a [TransactionBuilder] representing the built transaction.
98+ */
99+ @Suspendable
100+ fun FlowLogic <* >.buildTransaction (notary : Party , action : TransactionBuilder .() -> Unit ): TransactionBuilder {
101+ currentStep(BuildingTransactionStep )
102+ val transactionBuilder = TransactionBuilder (notary)
103+ action(transactionBuilder)
104+ return transactionBuilder
105+ }
106+
107+ /* *
108+ * Verifies a transaction.
109+ * To use this function, [VerifyingTransactionStep] will need to be evident in your progress tracker.
110+ *
111+ * @param transaction The transaction to verify.
112+ */
113+ @Suspendable
114+ fun FlowLogic <* >.verifyTransaction (transaction : TransactionBuilder ) {
115+ currentStep(VerifyingTransactionStep )
116+ transaction.verify(serviceHub)
117+ }
118+
119+ /* *
120+ * Signs a transaction
121+ * To use this function, [SigningTransactionStep] will need to be evident in your progress tracker.
122+ */
123+ @Suspendable
124+ fun FlowLogic <* >.signTransaction (transaction : TransactionBuilder ): SignedTransaction {
125+ currentStep(SigningTransactionStep )
126+ val ourSigningKeys = transaction.getOurSigningKeys(serviceHub.keyManagementService)
127+ return serviceHub.signInitialTransaction(transaction, ourSigningKeys)
128+ }
129+
130+ /* *
131+ * Collects all remaining required signatures from the specified counter-parties.
132+ * To use this function, [CollectTransactionSignaturesStep] will need to be evident in your progress tracker.
133+ *
134+ * Due to the way this function works, it is intended to be paired with [collectSignaturesHandler] in the counter-flow.
135+ * This function will filter out all required signing sessions from the sessions provided, and will then notify all
136+ * sessions whether they are required to sign or not. For those sessions required to sign, it will collect their signature.
137+ *
138+ * @param transaction The transaction for which to collect remaining signatures from the specified counter-parties.
139+ * @param sessions All flow sessions that have been passed to this flow.
140+ * @return Returns a transaction which should be signed by all required signers.
141+ * @throws FlowException if the local node has been passed to this function as a counter-party or in a flow session.
142+ */
143+ @Suspendable
144+ fun FlowLogic <* >.collectSignatures (transaction : SignedTransaction , sessions : Iterable <FlowSession >): SignedTransaction {
145+ currentStep(CollectTransactionSignaturesStep )
146+ val missingSigningKeys = transaction.getMissingSigners()
147+
148+ val signingSessions = sessions.filter {
149+ if (it.counterparty in serviceHub.myInfo.legalIdentities) {
150+ throw FlowException (" Do not pass flow sessions for the local node." )
151+ }
152+
153+ it.counterparty.owningKey in missingSigningKeys
154+ }
155+
156+ sessions.forEach { it.send(it in signingSessions) }
157+
158+ return if (signingSessions.isEmpty()) transaction
159+ else subFlow(
160+ CollectSignaturesFlow (transaction, signingSessions, CollectTransactionSignaturesStep .childProgressTracker())
161+ )
162+ }
163+
164+ /* *
165+ * Signs a transaction.
166+ * To use this function, [SigningTransactionStep] will need to be evident in your progress tracker.
167+ * Due to the way this function works, it is intended to be paired with [collectSignatures] in the initiating flow.
168+ *
169+ * @param session The flow session of the initiating flow that is requesting a transaction signature.
170+ * @param action Allows custom transaction checks to be performed before the transaction is signed.
171+ */
172+ @Suspendable
173+ fun FlowLogic <* >.collectSignaturesHandler (
174+ session : FlowSession ,
175+ action : (SignedTransaction ) -> Unit = {}
176+ ): SignedTransaction ? {
177+ val isRequiredToSign = session.receive<Boolean >().unwrap { it }
178+ return if (isRequiredToSign) {
179+ currentStep(SigningTransactionStep )
180+ subFlow(object : SignTransactionFlow (session, SigningTransactionStep .childProgressTracker()) {
181+ override fun checkTransaction (stx : SignedTransaction ) = action(stx)
182+ })
183+ } else null
184+ }
185+
186+ /* *
187+ * Finalizes a transaction.
188+ * To use this function, [FinalizingTransactionStep] will need to be evident in your progress tracker.
189+ *
190+ * @param transaction The transaction to be finalized.
191+ * @param sessions The sessions for all counter-parties and observers where this transaction should be recorded.
192+ * @param statesToRecord Determines which states from the transaction should be recorded.
193+ * @return Returns a fully signed, finalized and recorded transaction.
194+ */
195+ @Suspendable
196+ fun FlowLogic <* >.finalize (
197+ transaction : SignedTransaction ,
198+ sessions : Iterable <FlowSession >,
199+ statesToRecord : StatesToRecord = StatesToRecord .ONLY_RELEVANT
200+ ): SignedTransaction {
201+ currentStep(FinalizingTransactionStep )
202+ return subFlow(FinalityFlow (transaction, sessions.toSet(), statesToRecord))
203+ }
204+
205+ /* *
206+ * Finalizes a transaction.
207+ * To use this function, [RecordingFinalizedTransactionStep] will need to be evident in your progress tracker.
208+ *
209+ * @param session The flow session of the initiating flow that is requesting the transaction to be finalized.
210+ * @param expectedTransactionId The expected transaction ID of the transaction to be recorded.
211+ * @param statesToRecord Determines which states from the transaction should be recorded.
212+ * @return Returns a fully signed, finalized and recorded transaction.
213+ */
214+ @Suspendable
215+ fun FlowLogic <* >.finalizeHandler (
216+ session : FlowSession ,
217+ expectedTransactionId : SecureHash ? = null,
218+ statesToRecord : StatesToRecord = StatesToRecord .ONLY_RELEVANT
219+ ): SignedTransaction {
220+ currentStep(RecordingFinalizedTransactionStep )
221+ return subFlow(ReceiveFinalityFlow (session, expectedTransactionId, statesToRecord))
222+ }
0 commit comments