generateSpend, исходящий из другого узла - PullRequest
0 голосов
/ 21 ноября 2018

Можно ли использовать следующий метод для создания расходов от Стороны B к Стороне A, но при вызове потоком, выполняющимся на Стороне A?

Это заменяет идентификатор текущего узла, выполняющего поток для стороны B. Однако, он возвращает исключение для cashKeys:

java.util.NoSuchElementException: Collection contains no element matching the predicate.

Метод:

val (_, cashKeys) = Cash.generateSpend(serviceHub, builder, amount, partyBCert, forwardState.initiator)

Получатель PartyAndCertificate:

private fun getPartyBCert(): PartyAndCertificate {
    val partyBIdentityAndCertList = serviceHub.networkMapCache.getNodeByLegalName(CordaX500Name("PartyB", "New York", "US"))
            ?.legalIdentitiesAndCerts
            ?: throw FlowException("PartyB not found on network.")
    return partyBIdentityAndCertList.component1()
}

Трассировка стека:

java.util.NoSuchElementException: Collection contains no element matching the predicate.
at net.corda.node.services.keys.PersistentKeyManagementService.getSigningKeyPair(PersistentKeyManagementService.kt:110) ~[corda-node-3.3-corda.jar:?]
at net.corda.node.services.keys.PersistentKeyManagementService.getSigner(PersistentKeyManagementService.kt:85) ~[corda-node-3.3-corda.jar:?]
at net.corda.node.services.keys.PersistentKeyManagementService.freshKeyAndCert(PersistentKeyManagementService.kt:83) ~[corda-node-3.3-corda.jar:?]
at net.corda.finance.contracts.asset.Cash$Companion.generateSpend(Cash.kt:332) ~[corda-finance-3.3-corda.jar:?]
at net.corda.finance.contracts.asset.Cash$Companion.generateSpend(Cash.kt:265) ~[corda-finance-3.3-corda.jar:?]
at net.corda.finance.contracts.asset.Cash$Companion.generateSpend$default(Cash.kt:264) ~[corda-finance-3.3-corda.jar:?]
at com.template.flows.SettleCashFlow.call(SettleCashFlow.kt:117) ~[cordapp-0.1.jar:?]
at com.template.flows.SettleCashFlow.call(SettleCashFlow.kt:31) ~[cordapp-0.1.jar:?]
at net.corda.node.services.statemachine.FlowStateMachineImpl.run(FlowStateMachineImpl.kt:96) [corda-node-3.3-corda.jar:?]
at net.corda.node.services.statemachine.FlowStateMachineImpl.run(FlowStateMachineImpl.kt:44) [corda-node-3.3-corda.jar:?]
at co.paralleluniverse.fibers.Fiber.run1(Fiber.java:1092) [quasar-core-0.7.9-jdk8.jar:0.7.9]
at co.paralleluniverse.fibers.Fiber.exec(Fiber.java:788) [quasar-core-0.7.9-jdk8.jar:0.7.9]
at co.paralleluniverse.fibers.RunnableFiberTask.doExec(RunnableFiberTask.java:100) [quasar-core-0.7.9-jdk8.jar:0.7.9]
at co.paralleluniverse.fibers.RunnableFiberTask.run(RunnableFiberTask.java:91) [quasar-core-0.7.9-jdk8.jar:0.7.9]
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511) [?:1.8.0_191]
at java.util.concurrent.FutureTask.run(FutureTask.java:266) [?:1.8.0_191]
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$201(ScheduledThreadPoolExecutor.java:180) [?:1.8.0_191]
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:293) [?:1.8.0_191]
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) [?:1.8.0_191]
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) [?:1.8.0_191]
at net.corda.node.utilities.AffinityExecutor$ServiceAffinityExecutor$1$thread$1.run(AffinityExecutor.kt:62) [corda-node-3.3-corda.jar:?]

Получатель платежа может измениться в моем потоке, есть ли другой способ для этого сценария без необходимости разбивать его на два отдельных потока?

Редактировать: трассировка стека для отсутствующих вложений

