Skip to content

区块链桥接组件开发手册 V1

0xstride edited this page Apr 28, 2026 · 2 revisions

1. BBC 在跨链系统中的职责 🔌

1.1 开发目标

BBC(Blockchain Bridge Component,区块链桥接组件)是 AntChain Bridge 接入异构链的适配层。它把 Relayer 的统一操作翻译成具体区块链能够执行的读写动作:读区块、读跨链消息、读共识状态、部署系统合约、投递 AM 消息,以及维护 PTC 相关链上数据。

这份手册围绕一条真实开发中最常见的异构链路展开:

eth.from.domain -> Relayer1 -> Relayer2 -> fisco.to.domain

其中 eth.from.domain 是 Ethereum2 源链域名,fisco.to.domain 是 FISCO BCOS 目标链域名。读完后,你应该能判断一个 BBC 插件需要实现哪些接口、每类接口在跨链流程中什么时候被调用、Ethereum2 和 FISCO BCOS 的实现差异在哪里,以及这些接口如何和 HCDVS、PTC、TpBTA 配合。

1.1.1 你会看到什么

  • 解释 BBC、HCDVS(异构链数据验证服务)、PTC(第三方信任组件)在跨链消息中的边界。
  • 按职责分类说明 BBC 接口,而不是只按接口出现顺序平铺。
  • 重点说明 Ethereum2 与 FISCO BCOS 的实现差异。
  • 在关键接口下面加入带注释的源码块,帮助开发者把接口语义和真实实现对应起来。

1.2 示例链路:eth.from.domain 到 fisco.to.domain

在示例链路中,业务合约先在 Ethereum2 源链调用 SDP 合约发送消息。Relayer1 通过 Ethereum2 BBC 扫描源链,读到 AM 合约发出的 SendAuthMessage 事件,并把消息、账本数据、证明数据交给可信验证流程。Committee PTC 调用 Ethereum2 HCDVS 验证消息确实存在于可信的 Ethereum2 共识状态中。验证通过后,Relayer2 通过 FISCO BCOS BBC 把 AM 消息投递到 FISCO BCOS 目标链。

1.2.1 源链侧

Ethereum2 侧 BBC 需要同时访问执行层 JSON-RPC 和 Beacon API。执行层提供交易、收据、日志、合约调用;Beacon API 提供 slot、finality(最终确定性)、light client update(轻客户端更新)和 sync committee(同步委员会)相关数据。

1.2.2 目标链侧

FISCO BCOS 侧 BBC 需要使用 FISCO Java SDK 连接节点,提交交易到 AM 合约。AM 合约收到 Relayer 投递的包后再调用 SDP 合约,最终由 SDP 合约调用业务接收合约。

1.2.3 双 Relayer 不是信任根

Relayer1 -> Relayer2 只是传输路径,不是信任路径。目标链是否接受消息,依赖 PTC/TpBTA/HCDVS 所形成的可信验证结果,而不是因为 Relayer2 信任 Relayer1。

1.3 总体架构

1.3.1 Mermaid 架构图

flowchart LR
    User["业务用户或应用"] --> EthApp["Ethereum2 业务合约"]
    EthApp --> EthSDP["Ethereum2 SDP/AM 合约"]
    EthSDP --> EthBBC["Ethereum2 BBC"]
    EthBBC --> R1["Relayer1"]
    R1 --> PTC["Committee PTC"]
    PTC --> EthHCDVS["Ethereum2 HCDVS"]
    PTC --> BCDNS["Embedded BCDNS"]
    R1 --> R2["Relayer2"]
    R2 --> FiscoBBC["FISCO BCOS BBC"]
    FiscoBBC --> FiscoAM["FISCO BCOS AM/SDP 合约"]
    FiscoAM --> FiscoApp["FISCO BCOS 业务接收合约"]
    PluginServer["PluginServer"] --> EthBBC
    PluginServer --> FiscoBBC
    CommitteeNodes["四个 Committee Node"] --> PTC
Loading

