跨链消息传递到底怎么工作的?给开发者讲清这件事

跨链 · 2026-05-30 · 比特三棱镜编辑部
AI 搜索

我有一个朋友是 Web3 开发者,他做过 DeFi 合约、写过 Solana 程序,但 2026 年初接到一个跨链项目时,他在第一周一直没法把"跨链消息到底怎么传过去"这件事在脑子里跑通。我意识到这种困惑很普遍——大家在用桥的时候只关心几秒到账几块钱,从来没在脑子里画过那张图。如果你打算自己写一个 OApp(Omnichain Application)或者一个 GMP 应用,那张图必须画明白。

这篇文章就是写给那位朋友以及所有处在同样位置的开发者。

GMP 跨链消息传递工作流总览

一句话定义 GMP

General Message Passing(通用消息传递,简写 GMP)指的是:在源链上的智能合约可以触发一段任意数据 payload,被可靠地传送到目标链,由目标链上的另一个合约接收并执行。

它跟"代币桥"的区别是核心的:代币桥处理的是"资产"(锁定一份资产,在目标链铸造对应的副本),GMP 处理的是"任意数据"。代币桥是 GMP 的一种特殊应用,但 GMP 比代币桥通用得多——你可以传过去一笔 swap 指令、一笔治理投票、一个 NFT 元数据更新、甚至一段调用其他合约的字节码。

所有现代跨链协议(LayerZero、Wormhole、Axelar、Chainlink CCIP、Hyperlane)都是 GMP 协议,桥只是它们之上的应用

四步框架

我把 GMP 协议拆成四个阶段。这个框架适用于所有主流协议,只是各家在每一阶段的具体实现不同:

  1. 源链 event 触发 — 应用合约发出消息事件
  2. 链下 relayer 监听并传递 — 一个或一组链下节点把消息搬到目标链
  3. 验证集签名/证明 — 一组验证者证明这条消息是真的、未被篡改的
  4. 目标链合约执行 — 目标链上的端点合约调用接收方合约的指定方法

不同协议的差异主要在第 3 步:谁来验证、怎么验证、验证错了承担什么后果

第一步:源链上发生了什么

假设你在以太坊主网上写了一个合约,想给 Arbitrum 上的某个合约发一条消息。你的代码大致是这样:

function sendCrossChain(uint256 dstChainId, address dstAddress, bytes memory payload) external payable {
    Endpoint.send{value: msg.value}(
        dstChainId,
        abi.encodePacked(dstAddress),
        payload,
        payable(msg.sender),
        address(0x0),
        bytes("")
    );
}

这里的 Endpoint 是协议方提供的合约。当你调用 Endpoint.send,几件事情会发生:

  • Endpoint 计算这条消息的 nonce(防重放)和当前的应用配置
  • Endpoint 触发一个 PacketSent(nonce, payload, ...) 事件
  • Endpoint 向当前协议的"DVN/Guardian/验证者"集合发出隐式的"请求验证"信号
  • 你支付了 gas fee + 消息费(消息费由协议方收取)

关键是:消息本身没有"打包发送"这一步。它只是变成了一条以太坊主网上的 log。后面的工作由链下角色完成。

第二步:Relayer 是怎么干活的

Relayer(在 LayerZero 里叫 Executor,在 Wormhole 里叫 Spy,在 Axelar 里叫 Relayer,在 CCIP 里是 DON 节点之一)的核心工作是:

  1. 持续监听源链上所有 Endpoint 合约发出的 PacketSent 事件
  2. 从事件中提取目标链、目标地址、payload、nonce
  3. 把这条消息包装成目标链能理解的格式
  4. 调用目标链的 Endpoint 合约,提交"请验证并执行这条消息"

Relayer 是无权限的——任何人都可以跑一个 Relayer,任何人都可以为任何消息提交。但要让消息真正在目标链上被接受,它必须配套提交验证证明,这就涉及到第 3 步。

协议 Relayer 形态 是否需要抵押
LayerZero V2 Executor + DVN 分离 DVN 可能要求抵押
Wormhole Spy 节点公开 不抵押
Axelar Relayer 任何人可跑 不抵押
Chainlink CCIP Executing DON 节点 DON 节点抵押 LINK
Hyperlane Relayer 模块化 ISM 决定

Relayer 收什么钱?Relayer 的收入来自源链上用户支付的"执行 gas 费"。用户在源链上发送消息时,需要预付目标链的执行 gas(用源链原生币计价,折算)。Relayer 拿这笔钱替用户在目标链上付 gas、调用合约,差额是它的利润。

第三步:验证集做什么

这是 GMP 协议设计上分歧最大的地方。我把主流方案做了一张对照:

