Corda State Participants列表意义及Cordapp节点状态可见性异常咨询
嘿,这个问题我之前开发Cordapp的时候也踩过类似的坑,咱们来捋清楚到底是怎么回事:
核心原因分析
你遇到的情况,大概率是Corda Vault的默认查询规则加上线性状态的生命周期特性共同导致的:
线性状态的消耗机制:如果你的State实现了
LinearState接口(这是Corda里做可流转资产的标准模式),那么流程2的转移操作会创建一个新的状态版本,同时把流程1生成的旧状态(参与者是A+B)标记为已消耗(Consumed)。Vault默认只显示未消耗状态:Corda节点的Vault默认查询只会返回**未消耗(Unconsumed)**的状态。所以A节点虽然确实持有旧状态的副本,但因为它已经被标记为消耗状态,默认查询就找不到了——这就是你看不到它的原因。
还有一种小概率情况:如果流程2的实现里,调用FinalityFlow时没有把旧状态的参与者A包含进去,导致A节点没收到旧状态被消耗的通知。不过这种情况比较少见,因为Corda的框架通常会自动处理所有相关参与者的事件同步。
验证与解决办法
先验证问题
你可以在A节点的Shell或者测试代码里执行一个包含所有状态的查询,看看旧状态是不是还在,只是被标记成消耗了:
// 在A节点执行这段查询 val queryCriteria = QueryCriteria.VaultQueryCriteria(status = Vault.StateStatus.ALL) val allStates = serviceHub.vaultService.queryBy<你的State类>(queryCriteria).states println(allStates)
如果能看到流程1生成的旧状态,那就坐实了是默认查询规则的问题。
针对性解决
根据你的业务需求,有两种可选方案:
- 方案1:调整查询逻辑:如果业务上需要A节点能查看历史状态,那以后查询Vault时,就指定要包含所有状态(已消耗+未消耗),或者单独查询已消耗状态。比如上面代码里用的
Vault.StateStatus.ALL,或者用Vault.StateStatus.CONSUMED只查已消耗的。 - 方案2:修改状态/流程设计:如果希望A节点一直持有未消耗的状态副本,那可能要重新设计状态模型——比如把流程1的状态改成不可消耗的类型,或者在流程2里把A也加入新状态的参与者列表(不过这可能不符合你B到C转移的业务逻辑,得看你的需求)。
另外也可以检查一下流程2里的FinalityFlow调用,确保没有遗漏旧状态的参与者A。比如正确的调用应该覆盖新旧状态的所有参与者:
// 流程2中FinalityFlow的示例调用 val allRelevantParticipants = oldState.participants + newState.participants subFlow(FinalityFlow(transactionBuilder, allRelevantParticipants))
不过一般来说Corda会自动处理这个,手动确认一下更放心。
内容的提问来源于stack exchange,提问作者Shailesh Pratapwar
相关产品推荐
相关产品推荐