1.3.2 图中角色说明

  • PluginServer 加载 BBC 插件,并接受 Relayer 的远程调用。
  • BBC 直接和异构链节点、系统合约交互。
  • HCDVS 被 PTC 调用,用来验证 BBC 读出来的数据是否可信。
  • Embedded BCDNS 保存域名证书、PTC trust root、TpBTA 等跨链信任材料。
  • Committee PTC 负责组织多节点背书,本文默认四节点 3/4 策略。

1.4 BBC、HCDVS、PTC 的边界

1.4.1 BBC 负责读链和写链

BBC 的核心任务是把异构链能力包装成统一接口。例如 Ethereum2 的 readConsensusState 返回 Beacon slot 对应的共识状态;FISCO BCOS 的 readConsensusState 返回区块高度对应的共识状态。Relayer 不需要理解每条链的 SDK 细节。

1.4.2 HCDVS 负责验证数据可信性

HCDVS 不负责发交易,也不负责部署合约。它验证 BBC 返回的 ConsensusStateCrossChainMessage 是否能被链自身共识规则证明。例如 Ethereum2 验证 sync committee 签名、receipt root、AM 日志;FISCO BCOS 验证 sealer 签名、receipt root、Merkle proof 和 SendAuthMessage 事件。

1.4.3 PTC 负责组织背书

PTC 调用 HCDVS 后,把验证结果组织成第三方可信证明。四节点 Committee PTC 下,四个节点均可参与背书,threshold > 2 表示至少 3 个节点背书通过。

2. 插件工程与配置 ⚙️

2.1 BBC 插件工程结构

2.1.1 链下插件

链下插件是 Java 插件包,核心类需要带 @BBCService 注解并实现 BBC SPI。PluginServer 加载插件后,会按 product 找到对应实现。例如:

@BBCService(products = "ethereum2", pluginId = "plugin-ethereum2")
public class EthereumBBCService extends AbstractBBCService {
    // 实现 IBBCService 中的链读写接口
}

FISCO BCOS 插件对应 product=fiscobcos。注册链时,Relayer 的 add-blockchain-anchor 命令里 product 必须和插件注解一致。

2.1.2 链上系统合约

链上系统合约通常包括:

  • AM 合约:接收和发送 Auth Message。
  • SDP 合约:维护跨链通道、顺序、授权和业务合约调用。
  • PTC Hub 合约:保存 PTC trust root、TpBTA、验证锚等可信材料。
  • Committee PTC Verifier 合约:验证 Committee PTC proof。

Ethereum2 和 FISCO BCOS 都使用 Solidity 风格系统合约,但合约部署、交易发送、ABI wrapper 生成、回执解析方式由各自 SDK 决定。

2.2 Ethereum2 配置重点

2.2.1 EL RPC 与 Beacon API

Ethereum2 BBC 必须同时配置:

  • url:执行层 JSON-RPC,用于部署合约、发交易、读 receipt/log。
  • beaconApiUrl:Beacon API,用于读 slot、finality、light client update、sync committee 数据。

只配置执行层 RPC 不够。执行层能出块,不代表 HCDVS 能验证该链的 Beacon 共识状态。

2.2.2 eth2ChainConfig 与 Deneb/finality

eth2ChainConfig 是 Ethereum2 验证链路的关键配置,包含 genesis、fork、远端 spec 等信息。本地私链每次重建后都要重新生成。推荐使用 Deneb-only 私链,并让 blockHeightPolicy 使用 FINALIZED,避免读取未 finalized 的 slot 作为可信状态。

2.2.3 源码逐行注释:EthereumConfig

下面是配置类中的关键字段摘录。这里不是完整源码,只保留最容易影响跨链验证的字段。

// 执行层 JSON-RPC 地址;部署系统合约、发交易、查回执都走这里。
private String url;

// Beacon API 地址;读 slot、finality、light client update、sync committee 都走这里。
private String beaconApiUrl;

// Relayer 在该链上的交易发送私钥;不要和业务部署账户、MetaMask 测试账户长期共用。
private String privateKey;

// 可信跨链建议使用 finalized slot,避免把未最终确定状态注册进可信链路。
private BlockHeightPolicyEnum blockHeightPolicy = BlockHeightPolicyEnum.FINALIZED;

