【问题标题】:Is there a limit to the number of inputs/outputs states during transaction building?交易构建期间输入/输出状态的数量是否有限制?
【发布时间】:2019-01-17 18:15:15
【问题描述】:

在 Corda Open Source 3.2 和 postgres 9.6 上。我在交易中有 300 个义务状态,它们必须自动转换为 SETTLED AND 现金状态作为输入来取消这些义务。

recordTransactions 期间出现分页错误。可以将多少个状态放入事务中是否有限制?

下面的堆栈跟踪

[ERROR] 2018-08-10T06:40:38,702Z [Node thread-1] flow.[a80ddfb6-628e-4194-98ef-77261512b6fb].call - mutedTry 期间出错 {} net.corda.core.node.services.VaultQueryException:请指定“PageSpecification”,因为结果 [201] 比默认页面大小 [200] 多 在 net.corda.node.services.vault.NodeVaultService._queryBy(NodeVaultService.kt:426) ~[corda-node-3.2.1847-corda.jar:?] 在 net.corda.node.services.vault.NodeVaultService.loadStates(NodeVaultService.kt:546) ~[corda-node-3.2.1847-corda.jar:?] 在 net.corda.node.services.vault.NodeVaultService.access$loadStates(NodeVaultService.kt:49) ~[corda-node-3.2.1847-corda.jar:?] 在 net.corda.node.services.vault.NodeVaultService$makeUpdates$1.invoke(NodeVaultService.kt:143) ~[corda-node-3.2.1847-corda.jar:?] 在 net.corda.node.services.vault.NodeVaultService.makeUpdates(NodeVaultService.kt:188) ~[corda-node-3.2.1847-corda.jar:?] 在 net.corda.node.services.vault.NodeVaultService.access$makeUpdates(NodeVaultService.kt:49) ~[corda-node-3.2.1847-corda.jar:?] 在 net.corda.node.services.vault.NodeVaultService$notifyAll$1.invoke(NodeVaultService.kt:119) ~[corda-node-3.2.1847-corda.jar:?] 在 net.corda.node.services.vault.NodeVaultService.notifyAll(NodeVaultService.kt:130) ~[corda-node-3.2.1847-corda.jar:?] 在 net.corda.node.services.api.ServiceHubInternal$DefaultImpls.recordTransactions(ServiceHubInternal.kt:118) ~[corda-node-3.2.1847-corda.jar:?] 在 net.corda.node.internal.AbstractNode$ServiceHubInternalImpl$recordTransactions$1.invoke(AbstractNode.kt:857) ~[corda-node-3.2.1847-corda.jar:?] 在 net.corda.node.internal.AbstractNode$ServiceHubInternalImpl$recordTransactions$1.invoke(AbstractNode.kt:818) ~[corda-node-3.2.1847-corda.jar:?] 在 net.corda.nodeapi.internal.persistence.CordaPersistence.transaction(CordaPersistence.kt:136) ~[corda-node-api-3.2.1847-corda.jar:?] 在 net.corda.nodeapi.internal.persistence.CordaPersistence.transaction(CordaPersistence.kt:124) ~[corda-node-api-3.2.1847-corda.jar:?] 在 net.corda.nodeapi.internal.persistence.CordaPersistence.transaction(CordaPersistence.kt:131) ~[corda-node-api-3.2.1847-corda.jar:?] 在 net.corda.node.internal.AbstractNode$ServiceHubInternalImpl.recordTransactions(AbstractNode.kt:856) ~[corda-node-3.2.1847-corda.jar:?] 在 net.corda.core.node.ServiceHub$DefaultImpls.recordTransactions(ServiceHub.kt:201) ~[corda-core-3.2.1847-corda.jar:?] 在 net.corda.node.services.api.ServiceHubInternal$DefaultImpls.recordTransactions(ServiceHubInternal.kt) ~[corda-node-3.2.1847-corda.jar:?] 在 net.corda.node.internal.AbstractNode$ServiceHubInternalImpl.recordTransactions(AbstractNode.kt:818) ~[corda-node-3.2.1847-corda.jar:?] 在 net.corda.core.node.ServiceHub$DefaultImpls.recordTransactions(ServiceHub.kt:193) ~[corda-core-3.2.1847-corda.jar:?] 在 net.corda.node.services.api.ServiceHubInternal$DefaultImpls.recordTransactions(ServiceHubInternal.kt) ~[corda-node-3.2.1847-corda.jar:?] 在 net.corda.node.internal.AbstractNode$ServiceHubInternalImpl.recordTransactions(AbstractNode.kt:818) ~[corda-node-3.2.1847-corda.jar:?] 在 net.corda.core.flows.FinalityFlow.notariseAndRecord(FinalityFlow.kt:78) ~[corda-core-3.2.1847-corda.jar:?] 在 net.corda.core.flows.FinalityFlow.call(FinalityFlow.kt:56) ~[corda-core-3.2.1847-corda.jar:?] 在 net.corda.core.flows.FinalityFlow.call(FinalityFlow.kt:28) ~[corda-core-3.2.1847-corda.jar:?] 在 net.corda.core.flows.FlowLogic.subFlow(FlowLogic.kt:290) ~[corda-core-3.2.1847-corda.jar:?] 在 example.template.flows.SettleOblgiations$Initiator.call(SettleOblgiations.kt:105) ~[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_171] 在 java.util.concurrent.FutureTask.run(FutureTask.java:266) [?:1.8.0_171] 在 java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$201(ScheduledThreadPoolExecutor.java:180) [?:1.8.0_171] 在 java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:293) [?:1.8.0_171] 在 java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) [?:1.8.0_171] 在 java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) [?:1.8.0_171] 在 net.corda.node.utilities.AffinityExecutor$ServiceAffinityExecutor$1$thread$1.run(AffinityExecutor.kt:62) [corda-node-3.2.1847-corda.jar:?]

