首页 > 解决方案 > 指向新合约版本的国家仍然试图反序列化旧合约?

问题描述

我有一个场景,我已将我的义务从 V1 升级到 V2,并成功地指出了正确的 V2 合同。接下来,我尝试SettleObligation对这些升级的 V2 状态进行分析。当交易形成并发送出去时CollectSignatureFlowjava.lang.NoSuchMethodError在我的isGreaterThan方法中找到了一个verifySettle在合同中的命令中调用的方法。

这个特定的函数最初存在于包“com.example.base”中的一个文件BaseHelper.kt中,一路上,在 V2 中,我们将该函数迁移到另一个文件MathHelper.kt,这个移动并没有导致任何未解析的引用,因为包是相同的。

想了解:

  1. 合约是否通过文件名而不是包名来引用函数位置?一旦你编译它就不会改变contract-v1.jar
  2. 为什么 V2 状态仍然尝试反序列化 V1 合约?这是通过以某种方式走链来完成的吗?

下面的堆栈跟踪

[WARN] 2018-11-13T00:05:12,777Z [Node thread-1] flow.[cd538d42-1715-4ed3-bde6-38eca94ef79f].run - 由于接收异常 {} 而结束了流程
net.corda.core.contracts.TransactionVerificationException$ContractRejection:合同验证失败:com.example.base.BaseHelperKt.isGreaterThan(Ljava/math/BigDecimal;Ljava/math/BigDecimal;)Z,
合约:com.example.contracts.ObligationContractV1,交易:8B8780A16D330A93A361F747B77C227442BD310C9DAAA561376DED69F580C794
        在 net.corda.node.services.statemachine.FlowStateMachineImpl.erroredEnd(FlowStateMachineImpl.kt:497) ~[corda-node-3.2.1847-corda.jar:?]
        在 net.corda.node.services.statemachine.FlowStateMachineImpl.confirmNoError(FlowStateMachineImpl.kt:481) ~[corda-node-3.2.1847-corda.jar:?]
        在 net.corda.node.services.statemachine.FlowStateMachineImpl.waitForMessage(FlowStateMachineImpl.kt:444) ~[corda-node-3.2.1847-corda.jar:?]
        在 net.corda.node.services.statemachine.FlowStateMachineImpl.receiveInternal(FlowStateMachineImpl.kt:376) ~[corda-node-3.2.1847-corda.jar:?]
        在 net.corda.node.services.statemachine.FlowStateMachineImpl.receive(FlowStateMachineImpl.kt:229) ~[corda-node-3.2.1847-corda.jar:?]
        在 net.corda.node.services.statemachine.FlowSessionImpl.receive(FlowSessionImpl.kt:44) ~[corda-node-3.2.1847-corda.jar:?]
        在 net.corda.node.services.statemachine.FlowSessionImpl.receive(FlowSessionImpl.kt:48) ~[corda-node-3.2.1847-corda.jar:?]
        在 net.corda.core.flows.CollectSignatureFlow.call(CollectSignaturesFlow.kt:290) ~[corda-core-3.2.1847-corda.jar:?]
        在 net.corda.core.flows.CollectSignatureFlow.call(CollectSignaturesFlow.kt:135) ~[corda-core-3.2.1847-corda.jar:?]
        在 net.corda.core.flows.FlowLogic.subFlow(FlowLogic.kt:290) ~[corda-core-3.2.1847-corda.jar:?]
        在 net.corda.core.flows.CollectSignaturesFlow.call(CollectSignaturesFlow.kt:114) ~[corda-core-3.2.1847-corda.jar:?]
        在 net.corda.core.flows.CollectSignaturesFlow.call(CollectSignaturesFlow.kt:64) ~[corda-core-3.2.1847-corda.jar:?]
        在 net.corda.core.flows.FlowLogic.subFlow(FlowLogic.kt:290) ~[corda-core-3.2.1847-corda.jar:?]
        在 com.example.flows.flows.SettleObligation$Initiator.collectSignature(SettleObligation.kt:178) ~[obligation-1.0.jar:?]
        在 com.example.flows.flows.SettleObligation$Initiator.call(SettleObligation.kt:87) ~[obligation-1.0.jar:?]
        在 com.example.flows.flows.SettleObligation$Initiator.call(SettleObligation.kt:51) ~[obligation-1.0.jar:?]
        在 net.corda.node.services.statemachine.FlowStateMachineImpl.run(FlowStateMachineImpl.kt:96) [corda-node-3.2.1847-corda.jar:?]
        在 net.corda.node.services.statemachine.FlowStateMachineImpl.run(FlowStateMachineImpl.kt:44) [corda-node-3.2.1847-corda.jar:?]
        在 co.paralleluniverse.fibers.Fiber.run1(Fiber.java:1092) [quasar-core-0.7.9-jdk8.jar:0.7.9]
        在 co.paralleluniverse.fibers.Fiber.exec(Fiber.java:788) [quasar-core-0.7.9-jdk8.jar:0.7.9]
        在 co.paralleluniverse.fibers.RunnableFiberTask.doExec(RunnableFiberTask.java:100) [quasar-core-0.7.9-jdk8.jar:0.7.9]
        在 co.paralleluniverse.fibers.RunnableFiberTask.run(RunnableFiberTask.java:91) [quasar-core-0.7.9-jdk8.jar:0.7.9]
        在 java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511) [?:1.8.0_181]
        在 java.util.concurrent.FutureTask.run(FutureTask.java:266) [?:1.8.0_181]
        在 java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$201(ScheduledThreadPoolExecutor.java:180) [?:1.8.0_181]
        在 java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:293) [?:1.8.0_181]
        在 java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) [?:1.8.0_181]
        在 java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) [?:1.8.0_181]
        在 net.corda.node.utilities.AffinityExecutor$ServiceAffinityExecutor$1$thread$1.run(AffinityExecutor.kt:62) [corda-node-3.2.1847-corda.jar:?]
引起:net.corda.core.CordaRuntimeException: java.lang.NoSuchMethodError: com.example.base.BaseHelperKt.isGreaterThan(Ljava/math/BigDecimal;Ljava/math/BigDecimal;)Z
[INFO] 2018-11-13T00:05:12,807Z [RxIoScheduler-2] network.PersistentNetworkMapCache.addNode - 前一个节点与传入节点相同 - 什么都不做{}
[INFO] 2018-11-13T00:05:12,807Z [RxIoScheduler-2] network.PersistentNetworkMapCache.addNode - 使用信息添加节点:NodeInfo

标签: corda

解决方案


在 Kotlin 中,每个文件都被编译为一个 JVM 级别的类。名为 Foobar.kt 的文件将成为名为 FoobarKt 的类。

因此,当您将顶级函数从一个文件移动到另一个文件时,文件的名称会烘焙到编译的代码中,并且这种更改不是二进制兼容的,即使它是源兼容的。

不幸的是,这是所有软件开发中隐藏的复杂性之一——源编译器解析符号范围的方式并不总是与运行时链接器的方式相同。它发生在每种语言和运行时,尽管 JetBrains 的人有办法在很长一段时间内修复它,如果他们选择这样做的话。对不起。您必须将函数移回,或提供别名(查看@JvmName注释)。


推荐阅读