合同约束失败...流程执行期间的corda异常

阿顿·贝里沙

我在corda中实现一个简单的用例时遇到了一些麻烦。我想实施免费的付款转账。生命周期在corda中维护。

首先,我创建了一个绑定状态,该状态将仅保存在可以正常工作的 nodeA 上)。之后我想创建一个代表 FOP 提议的新状态,接收者(nodeB)可以接受。这个想法是在创建 fop 提案时将消耗债券。在接收者接受提案(另一个需要实现的流程)后,将创建一个新的绑定状态,并且接收者是所有者。

创建 FOP 提议的流程(应该保存在 nodeA 和 nodeB 上的状态)是这样的:

object IssueFopFlow {

@InitiatingFlow
@StartableByRPC
class Initiator(private val sender: AbstractParty,
                private val receiver: AbstractParty,
                private val amount: Int,
                private val bondLinearId: UniqueIdentifier) : MyBaseFlow() {

    companion object {
        object INITIALISING : ProgressTracker.Step("Performing initial steps.")
        object BUILDING : ProgressTracker.Step("Building and verifying transaction.")
        object SIGNING : ProgressTracker.Step("Signing transaction.")
        object COLLECTING : ProgressTracker.Step("Collecting counterparty signature.") {
            override fun childProgressTracker() = CollectSignaturesFlow.tracker()
        }

        object FINALISING : ProgressTracker.Step("Finalising transaction.") {
            override fun childProgressTracker() = FinalityFlow.tracker()
        }

        fun tracker() = ProgressTracker(INITIALISING, BUILDING, SIGNING, COLLECTING, FINALISING)
    }

    override val progressTracker: ProgressTracker = tracker()

    @Suspendable
    override fun call(): SignedTransaction {
        // Step 1. Initialisation.
        progressTracker.currentStep = INITIALISING
        val bondForFop = getBondByLinearId(bondLinearId)
        val inputBond = bondForFop.state.data

        // check that the bond owner is calling this flow
        check(inputBond.owner == ourIdentity) {
            throw FlowException("Issue fop transfer must be initiated by the bond owner.")
        }

        // check the amount
        check(inputBond.amount >= amount) {
            throw FlowException("Not enough of the bond ${inputBond.isin}. Quantity: ${inputBond.amount}. Amount to transfer: ${amount}")
        }

        // create fop transfer state
        val fopTransfer = FopState(sender, receiver, amount, inputBond.isin)
        val ourSigningKey = fopTransfer.sender.owningKey

        // Step 2. Building.
        progressTracker.currentStep = BUILDING
        val utx = TransactionBuilder(firstNotary)
                .addInputState(bondForFop)
                .addOutputState(fopTransfer, FOP_CONTRACT_ID)
                .addCommand(FopContract.Commands.Issue(), listOf(sender.owningKey, receiver.owningKey))
                .setTimeWindow(serviceHub.clock.instant(), 30.seconds)

        // create new bond state
        if (amount < inputBond.amount) {
            val (command, newState) = inputBond.reduce(amount)
            utx
                    .addOutputState(newState, BOND_CONTRACT_ID)
                    .addCommand(command, newState.owner.owningKey)
        }

        utx.verify(serviceHub)

        // Step 3. Sign the transaction.
        progressTracker.currentStep = SIGNING
        val ptx = serviceHub.signInitialTransaction(utx, ourSigningKey)

        // Step 4. Get the counter-party signature.
        progressTracker.currentStep = COLLECTING
        val senderFlow = initiateFlow(ourIdentity)
        val stx = subFlow(
                CollectSignaturesFlow(
                        ptx,
                        setOf(senderFlow),
                        listOf(sender.owningKey, receiver.owningKey),
                        COLLECTING.childProgressTracker()
                )
        )

        // Step 5. Finalise the transaction.
        progressTracker.currentStep = FINALISING
        return subFlow(FinalityFlow(stx, FINALISING.childProgressTracker()))
    }
}

@InitiatedBy(Initiator::class)
class Responder(private val otherFlow: FlowSession) : FlowLogic<SignedTransaction>() {
    @Suspendable
    override fun call(): SignedTransaction {
        subFlow(IdentitySyncFlow.Receive(otherFlow))
        val stx = subFlow(SignTxFlowNoChecking(otherFlow))
        return waitForLedgerCommit(stx.id)
    }
}

}

我目前的问题是,我得到一个例外:

net.corda.core.contracts.TransactionVerificationException$ContractConstraintRejection: Contract constraints failed for com.models.BondContract, transaction: 44A52F07B9579C5106321361A6154C1EE5EF5670FA94CEFF24AB487F0B20D733
at net.corda.core.transactions.LedgerTransaction.verifyConstraints(LedgerTransaction.kt:91) ~[corda-core-2.0.0.jar:?]
at net.corda.core.transactions.LedgerTransaction.verify(LedgerTransaction.kt:67) ~[corda-core-2.0.0.jar:?]
at net.corda.core.transactions.TransactionBuilder.verify(TransactionBuilder.kt:113) ~[corda-core-2.0.0.jar:?]
at com.flow.IssueFopFlow$Initiator.call(IssueFopFlow.kt:78) ~[cordapp-0.1.jar:?]
at com.flow.IssueFopFlow$Initiator.call(IssueFopFlow.kt:19) ~[cordapp-0.1.jar:?]
at net.corda.node.services.statemachine.FlowStateMachineImpl.run(FlowStateMachineImpl.kt:96) [corda-node-2.0.0.jar:?]
at net.corda.node.services.statemachine.FlowStateMachineImpl.run(FlowStateMachineImpl.kt:41) [corda-node-2.0.0.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_162]
at java.util.concurrent.FutureTask.run(FutureTask.java:266) [?:1.8.0_162]
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$201(ScheduledThreadPoolExecutor.java:180) [?:1.8.0_162]
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:293) [?:1.8.0_162]
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) [?:1.8.0_162]
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) [?:1.8.0_162]

