You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

Corda交易打包:单Flow内创建多个Transaction Builder的可行性

Can I Create Multiple Transaction Builders in a Single Corda Flow?

Absolutely! You can create multiple Transaction Builders within a single Flow to batch transactions and reuse the same Flow thread—you just need to work around the default single SignedTransaction return type of the Flow's call() method. Here's how to make it work:

1. Adjust the Flow's Return Type

Instead of returning a single SignedTransaction, change your Flow's return type to a List<SignedTransaction> (or any serializable custom object that holds your transactions). Corda fully supports custom serializable return types for Flows, so this is a valid approach.

Example Implementation

@InitiatingFlow
@StartableByRPC
class MultiTransactionFlow(private val otherParty: Party) : FlowLogic<List<SignedTransaction>>() {
    override fun call(): List<SignedTransaction> {
        val finalTransactions = mutableListOf<SignedTransaction>()
        val notary = serviceHub.networkMapCache.notaryIdentities.first()
        val sessions = listOf(initiateFlow(otherParty))

        // Build, sign, finalize first transaction
        val txBuilder1 = TransactionBuilder(notary)
            .addOutputState(MyState("First Transaction State"), MY_CONTRACT_ID)
            .addCommand(MyContract.Commands.Create(), ourIdentity.owningKey, otherParty.owningKey)
        
        txBuilder1.verify(serviceHub)
        val partiallySignedTx1 = serviceHub.signInitialTransaction(txBuilder1)
        val fullySignedTx1 = subFlow(CollectSignaturesFlow(partiallySignedTx1, sessions))
        val finalizedTx1 = subFlow(FinalityFlow(fullySignedTx1, sessions))
        finalTransactions.add(finalizedTx1)

        // Build, sign, finalize second transaction
        val txBuilder2 = TransactionBuilder(notary)
            .addOutputState(MyState("Second Transaction State"), MY_CONTRACT_ID)
            .addCommand(MyContract.Commands.Create(), ourIdentity.owningKey, otherParty.owningKey)
        
        txBuilder2.verify(serviceHub)
        val partiallySignedTx2 = serviceHub.signInitialTransaction(txBuilder2)
        val fullySignedTx2 = subFlow(CollectSignaturesFlow(partiallySignedTx2, sessions))
        val finalizedTx2 = subFlow(FinalityFlow(fullySignedTx2, sessions))
        finalTransactions.add(finalizedTx2)

        return finalTransactions
    }
}

2. Key Considerations

  • Independent Transaction Lifecycles: Each Transaction Builder needs its own verification, signing, and finality steps. Never skip verification for any transaction—this ensures compliance with your contract's business rules.
  • Handling Dependent Transactions: If your transactions rely on each other (e.g., the second uses an output state from the first), wait until the first transaction is fully finalized and its state is available in the vault before building the second. You can confirm state existence with serviceHub.vaultService.queryBy<MyState>().
  • Performance & Timeouts: Reusing a single Flow thread reduces overhead, but if you're processing many transactions, adjust your node's Flow timeout settings in node.conf to avoid premature termination.
  • Optional Return Value: If you don't need to send all transactions back to the caller, you can skip returning a list and just process transactions internally, returning a simple success flag or a single representative transaction instead.

内容的提问来源于stack exchange,提问作者Dinesh Rivankar

火山引擎 最新活动