在回答之前,我将介绍一些背景知识......平台中仍然存在相关性的概念。如您所知,在 Corda 中有两个数据持久性存储;存储服务和保管库。
存储服务
存储服务是一个键 -> 值存储,用于持久化数据,例如:
存储服务非常适合存储大量可以通过哈希索引和检索的序列化数据。但是,如果希望在其中一个存储对象中搜索数据,那就很尴尬了。例如。使用事务存储时,无法轻松搜索特定类型的事务输出状态。该方法将遍历所有事务,将它们一一反序列化,并按输出类型进行过滤。这很麻烦而且效率不高。这就是为什么存在 Vault 和相关性概念的原因!
保险库
保险库的存在是为了存储状态对象,而不是交易。有一个主 states 表,其中存储状态引用、事务 id(生成输出状态)和一些其他元数据,例如状态是否被消费(或不消费)。还有一个LinearStates 的表格和一个OwnableStates 的表格。此外,如果希望将 ORM 添加到他们的状态,则为反映 ORM 定义的每种状态对象创建一个数据库表。然后可以查询这些属性以从 Vault 中提取满足特定查询的状态,例如“任何债务都表明爱丽丝作为贷方尚未消费超过 1000 英镑”。这就是保险库的力量!
相关性
现在,并非节点收到的所有交易都会产生与该节点相关的状态。一个例子是支付与支付交易,其中 Alice 向 Bob 发送美元,而 Bob 向 Alice 发送英镑。由于 Bob 现在拥有 Alice 之前拥有的美元,这些美元现在与 Alice 无关。因此,Alice 不应该记录代表这些美元的输出状态,因为她不拥有这些美元的权利和义务。 Alice 所做的是将旧的美元状态标记为已消耗,因此它现在不会计入她的总美元余额,并且不能用作另一个交易的输入(因为它已经被花费了)。
相关性在 Corda 中的工作原理
因此,当一个节点接收到一个新交易时,它会将每个输出状态的participants 属性中定义的公钥与VaultService 知道的所有公钥相交。如果特定状态的结果集不为空,则该状态与节点相关。很简单。
这意味着,如果一个节点收到一笔交易,其中他们的公钥未列在输出状态的参与者字段中,那么他们将不会将该输出状态存储在保险库中。但是,他们会将事务存储在事务存储中,并且仍然可以查询。
OwnableStates 的相关性概念很简单,要么拥有它,要么不拥有它。代表多边协议的LinearStates 的概念更为复杂。在 M14 及以下版本中,可以在 LinearState 中覆盖 isRelevant 的功能,但在 V1 中,这已被删除,以支持一种更简单的方法,即仅将参与者密钥与保险库密钥进行比较(如上所述)。
V1 方法对相关性的影响
正如 OP 所指出的,在 V1 中,将有交易观察者的概念,其中不是状态参与者的节点仍然可以将状态存储在其保险库中并将其作为“第三方”状态进行查询。 IE。它不能被消耗或计入余额总计,但可以查询。与此同时,我们将不得不解决缺少该功能的问题,选项如下:
- 对于
LinearStates,将所有预期的观察者添加到participants 列表中。然后,向状态对象添加一个名为consumers 的附加属性,它只包含可以在有效交易中使用此状态的参与者列表,即签署包含它的交易。然后,该状态的合约会将命令中的这些公钥与consumers 列表中的公钥进行比较。这样,所有观察者仍将状态存储在他们的保险库中。 FinalityFlow 会将此交易广播给所有participants。如果您不希望其他参与者知道观察者,可以使用随机生成的公钥。
- 对于
OwnableStates,和Cash一样,participants中只能有一个身份,所有者。所以方法是使用FinalityFlow 将事务发送给一组观察者,然后这些观察者必须直接从事务中获取输出状态。繁琐但暂时的,因为我们目前正在研究事务观察器:https://r3-cev.atlassian.net/browse/CORDA-663。