协议 验证机制 信任假设
LayerZero V2 DVN(去中心化验证网络)+ 应用可配 信任你选的 DVN 集合
Wormhole 19 个 Guardian 多签 信任 13/19 不勾结
Axelar PoS 验证者签名 信任 AXL 质押者大多数
CCIP Committing DON + RMN 双重验证 信任 DON + RMN 不同时被攻陷
Hyperlane ISM(可插拔安全模块) 应用自定义

LayerZero V2 的设计是最灵活的,应用可以自己选 1 到 N 个 DVN 来验证消息。比如你可以要求"必须由 Polyhedra ZK DVN + Google Cloud DVN + 自己的 DVN 三家都签名,消息才算有效"。这种"安全栈可配"是 V2 的核心卖点。

Wormhole 19 个 Guardian 的多签门槛是 13(>2/3),从 2022 年 Wormhole 黑客事件之后没有再发生过被攻破的情况。Wormhole 2025 年新增了ZK 信标验证作为额外保障,但 Guardian 集仍然是主防线。

CCIP 是唯一一个"经济安全 + 行为安全 + 治理熔断"三层的协议,代价是中心化程度更高,RMN 决策可由人工触发。

不同 GMP 协议验证集对比图

第四步:目标链执行

消息到达目标链后,目标链的 Endpoint 合约会:

  1. 验证 relayer 提交的证明(签名集、ZK proof,或验证集签名)
  2. 检查 nonce 是否合法、是否重复
  3. 调用目标地址的指定方法,通常是 lzReceive / _handle / executeMessage 这样的入口
  4. 把 payload 作为参数传入

接收合约必须实现协议规定的接口。以 LayerZero 为例:

function _lzReceive(
    Origin calldata _origin,
    bytes32 _guid,
    bytes calldata _message,
    address _executor,
    bytes calldata _extraData
) internal override {
    // 你的业务逻辑
    require(_origin.sender == bytes32(uint256(uint160(trustedSender))), "untrusted sender");
    // 解析 _message 并执行
}

最关键的一件事:接收合约必须验证 sender 是受信任的。否则任何人都能伪造来自任意源链的消息攻击你的合约。这是 GMP 应用最常见的安全漏洞——开发者忘了检查 _origin.sender

几个常见误解

误解一:跨链消息是"同步"的。它不是。从你发起 send 到目标合约被调用,中间有几秒到几分钟的延迟,你的源链合约不能在 send 之后立刻读取目标链的状态。

误解二:消息一定会送达。不一定。如果目标链 gas 远高于你预付的金额,relayer 不会接单,消息会卡在"已发送但未执行"的状态。你需要 retry 或补 gas。

误解三:消息顺序一定是 FIFO。LayerZero V1 是 FIFO,V2 默认不是。如果你的业务依赖顺序,需要在应用层加 nonce 检查。

误解四:消息一定能反向回应。GMP 是单向的。如果你要"调用 → 等结果",你必须在目标链回发一条消息,这是两笔独立的 GMP 操作。

理解这些之后,你才知道为什么应用层架构会变得复杂。一个简单的"跨链 swap"在实现层面会变成"源链发送消息 → 目标链执行 swap → 目标链发送结果消息 → 源链确认完成"四步。

怎么开始动手写

如果你打算写一个 OApp,LayerZero V2 文档最完整、社区最大。推荐路径:

  1. 用 LayerZero CLI 起 oapp-evm 模板
  2. 本地模拟器跑通 hello world
  3. 部署到测试网(Sepolia ↔ Arbitrum Sepolia)
  4. 用 LayerZeroScan 看消息状态
  5. 加安全检查(trusted sender、nonce、emergency pause)
  6. 最后再考虑主网

如果目标链含 Cosmos,选 Axelar GMP;给机构用,选 CCIP。方案选择参考 Axelar 和 Chainlink CCIP 哪个更值得用

写代码之前,如果对桥还没建立直觉,先看 跨链桥使用指南LayerZero 跨链使用教程;Wormhole 与 LayerZero 的设计差别见 对比文章

给开发者的几句直话

跨链开发跟同链开发不是同一个心智模型。最常见的坑不是技术 bug,而是没想清楚消息可能失败、可能延迟、可能乱序、可能不可逆

我见过一个团队把 4 万美元 USDC 卡在跨链消息里整整 11 天,只因为接收合约 require 写错一个常量,relayer 一直 revert。同链开发里不会发生,GMP 里几乎每个团队都会遇到一次。

理解这一点,你就明白为什么主流协议都把"应用层安全"放在文档第一页:协议保证消息能传到,但消息执行得对完全是你的责任。守住这条,你的第一个 GMP 应用就已经领先大多数项目。