【摘要】 Merkle Bridge的目标是成为一个简单轻巧的协议,用于在区块链之间资产转移,同时提供分布式的监管和审查阻力。第一个应用程序是将Aergo ERC20代币转移到Ae
Merkle Bridge的目标是成为一个简单轻巧的协议,用于在区块链之间资产转移,同时提供分布式的监管和审查阻力。第一个应用程序是将Aergo ERC20代币转移到Aergo的主网原生代币。一旦部署了网桥,任何以太坊或Aergo资产都将可以在这些网络之间直接转移。在本文中,我们将介绍该协议的一些技术细节。
我们可以用以下两种方式锚定(2WP)的资产转移:首先在区块链A上存入代币,然后要将代币转移到区块链B上,必须先将区块链A上代币进行锁定,并以1:1的比例在区块链B上铸造一个副本,最后副本区块链B上销毁后,才能解锁区块链A上的锁定代币。
维持固定汇率的简单方法是将资产锁定在单个密钥或多重签名合同中(大多数交易所如何存储资金)。
第一种情况(单个密钥)不安全,因为密钥可能会被盗或丢失。
第二种情况(multisig)更安全,但是转让费用昂贵,因为它们每次转让都需要链上进行2/3签名验证。让每个传输进行多重签名处理也意味着很容易审查单个用户的传输。还有其他更安全和无需信任的方法,例如ETH-ETC的平桥,但需要资本锁定才能进行抵押和削减。
我们的目标是实现允许20多个验证者的分散资金锁定/解锁,但同时通过设计一种简单的协议(无需桥接操作员来处理单个转账),将桥接转账费用保持在较低水平。
Merkle桥设计
Aergo Merkle桥可实现分散式保管和资产的有效铸造。
权限证明(PoA)侧链通常使用其状态根在公共链上的锚定来提供可验证的真相来源。Merkle桥使用这些锚定状态根来允许用户提交侧链状态的证明。
资金保管
这种设计的安全性取决于锚定根的有效性。固定的区块链状态根包含锁定和已用余额的信息,因此任何无效的状态根都可用于窃取锁定的用户资金。
为了确保状态根的有效性,锚定使用类似于multisig oracle的简单形式的DAO(分散式自治组织)。该DAO的成员称为验证者。
验证者有以下职责:
· 在将要锚定的根源上达成共识(因此它们必须是具有信誉的已知实体,以确保有效的锚定)。
· 同意验证者集更新建议(使用2/3当前验证者的签名添加或删除验证者)。
· 同意Merkle桥设置更新建议(还需要获得2/3验证者的批准).
操作方式
提案人(愿意支付锚定费的人)会定期在桥接链上发布桥接合约的状态根。仅在状态根已由2/3验证者签名的情况下才会记录。
然后,用户钱包可以通过使用锚定状态根验证其锁定资产的Merkle证明来独立铸造目标桥合约上的资产。
锁定并跟踪帐户的总代币余额。创建了包含此余额的Merkle证明,并且可以在桥的另一侧铸造该代币余额。铸造记录了总的造币余额,因此帐户造币的金额永远不会超过存入的金额。烧毁和解锁余额也是使用相同的过程。
这种设计使合约的存储管理和操作变得简单,因为它不需要记录传输随机数或返回值。 局限性在于,随着用户数量和固定代币数量的增长,Merkle证明的大小会增加(合约状态树会更深),从而使转移变得更加昂贵。
使用Merkle Bridge将ERC20代币从以太坊转移到Aergo
优点:
· 验证者实现起来很简单,因为它们只需要签署它们认为有效的最终状态根(通过在桥的两边运行完整的节点)。验证者不需要监视和验证用户的转移。
· 用户钱包直接通过网桥合同进行转账,不需要验证者批准。
· 锚定周期是灵活的,状态根可以由许多验证器(20 +)签名。
· 如果没有超过2/3验证者共同认可并广播无效的侧链状态根,则不能任意审查代币传输。
· 可以进行小额转账,并且可以随时铸造/解锁总存款余额。
· 链上的Merkle证明验证比签名验证便宜。
· 任何新资产都可以通过网桥进行转移,而无需获得验证者的批准(由于在铸造时会部署新的固定合约,因此第一次转移的成本会更高)。
· 可以通过一次交易完成对另一个链上同一帐户的多次转账,提取发送到该帐户的总锁定余额。
局限性:
· 一旦启动,传输就应该在网桥的另一端完成(没有超时限制),但这意味着无法取消传输。
· 如果超过1/3的验证者停止合作,网桥将无限期暂停(不可能有新的取款)。
部署
在此存储库中可以找到2个Aergo区块链之间的Merkle桥的POC实现:https://merkle-bridge.readthedocs.io
以太坊和Aergo区块链之间的Merkle桥的POC实现可以在以下存储库中找到:https://eth-merkle-bridge.readthedocs.io
在此存储库中可以找到用于在以太坊和Aergo之间转移资产的Javascript SDK:https://github.com/aergoio/eth-merkle-bridge-js?source=post_page-----32bd0f06c308----------------------
桥的操作员
他们要为桥接的每个区块链运行一个完整节点。 每隔固定的时间间隔(每10分钟?),他们将获得最新的最终状态根,并将其注册在桥合约的Root和Height状态变量中的相反区块链上。
桥操作员有2种类型:广播set_root()事务的建议者和为建议者请求的两个桥接链状态根签名的验证器任何人都可以是提议者:桥合约只允许在锚定期之后发生且具有有效签名的状态根更新。验证者的数量可以根据所需的multisig安全性而变化,如果请求的状态根有效,验证者会对其进行签名。
function newAnchor(
bytes32 root,
uint height,
uint[] memory signers,
uint8[] memory vs,
bytes32[] memory rs,
bytes32[] memory ss
) public {
require(height > _anchorHeight + _tAnchor, "Next anchor height not reached");
bytes32 message = keccak256(abi.encodePacked(root, height, _nonce, _contractId, "R"));
validateSignatures(message, signers, vs, rs, ss);
_anchorRoot = root;
_anchorHeight = height;
_nonce += 1;
emit anchorEvent(root, height);
}
操作员调用newAnchor(…)来锚定新的状态根
桥验证者集更新:
如果2/3的当前验证者同意新的验证者集,则可以定义新的验证者集。
function validatorsUpdate(
address[] memory newValidators,
uint[] memory signers,
uint8[] memory vs,
bytes32[] memory rs,
bytes32[] memory ss
) public {
// validators should not sign a set that is equal to the current one to prevent spamming
bytes32 message = keccak256(abi.encodePacked(newValidators, _nonce, _contractId, "V"));
validateSignatures(message, signers, vs, rs, ss);
_validators = newValidators;
_nonce += 1;
emit newValidatorsEvent(newValidators);
}
桥验证者集更新
版本2
在Merkle桥的版本2中,签名验证将在单独的Oracle合约中重构,该合约将对桥合约具有完全控制权。这样可以升级oracle合同的共识机制,并为用户转移保留相同的桥接合约。 桥的安全属性保持不变。
用户资产转移:
要传输代币,用户会将其锁定在桥接合约中,并等待目标区块链上的下一个锚。
function lock(
string memory receiver,
uint amount,
IERC20 token
) public returns (bool) {
// Add locked amount to total
bytes memory accountRef = abi.encodePacked(receiver, token);
_locks[accountRef] += amount;
// Pull token from owner to bridge contract (owner must set approval before calling lock)
// using msg.sender, the owner must call lock, but we can make delegated transfers with sender
// address as parameter.
require(token.transferFrom(msg.sender, address(this), amount), "Failed to burn");
emit lockEvent(token, receiver, amount);
return true;
}
lock(…)记录用户存入的总余额。
用户钱包将读取目标区块链上的新锚定状态根(Root,Height),并向该节点请求Merkle证明,包括该状态根的锁定余额。用户的锁定平衡被记录在锁状态映射,其中键是用于一个令牌帐户参考。 帐户参考是用户地址和令牌地址的串联。 然后可以使用锁定令牌的Merkle证明在目标区块链上进行薄荷交易。 用户的造币金额不能超过合同所存入和记录的总金额。
function mint(
address receiver,
uint balance,
string memory tokenOrigin,
bytes32[] memory mp, // bytes[] is not yet supported so we use a bitmap of proof elements
bytes32 bitmap,
uint8 leafHeight
) public returns(bool) {
require(balance>0, "Balance must be positive");
bytes memory accountRef = abi.encodePacked(receiver, tokenOrigin);
require(verifyMp("_sv__locks-", accountRef, balance, mp, bitmap, leafHeight), "Failed to verify lock proof");
uint mintedSoFar = _mints[accountRef];
uint amountToTransfer = balance - mintedSoFar;
require(amountToTransfer>0, "Lock tokens before minting");
MintedERC20 mintAddress = _bridgeTokens[tokenOrigin];
if (mintAddress == MintedERC20(0)) {
// first time bridging this token
mintAddress = new MintedERC20();
_bridgeTokens[tokenOrigin] = mintAddress;
_mintedTokens[address(mintAddress)] = tokenOrigin;
emit newMintedERC20(tokenOrigin, mintAddress);
}
_mints[accountRef] = balance;
require(mintAddress.mint(receiver, amountToTransfer), "Failed to mint");
emit mintEvent(mintAddress, receiver, amountToTransfer);
return true;
}
mint(…)验证存款的Merkle证明并铸造正确数量的代币。 如果从未铸造过令牌,则部署新的固定代币合约。
如果桥的操作员在用户产生余额之前锚定了新的状态根,则用户的钱包可以为新锚定的状态根简单地创建新的Merkle证明。
用户的钱包在原始区块链上解锁代币之前,会重复类似的烧毁代币的过程。
有关Merkle桥合约中的Merkle证明验证的详细信息,请参阅:
[http://bitoken.world/?p=297](以太坊Patricia树的Merkle证明验证 "http://bitoken.world/?p=297")
相关作品
Merkle Bridge采取的方法是尽可能使用最简单,最可靠的设计,以使验证者无需就用户转移达成共识,而是将所有资源集中在他们锚定的区块链状态根的有效性上。此外,用户没有完成转账的时间限制,并且可以通过一次交易完成对同一帐户的多次转账。这是与以下协议的主要区别:
ICS(链间标准)
其他项目,如cosmos ibc,则采用不同的方法,将所有单个跨链资产传输抽象为数据包(也可以支持契约调用),并且peg区域验证器在这些数据包上达成共识。这是一种非常有趣的方法,可以减少对跨链资产的信任,但当peg验证器锁定的资金的价值超过所涉原子的价值时,这种设计也最终依赖于验证器的声誉时,就会产生问题。
需要注意的是,为了连接比特币和EOS这样的区块链,将存款事件转发到传输代币上是必要的,而EOS并不是Merkelize状态。
Plasma
Merkle桥的设计灵感来自对Plasma的研究,并解决了在Plasma上运行合约的问题。Merkel桥并不是Plasma的,因为它不具有相同的安全性:没有退出提示可以挑战来自侧链的退出,并且提款必须在侧链上进行。 Merkle桥的安全性取决于锚定验证者的分散性。
由于可以为单个状态根进行无限数量的传输,因此该状态根所需的签名数量可能很高。用户无需关注区块链上的无效提款和大规模退出情况,而应该信任去中心化的验证者。同样在POA企业侧链的情况下,我们通常会假设共识安全性,因此可以在侧链上初始化提款是可以接受的,并且侧链运营商不需要监视父级挂链的退出。
结论
Merkle桥由一个简单的DAO(multisig oracle)组成,用于验证锚,更新验证者集和桥设置。用户钱包可以独立创建其锁定/烧毁余额的Merkle证明,以进行跨链转移,而无需验证者观看转移事件。
EthAergo网桥将用于在Aergo和以太坊主网之间发送AergoERC20和任何其他代币。
AERGO-AERGO桥接器将被企业侧链的用户用于以一种成本高效和安全的方式在AERGO主网之间转移他们的资产。
这使MakerDAO的DAI稳定币和其他任何ERC20等令人兴奋的应用程序都可以供Aergo主网用户使用,并由Merkle桥锚定保护。(链三丰)