// Ethereum2 默认可用日志过滤扫描 AM 事件;节点能力不稳定时再考虑区块扫描。
private CrossChainMessageScanPolicyEnum msgScanPolicy = CrossChainMessageScanPolicyEnum.LOG_FILTER;

// BCDNS 根证书;链上 PTC Hub 和跨链信任材料验证都需要它。
private String bcdnsRootCertPem;

// 网络类型;private-net/mainnet/holesky 等逻辑会依赖它选择链配置。
private Eth2NetworkEnum ethNetwork;

// Ethereum2 私链最关键的显式配置;本地私链重建后必须重新生成。
private Eth2ChainConfig eth2ChainConfig;

2.3 FISCO BCOS 配置重点

2.3.1 标准链证书与 groupID

FISCO BCOS 标准链配置至少需要:

  • caCert:CA 证书内容。
  • sslCert:SDK 连接证书。
  • sslKey:SDK 连接私钥。
  • connectPeer:连接节点地址,例如 127.0.0.1:20200
  • groupID:群组 ID,通常为 group01,以链实际配置为准。
  • privateKey:发送交易的账户私钥。

2.3.2 useSMCrypto=false 与标准链路线

本文默认 FISCO BCOS 标准链,useSMCrypto=false。国密链需要额外国密证书和国密 SDK 配置,不能直接复用标准链配置。

2.3.3 源码逐行注释:FISCOBCOSConfig

// 是否启用国密链;本文标准链路线必须保持 false。
private String useSMCrypto = "false";

// FISCO SDK 与节点建立 TLS 连接所需的 CA 证书。
private String caCert;

// SDK 连接证书;建议把证书内容写入 JSON,避免相对路径在 PluginServer 中失效。
private String sslCert;

// SDK 连接私钥;和 sslCert 配套使用。
private String sslKey;

// BBC 连接的 FISCO 节点地址;四节点链中连接任一可用节点即可。
private String connectPeer = "127.0.0.1:20200";

// FISCO 群组 ID;填错会导致合约地址存在但读写落到错误群组。
private String groupID;

// BBC 发送 FISCO 交易的账户私钥;建议和系统合约 owner/relayer 权限保持一致。
private String privateKey;

// 已预部署 AM 合约地址;配置后 startup 可直接写回 bbcContext,避免重复部署。
private String amContractAddressDeployed;

// 已预部署 SDP 合约地址;配置后后续 setAmContract/setLocalDomain 可继续初始化。
private String sdpContractAddressDeployed;

// 已预部署 PTC Hub 合约地址;目标链可信消息验证依赖它读取 PTC/TpBTA。
private String ptcHubContractAddressDeployed;

// FISCO 默认推荐 BLOCK_SCAN,逐区块扫描交易和回执,稳定性优先。
private CrossChainMessageScanPolicyEnum msgScanPolicy = CrossChainMessageScanPolicyEnum.BLOCK_SCAN;

3. BBC 接口按职责分类 🧭

3.1 生命周期接口

3.1.1 startup / shutdown / getContext

startup 在 PluginServer 创建 BBC 实例时调用。它应完成配置解析、SDK 初始化、预部署合约上下文恢复。shutdown 释放 SDK 或网络资源。getContext 返回当前系统合约状态,供 Relayer 判断后续步骤。

3.1.2 源码逐行注释:startup

以 Ethereum2 的启动逻辑为例:

// 解析 Relayer 注册链时传入的 BBC 配置;配置格式由插件自己定义。
config = EthereumConfig.fromJsonString(new String(context.getConfForBlockchainClient()));

// 如果没有启用 KMS,就必须提供本地私钥;否则后续部署和投递交易无法签名。
if (!config.isKmsService() && StrUtil.isEmpty(config.getPrivateKey())) {
    throw new RuntimeException("private key is empty");
}

// 初始化 Ethereum2 客户端;内部同时使用执行层 RPC 和 Beacon API。
this.acbEthClient = new AcbEthClient(config, getBBCLogger());

// 保存上下文;后续系统合约地址、状态、PTC 合约信息都从这里读写。
this.bbcContext = context;

3.2 系统合约部署与初始化接口

