user150599
user150599

Reputation: 49

R3 Corda - java.lang.IllegalArgumentException: The Initiator of CollectSignaturesFlow must have signed the transaction

I have written the following flow to facilitate a transaction between 2 parties - issuer and subscriber. I have been getting this error at the Gathering the counterparty's signature. stage:

java.lang.IllegalArgumentException: The Initiator of CollectSignaturesFlow must have signed the transaction.

Stacktrace:

java.lang.IllegalArgumentException: The Initiator of CollectSignaturesFlow must have signed the transaction.
    at net.corda.core.flows.CollectSignaturesFlow.call(CollectSignaturesFlow.kt:89) ~[corda-core-3.3-corda.jar:?]
    at net.corda.core.flows.CollectSignaturesFlow.call(CollectSignaturesFlow.kt:64) ~[corda-core-3.3-corda.jar:?]
    at net.corda.core.flows.FlowLogic.subFlow(FlowLogic.kt:290) ~[corda-core-3.3-corda.jar:?]
    at com.sample.flow.sampleFlow$Initiator.call(sampleFlow.kt:106) ~[main/:?]
    at com.sample.flow.sampleFlow$Initiator.call(sampleFlow.kt:30) ~[main/:?]
    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_181]
    at java.util.concurrent.FutureTask.run(FutureTask.java:266) [?:1.8.0_181]
    at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$201(ScheduledThreadPoolExecutor.java:180) [?:1.8.0_181]
    at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:293) [?:1.8.0_181]
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) [?:1.8.0_181]
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) [?:1.8.0_181]
    at net.corda.node.utilities.AffinityExecutor$ServiceAffinityExecutor$1$thread$1.run(AffinityExecutor.kt:62) [corda-node-3.3-corda.jar:?]

My code: flow.kt

progressTracker.currentStep = GATHERING_SIGS
val participantsParties = sampleState.participants.map { serviceHub.identityService.wellKnownPartyFromAnonymous(it)!! }
val flowSessions = (participantsParties - serviceHub.myInfo.legalIdentities.get(0)).map { initiateFlow(it) }.toSet()
val fullySignedTx = subFlow(CollectSignaturesFlow(partSignedTx, flowSessions, listOf(ourSigningKey), GATHERING_SIGS.childProgressTracker()))

I tried the solutions which were presented online that is:

  1. to add all parties' sessions as a parameter to CollectSignaturesFlow
  2. I tried with all constructors of CollectSignaturesFlow mentioned on the documentation

I am not able to figure out where I am going wrong. Could someone please help me out with this? Thanks in advance!

Upvotes: 0

Views: 242

Answers (1)

Adel Rustum
Adel Rustum

Reputation: 2548

Your solution is wrong; I will demonstrate using cordapp-example flow how 2 (or more) parties sign a transaction:

  1. First, your flow should have 2 parts: Initiator and Responder.
  2. Assuming your issuer is the party that starts the Initiator, then your subscriber is the party that runs the Responder.
  3. issuer starts by creating the transaction which identifies the inputs, outputs, command, and required signers.
  4. issuer signs the transaction, notice how the result is called partSignedTx; that's because subscriber hasn't signed yet.
  5. issuer creates a session with subscriber to be used as a communication channel through which they collect the signature of the subscriber (you don't create a session with yourself like you did, only with others).
  6. issuer requests the signature from subscriber using that session.
  7. subscriber inside Responder flow signs the transaction.
  8. issuer inside Initiator flow receives the signature. CollectSignaturesFlow has a send (to send the transaction to be signed) and a receive (to receive the signature). Notice how the result is called fullySignedTx, because now both issuer and subscriber signed the transaction.

Upvotes: 1

Related Questions