【问题讨论】:

    标签: corda


    【解决方案1】:

    感谢您提出此问题。 从 5 月开始,它确实已在 master 上修复,并将包含在下一个 OS 3.3 版本中。 见https://github.com/corda/corda/pull/3788

    【讨论】:

      【解决方案2】:

      一般来说,如果您执行一个返回超过 200 个结果的保险库查询,您需要提供一个PageSpecification 来定义返回结果的方式。这是为了防止返回太多结果时出现内存溢出错误。下面是一个使用PageSpecification 的保管库查询示例:

      val vaultSnapshot = serviceHub.vaultService.queryBy<ContractState>(
          criteria = VaultQueryCriteria(UNCONSUMED),
          paging = PageSpecification(DEFAULT_PAGE_NUM, 200))
      

      FinalityFlow 调用NodeVaultService.loadStates,这是您的错误被抛出的地方。从 Corda 3.2 开始,NodeVaultService.loadStates 没有做任何事情来阻止它一次请求超过 200 个结果,从而导致抛出分页错误。这已在master 中修复,该修复将包含在 Corda 3.3/Corda 4 中,如下所示:

      private fun loadStates(refs: Collection<StateRef>): Collection<StateAndRef<ContractState>> {
          val states = mutableListOf<StateAndRef<ContractState>>()
          if (refs.isNotEmpty()) {
              val refsList = refs.toList()
              val pageSize = PageSpecification().pageSize
              (0..(refsList.size - 1) / pageSize).forEach {
                  val offset = it * pageSize
                  val limit = minOf(offset + pageSize, refsList.size)
                  val page = queryBy<ContractState>(QueryCriteria.VaultQueryCriteria(stateRefs = refsList.subList(offset, limit))).states
                  states.addAll(page)
              }
          }
          return states
      }
      

      【讨论】:

      • 嗯,如果我的查询引发了错误,我会理解的。但 Finality Flow 是个例外?
      • 啊,对不起。这似乎是一个错误。更新了我上面的答案。
      • 此错误来自 OpenSource 3.2。你知道企业是否也有同样的行为吗?
      • Enterprise 上的行为相同。但这很奇怪——因为代码确实试图一次只获取一定数量的结果(小于页面大小)。有些事情没有按预期工作。
      • 在这里复制,测试在我的机器上运行得很慢(在collectSignature期间),响应者需要一段时间才能签名,可能是由于tx大,但最后会抛出同样的错误。 github.com/adrian-soon/obligation-cordapp/blob/…
      猜你喜欢
      • 2014-02-18
      • 2015-06-30
      • 1970-01-01
      • 1970-01-01
      • 2019-02-11
      • 1970-01-01
      • 2016-08-27
      • 1970-01-01
      • 2019-03-12
      相关资源
      最近更新 更多