9. 非事务场景跨链使用文档

跨链的背景知识可以参考超级链的设计文档 超级链跨链技术 ,这里介绍一下超级链自带的跨链工具的使用方式。

9.1. 中继同步合约

合约的代码在 xuperchain/core/contractsdk/cpp/example/xuper_relayer.cc 中,主要功能是存储其他链上的有前后关系的区块在合约中,并可以查询指定交易在所存区块中是否存在、是否合法。

  • initAnchorBlockHeader:此方法用于存储第一个区块,每个合约只能调用一次,存储时不需要检查区块的合法性

  • putBlockHeader:此方法用于存储后继的区块,调用次数无限制,但存储的区块需是某个已存区块的后继块

  • verifyTx:此方法用于校验指定的交易是否存在且合法,需要提供交易所在区块和梅克尔路径信息

  • printBlockHeader:调用此方法可使用区块id获取存储块的内容

9.2. 合约使用方法

合约部署调用在 创建合约 中有提到,中继同步合约在部署上和其他合约无异,但调用过程中可能有些不同的地方。

中继同步合约在调用过程中往往需要传入区块内容的参数,这个参数以字符串形式传入,解析时则以序列化Protobuf来处理

1
2
3
4
std::unique_ptr<relayer::InternalBlock> anchorBlockHeader(
    new relayer::InternalBlock);
std::string anchorBlockHeaderStr = ctx->arg("blockHeader");
bool succ = anchorBlockHeader->ParseFromString(anchorBlockHeaderStr);

这里如果在命令行中操作就会遇到一些麻烦,在命令行中调用,blockHeader字段需要使用base64编码放在json中;更多的是序列化的InternalBlock数据从哪里来。

proto文件位于 xuperchain/core/contractsdk/cpp/example/xuper_relayer/src/relayer.proto,其中的InternalBlock和 xuperchain/core/pb/xchain.proto 超级链的InternalBlock定义是一致的,我们可以使用超级链提供的RPC接口

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
rpc GetBlock(BlockID) returns (Block);
message BlockID {
    Header header = 4;
    string bcname = 1;
    bytes blockid = 2;
    // if need content
    bool need_content = 3; //是否需要内容
}
message Block {
    Header header = 1;
    string bcname = 2;
    bytes blockid = 3;
    enum EBlockStatus {
        ERROR = 0;
        TRUNK = 1;
        BRANCH = 2;
        NOEXIST = 3;
    }
    EBlockStatus status = 4;
    InternalBlock block = 5;
}

来获取InternalBlock内容,注意输入中的 need_content 需要置为true。

对于查询交易的方法,除了所在区块id外,还需要传入一个“梅克尔路径”。对于梅克尔树的定义,这里不再赘述,可参考 Merkle_tree ,在梅克尔树中,待验证交易的txid是存在于某个叶子结点中的,我们需要给出此叶子结点合并计算hash至根节点的路径,以下图为例

../_images/merkle_tree.png

假如我们需要验证node8的合法性,我们需要给出从node8计算出root的所有节点,即node7、node8与node4,他们的相对顺序需要按照二叉树的中序遍历位置给出,即我们需要如下构造输入参数

1
2
3
4
{
    "proofPath": "[node7 hash],[node8 hash],[node4 hash]",
    "txIndex": 1
}

其中的hash字段使用逗号分隔,待验证的id在其中的位置需要给出。

9.3. 中继同步进程

中继同步进程的代码位于 xuperchain/core/cmd/relayer 中,是“自动”调用中继同步合约的一个工具,运行配置文件如下:此方法用于

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
anchorBlockHeight: 20
chains:
srcChain:
    rpcAddr: "remotehost:37101"
    bcname: "xuper"
dstChain:
    rpcAddr: "localhost:37101"
    bcname: "xuper"
    keys: "./data/keys"
    contractConfig:
        moduleName: "wasm"
        contractName: "relayer"
        updateMethod: "putBlockHeader"
        anchorMethod: "initAnchorBlockHeader"

其中的srcChain是需要存储的区块信息的来源链,dstChain是部署中继合约的目标链,使用中继同步进程需要事先部署完成中继合约,并将合约的名称填入contractName字段。anchorBlockHeight表示是从来源链中的高度20的区块开始同步,需要视具体情况修改。

运行除了配置文件不需要额外参数,不过需要注意的是,同步区块的过程是自动的,如果您试图从较小的高度同步一个已经很高的链,请做好接收大量数据的准备。