net.corda.core.contracts.TransactionVerificationException $ ContractRejection:合同验证失败:

时间:2018-05-21 13:02:19

标签: corda

我在执行流量测试时遇到异常

net.corda.core.contracts.TransactionVerificationException$ContractRejection: Contract verification failed: Required com.example.contract.InvoiceContract.Commands command, contract: com.example.contract.InvoiceContract

我有一个txn,它消耗4种不同类型的线性状态,更新一些字段并将它们添加到输出状态。 txn有一个命令,其逻辑在上述状态契约中定义。 以下是我的流程代码:

object SubmitDocuments {

@InitiatingFlow
@StartableByRPC
class SubmitDocumentsToBank(val locState: StateAndRef<LOCState>, val invoiceState: StateAndRef<InvoiceState>, val packingListState: StateAndRef<PackingListState>, val bolState: StateAndRef<BillOfLadingState>, val updatedlocState: LOCState, val bank: Party) : FlowLogic<SignedTransaction>(){

    companion object{
        object CREATING_BUILDER : ProgressTracker.Step("Creating a Transaction builder")
        object ADDING_STATES : ProgressTracker.Step("Adding Purchase order State in the transation output")
        object ADDING_COMMAND : ProgressTracker.Step("Adding a Create Command in the transaction")
        object VERIFIYING_TX : ProgressTracker.Step("Verifying the txn")
        object SIGNING_TX : ProgressTracker.Step("Signing the transaction")
        object SENDING_TX : ProgressTracker.Step("Sending and committing the transaction")

        fun tracker() = ProgressTracker(CREATING_BUILDER, ADDING_STATES, ADDING_COMMAND, SIGNING_TX, VERIFIYING_TX, SENDING_TX  )
    }

    override val progressTracker: ProgressTracker = tracker()

    @Suspendable
    override fun call(): SignedTransaction {

        val notary = serviceHub.networkMapCache.notaryIdentities.first()

        progressTracker.currentStep = CREATING_BUILDER
        val buider = TransactionBuilder(notary)
        buider.setTimeWindow(Instant.now(), Duration.ofSeconds(60))

        progressTracker.currentStep = ADDING_STATES

        val newInvoiceState = invoiceState.state.data.copy(participants = listOf(invoiceState.state.data.seller, bank))
        val newpackingListState = packingListState.state.data.copy(participants = listOf(invoiceState.state.data.seller, bank))
        val newbolState = bolState.state.data.copy(owner = bank, participants = listOf(bank) )

        buider.addInputState(invoiceState)
        buider.addInputState(packingListState)
        buider.addInputState(bolState)
        buider.addInputState(locState)

        buider.addOutputState(newInvoiceState, LOCContract.LOC_CONTRACT_ID)
        buider.addOutputState(newpackingListState, LOCContract.LOC_CONTRACT_ID)
        buider.addOutputState(newbolState, LOCContract.LOC_CONTRACT_ID)
        buider.addOutputState(updatedlocState, LOCContract.LOC_CONTRACT_ID)


        progressTracker.currentStep = ADDING_COMMAND

        val verifyDocHashCommand = Command(LOCContract.Commands.VerifySubmittedDocuments(), listOf(serviceHub.myInfo.legalIdentities.first().owningKey))
        buider.addCommand(verifyDocHashCommand)


        progressTracker.currentStep = VERIFIYING_TX
        buider.verify(serviceHub)

        progressTracker.currentStep = SIGNING_TX
        val stx = serviceHub.signInitialTransaction(buider)

        progressTracker.currentStep = SENDING_TX

        return subFlow(FinalityFlow(stx))

    }

}

}

下面是我的合同代码,其中包含指定命令的逻辑:

open class LOCContract: Contract {

companion object {
    @JvmStatic
    val LOC_CONTRACT_ID = "com.example.contract.LOCContract"
}

interface  Commands: CommandData {
    class IssueLoc(val referenceState: String): Commands
    class VerifySubmittedDocuments: Commands
    class EndorseDocuments(val caller: Party): Commands
    class ReleaseDocuments: Commands
}

override fun verify(tx: LedgerTransaction) {

    val time = Instant.now()
    val command = tx.commands.requireSingleCommand<Commands>()
    when (command.value) {


        is LOCContract.Commands.VerifySubmittedDocuments -> {
            val inputInvoiceState = tx.inputsOfType<InvoiceState>().single()
            val inputplistState = tx.inputsOfType<PackingListState>().single()
            val inputbolState = tx.inputsOfType<BillOfLadingState>().single()
            val bolHash = inputbolState.props.billOfLadingAttachment.hash
            val invoiceHash = inputInvoiceState.props.invoiceAttachmentHash.hash
            val packinglistHash = inputplistState.props.packingListAttachment.hash

            val nonContractAttachments:List<Attachment> = tx.attachments.filter { it !is ContractAttachment }

            requireThat {

                "Attachments are empty" using (nonContractAttachments.isNotEmpty())

                var  list: ImmutableList<SecureHash>? = null
                nonContractAttachments.forEach((fun (data){
                    list!!.add(data.id)
                }))

                "transaction should have valid Bill of lading document hash" using (list!!.contains(bolHash))
                "transaction should have valid Invoice document hash" using (list!!.contains(invoiceHash))
                "transaction should have valid Packing List document hash" using (list!!.contains(packinglistHash))
            }

        }

    }
}

}

为什么抱怨=&gt;必需的com.example.contract.InvoiceContract.Commands命令,contract:com.example.contract.InvoiceContract,transaction: 我在流程中构建txn时是否遗漏了什么?

2 个答案:

答案 0 :(得分:0)

似乎您的InvoiceContract继承自LOCContractInvoiceContract tx.commands.requireSingleCommand<Commands>()内的@foreach($group as $key=>$data) <td>{{$data->value}}</td> @endforeach 正在抛出此错误。

答案 1 :(得分:0)

错误有效:交易需要参考 com.example.contract.InvoiceContract.Commands

在流程类中,您正在更新InvoiceState,但transaction没有找到command InvoiceContract的引用。

  

修复应该是:

  1. 输出状态应参考InvoiceContract合同类buider.addOutputState(newInvoiceState, InvoiceContract.INVOICE_CONTRACT_ID)
  2. 然后创建适当的InvoiceContract Command并将其添加到事务构建器。