Corda将代币从一个帐户移动到另一方(托管在另一方的帐户)

Corda将代币从一个帐户移动到另一方(托管在另一方的帐户),corda,Corda,除了公证人外,我们的Corda网络还有3个节点。 此图显示了每个节点应执行的操作 只有在这种情况下,我们才有麻烦“需要将代币从账户持有人转移到乙方” 流程代码: class TransferETokenDiffNodeFlow(val actualHolder: AbstractParty, val newHolder: AbstractParty,

除了公证人外,我们的Corda网络还有3个节点。 此图显示了每个节点应执行的操作

只有在这种情况下,我们才有麻烦“需要将代币从账户持有人转移到乙方”

流程代码:

class TransferETokenDiffNodeFlow(val actualHolder: AbstractParty, val newHolder: AbstractParty, val numEtokens: Double, val observables: MutableList = mutableListOf()) : FlowLogic() { private fun notary() = serviceHub.networkMapCache.notaryIdentities.first() @Suspendable override fun call(): SignedTransaction { progressTracker.currentStep = INITIALIZING val txBuilder = TransactionBuilder(notary()) val actualHolderStateRef = accountService.accountInfo(actualHolder.owningKey) ?: throw AccountNotFoundException("Account not found exception.") val actualHolderInfo = actualHolderStateRef.state.data val actualHolderSession = initiateFlow(actualHolderInfo.host) actualHolderSession.send(numEtokens) actualHolderSession.send(actualHolder) actualHolderSession.send(newHolder) val inputs = subFlow(ReceiveStateAndRefFlow(actualHolderSession)) val tokens: List = actualHolderSession.receive>().unwrap { it -> it} progressTracker.currentStep = BUILDING addMoveTokens(txBuilder, inputs, tokens) progressTracker.currentStep = SIGNING val initialSignedTrnx = serviceHub.signInitialTransaction(txBuilder) progressTracker.currentStep = GATHERING_SIGS val fulySignedTx= subFlow(CollectSignaturesFlow(initialSignedTrnx, listOf(actualHolderSession))) progressTracker.currentStep = FINALISING_CREATE val stx = subFlow(FinalityFlow(fulySignedTx, listOf(actualHolderSession))) progressTracker.currentStep = FINALISING val statesTx = stx.tx.outRefsOfType() statesTx.forEach { state -> observables.forEach { observable -> subFlow(ShareStateAndSyncAccounts(state, observable)) } } return stx } } //ResponderFlow code: class TransferETokenDiffNodeFlowResponder(val counterpartySession: FlowSession) : FlowLogic() { @Suspendable override fun call(): SignedTransaction { val numEtokens = counterpartySession.receive().unwrap { it } val actualHolder = counterpartySession.receive().unwrap { it } val newHolder = counterpartySession.receive().unwrap { it } val partyAndAmount = PartyAndAmount(newHolder, numEtokens of EnergyTokenType.getInstance("ENERGY")) val actualHolderStateRef = accountService.accountInfo(actualHolder.owningKey) ?: throw AccountNotFoundException("Account not found exception.") val actualHolderInfo = actualHolderStateRef.state.data val criteria = QueryCriteria.VaultQueryCriteria(externalIds = listOf(actualHolderInfo.identifier.id), status = Vault.StateStatus.UNCONSUMED) val selector = DatabaseTokenSelection(serviceHub) val (inputs, outputs) = selector.generateMove(listOf(partyAndAmount).toPairs(), actualHolder, TokenQueryBy(queryCriteria = criteria), runId.uuid) subFlow(SendStateAndRefFlow(counterpartySession, inputs)) counterpartySession.send(outputs) subFlow(object : SignTransactionFlow(counterpartySession) { @Throws(FlowException::class) override fun checkTransaction(stx: SignedTransaction) { } }) return subFlow(ReceiveFinalityFlow(counterpartySession)) } } 类TransferTokenDiffNodeFlow(val-actualHolder:AbstractParty, 瓦尔·纽霍尔德:抽象党, 瓦尔·努梅托肯斯:双倍, val可观测值:MutableList=mutableListOf()): FlowLogic(){ private fun公证人()=serviceHub.networkMapCache.NotaryIdentity.first() @暂停 重写趣味调用():SignedTransaction{ progressTracker.currentStep=正在初始化 val txBuilder=TransactionBuilder(公证人()) val actualHolderStateRef=accountService.accountInfo(actualHolder.owningKey) ?:抛出AccountNotFoundException(“Account not found exception.”) val actualHolderInfo=actualHolderStateRef.state.data val actualHolderSession=initiateFlow(actualHolderInfo.host) 实际HolderSession.send(numEtokens) actualHolderSession.send(actualHolder) 实际持有人会话发送(新持有人) val输入=子流(接收状态和流出(实际HolderSession)) val标记:List=actualHolderSession.receive>()。展开{it->it} progressTracker.currentStep=建筑 addMoveTokens(txBuilder、输入、标记) progressTracker.currentStep=签名 val initialSignedTrnx=serviceHub.signInitialTransaction(txBuilder) progressTracker.currentStep=收集信号 val fulySignedTx=子流(CollectSignaturesFlow(InitializedTnx,listOf(actualHolderSession))) progressTracker.currentStep=完成创建 val stx=子流(最终流(fulySignedTx,listOf(actualHolderSession))) progressTracker.currentStep=最终确定 val statesTx=stx.tx.outRefsOfType() statesTx.forEach{state-> observables.forEach{observables-> 子流(ShareStateAndSyncAccounts(状态,可观察)) } } 返回stx } } //响应流代码: 类TransferTokenDiffNodeFlowResponder(val countpartySession:FlowSession):FlowLogic(){ @暂停 重写趣味调用():SignedTransaction{ val numEtokens=counterpartySession.receive().unwrap{it} val actualHolder=countpartysession.receive().unwrap{it} val newHolder=counterpartySession.receive().unwrap{it} val partyAndAmount=partyAndAmount(newHolder,EnergyTokenType.getInstance(“ENERGY”)的numotekens) val actualHolderStateRef=accountService.accountInfo(actualHolder.owningKey) ?:抛出AccountNotFoundException(“Account not found exception.”) val actualHolderInfo=actualHolderStateRef.state.data val条件=QueryCriteria.VaultQueryCriteria(ExternalId=listOf(actualHolderInfo.identifier.id), 状态=Vault.StateStatus.Unused) val选择器=数据库令牌选择(serviceHub) val(输入,输出)=选择器.generateMove(listOf(partyAndAmount).toPairs(), actualHolder,TokenQueryBy(queryCriteria=criteria),runId.uuid) 子流(SendstateAndReflow(对方会话、输入)) 对方会话发送(输出) 子流(对象:SignTransactionFlow(对方会话){ @抛出(FlowException::类) 覆盖趣味支票交易(stx:SignedTransaction){ } }) 返回子流(接收最终流(对方会话)) } } 我们需要在丙方执行流程,实际持有人为账户持有人,新持有人为乙方

此代码返回一个错误: net.corda.core.CORDARUNTIMEEException:java.lang.IllegalArgumentException:未为以下交易参与者提供流程会话:[O=乙方,L=库里蒂巴,C=BR]

但如果我更改代码并添加乙方会话,它将返回错误: java.lang.IllegalArgumentException:CollectSignaturesFlow的发起人必须准确地传入事务签名所需的会话

问题是,为什么addMoveTokens不将newHolder作为必需的签名者?
我该如何解决这个问题呢?

代码中有许多要点需要讨论;让我们从错误开始:

  • 移动代币时,唯一需要的签名者是当前持有人;因此,在您的情况下,您应该只传递一个
    FlowSession
    ,这是与
    PartyA
    的会话(因为它是令牌的持有者);因此,您应该只有:
    CollectSignaturesFlow(initialSignedTrnx,listOf(actualHolderSession))
    
  • 至于完成交易,必须通过所有参与者的会话。您案例中所有参与者的联合是代币的当前持有人(即
    PartyA
    )和新持有人(即
    PartyB
    );因此,你应该:
    FinalityFlow(fulySignedTx,listOf(实际股东会话,party))
    
    这就是为什么当您只为两个子流传递
    actualHolderSession
    时;您收到缺少会话的消息(因为finality flow也希望为
    PartyB
    创建会话);当您为两者添加了
    PartyB
    会话时,收集签名流抱怨您正在传递一个额外的会话(
    PartyB
    不需要对move命令进行签名,只有当前持有者是)
  • 因为您的响应者流正在处理这两个任务(签名和完成);您必须从发起者向响应者发送一些数据(字符串或您选择的任何内容),以表示