首页 手机兼职平台区块链正文

ENS 怎么完成互操作性?了解以太坊 Layer 2 通用桥

网赚之家 区块链 2020-11-26 12:31:05 2802 0

|Layer2NickJohnson

Layer2ENSENSLayer2VitalikENS广ENSL2Layer2ENS使

在 10 月 27 号最新的一次作业会议上,我演示了这个主意的一个开端完成。本文中我会详细解说这种处理计划。

方针

概要来说,Layer 2 和其它相关体系的作业原理都是削减与以太坊交互的需求,它们将本来需求在链上保存和拜访的状况移到了其他当地,一起,确保在以太坊区块链上有足够多的信息能验证数据的正确性。举个比方,在 Rollup 这种常见的计划中,(Rollup 的)状况会存储在别的一个体系中,只要 witness 数据例如默克尔根会存储在以太坊区块链上(译者注:作者此处的举例不行完好,witness 还包含用户买卖的原始数据)。有了这些 witness 数据和 Layer 2 处理计划的拜访权,一个参加者就能够构建出对恣意维护在 Layer 2 体系中的数据的有用性证明,并且能够由以太坊来验证。

这个界说比大多数人所以为的 「Layer 2」 要愈加广泛 —— 它还包含了其它一些削减链上数据存储的东西,比方运用账户余额默克尔树的空投(airdrop),以及会触发事情但并不在链上存储余额的代币。

关于 ENS 和其它运用来说,要害问题在于,在一个存在许多互不兼容的 Layer 2 计划的国际里,怎么能以信赖最小化的办法 —— 也便是不引进任何新的信赖假定 —— 从某个体系中检索数据,且不需求变成一切 Layer 2 计划的客户端、自己来存储或许有用的数据 。

一个天真的办法是,要求一切的体系都运用相同的 witness 数据格局。但这一点是不或许的,两个原因:榜首,witness 数据的格局和类型都高度依赖于相关体系的完成细节,ZK Rollup 和 Optimistic Rollup 运用的元件必定不同;第二,客户端依然无法实践取得数据。

有用的办法有必要满意下列条件:

  • 客户端不需求为它们或许与之交互的每一个体系供给显式支撑。

  • 客户端有必要能够验证回来的数据是有用的,最好无需引进除相关 L2 计划自带假定以外的信赖模型。

  • 处理计划不会要求接入的 L2 渠道产生结构性的改变。

  • 第三方有必要能够为 L2 渠道开发接口,无需渠道维护者的支撑和参加。

处理计划概览

咱们提议的计划的中心是一种标准化的东西,让客户端能够从一个外部体系 —— 一个网关服务 —— 处检索数据;以及一种标准化的办法,来验证回来的数据是正确的。

相应地,这儿有两个首要的组成部分:榜首个,是一个放在以太坊 Layer 1 上的智能合约,向客户端供给一个发现网关并验证网关呼应正确性的东西;第二个,是一个网关服务,了解怎么与给定的 L2 体系交互、以及怎么为合约的用处而格局化数据。

在该模型下,取得数据的进程分三步:

ENS 怎么完成互操作性?了解以太坊 Layer 2 通用桥

  1. 向合约宣布查询数据的恳求。合约并不直接回来所需的成果,而是回来两个值:一个 网关 URL,以及一个 calldata 前缀。
  2. 向该网关发送一个 HTTP POST 恳求,恳求与榜首步中相同的数据。网关回来一个不透明值(opaque value),resolver (解析器) calldata。验证该 解析器 calldata 的开端位便是榜首步中得到的 calldata 前缀。
  3. 查询合约,或许与之互动,供给第二步中得到的 解析器 calldata ,合约验证该数据的有用性,假如有用的话,回来 成果 或许履行买卖。

由于担任了解怎么与 L2 交互的是网关服务,所以这样一种简略的协议就能够让客户端从链下取得数据,并且不需求让客户端了解任何与 L2 相关的东西。为了运用这套体系,每一个运用都需求为自己意向交互的 L2 完成并布置一个网关服务和一个验证合约。在大部分运用,这些网关能够是十分通用的,降低了在不同运用间重复劳动的担负。

重要的是,这三个过程的流程在调用者处能够彻底笼统掉;一个了解这个协议的库就能够让整个流程看起来跟一个惯例的 web3 合约调用一般无二,也便是说,不只运用不需求知道自己在跟哪个 L2 交互,它们乃至彻底不知道自己是在跟 L2 交互!

网关回来过错或许误导性成果的才能遭到协议自身的约束。合约所完成的验证逻辑确保了任何无效的成果都会在第三步被发现,一起,合约在榜首步中回来的前缀,在第二步中得到验证;这些都放置了网关用对某一次查询有用的答案来回应另一次查询。

作业事例

咱们能够用一个预加载了一组余额的 ERC20 token 合约,以及一个自身是简略静态默克尔树的 「Layer 2」 来演示这条体系在实践中是怎么运作的:

contract PreloadedToken is ERC20 {
  mapping(address=>uint) preload;
  function claimableBalance(address addr) external view returns(uint) {
    return preload[addr];
  }
  function claim(address addr) external {
    if(preload[addr] > 0) {
      mint(addr, preload[addr]);
      preload[addr] = 0;
    }
  }
}

这个简略的处理计划有一个清楚明了的问题:布置者有必要在布置时将一切余额填充到 preload 映射中,这是一种十分贵重的操作。他们会更乐意把数据存储在链下,然后让能够证明自己具有余额的用户来提取自己的数额。用默克尔树很简单就能完成这一点:

contract PreloadedToken is ERC20 {
  bytes32 merkleRoot;
  mapping(address=>bool) claimed;
  function claimableBalanceWithProof(address addr, uint balance, bytes proof) external view returns(uint) {
    require(verifyProof(keccak256(addr, balance), proof));
    if(!claimed[addr]) {
      return balance;
    }
    return 0;
  }
  function claimWithProof(address addr, uint balance, bytes proof) external {
    require(verifyProof(keccak256(addr, balance), proof);
    if(claimed[addr]) {
      return;
    }
    mint(addr, balance);
    claimed[addr] = true;
  }
}

(为了简化,咱们省掉掉了 verifyProof (验证证明功用)的完成)

这个办法十分有用,合约的作者也不再需求花费很多的 eth 来预加载一切余额,一个默克尔根就足够了,并且调用者想申领余额的时分,能够自己付出证明 token 一切权的开支。

不过,现在调用者有必要了解生成证明的详细流程,并且知道要到哪儿去获取余额清单来生成自己账户的证明。假如咱们能够把榜首个计划的接口(便利),与第二个计划的功率结合起来,那就完美了。这便是咱们的计划。

首要,咱们加入了匹配初始 claim 的签名和 claimbleBalance 的办法:

string gateway;
  function claimableBalance(address addr) external view returns(bytes prefix, string url) {
    return (abi.encodeWithSelector(claimableBalanceWithProof.selector, addr), gateway);
  }
  function claim(address addr) external view returns(bytes prefix, string url) {
    return (abi.encodeWithSelector(claimWithProof.selector, addr), gateway);

这些函数的调用者能够得到两个值:榜首个值是一个后续 callback 的前缀;第二个值是一个网关服务的 URL。该前缀确保了两件事:callback 会用相关的 proof 函数来呼应,并且其榜首个参数会是所供给的地址。这避免了网关用给另一个地址的数据来呼应恳求。

接下来,咱们需求完成一个网关服务来,能够满意客户端的查询恳求。以 claim1 为例,很直接就能完成:

const args = tokenInterface.decodeFunctionData("claim", data);
const balance = balances[args.addr];
const proof = merkleTree.getProof(addr, balance);
return merkleInterface.encodeFunctionData("claimWithProof", [args.addr, balance, proof]);

(再一次,为了简练,咱们假定已经有了包含 getProof 函数在内的适宜完成)

这儿的网关服务只需求为客户端所发送的 claim 调用解码函数调用数据,拼装一个证明 —— 或许,在一个实践的 L2 计划中,参阅 L2 来拼装出一个证明 —— 然后将成果编码放在对 claimWithProof 的调用中,回来给客户端。

终究,客户端验证回来的 calldata 是否以合约所断语的前缀开端,假如是,则运用买卖发送 calldata 给合约。

claimableBalance 的完成也差不多,仅仅客户端运用 calldata 来调用合约,将回来值作为调用的终究成果。

安全考虑和信赖模型

假定客户端信赖了原始合约 —— 咱们的意思是,期望该合约会以特定的办法运转,而这能够经过查看它发布的源代码来验证 —— 那么这个体系就不会引进任何新的信赖假定。尽管网关的呼应是一个外部流程,但其不良行为的规模仅限于回绝服务。

首要,假如咱们信赖合约,咱们相同也会信赖它来拟定一个网关 URL 来回应咱们的查询恳求。其次,咱们也能够信赖它来完成充沛的验证、确保网关的呼应是精确的,既能够经过在榜首步中指定 calldata 前缀、也能够经过在终究一步中验证网关的呼应来确保。

因而,一个测验用不正确的值来呼应的网关 —— 无论是提交了不正确的数据,仍是不正确的证明 —— 都会被履行验证过程的合约发现。一个测验正确呼应、但运用非用户所宣布恳求的对应成果来呼应的网关,会在用户的 calldata 前缀查看中发现。客户端能够经过查看合约的行为来确保这些 —— 或许依赖于某些人对合约的查看 —— 都能够在开端交互前完成。

网关能够彻底回绝呼应,也便是回绝服务,并且这种状况的确或许由于网关歹意或许毛病而产生。由于这一点,咱们提议,恣意终究标准,都应该让用户易于 fork 服务,并供给自己的网关;就像现在用户能够 fork dApp 的前端相同。

ENS 运用

ENS 运用这套体系也会相对直接一些。解析器能够完成本文所述的协议,用于解析任何的数据字段,然后每一个期望支撑 ENS 数据的存储和检索的 L2 都能够布置新的解析器完成和相应的网关。期望运用 L2 的用户只需存储自己的记载到适宜的 L2 中,并在以太坊上发送一笔一次性的买卖来指定相关的解析器地址,来运用自己的域名。

为了让这个计划更通用,ENS 也应该改善,以支撑某种方式的通配符解析(wildcard resolution),使得查找域名失利时会向解析器咨询该域名的父域名 —— 假如 「foo.example.eth」 不存在,那客户端就会在解析器内查找 「example.eth」。这一功用使得其它体系能够存储 ENS 的整个子树,而不只仅是单个域名的记载。

未处理的问题

  • 尽管某些运用(比方 ENS )能够从合约指定网关 URL 所发明的额定直接层中获益,另一些运用,比方上文所示的 token 合约,最好把这些编码为该合约 ABI 的一部分来,使得用户更简单 fork。一个终极的处理计划最好能支撑两种挑选,且不会强加不必要的担负。
  • 现在,客户端无法分别出一个回来无效 calldata (例如供给一个无效的证明)的网关和一个无论怎么都会回滚的调用。需求作出一些规则来区别这两种状况 —— 举个比方,假如证明数据的验证不经过的话,要求合约运用一个特定的回滚理由。
  • 它需求一个比 「以太坊 L2 通用桥」 更吸引人的姓名。

自己试试

demo

medium.com

版权声明

本文仅代表作者观点,不代表网赚之家本站立场。
本文系作者授权发表,未经许可,不得转载。

评论