3.2.1 setupAuthMessageContract / setupSDPMessageContract

这两个接口在注册链后执行。setupAuthMessageContract 部署或确认 AM 合约,setupSDPMessageContract 部署或确认 SDP 合约。接口返回前应把合约地址写入 bbcContext,并设置合约状态。

3.2.1.1 实现要求

  • 如果配置中已有预部署地址,应优先复用。
  • 如果由 BBC 自动部署,部署成功后必须写回 bbcContext
  • 只部署成功通常是 CONTRACT_DEPLOYED,完成协议绑定后才是 CONTRACT_READY

3.2.2 setupPTCContract / setPtcContract

setupPTCContract 部署或确认 PTC Hub 合约。setPtcContract 把 PTC Hub 地址设置到 AM/SDP 或本链系统上下文中。目标链接收可信消息前,PTC Hub 必须能读取 PTC trust root 和 TpBTA。

3.2.3 setProtocol / setAmContract / setLocalDomain

这三个接口完成 AM 与 SDP 的互相绑定:

  • setProtocol:在 AM 中登记 SDP 协议地址。
  • setAmContract:在 SDP 中登记 AM 地址。
  • setLocalDomain:在 SDP 中登记本链域名,例如 eth.from.domainfisco.to.domain

3.2.3.1 常见边界

如果 AM 和 SDP 写在同一个合约里,也可以在接口内做兼容处理,但必须保证 bbcContext 的合约状态最终被正确更新,否则 Relayer 会认为系统合约未就绪。

3.3 源链扫描接口

3.3.1 queryLatestHeight

queryLatestHeight 返回 Relayer 应扫描到的最新高度。Ethereum2 中这个“高度”实际是 slot;FISCO BCOS 中是区块高度。

3.3.1.1 Ethereum2

Ethereum2 推荐返回 finalized slot。head slot 虽然更新更快,但可能被重组或还没有满足可信验证需要。

3.3.1.2 FISCO BCOS

FISCO BCOS 返回最新区块高度。四节点标准链出块正常时高度会稳定推进。

3.3.2 readCrossChainMessagesByHeight

该接口从指定高度读取跨链消息。返回的 CrossChainMessage 必须包含:

  • AM 原文。
  • 消息类型。
  • 所在高度、区块 hash、交易 hash。
  • 能被 HCDVS 验证的 ledgerDataproof

3.3.3 readConsensusState

该接口读取指定高度的共识状态。HCDVS 会使用该状态验证跨链消息,因此它不是普通区块头快照,而是“可验证状态”的统一封装。

3.3.3.1 Ethereum2 输出重点

  • height:slot。
  • hash:Beacon block root。
  • parentHash:父 Beacon block root。
  • stateData:Beacon header、execution payload header、light client update 等。
  • endorsements:sync aggregate 等背书信息。

3.3.3.2 FISCO BCOS 输出重点

  • height:区块高度。
  • hash:区块 hash。
  • parentHash:父区块 hash。
  • stateData:交易根、收据根、状态根等关键区块头字段。
  • consensusNodeInfo:sealer list。
  • endorsements:区块签名集合。

3.4 目标链投递接口

3.4.1 relayAuthMessage

Relayer 在目标链投递消息时调用该接口。BBC 应把 AM 原文提交到目标链 AM 合约,通常调用 recvPkgFromRelayer

3.4.2 readCrossChainMessageReceipt

该接口根据交易哈希读取投递结果。返回值应包含:

  • 是否确认。
  • 是否成功。
  • 交易哈希。
  • 失败原因。

FISCO BCOS 发送交易后通常同步拿到回执,可以直接把 confirmed 设置为 true;Ethereum2 需要结合交易回执状态判断。

3.5 PTC 链上数据接口

3.5.1 updatePTCTrustRoot

把 PTC trust root 写入链上 PTC Hub。目标链验证跨链消息时,需要通过 PTC Hub 找到可信的 PTC 根。

3.5.2 addTpBta / getTpBta / hasTpBta

TpBTA 是某条源链 BTA 被 PTC 验证后的可信锚。目标链收到源链消息时,需要能按 lane 查询对应 TpBTA。