net.corda.core.contracts.TransactionVerificationException$MissingAttachmentRejection: Contract constraints failed, could not find attachment for: com.template.ForwardContract, transaction: B5606C7142B87D424DD0BDF8FF749987D53BF5B7D279795F32DA6AA4340D5403
at net.corda.core.transactions.LedgerTransaction.verifyConstraints(LedgerTransaction.kt:96) ~[corda-core-3.3-corda.jar:?]
at net.corda.core.transactions.LedgerTransaction.verify(LedgerTransaction.kt:79) ~[corda-core-3.3-corda.jar:?]
at net.corda.core.transactions.TransactionBuilder.verify(TransactionBuilder.kt:143) ~[corda-core-3.3-corda.jar:?]
at com.template.flows.SettleCashFlow.call(SettleCashFlow.kt:119) ~[cordapp-0.1.jar:?]
at com.template.flows.SettleCashFlow.call(SettleCashFlow.kt:32) ~[cordapp-0.1.jar:?]
at net.corda.node.services.statemachine.FlowStateMachineImpl.run(FlowStateMachineImpl.kt:96) [corda-node-3.3-corda.jar:?]
at net.corda.node.services.statemachine.FlowStateMachineImpl.run(FlowStateMachineImpl.kt:44) [corda-node-3.3-corda.jar:?]
at co.paralleluniverse.fibers.Fiber.run1(Fiber.java:1092) [quasar-core-0.7.9-jdk8.jar:0.7.9]
at co.paralleluniverse.fibers.Fiber.exec(Fiber.java:788) [quasar-core-0.7.9-jdk8.jar:0.7.9]
at co.paralleluniverse.fibers.RunnableFiberTask.doExec(RunnableFiberTask.java:100) [quasar-core-0.7.9-jdk8.jar:0.7.9]
at co.paralleluniverse.fibers.RunnableFiberTask.run(RunnableFiberTask.java:91) [quasar-core-0.7.9-jdk8.jar:0.7.9]
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511) [?:1.8.0_191]
at java.util.concurrent.FutureTask.run(FutureTask.java:266) [?:1.8.0_191]
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$201(ScheduledThreadPoolExecutor.java:180) [?:1.8.0_191]
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:293) [?:1.8.0_191]
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) [?:1.8.0_191]
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) [?:1.8.0_191]
at net.corda.node.utilities.AffinityExecutor$ServiceAffinityExecutor$1$thread$1.run(AffinityExecutor.kt:62) [corda-node-3.3-corda.jar:?]

Это связано с отсутствием ключей в generateSpend?Если да, как вы извлекаете ключи из потока контрагента аналогично получению денежных средств Стороной A -> B.verifyConstraints () говорит, что транзакции, исходящие из другого узла, требуют проверки вложений.

1 Ответ

0 голосов
/ 21 ноября 2018

Вызов Cash.generateSpend от имени кого-то другого просто не сработает.Ожидается, что он будет вызван владельцем денежных средств.

Однако вы все равно можете добавить денежные средства в одном потоке.Возможно, проще всего отправить TransactionBuilder контрагенту и заставить его позвонить Cash.generateSpend.В псевдокоде:

@InitiatingFlow
@StartableByRPC
class Initiator(val counterparty: Party) : FlowLogic<Unit>() {
    override val progressTracker = ProgressTracker()

    @Suspendable
    override fun call() {
        val txBuilder = TransactionBuilder()

        // TODO: Update TransactionBuilder.

        val counterpartySession = initiateFlow(counterparty)

        val updatedTxBuilder = counterpartySession
                .sendAndReceive<TransactionBuilder>(txBuilder)
                .unwrap { it -> it }

        // Check `updatedTxBuilder still has all the stuff you put in
        // originally, plus a new set of input/output cash states.

        // Finish flow using the `updatedTxBuilder`.
    }
}

@InitiatedBy(Initiator::class)
class Responder(val counterpartySession: FlowSession) : FlowLogic<Unit>() {
    @Suspendable
    override fun call() {
        val txBuilder = counterpartySession
                .receive<TransactionBuilder>()
                .unwrap { it -> it }

        // Pass the correct arguments here.
        Cash.generateSpend(serviceHub, txBuilder, ...)

        counterpartySession.send(txBuilder)
    }
}

Обратите внимание, что вам нужно будет добавить TransactionBuilder в белый список сериализации узлов, чтобы отправлять и получать его экземпляры в потоках.

...