工作流
概念概述
回顾一下,每个Operator
负责维护两个安全进程:
一个完全同步的Injective链验证节点(
injectived
进程)与两个网络交互的协调器服务(
peggo orchestrator
进程)。隐式地,还需要一个完全同步的以太坊节点的RPC端点(请参阅peggo .env
示例)
这两个实体共同完成三件事:
将代币资产从以太坊转移到Injective
将代币资产从Injective转移到以太坊
保持
Peggy.sol
合约与Injective上的活动验证者集同步
即使不成为验证者,也可以运行peggo
。当配置为使用与验证者地址无关的地址时,peggo
会自动以“中继者模式”运行。在这种模式下,只有两件事可以发生:
可以在Injective上创建新的代币批次
已确认的验证者集/批次可以被转发到以太坊
资产类型
以太坊原生资产
任何来自以太坊的资产,只要实现了ERC-20标准,都可以通过调用sendToInjective
函数在Peggy.sol
合约中从以太坊转移到Injective,该函数将代币从发送者的余额转移到Peggy合约。
所有Operators
都运行他们的peggo
进程,这些进程提交MsgDepositClaim
消息,描述它们观察到的存款。一旦超过66%的所有投票权提交了该特定存款的声明,代表代币就会被铸造并发行到发送者请求的Injective链地址。
这些代表代币的面额前缀为peggy
,后接ERC-20代币的十六进制地址,例如peggy0xdac17f958d2ee523a2206206994597c13d831ec7
。
原生 Cosmos SDK 资产
来自Cosmos SDK链的本地资产(例如ATOM)必须首先在以太坊上表示,才能进行桥接。为此,Peggy
合约允许任何人通过调用deployERC20
函数来创建一个表示Cosmos资产的新的ERC-20代币。
此端点没有权限限制,因此由验证者和Peggy桥的用户来声明任何给定的ERC-20代币作为某个资产的表示。
当以太坊上的用户调用deployERC20
时,他们会传递描述所需资产的参数。Peggy.sol
使用ERC-20工厂部署实际的ERC-20合约,并将新代币的全部余额的所有权赋予Peggy
合约本身,然后触发ERC20DeployedEvent
事件。
peggo
协调者会观察到这个事件,并决定Cosmos资产是否已被准确表示(正确的小数位,正确的名称,没有预先存在的表示)。如果是这样,ERC-20合约地址将被采用并存储为该Cosmos资产在以太坊上的最终表示。
协调器(Peggo)子进程
peggo
协调器进程由四个子进程组成,这些子进程在精确的时间间隔内并发运行(循环)。它们分别是:
Signer:使用操作员的以太坊密钥签署新的验证者集更新和代币批次,并通过消息提交。
Oracle:观察以太坊事件并将其作为声明发送到Injective。
Relayer:将已确认的验证者集更新和代币批次提交到以太坊上的
Peggy
合约。Batch Creator:观察Injective上的(新)提款,并根据其类型和配置的
PEGGO_MIN_BATCH_FEE_USD
值决定哪些提款需要打包。
Batch Creator
Batch Creator
的目的是仅在 Injective 端创建代币批次。相关的 Peggy 模块 RPC 没有权限限制,因此任何人都可以创建批次。
当用户想要从 Injective 提取资产到以太坊时,他们会发送一条特殊消息到 Injective(MsgSendToEth
),该消息将他们的提取请求添加到 Peggy Tx Pool 中。Batch Creator 会持续查询池中的提取请求(按代币类型),并在潜在批次满足配置的 PEGGO_MIN_BATCH_FEE_USD
值时(参见 .env 示例),向 Injective 发出 MsgRequestBatch
。
在接收端,所有与请求中的代币类型匹配的池中提取请求将从 Outgoing Tx Pool 中移动,作为一个单独的批次放入 Outgoing Batch Pool 中。
Signer
Signer 的职责是提供确认,证明一个操作员(Orchestrator
)参与了桥接活动。如果未能提供这些确认,将导致该操作员的验证节点遭受惩罚。换句话说,这个过程必须始终运行在验证节点上。
任何在 Injective->Ethereum 流水线中移动的负载(如验证器集更新/代币批次)都需要验证器签名才能成功转发到以太坊。某些在 Peggy 合约上的调用接受一组签名,并与合约中的验证器集进行比对。Orchestrators
使用他们的委托以太坊地址来生成这些签名:这是操作员在初始设置时决定的以太坊地址(SetOrchestratorAddress
)。这个地址代表了该验证器在以太坊区块链上的身份,并将作为多签名成员添加,拥有尽可能接近 Injective 链投票权的加权投票权。
每当 Signer 发现 Peggy 模块中存在未确认的验证器集更新(代币批次)时,它会发出 MsgConfirmValset
(MsgConfirmBatch
)作为证明,证明该操作验证器在桥接活动中是活跃的。
Oracle
监控以太坊网络中涉及 Peggy 合约的新事件。
每个由合约触发的事件都有一个唯一的事件 nonce。这个 nonce 值对于协调 Orchestrators
正确观察合约活动至关重要,并确保 Injective 通过 Claims 进行确认。多个相同 nonce 的 claims 组成一个 Attestation
,当大多数(2/3)的 Orchestrators
观察到某个事件时,其特定的逻辑会在 Injective 上执行。
如果 2/3 的验证器无法就单个 Attestation
达成一致,oracle 将被暂停。这意味着在一些验证器改变他们的投票之前,不会有新的事件从以太坊转发过来。对此没有 slashing 条件,详细理由在 slashing 规范中列出。
Peggy.sol 触发了 4 种类型的事件:
TransactionBatchExecutedEvent
- 表示一个代币批次(提取)已成功转发到以太坊的事件ValsetUpdatedEvent
- 表示验证器集更新已成功转发到以太坊的事件SendToInjectiveEvent
- 表示已启动新的 Injective 存款的事件ERC20DeployedEvent
- 表示新 Cosmos 代币已在以太坊上注册的事件
Injective 的 Oracle 实现忽略以太坊上的最后 12 个区块,以确保区块最终性。实际上,这意味着最新的事件会在发生后的 2-3 分钟后被观察到。
Relayer
Relayer
将验证器集更新(或代币批次)及其确认打包成以太坊交易,并发送到 Peggy 合约。
请注意,这些消息的费用会根据以太坊 gas 价格的剧烈波动而变化,因此一个单独的批次可能需要消耗超过一百万的 gas。我们为 relayer 奖励做出的一个重要设计决策是始终在以太坊链上发放奖励。这有其缺点,尤其是在验证器集更新奖励的情况下可能会出现一些奇怪的行为。
但其优点是显而易见的,因为以太坊上的消息会支付给 msg.sender
,任何现有的机器人都会在以太坊生态系统中接收并尝试提交这些消息。这使得转发市场更加竞争激烈,减少了类似秘密团体的行为。
端到端生命周期
本文档描述了 Peggy 桥接的端到端生命周期。
Peggy 智能合约部署
为了部署 Peggy 合约,必须先知道原生链(Injective 链)的验证器集。在部署 Peggy 合约套件(Peggy 实现、代理合约和 ProxyAdmin 合约)时,必须使用验证器集初始化 Peggy 合约(即代理合约)。在初始化过程中,合约会触发一个 ValsetUpdatedEvent
事件。
代理合约用于升级 Peggy 实现合约,这对于在初始阶段修复错误和进行潜在改进是必要的。它是一个简单的包装器或“代理”,用户直接与之交互,并负责将事务转发到 Peggy 实现合约,后者包含实际的逻辑。需要理解的关键概念是,实施合约可以被替换,但代理(访问点)永远不会改变。
ProxyAdmin 是 Peggy 代理的中央管理员,简化了管理工作。它控制着升级功能和所有权转移。ProxyAdmin 合约本身有一个内置的过期时间,一旦过期,便会阻止未来对 Peggy 实现合约的升级。
接下来,应更新以下 Peggy 初始化参数:
bridge_ethereum_address
为 Peggy 代理合约地址bridge_contract_start_height
为 Peggy 代理合约部署时的区块高度
这完成了 Peggy 桥接的引导过程,链可以开始运行。之后,Operators 应该启动他们的 peggo 进程,并最终观察到最初的 ValsetUpdatedEvent
在 Injective 上被确认。
在以太坊上更新 Injective 链验证者集
验证器集 是一系列以太坊地址,附带规范化的权重,用于表示 Peggy 合约中以太坊上的 Injective 验证器集(Valset)。通过以下机制,Peggy 合约与 Injective 链的验证器集保持同步:
在 Injective 上创建新的验证器集:当以下任意情况发生时,Injective 链上会自动创建新的验证器集:
当前验证器集的累计权重与上一个记录的验证器集相比,差值超过 5%
某个验证器开始从验证器集解绑
在 Injective 上确认验证器集:每个 Operator 负责确认在 Injective 上创建的验证器集更新。Signer 进程通过
MsgConfirmValset
发送这些确认,方法是让验证器的委托以太坊密钥对验证器集数据的压缩表示签名。Peggy 模块验证签名的有效性,并将其持久化到状态中。更新 Peggy 合约中的验证器集:在 2/3+1 多数验证器提交其确认后,Relayer 通过调用
updateValset
向 Peggy 合约提交新的验证器集数据。Peggy 合约随后验证数据、更新验证器集检查点、将验证器集奖励转给发送者,并触发ValsetUpdatedEvent
。在 Injective 上确认
ValsetUpdatedEvent
:Oracle 见证以太坊上的ValsetUpdatedEvent
,并发送MsgValsetUpdatedClaim
,通知 Peggy 模块验证器集已在以太坊上更新。在 Injective 上修剪验证器集:一旦 2/3 多数的验证器对某个
ValsetUpdateEvent
提交了声明,所有先前的验证器集将从 Peggy 模块的状态中修剪掉。验证器惩罚:在配置的时间窗口(
SignedValsetsWindow
)内未提供确认的验证器将面临惩罚。有关验证器惩罚的更多信息,请参阅 valset slashing。
将ERC-20代币从以太坊转移到Injective
ERC-20代币通过以下机制从以太坊转移到Injective:
将ERC-20代币存入Peggy合约:用户通过调用Peggy合约中的
sendToInjective
函数发起将ERC-20代币从以太坊转移到Injective的操作,向Peggy合约存入代币并触发SendToInjectiveEvent
事件。存入的代币将保持锁定状态,直到在未来某个不确定的时刻被提取。该事件包含代币的数量和类型,以及接收资金的Injective链上的目标地址。确认存款:每个Oracle见证
SendToInjectiveEvent
并发送MsgDepositClaim
,该消息包含存款信息,发送到Peggy模块。在Injective上铸造代币:一旦大多数验证者确认存款声明,存款将被处理。
如果资产来源于以太坊,代币将在Injective链上被铸造,并转移到目标接收者的地址。
如果资产来源于Cosmos-SDK,代币将被解锁并转移到目标接收者的地址。
将代币从Injective提取到以太坊
请求从Injective提取:用户可以通过向Peggy模块发送
MsgSendToEth
交易来发起从Injective链到以太坊的资产转移。如果资产是以太坊原生资产,表示的代币将被销毁。
如果资产是Cosmos SDK原生资产,代币将在模块中被锁定。随后,提取请求将被加入到
Outgoing Tx Pool
中。
批次创建:批次创建者观察待处理的提取池。批次创建者(或任何外部第三方)通过向Injective链发送
MsgRequestBatch
请求为指定的代币创建批次。Peggy模块将匹配的代币类型的提取请求收集到一个批次中,并将其放入Outgoing Batch Pool
。批次确认:当检测到存在
Outgoing Batch
时,签名者使用其以太坊密钥对该批次进行签名,并向Peggy模块提交MsgConfirmBatch
交易。将批次提交到Peggy合约:一旦大多数验证者确认了该批次,转发者将调用Peggy合约上的
submitBatch
函数,提交该批次及其确认信息。Peggy合约验证签名,更新批次检查点,处理批次中的ERC-20提取请求,将批次费用转移到交易发送者,并触发TransactionBatchExecutedEvent
事件。发送提取声明到Injective:Oracles见证
TransactionBatchExecutedEvent
事件,并向Peggy模块发送包含提取信息的MsgWithdrawClaim
。修剪批次:一旦大多数验证者提交了他们的
MsgWithdrawClaim
,该批次将被删除,所有之前的批次也将被取消。取消的批次中的提取请求将被移回Outgoing Tx Pool
。批次处罚:验证者负责确认批次,如果未能完成此操作,将受到处罚。有关批次处罚的更多信息,请参阅批次处罚。
注意:虽然批次处理显著降低了单次提取的费用,但这也带来了延迟和实现复杂度。如果用户希望快速提取,他们将需要支付更高的费用。然而,这个费用将大致与非批次系统中每次提取所需的费用相同。
Last updated