Skip to content

异构链数据验证服务开发手册

zouxyan edited this page Jan 10, 2025 · 1 revision

1 介绍

异构链数据验证服务(Hetero-Chain Data Verifier Service, HCDVS)提供了异构链数据在跨链过程中的验证能力,比如验证共识状态(区块头的抽象)、跨链消息的正确性、合法性,PTC会使用HCDVS完成背书功能,PTC通过调用HCDVS来确认Relayer发送过来的共识状态、跨链消息等数据的正确性,从而判断是否可以对其背书。

目前HCDVS是以Java插件的形式实现并提供服务。HCDVS需要和BBC插件配套使用,因为HCDVS的很多输入参数,是从同类型(product)BBC返回的,在插件之外以bytes传播。

要实现HCDVS插件,方法和BBC插件类似,只需要_实现特定的接口,并在实现类打上特定的注解即可_。

下面是一个简单的HCDVS实现。可以看到,目前仅需要实现下面四个接口即可,后面会详细解释每个接口的含义,下面需要先准备好开发环境。

package com.alipay.antchain.bridge.plugins.demo.testchain;

import com.alipay.antchain.bridge.commons.core.base.ConsensusState;
import com.alipay.antchain.bridge.commons.core.base.CrossChainMessage;
import com.alipay.antchain.bridge.commons.core.bta.IBlockchainTrustAnchor;
import com.alipay.antchain.bridge.plugins.lib.HeteroChainDataVerifierService;
import com.alipay.antchain.bridge.plugins.spi.ptc.AbstractHCDVSService;
import com.alipay.antchain.bridge.plugins.spi.ptc.core.VerifyResult;

/**
 * This {@code TestChainHCDVSService} is a demo implementation of {@link HeteroChainDataVerifierService}.
 * <p>
 * It's a <b>{@code Blockchain Bridge Component}</b> plugin for the heterogeneous blockchain <b>testchain</b>
 * in this demo.
 * </p>
 */
@HeteroChainDataVerifierService(products = "testchain", pluginId = "testchain_hcdvsservice")
public class TestChainHCDVSService extends AbstractHCDVSService {

    private TestChainSDK sdk;

    private AbstractHCDVSService hcdvsContext;

    @Override
    public VerifyResult verifyAnchorConsensusState(IBlockchainTrustAnchor bta, ConsensusState anchorState) {
        return VerifyResult.builder()
                .success(true).build();
    }

    @Override
    public VerifyResult verifyConsensusState(ConsensusState stateToVerify, ConsensusState anchorState) {
        return VerifyResult.builder()
                .success(true).build();
    }

    @Override
    public VerifyResult verifyCrossChainMessage(CrossChainMessage message, ConsensusState anchorState) {
        return VerifyResult.builder()
                .success(true).build();
    }

    @Override
    public byte[] parseMessageFromLedgerData(byte[] ledgerData) {
        return new byte[0];
    }
}

环境准备 💻

要开发HCDVS插件,需要下面两个依赖。

<dependency>
  <groupId>com.alipay.antchain.bridge</groupId>
  <artifactId>antchain-bridge-plugin-lib</artifactId>
  <version>1.0.0-SNAPSHOT</version>
</dependency>
<dependency>
  <groupId>com.alipay.antchain.bridge</groupId>
  <artifactId>antchain-bridge-spi</artifactId>
  <version>1.0.0-SNAPSHOT</version>
  <scope>provided</scope>
</dependency>

找到ACB SDK的代码,注意版本,然后在项目目录下执行:

mvn clean install -Dmaven.test.skip=true

Tip

如果编译bcdns相关模块有问题,可以在项目的pom.xml的modules标签下找到bcdns-services/embedded-bcdns/embedded-bcdns-coreantchain-bridge-bcdns-factory先注释掉。

开发教程 🧑‍💻

注解和接口

首先你需要新建一个类文件,比如上面的TestChainHCDVSService

在你的实现类加上注解@HeteroChainDataVerifierService,类似@BBCService,通过products设置当前HCDVS支持的链类型,通过pluginId设置插件ID:

/**
 * The annotation to mark PTC plugin implementation.
 */
@Retention(RUNTIME)
@Target(TYPE)
@Inherited
@Documented
public @interface HeteroChainDataVerifierService {

    /**
     * the blockchain product name like {@code Ethereum} etc.
     *
     * @return {@link String[]}
     */
    String[] products() default {};

    /**
     * the unique identity of the plugin
     *
     * @return {@link String[]}
     */
    String[] pluginId() default {};
}

然后你需要继承AbstractHCDVSService,它实现了接口IHeteroChainDataVerifierService,并提供了getHCDVSLogger方法,可以通过这个获取一个运行环境的logger对象,打印日志:

public abstract class AbstractHCDVSService implements IHeteroChainDataVerifierService {

    private Logger hcdvsLogger = NOPLogger.NOP_LOGGER;

    private void setLogger(Logger hcdvsLogger) {
        this.hcdvsLogger = hcdvsLogger;
    }

    public final Logger getHCDVSLogger() {
        return hcdvsLogger;
    }
}

接口IHeteroChainDataVerifierService如下:

包含接口:

  • VerifyResult verifyAnchorConsensusState(IBlockchainTrustAnchor bta, ConsensusState anchorState);

验证最初的锚定共识状态的正确性,比如检查下BTA中共识节点信息是否可以验证anchorState的共识证明等。

  • VerifyResult verifyConsensusState(ConsensusState stateToVerify, ConsensusState parentState);