3.5.3 queryValidatedBlockStateByDomain

该接口查询目标链 SDP 中已经验证过的源链区块状态。它用于判断目标链是否已经接受某个源域名的可信状态。

4. Ethereum2 BBC 实现重点 🔍

4.1 Ethereum2 为什么特殊

4.1.1 执行层与共识层分离

Ethereum2 的交易执行发生在执行层,但可信最终性由共识层提供。BBC 扫描跨链消息时要从执行层读 receipt/log;构造可信状态时要从 Beacon API 读 Beacon header、execution payload header、sync committee 和 light client update。

4.1.2 receipt proof 与 Beacon 状态

跨链消息存在性由 receipt proof 证明;receipt root 是否可信,则要回到 Beacon 状态中的 execution payload header。也就是说,verifyCrossChainMessage 的验证链条是:

AM log -> transaction receipt -> receipt proof -> receiptsRoot -> execution payload header -> Beacon consensus state

4.2 readConsensusState

4.2.1 数据来源

Ethereum2 BBC 通过 AcbEthClient.getEthConsensusStateData 读取指定 slot 的共识状态数据,并继续寻找后续可用 slot 的 sync aggregate。因为目标 slot 可能 missed,代码需要容忍若干个连续 missed slot。

4.2.2 输出字段

ConsensusState 中的 stateData 保存 Ethereum2 专有 JSON;endorsements 保存 sync aggregate;hashparentHash 使用 Beacon block root。

4.2.3 源码逐行注释:EthereumBBCService.readConsensusState

// 读取指定 slot 的 Ethereum2 共识状态数据,同时带入 AM 合约地址供 HCDVS 校验。
var data = acbEthClient.getEthConsensusStateData(slot, amContract);

// Ethereum2 允许 missed slot;没有 Beacon block header 时不能伪造区块。
if (data.getBeaconBlockHeader() == null) {
    // 返回一个可被上层识别的空状态,后续消息验证不能从 missed slot 通过。
    return missedSlotState(slot, data);
}

// 当前 slot 的签名证明可能出现在后续非 missed slot 的 sync aggregate 中。
for (int i = 1; i <= maxTolerateMissedSlots; i++) {
    // 向后查找可用 Beacon block,避免因为少量 missed slot 直接失败。
    var nextBlock = acbEthClient.getBeaconBlockBySlot(slot.add(BigInteger.valueOf(i)));
    if (nextBlock != null) {
        // 把 sync aggregate 和签名 slot 组织成 HCDVS 可解析的 endorsements。
        endorsements = new EthConsensusEndorsements(nextBlock.getSyncAggregate(), nextBlock.getSlot());
        break;
    }
}

// 返回统一 ConsensusState;Relayer/PTC 不解析内部 JSON,只把它传给 Ethereum2 HCDVS。
return new ConsensusState(slot, root, parentRoot, timestamp, dataJson, emptyNodeInfo, endorsementsJson);

4.3 readCrossChainMessagesByHeight

4.3.1 AM 事件与 receipt proof

Ethereum2 BBC 在指定 slot 对应的执行层区块中查找 AM 合约的 SendAuthMessage 日志。构造 CrossChainMessage 时,message 是 AM 原文,ledgerData 是 AM 日志及其上下文,proof 是 receipt proof。

4.3.2 源码逐行注释:EthereumBBCService.readCrossChainMessagesByHeight

// 源链扫描必须知道 AM 合约地址;否则无法限定日志来源。
if (bbcContext.getAuthMessageContract() == null) {
    throw new RuntimeException("empty am contract in bbc context");
}

// 接口名里叫 height,但 Ethereum2 插件按 Beacon slot 使用。
return acbEthClient.readAuthMessagesFromBlock(
    // 把 slot 转成 BigInteger 传给 Ethereum2 客户端。
    BigInteger.valueOf(slot),
    // 只读取 AM 合约发出的跨链事件,避免把普通业务事件误识别为跨链消息。
    bbcContext.getAuthMessageContract().getContractAddress()
);

4.4 EthBbcTools

4.4.1 getEth2Config

