'CommercialPaper Tutorial, creating a flow to issue,move and redeem a currency

I'm trying to create a flow to Issue and Move currency. The Contract i have use is the CommercialPaper from the tutorial https://docs.corda.net/tutorial-contract.html. But i can't get it to work. Here is my flow from the code. I use following commands in the CLI after starting up all the nodes (notery/networkmap,PartyA,PartyB)

  1. start CPIssueFlow value: 6
  2. start CPMoveFlow value: 3, otherParty: "O=PartyB,L=New York,C=US"

The error i get is 'Insufficient funds' from the function 'gatherOurInputs'. Can How can i fix this?

UPDATE: The github repo is : https://github.com/WesleyCap/Corda/ The Code is updated. The CPIssueFlow didnt work correctly. Now i get the next error.

Contract verification failed: Failed requirement: for reference [00] at issuer C=GB,L=London,O=PartyA the amounts balance: 6 - 0 != 0, contract: net.corda.finance.contracts.asset.Cash@58e904ed, transaction: 71F70042CDA3D46E05ABE319DA5F14D3BDBBB1C80A24753AA9AC660DCD830109

 package com.template

import co.paralleluniverse.fibers.Suspendable
import com.template.CommercialPaperContract.Companion.CP_PROGRAM_ID
import net.corda.core.contracts.*
import net.corda.core.flows.*
import net.corda.core.identity.AbstractParty
import net.corda.core.identity.Party
import net.corda.core.node.ServiceHub
import net.corda.core.node.services.VaultService
import net.corda.core.node.services.vault.QueryCriteria
import net.corda.core.transactions.SignedTransaction
import net.corda.core.transactions.TransactionBuilder
import net.corda.core.utilities.ProgressTracker
import net.corda.finance.DOLLARS
import net.corda.finance.EUR
import net.corda.finance.contracts.asset.CASH
import net.corda.finance.contracts.asset.Cash
import net.corda.finance.contracts.asset.PartyAndAmount
import net.corda.finance.issuedBy
import java.time.Instant
import java.util.*


import net.corda.core.node.services.vault.builder
import net.corda.core.utilities.OpaqueBytes
import net.corda.finance.flows.AbstractCashFlow
import net.corda.finance.flows.CashIssueFlow
import net.corda.finance.schemas.CashSchemaV1




import net.corda.core.contracts.Amount
import net.corda.core.flows.StartableByRPC




// *********
// * Flows *
// *********
object CPIssueFlow {

    @InitiatingFlow
    @StartableByRPC
    class Initiator(val value: Long) : FlowLogic<Unit>() {

        /** The progress tracker provides checkpoints indicating the progress of the flow to observers. */
        override val progressTracker = tracker()

        companion object {
            object PREPARING : ProgressTracker.Step("Gathering the required inputs.")
            object CREATECURRENCY : ProgressTracker.Step("Creating cash.")
            object SIGNING : ProgressTracker.Step("Sign the transaction.")
            object TOVAULT : ProgressTracker.Step("Returning the newly-issued cash state.")

            fun tracker() = ProgressTracker(PREPARING, CREATECURRENCY, SIGNING, TOVAULT)
        }

        /** The flow logic is encapsulated within the call() method. */
        @Suspendable
        override fun call() {

            progressTracker.currentStep = PREPARING
            val notary = serviceHub.networkMapCache.notaryIdentities[0]
            val builder = TransactionBuilder(notary)
            val amount = Amount(value , EUR)
            val issuer = ourIdentity.ref(1)

            progressTracker.currentStep = CREATECURRENCY
            val signers = Cash().generateIssue(builder, amount.issuedBy(issuer), ourIdentity, notary)

            progressTracker.currentStep = SIGNING
            val tx = serviceHub.signInitialTransaction(builder, signers)

            progressTracker.currentStep = TOVAULT
            subFlow(FinalityFlow(tx))
        }
    }

    @InitiatedBy(CPIssueFlow.Initiator::class)
    class Acceptor(val otherPartyFlow: FlowSession) : FlowLogic<SignedTransaction>() {
        @Suspendable
        override fun call(): SignedTransaction {
            val signTransactionFlow = object : SignTransactionFlow(otherPartyFlow) {
                override fun checkTransaction(stx: SignedTransaction) = requireThat {
                    val output = stx.tx.outputs.single().data
                    "This must be an CommercialPaperState transaction." using (output is CommercialPaperState)

                }
            }

            return subFlow(signTransactionFlow)
        }
    }
}

object CPMoveFlow {
    @InitiatingFlow
    @StartableByRPC
    class Initiator(val value: Long, val otherParty: Party) : FlowLogic<Unit>() {

        /** The progress tracker provides checkpoints indicating the progress of the flow to observers. */
        override val progressTracker = tracker()

        companion object {
            object PREPARING : ProgressTracker.Step("Getting the needed information")
            object PREPARESTATES : ProgressTracker.Step("Creating inputstates,outputstates and commands")
            object ADDSTATESTOTX : ProgressTracker.Step("Add inputstates,outputstates and commands to the transaction")
            object VERIFYTX : ProgressTracker.Step("Verify transaction")
            object SIGNING : ProgressTracker.Step("Signing the transaction")
            object SENDTOVAULT : ProgressTracker.Step("Put the transaction in the vault")

            fun tracker() = ProgressTracker(PREPARING, PREPARESTATES, ADDSTATESTOTX, VERIFYTX, SIGNING, SENDTOVAULT)
        }