使用parentState去验证stateToVerify,通常是用高度N的区块头中的共识公钥集合,去验证N+1高度的区块头的正确性。

  • VerifyResult verifyCrossChainMessage(CrossChainMessage message, ConsensusState currState);

使用当前消息对应高度的共识状态来验证跨链消息的正确性,比如,使用跨链事件所在高度的区块头来验证跨链消息MerkleProof的正确性。

  • byte[] parseMessageFromLedgerData(byte[] ledgerData);

CrossChainMessage.ProvableLedgerData#ledgerData中解析出AM消息原文,这个字段通常存放包含AM消息原文的账本数据,比如以太坊包含SendAuthMessage事件的收据,可以从中解析出AM原文。

下面详细介绍如何实现每个接口。

verifyAnchorConsensusState

先验知识

验证最初的锚定共识状态的正确性,PTC会调用这个接口来验证第一个共识状态的正确性,并作为后续的锚定共识状态。

  • 入参中,IBlockchainTrustAnchor bta是用来验证区块的工具,包含了一些能代表区块链的数据,比如最初的共识公钥集合,能用来验证anchorState的正确性。
  • anchorState是最开始锚定的共识状态,也就是一个区块头。

首先需要了解一下ConsensusState这个类

  • csVersion:代表这个结构的版本号,目前仅有v1
  • domain:为这个共识状态来自哪个域名
  • height:这个共识状态的区块高度是多少
  • hash:这个共识状态的区块hash是多少
  • parentHash:这个共识状态的父区块hash是多少
  • stateTimestamp:这个共识状态的区块时间戳是多少(如果有的话)
  • stateData:共识状态的主要内容,这个由和HCDVS配套的BBC插件的readConsensusState确定,往往是包含整个区块头
  • consensusNodeInfo:共识节点的信息内容,往往是共识节点的公钥集合,或者其他内容,用于验证共识对于这个高度的证明
  • endorsements:共识对于这个高度的背书证明内容,往往是共识节点的签名集合

然后认识一下接口IBlockchainTrustAnchor,这里比较关键的是getSubjectIdentity方法,BTA里面存储了序列化的链关键信息,并且这个信息是被域名持有者放在subjectIdentity字段并签名过的,因此通过从BTA获取subjectIdentity,并于区块头中的consensusNodeInfo进行对比,可以知道这部分共识相关内容是否正确。

最后认识一下返回类型VerifyResult,它只包含两个字段,用来返回验证的结果:

  • success:是否验证通过
  • errorMsg:验证不通过的原因

实现逻辑参考

  1. 从BTA获取subjectIdentity,这里按照插件本身逻辑,从bytes反序列化比如某个类(这需要插件开发者自己定制),可以从中获取到共识节点集合;
  2. 从anchorState获取共识节点集合,和从BTA中获取的进行对比,不相同则返回VerifyResult为false;
  3. 使用共识节点集合,验证anchorState中的endorsements的正确性;
  4. 从anchorState的stateData中解析出链的区块头,检查hash和高度等字段和共识状态中相同;
  5. 所有验证都正确则返回VerifyResult为true;

verifyConsensusState

先验知识

使用parentState去验证stateToVerify,通常是用高度N的区块头中的共识公钥集合,去验证N+1高度的区块头的正确性。

实现逻辑参考

  1. parentState是经过PTC验证的可靠的父状态,从parentState获取共识节点集合
  2. 从stateToVerify中获取endorsements,并用上面的共识节点集合验证
  3. 从stateToVerify的stateData中解析出链的区块头,检查hash和高度等字段和共识状态中相同;

verifyCrossChainMessage

先验知识

使用当前消息对应高度的共识状态来验证跨链消息的正确性,比如,使用跨链事件所在高度的区块头来验证跨链消息MerkleProof的正确性。

首先看下入参类型CrossChainMessage,它来自BBC插件的readCrossChainMessagesByHeight接口,可以参考.

CrossChainMessage包含三个字段:

  • message:序列化好的消息内容,比如AM消息
  • type:跨链消息类型,比如AM(目前只有AM类型)
  • provableData:跨链消息相关的可证明数据

ProvableLedgerData包含下面字段:

  • height:该消息所在的区块高度
  • txHash:发出该消息的交易hash
  • blockHash:该消息所在的区块hash
  • timestamp:该消息产生的时间戳
  • ledgerData:异构链插件放入的包含跨链消息的账本数据,用于执行账本数据存在性验证
  • proof:异构链插件放入的账本数据存在性证明,比如Merkle Proof

实现逻辑参考

  1. currState是PTC已经验证过的共识状态,使用该共识状态作为验证锚点
  2. 从跨链消息的provableData中拿到ledgerData,比如包含以太坊SendAuthMessage事件的Receipt
  3. 从跨链消息的provableData中拿到proof,假设是Merkle Proof,这里解析并验证上面ledgerData符合证明,
  4. 获得receipt root后,从currState中解析出区块头,对比区块头中receipt root和merkle proof计算出来的相同,则证明验证通过

parseMessageFromLedgerData

先验知识

CrossChainMessage.ProvableLedgerData#ledgerData中解析出AM消息原文,这个字段通常存放包含AM消息原文的账本数据,比如以太坊包含SendAuthMessage事件的收据,可以从中解析出AM原文。

实现逻辑参考

  1. 从bytes中解析出比如包含以太坊SendAuthMessage事件的Receipt
  2. 从Receipt中获取SendAuthMessage的data字段,并返回