getEth2Config <beacon-url> <eth2-network> 从 Beacon API 生成 eth2ChainConfig。本地私链每次重建后都要重新运行,否则 genesis、fork、spec 和 sync committee 参数可能不一致。

4.4.1.1 示例

java -cp /path/to/ethereum2-acb-plugin-1.0.0-plugin.jar \
  com.alipay.antchain.bridge.plugins.ethereum2.tools.EthBbcTools \
  getEth2Config http://127.0.0.1:33001 private-net

4.4.2 buildEthSubjectIdentity

buildEthSubjectIdentity <beacon-url> <eth2-network> <curr_slot> 生成 BTA subject identity。它会把当前 sync committee、链配置和初始可信状态相关信息打包进 BTA。

4.4.2.1 边界说明

不要在 sync committee period 边界随意选 slot。若 slot 与签名 slot、light client update 不匹配,后续可能出现 sync committee signature is invalidnone light client update at last slot in period

5. FISCO BCOS BBC 实现重点 🧩

5.1 FISCO 作为目标链

5.1.1 relayAuthMessage 到 AM 合约

当示例方向为 eth.from.domain -> fisco.to.domain 时,FISCO BCOS BBC 的核心动作是投递 AM 消息。Relayer2 调用 FISCO BBC 的 relayAuthMessage,BBC 使用 FISCO Java SDK 发交易到 AM 合约。

5.1.2 AM -> SDP -> 业务合约

AM 合约验证包格式后调用 SDP;SDP 检查授权、顺序和接收方,再调用业务接收合约。因此目标链业务合约没有收到消息时,不能只看 relayAuthMessage 返回成功,还要继续看 SDP 授权和业务合约状态。

5.1.3 源码逐行注释:FISCOBCOSBBCService.relayAuthMessage

// 目标链投递前先拿到 AM 合约地址;它来自系统合约部署或预配置。
String amContractAddress = bbcContext.getAuthMessageContract().getContractAddress();

// 调用 FISCO Java SDK 发送交易,目标函数是 AM 合约的 recvPkgFromRelayer。
TransactionResponse response = transactionProcessorAM.sendTransactionAndGetResponse(
    amContractAddress,
    AuthMsg.ABI,
    AuthMsg.FUNC_RECVPKGFROMRELAYER,
    // rawMessage 是 PTC 验证后允许投递的 AM 原文。
    Collections.singletonList(new DynamicBytes(rawMessage))
);

// FISCO SDK 通常同步返回回执,BBC 可以立即判断交易是否成功。
TransactionReceipt receipt = response.getTransactionReceipt();

// 已拿到回执,可认为该交易在 FISCO 链上已确认。
crossChainMessageReceipt.setConfirmed(true);

// 链执行状态写入跨链回执;成功不等于业务一定符合预期,但表示 AM 调用未被拒绝。
crossChainMessageReceipt.setSuccessful(receipt.isStatusOK());

// 保存目标链交易哈希,供 Relayer 后续归档和排障。
crossChainMessageReceipt.setTxhash(receipt.getTransactionHash());

5.2 FISCO 作为源链

5.2.1 BLOCK_SCAN 默认路线

FISCO BCOS 作为源链时,推荐默认 BLOCK_SCAN。BBC 逐区块读取交易哈希,再读取带 proof 的 transaction receipt,解析 SendAuthMessage 事件。

5.2.2 receipt 与 SendAuthMessage

FISCO 的 ledgerData 通常直接保存 transaction receipt JSON;proof 保存 receiptHashtxReceiptProofreceiptsRoot。HCDVS 会用这些字段验证消息确实存在于该区块的 receipt root 下。

5.2.3 源码逐行注释:FISCOBCOSBBCService.readCrossChainMessagesByHeight

// 按区块高度读取 FISCO 区块;最后一个 true 表示需要带出后续构造证明所需的信息。
BcosBlock.Block block = client.getBlockByNumber(BigInteger.valueOf(height), false, true).getBlock();

