Daniel Gretzke
Daniel Gretzke

Reputation: 446

Verifying a transaction

I need some help understanding how the verification of a transaction works in Corda. If I understood correctly, all parties in a transaction are responsible for verifying it themselves.

I have a use case very similar to the negotiation cordapp between 2 parties. When writing a flow, I verify the unsigned transaction in the initiator:

// build the state that will be used as an output
val utx = TransactionBuilder(notary)
    .addInputState(input)
    .addOutputState(output)
    .addCommand(RequestContract.Commands.Accept(), output.participants.map { it.owningKey })

// verify the transaction against the smart contract
utx.verify(serviceHub)

// Sign the transaction.
val ptx = serviceHub.signInitialTransaction(utx, ourIdentity.owningKey)

In the responder, I need to verify the transaction as well.

val signTransactionFlow = object : SignTransactionFlow(counterpartySession) {
    override fun checkTransaction(stx: SignedTransaction) {
        val state = stx.tx.outputStates.single() as RequestState
        requireThat {
            "Fulfilling a request has to be initiated by the fulfilling party" using (state.requestingParty == ourIdentity)
        }
    }
}

val stx = subFlow(signTransactionFlow)

// verify the transaction against the smart contract
stx.verify(serviceHub, checkSufficientSignatures = false)

return subFlow(ReceiveFinalityFlow(counterpartySession, stx.id))

Unless I set checkSufficientSignatures = false, I get an error that a signature is missing (SignedTransaction$SignaturesMissingException).

Why am I getting the error? I signed the transaction in the initiator and in the responder flow. How can I ensure that all signatures are present if I set checkSufficientSignatures to false? And lastly why doesn't the error show up when creating the RequestState, where both parties are signers as well and the flows are built pretty much identically?

Upvotes: 0

Views: 110

Answers (1)

Adel Rustum
Adel Rustum

Reputation: 2548

  1. I don't see you calling CollectSignaturesFlow in the initiator; without that call, how are you going to ask the counter parties to sign?
  2. No need to call verify() in the responder, if you open the code of SignTransactionFlow() you'll see here that when it receives the transaction; it resolves and verifies all of the transactions that lead to this transaction (including this one). So you can safely remove that call.

Upvotes: 1

Related Questions