corda - 指向新合约版本的国家仍然试图反序列化旧合约?
问题描述
我有一个场景,我已将我的义务从 V1 升级到 V2,并成功地指出了正确的 V2 合同。接下来,我尝试SettleObligation
对这些升级的 V2 状态进行分析。当交易形成并发送出去时CollectSignatureFlow
,java.lang.NoSuchMethodError
在我的isGreaterThan
方法中找到了一个verifySettle
在合同中的命令中调用的方法。
这个特定的函数最初存在于包“com.example.base”中的一个文件BaseHelper.kt
中,一路上,在 V2 中,我们将该函数迁移到另一个文件MathHelper.kt
,这个移动并没有导致任何未解析的引用,因为包是相同的。
想了解:
- 合约是否通过文件名而不是包名来引用函数位置?一旦你编译它就不会改变
contract-v1.jar
? - 为什么 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
解决方案
在 Kotlin 中,每个文件都被编译为一个 JVM 级别的类。名为 Foobar.kt 的文件将成为名为 FoobarKt 的类。
因此,当您将顶级函数从一个文件移动到另一个文件时,文件的名称会被烘焙到编译的代码中,并且这种更改不是二进制兼容的,即使它是源兼容的。
不幸的是,这是所有软件开发中隐藏的复杂性之一——源编译器解析符号范围的方式并不总是与运行时链接器的方式相同。它发生在每种语言和运行时,尽管 JetBrains 的人有办法在很长一段时间内修复它,如果他们选择这样做的话。对不起。您必须将函数移回,或提供别名(查看@JvmName
注释)。
推荐阅读
- python - 如何使 django 模型“可评论”、“可爱”和“可评价”
- sqlite - SQLite Custom ORDER BY over Strings导致解析器堆栈溢出
- javascript - 如何使用 jquery 放置 json 值?
- java - 保存具有 Gson 上下文的对象
- r - R keras LSTM 输入形状
- ajax - 如何在 console.log 中获取最后一个 ID 号?
- node.js - 在 Windows 2016 上配置具有 jpeg 支持的 Node Canvas 模块时出错
- logging - AWS ECS Fargate Splunk 日志记录
- html - 使用 Webpack 的平均堆栈应用程序:无法显示具有 CSS 背景图像属性的图像
- recursion - 如何在 SML 中递归地计算数字的位数