// 按配置选择消息扫描策略。
switch (config.getMsgScanPolicy()) {
    case BLOCK_SCAN:
        // 稳定默认路线:遍历区块内交易,读取每笔交易回执,再寻找 SendAuthMessage。
        messageList = readMessagesFromEntireBlock(block);
        break;
    case LOG_FILTER:
        // 可选优化路线:使用事件过滤方式读取日志,依赖节点事件订阅能力。
        messageList = readMessagesByFilter(block);
        break;
}

// 返回当前区块内所有可证明的跨链消息。
return messageList;

5.3 FISCO readConsensusState

5.3.1 sealer list

FISCO 共识状态需要携带 sealer list。HCDVS 使用 sealer list 判断区块签名是否来自有效共识节点。

5.3.2 区块签名

FISCO 四节点标准链不能只验证一个签名。HCDVS 应按多数阈值判断有效签名数量,常见四节点情况下至少需要 3 个有效签名。

5.3.3 源码逐行注释:FISCOBCOSBBCService.readConsensusState

// 读取指定高度的 FISCO 区块;不存在时应失败或等待重试,不能伪造状态。
BcosBlock.Block block = client.getBlockByNumber(height, false, false).getBlock();

// 区块 hash 写入 ConsensusState.hash,后续 HCDVS 用它验证签名对象。
byte[] blockHash = decode(block.getHash());

// 父区块 hash 写入 ConsensusState.parentHash,后续验证父子链接关系。
byte[] parentHash = decode(block.getParentInfo().get(0).getBlockHash());

// stateData 保存 HCDVS 验证消息存在性需要的关键区块头字段。
JSONObject stateData = new JSONObject();

// 交易根用于描述区块交易集合。
stateData.put("transactionsRoot", block.getTransactionsRoot());

// 收据根是验证 transaction receipt proof 的核心字段。
stateData.put("receiptsRoot", block.getReceiptsRoot());

// 状态根用于补充描述区块执行后的状态。
stateData.put("stateRoot", block.getStateRoot());

// 把 FISCO 专有状态压进统一 ConsensusState,交给 PTC/HCDVS 后续验证。
return new ConsensusState(height, blockHash, parentHash, timestamp, stateDataBytes, nodeInfoBytes, endorsementsBytes);

6. 示例流程:Ethereum2 到 FISCO BCOS 🚀

6.1 注册链与系统合约

6.1.1 Ethereum2 源链

注册 eth.from.domain 时:

product = ethereum2
blockchainId = eth-from
confFile = /path/to/eth-from-bbc.json

BBC 配置必须包含执行层 RPC、Beacon API、eth2ChainConfig、私钥、BCDNS 根证书。

6.1.2 FISCO BCOS 目标链

注册 fisco.to.domain 时:

product = fiscobcos
blockchainId = fisco-to
confFile = /path/to/fisco-to-bbc.json

BBC 配置必须包含 SDK 证书、连接节点、groupID、私钥、BCDNS 根证书。

6.2 构造 BTA/TpBTA

6.2.1 Ethereum2 BTA

Ethereum2 的 BTA subject identity 应通过 EthBbcTools buildEthSubjectIdentity 生成,不能手工拼接。它要和当前 Beacon chain config、当前 sync committee、AM 合约地址保持一致。

6.2.2 FISCO BCOS BTA

FISCO 的 BTA subject identity 应包含 AM 合约地址和共识节点信息。四节点标准链下,HCDVS 会按 sealer list 和签名阈值验证初始共识状态。

6.2.3 TpBTA

Committee PTC 注册 BTA 成功后生成 TpBTA。再把 TpBTA 上传到 BCDNS,目标链才能按源域名查询可信锚。

6.3 启动 Anchor

两条链都需要启动 Anchor:

start-blockchain-anchor --product ethereum2 --blockchainId eth-from
start-blockchain-anchor --product fiscobcos --blockchainId fisco-to

Anchor 推进成功的标志不是命令返回,而是高度持续推进,且不会在 PTC/HCDVS 验证阶段反复失败。

6.4 发送无序消息

业务发送方在 Ethereum2 上调用发送合约,目标域名填写 fisco.to.domain,接收方地址按 32Bytes 表达。以太坊地址和 FISCO 合约地址本身都是 20Bytes,跨链参数里需要左侧补 12Bytes 的 0x00

6.4.1 Mermaid 时序图

