非事务场景跨链¶
什么是非事务性场景跨链¶
非事务场景跨链是指跨链行为并不是要求不同链上的交易具备事务性,即不要求不同链上的跨链交易同时生效或同时失败,跨链交易只对当时被跨链的交易状态进行确认,并根据目标交易状态执行交易后续操作。
举例来讲,在A链上发起的交易tx1执行成功后,发起B链上的交易tx2,但tx2执行失败并不会影响tx1,即不会发生tx1回滚。这种存在依赖的交易,但不保证多个交易执行满足事务性的场景,是典型的非事务跨链。
非事务跨链的典型场景比如身份验证、预言机、资产跨链转移等等,在技术上主要强调跨链交易的存在性证明,但对跨链交易的原子性没有要求。
整体方案¶
非事务跨链典型技术是通过中继实现对目标链数据的数据同步和交易存在性验证,类似BTCRelay。在超级链中,我们也实现了一套中继机制,通过对目标链的区块头同步,以及梅克尔验证技术,可以做到在原链上直接验证目标链的交易是否存在。
- 如下图是中继机制的整体结构,主要分为以下两个部分:
链上中继合约(XuperRelayer):部署在原链上的一个智能合约,会保存目标链的所有块头信息,并提供基于梅克尔证明的目标链交易存在性验证。
中继同步进程(Relay Process):在目标链和原链之间,会有一个或多个中继进程,持续监听目标链的最新出块信息,并抽取出块头信息写入
以一个典型的资产转移的场景为例,首先在B链上发起tx1交易,然后原链上发起tx2交易。tx2交易成功的前提条件是确认tx1交易已经生效。因此整个跨链交易生效流程:
用户首先在目标链提交tx1交易;
当tx1交易打包在块中后,中继同步进程会将块头同步到原链上,并保存在链上中继合约中;
用户在原链上发起资产转移交易tx2,同时在合约参数中填写tx1的信息以及tx1的梅克尔路径;
原链中的用户合约通过跨合约调用调用链上中继合约,进行梅克尔验证,如果证明tx1确实存在在目标链中,则返回验证成功,否则返回验证失败;
用户合约在拿到tx1验证成功的结果后,执行后续资产转移操作,并返回结果。
梅克尔证明¶
在超级链中,区块头保存了块中所有交易的txid构造出的梅克尔树的树根。下图是一颗区块中的梅克尔树举例,区块中的8个交易是梅克尔树的叶子节点,按照交易顺序,每两个相邻的交易的txid通过SHA256计算出梅克尔树的父节点id,依次向上直到计算出了梅克尔树根。在这个树形结构中,任何一个节点的id都直接和自己的父子节点相关,因此树中任何一个节点数据的修改,都会导致整个梅克尔树的树根变化。
交易的验证方只需要知道待验证交易tx1的txid,tx1所在块的block1,并知道从tx1所在梅克尔树的叶子节点开始到梅克尔树根的路径上所有兄弟节点的hash值,就可以计算出梅克尔树根。例如我们要验证梅克尔树中绿色节点9Dog的存在性,那么我们同时给出从9Dog到梅克尔树根的路径上的所有兄弟节点数组[1FXq, ec20, 8f74],则从下而上:
Hash(1FXq+9Dog) ⇒ 781a
Hash(ec20+781a) ⇒ 5c71
Hash(5c71+8f74) ⇒ 6c0a
在得到计算出的根Hash后,我们从链上中继合约中获取之前已经保存的block1对应的区块头中的梅克尔树根,如果也是6c0a则证明验证通过,否则验证不通过。
链上中继合约¶
链上中继合约是跨链存在性证明的核心,提供对目标链中的区块头同步存储,并通过梅克尔验证技术提供交易查询接口。链上中继合约主要解决三个问题,交易的真实性、及时性证明、区块头分叉管理。
真实性证明:即证明交易确实存在,主要通过Merkle Proof证明交易是否真的存在于链中以及是否在主干上。
及时性证明:即证明交易是否确认,跟目标链采用的共识算法相关。对于同步Byzantine类共识算法,及时性是内置的,只要交易在区块头中,那么交易必定在原链处于上链状态。对于PoW类共识算法,一般要求交易所在块距主干最新高度相差6个块以上。
区块头分叉管理:对同步的区块头按照树形结构维护依赖关系,并根据目标链的主干选择算法即使调整目标链的主干区块状态。
目前的跨链实现支持了对超级链同构链的链上中继合约,代码位于 https://github.com/xuperchain/xuperchain/tree/master/core/contractsdk/cpp/example/xuper_relayer 目录中。主要实现了对XPoS共识的区块头分叉管理和存在性证明,目前该功能仍处于实验状态,后续版本中会持续增加新的共识和异构链的支持。
合约主要接口如下:
接口名 |
参数 |
说明 |
|---|---|---|
initialize |
无 |
合约初始化函数 |
initAnchorBlockHe ader |
blockHeader: 区块头数据 |
初始化锚点区块头,锚点区块头一般是初始化后写入的第一个区块头,目 标链不一定需要从创世块开始同步,因此有了锚点区块的概念。 |
putBlockHeader |
blockHeader: 区块头数据 |
写入一个新区块头信息,会自动验证区块头数据是否正确并进行分叉管理 |
verifyTx |
blockid: 待验证交易的区块id txid:待验证的交易id proofPath:待验证交易的梅克尔路 径上的兄弟节点hash txIndex:待验证交易在区块所有交 易中的序号 |
交易验证接口,通过梅克尔证明验证他链上的交易id是否真实有效 |
printBlockHeader |
blockid: 区块id |
打印指定区块id的区块头信息 |
中继同步进程¶
中继同步进程相对简单,主要通过对目标链的出块监听,将最新区块中的区块头信息抽取出来,并同步到原链中。 中继同步进程的代码位于https://github.com/xuperchain/xuperchain/tree/master/core/cmd/relayer。