我不明白为什么。BondContract 的验证实现应该没问题(仅从我的角度来看:D)。这里也是债券合约的代码。

open class BondContract : Contract {

override fun verify(tx: LedgerTransaction) {
    val command = tx.commands.requireSingleCommand<Commands>()
    val setOfSigners = command.signers.toSet()
    when (command.value) {
        is Commands.Issue -> verifyIssue(tx, setOfSigners)
        is Commands.Reduce -> verifyReduce(tx, setOfSigners)
        else -> throw IllegalArgumentException("Unrecognised command.")
    }
}

private fun keysFromParticipants(bond: BondState): Set<PublicKey> {
    return bond.participants.map {
        it.owningKey
    }.toSet()
}

private fun verifyIssue(tx: LedgerTransaction, signers: Set<PublicKey>) = requireThat {
    "No inputs should be consumed when issuing an obligation." using (tx.inputStates.isEmpty())
    "Only one bond state should be created when issuing an obligation." using (tx.outputStates.size == 1)

    val bond = tx.outputsOfType<BondState>().single()
    "A newly issued bond must have a positive amount." using (bond.amount > 0)
    "Issuer may sign bond issue transaction." using
            (signers == keysFromParticipants(bond))
}

private fun verifyReduce(tx: LedgerTransaction, signers: Set<PublicKey>) = requireThat {
     val bond = tx.outputsOfType<BondState>().single()
    "A bond must have a positive amount." using (bond.amount > 0)
}

interface Commands : CommandData {
    class Move : TypeOnlyCommandData(), Commands
    class Issue : TypeOnlyCommandData(), Commands
    class Reduce : TypeOnlyCommandData(), Commands
}
}

// *********
// * State *
// *********
data class BondState(val isin: String,
                 val amount: Int,
                 override val owner: AbstractParty,
                 override val linearId: UniqueIdentifier = UniqueIdentifier()) : LinearState, QueryableState, OwnableState {

override val participants: List<AbstractParty> get() = listOf(owner)

override fun generateMappedObject(schema: MappedSchema): PersistentState {
    return when (schema) {
        is BondSchemaV1 -> BondSchemaV1.PersistentBond(
                this.owner.toString(),
                this.isin,
                this.amount,
                this.linearId.id
        )
        else -> throw IllegalArgumentException("Unrecognised schema $schema")
    }
}

override fun supportedSchemas(): Iterable<MappedSchema> = listOf(BondSchemaV1)

override fun withNewOwner(newOwner: AbstractParty) = CommandAndState(BondContract.Commands.Move(), copy(owner = newOwner))

fun reduce(amountToReduce: Int) =  CommandAndState(BondContract.Commands.Reduce(), copy(amount = amount - amountToReduce))
}

有人能帮我吗?

乔尔

这个问题是通过执行一个干净的构建来解决的,要么:

  • 使用 Gradleclean标志(例如gradlew clean deployNodes
  • build手动删除文件夹

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章

在哪里检查合同约束

Sonarqube 在 SonarQube Scanner 执行期间失败

Symfony 4迁移在执行期间迁移失败

可调用执行期间的异常

查询失败错误:查询执行期间超出了资源:无法在分配的内存中执行查询

命令“ go get github.com/gohugoio/hugo”失败,并在执行期间以2退出

Google ML Engine:预测失败:模型执行期间发生错误

Android上的代码执行期间React-Native-Gesture-Handler失败

程序执行期间Apache-Spark中的超时异常

转到异常“信号在CGO执行期间到达”

从Internet信息服务执行期间发生异常

corda Hello World pt 2 中的合同验证失败

协议约束使代码执行失败

Ansible:模块执行期间出现意外失败“find() 只需要 2 个参数(3 个给定)”

外键约束在“放置表”期间失败

执行期间的管道数据

执行期间 VHDL 复位

节点启动失败并出现错误:internal.Node.run - Corda 中节点启动 {} 期间出现异常

在运行期间根据设备更改约束

从Megento 2.0.2升级失败“在应用程序运行期间发生了错误。有关详细信息,请参见异常日志。”

travis错误:命令“ go get -u -v github.com/spf13/hugo”失败并在执行期间以1退出

Junit5验证执行期间是否引发了异常

如何在Flink作业执行期间记录未捕获的异常

当前Web请求的执行期间生成了未处理的异常。[HttpAntiForgeryException]

在 EMR 执行期间是什么导致 java.lang.NoClassDefFoundError 异常?

retrofit.RetrofitError请求网络执行期间发生异常:null

如何在 python 脚本的批处理文件执行期间捕获任何异常?

Ansible剧本导致任务执行期间发生一半的异常

当前Web请求的执行期间发生未处理的异常。ASP.NET