        /** The flow logic is encapsulated within the call() method. */
        @Suspendable
        override fun call() {

            progressTracker.currentStep = PREPARING
            val notary = serviceHub.networkMapCache.notaryIdentities[0]
            val txBuilder = TransactionBuilder(notary = notary)
            val issuer = ourIdentity.ref(1)
            val amount = Amount(value , EUR)

            progressTracker.currentStep = PREPARESTATES
            // We create the transaction components.
            val (inputStates, residual) = gatherOurInputs(serviceHub,runId.uuid ,amount.issuedBy(issuer) , notary)
            val outputState = CommercialPaperState(issuer, otherParty, amount.issuedBy(issuer), Instant.now())
            val outputContractAndState = StateAndContract(outputState, CP_PROGRAM_ID)
            val cmd = Command(CommercialPaperContract.Commands.Move(), listOf(ourIdentity.owningKey, otherParty.owningKey))

            progressTracker.currentStep = ADDSTATESTOTX
            txBuilder.withItems(outputContractAndState, cmd)
            txBuilder.addInputState(inputStates[0])

            progressTracker.currentStep = VERIFYTX
            txBuilder.verify(serviceHub)

            progressTracker.currentStep = SIGNING
            val signedTx = serviceHub.signInitialTransaction(txBuilder)
            val otherpartySession = initiateFlow(otherParty)// Creating a session with the other party.
            val fullySignedTx = subFlow(CollectSignaturesFlow(signedTx, listOf(otherpartySession), CollectSignaturesFlow.tracker())) // Obtaining the counterparty's signature.

            progressTracker.currentStep = SENDTOVAULT
            // Finalising the transaction.
            subFlow(FinalityFlow(fullySignedTx))
        }
    }

    @InitiatedBy(CPMoveFlow.Initiator::class)
    class Acceptor(val otherPartyFlow: FlowSession) : FlowLogic<SignedTransaction>() {
        @Suspendable
        override fun call(): SignedTransaction {
            val signTransactionFlow = object : SignTransactionFlow(otherPartyFlow) {
                override fun checkTransaction(stx: SignedTransaction) = requireThat {
                    val output = stx.tx.outputs.single().data
                    "This must be an IOU transaction." using (output is CommercialPaperState)

                }
            }

            return subFlow(signTransactionFlow)
        }
    }

    // This is equivalent to the Cash.generateSpend
    // Which is brought here to make the filtering logic more visible in the example
    private fun gatherOurInputs(serviceHub: ServiceHub,
                                lockId: UUID,
                                amountRequired: Amount<Issued<Currency>>,
                                notary: Party?): Pair<List<StateAndRef<Cash.State>>, Long> {
        // extract our identity for convenience
        val ourKeys = serviceHub.keyManagementService.keys
        val ourParties = ourKeys.map { serviceHub.identityService.partyFromKey(it) ?: throw IllegalStateException("Unable to resolve party from key") }
        val fungibleCriteria = QueryCriteria.FungibleAssetQueryCriteria(owner = ourParties)

        val notaries = notary ?: serviceHub.networkMapCache.notaryIdentities.first()
        val vaultCriteria: QueryCriteria = QueryCriteria.VaultQueryCriteria(notary = listOf(notaries as AbstractParty))

        val logicalExpression = builder { CashSchemaV1.PersistentCashState::currency.equal(amountRequired.token.product.currencyCode) }
        val cashCriteria = QueryCriteria.VaultCustomQueryCriteria(logicalExpression)

        val fullCriteria = fungibleCriteria.and(vaultCriteria).and(cashCriteria)

        val eligibleStates = serviceHub.vaultService.tryLockFungibleStatesForSpending(lockId, fullCriteria, amountRequired.withoutIssuer(), Cash.State::class.java)

        check(eligibleStates.isNotEmpty()) { "Insufficient funds" }
        val amount = eligibleStates.fold(0L) { tot, (state) -> tot + state.data.amount.quantity }
        val change = amount - amountRequired.quantity

        return Pair(eligibleStates, change)
    }

}


Solution 1:[1]

During the CPMoveFlow, you're attempting to gather cash from your vault. However, you don't have any at this point.

In order for the cash to be used as an input into this transaction, it will need to come from somewhere. In these situations where you're building out a prototype/testing, your best bet is to self issue yourself cash.

Take a look at the code in the flow here.

Edit: gatherOurInputs is insufficient to correctly spend cash. You will need both inputs and outputs where the inputs is cash you previously self issued and the output will x amount of that cash with the other party now as the owner.

The easiest way forward would be to use the Cash.generateSpend function which will add both the inputs and outputs for you to the transaction e.g.

Cash.generateSpend(serviceHub, txBuilder, amount, otherParty)

You will now see a different error pertaining to contract verification failing for your commercial paper, but I'll leave that to you to debug. The unit test framework within Corda is really good for this.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1