sequenceDiagram
    participant App as "Ethereum2 业务合约"
    participant E as "Ethereum2 AM/SDP"
    participant R1 as "Relayer1"
    participant P as "Committee PTC"
    participant H as "Ethereum2 HCDVS"
    participant R2 as "Relayer2"
    participant F as "FISCO BBC"
    participant T as "FISCO AM/SDP/业务合约"
    App->>E: sendUnorderedMessage
    R1->>E: 扫描 SendAuthMessage
    R1->>P: 提交消息和共识状态
    P->>H: 验证 Ethereum2 receipt proof
    H-->>P: VerifyResult.success
    R1->>R2: 转交可信消息
    R2->>F: relayAuthMessage
    F->>T: recvPkgFromRelayer
    T-->>R2: 目标链交易回执
Loading

6.5 三层验收

6.5.1 源链交易

确认 Ethereum2 源链交易成功,并且 AM 合约确实发出 SendAuthMessage 日志。交易哈希示例只写成 0xabc123...7890,不要在文档中固化真实完整哈希。

6.5.2 Relayer 消息表

检查消息是否从 pool 进入 archive,重点字段包括 tx_successtx_hashtx_fail_reason。若消息长期停留在 pool,要区分是验证未通过、目标链交易失败,还是等待确认。

6.5.3 目标链接收合约

在 FISCO BCOS 接收合约上读取 lastUnorderedMsg 或等价状态。若目标链交易成功但业务合约没有更新,重点检查 SDP 授权、接收地址 32Bytes 表达和业务合约回调函数。

7. Q&A ❓

7.1 Ethereum2 finality 不推进怎么办?

先检查 Beacon API 的 finalized checkpoint。如果 finalized slot 长期为 0,不要继续注册 BTA/TpBTA。应先修复私链客户端组合、validator 出块和 fork 配置。

7.2 Beacon API 返回 Fulu 数据怎么办?

如果当前插件链路按 Deneb 形态验证,返回 Fulu 表示私链 fork 配置不匹配。应重建 Deneb-only 私链,并重新生成 eth2ChainConfig

7.3 eth2ChainConfig 什么时候必须重建?

只要私链重建、genesis 改变、fork 参数改变、Beacon spec 改变,就必须重新运行 getEth2Config。继续使用旧配置会导致 sync committee、fork version 或 genesis root 不一致。

7.4 Ethereum2 nonce 冲突如何避免?

BBC 配置私钥、业务合约部署账户、手动测试账户尽量分开。Relayer 后台交易和 MetaMask 手动交易共用账户时,最容易出现 pending、replacement underpriced 或部署地址不符合预期。

7.5 FISCO native library 找不到怎么办?

FISCO HCDVS 在 Committee Node 中加载时可能需要 WedPR native library。应把 native library 解出到文件系统,并通过 JVM 参数指定可加载路径,例如:

-Djava.library.ffipath=/path/to/WeDPR_dynamic_lib

7.6 FISCO SDK warning 是否一定失败?

不一定。某些 provider library warning 可能只在进程退出或可选 provider 初始化时出现。判断是否失败应以交易回执、合约状态和 Relayer 归档结果为准。

7.7 系统合约 owner 与 BBC 账户不一致怎么办?

如果 AM/SDP/PTC 合约 owner 是旧账户,而 BBC 配置使用新私钥,后续更新 PTC trust root、TpBTA 或授权可能失败。处理方式是使用 owner 账户操作,或重新部署系统合约并更新 BBC 配置。

7.8 FISCO lane 高度缓存冲突如何识别?

如果 Anchor 日志出现按 product、instance、task 的唯一键冲突,同时又存在 lane-specific task,例如 fisco.to.domain@@@,应检查运行库唯一键是否包含 tpbta_lane_key。这类问题会表现为 Anchor 高度无法稳定落库。

7.9 BLOCK_SCAN 和 LOG_FILTER 怎么选?

FISCO 入门和稳定验证优先 BLOCK_SCAN。它慢一些,但路径明确。LOG_FILTER 依赖事件订阅,适合在节点能力确认稳定后再启用。

Clone this wiki locally