我有一个状态SomeBond
,我想在Corda网络上发布该状态并进行交易。当参与者A将SomeBond
状态转移给参与者B时,期望是A从X获得状态,或者A发出SomeBond
(假设为Y)。
为验证这一点,B运行与交易中所有状态关联的合同。预期的合同为SomeBondContract
,但B不能保证它会被运行。为确保此事务中的状态将运行SomeBondContract
,他将必须在签名前实际检查流程。
val outputsLegit = stx.tx.outputs.all { it.contract == "com.example.SomeBondContract" }
val inputsLegit = stx.tx.toLedgerTransaction(serviceHub).inputs.all { it.state.contract == "com.example.SomeBondContract" }
但是,如果他只是在流程中放入支票,那么它只会验证当前交易。我们仍然不能确定C将状态发送给A的先前事务是否具有分配给其输入状态的相同合同。也许是这样的:
C创建交易(101):
输入(空)
输出:
SomeBondState
,合同ID:com.example.EmptyContract
然后创建事务(102):
输入:101 [0]
输出:
SomeBondState
,合同ID:com.example.SomeBondContract
并将此交易的输出(即102 [0])用作对B的转移的输入。
这里的问题是C从来不是SomeBondState
的合法发行者,而且交易从未发生过,但是由于他向国家分配了错误的合同,因此他创建了没有问题的合同。
防止这种情况的一种方法是也将相同的支票放入合同中。这样,流程可以检查当前事务是否已将合同分配给其状态,并且合同本身可以检查输入状态是否已分配合同。那样,事务102将永远不会成功,因为它具有类型为SomeBondState
的输入但没有com.example.SomeBondState
作为合同。由于依存关系图经过递归验证直到出现问题,因此即使是故障节点也将无法传递假状态为真实状态。
当然,一种更简单的方法是确保广口瓶中没有EmptyContract
,但是可能会巧妙地滥用任何现有合同来跳过不需要的状态。我仅以EmptyContract
为例。
但是,在流程和合同中检查包名称似乎有些不安全和不可靠。我不完全了解类加载器的工作方式,如何处理具有相同程序包名称的两个相同的类名称,以及是否有恶意节点可以做事的方式。
此外,我真的不明白为什么我们在建立交易时被要求将合同与国家绑定?为什么合同不能绑定到状态定义本身内部的状态?也许可以用相关合同对州进行注释?是否可以在不同时间以相同状态使用不同的合同?但是,这不是什么命令吗?这样同一份合同在不同时间的行为可能会有所不同?
或者我整个担心“我如何确保在交易中执行正确的合同”缺少什么?预先感谢您的回答。
答案 0 :(得分:0)
为防止这种情况,Corda 4将引入一个@BelongsToContract
注释。此注释将状态与给定的合同相关联,并防止与此状态一起使用任何其他合同。
用法示例:
@BelongsToContract(TemplateContract::class)
class TemplateState(override val participants: List<AbstractParty>) : ContractState