2
votes

Alice and Bob have an IOU (I-owe-you) agreement. Is it possible for Alice to show the IOU agreement with Bob to Charlie if she wants to prove that she really has an agreement with Bob? How can Charlie verify the IOU between Alice and Bob is real and not fake? What is the flow of this use case?

1

1 Answers

2
votes

Alice can prove to Charlie that she has a valid agreement with Bob by sending the transaction that created the agreement to Charlie.

Charlie will then check that the transaction is valid, that it has all the required signers, and that it is signed by both Alice and Bob.

The following flow pair would achieve this:

/**
 * Sends a transaction with the given [txHash] to the [counterparty]:
 *
 * @param txHash the transaction to send.
 * @param counterparty the counterparty to send the transaction to.
 */
@InitiatingFlow
@StartableByRPC
class Initiator(val txHash: SecureHash,
                val counterparty: Party) : FlowLogic<Unit>() {

    @Suspendable
    override fun call() {
        val tx = serviceHub.validatedTransactions.getTransaction(txHash)!!
        val counterpartySession = initiateFlow(counterparty)
        counterpartySession.send(tx)
    }
}

/**
 * Receives a transaction from the counterparty and checks that:
 *  - It is valid
 *  - It has valid signatures from all required signers
 *  - The [requiredSigners] have all signed the transaction
 *
 * @param counterpartySession a session with the party sending the transaction to be checked.
 * @param requiredSigners the parties who are required to have signed the transaction.
 */
@InitiatedBy(Initiator::class)
class Acceptor(val counterpartySession: FlowSession,
               val requiredSigners: List<CordaX500Name>) : FlowLogic<SignedTransaction>() {

    @Suspendable
    override fun call(): SignedTransaction {
        return counterpartySession.receive<SignedTransaction>().unwrap { tx ->
            // Transaction is valid and all the required signatures are present and valid.
            tx.verify(serviceHub)

            val requiredSigningParties = requiredSigners.map { serviceHub.networkMapCache.getPeerByLegalName(it)!! }
            val allHaveSigned = requiredSigningParties.all { party -> tx.sigs.any { sig -> sig.by == party.owningKey } }

            if (!allHaveSigned) {
                throw FlowException("The required parties have not signed the transaction.")
            }

            // TODO: Additional checking of the transaction (e.g. the properties of the inputs and outputs).

            tx
        }
    }
}