火星一线 | Go-Ethereum核心开发者:轻节点可提高历史智能合约搜索的效率

火星财经APP(微信:hxcj24h)一线报道,6月29日,由CSDN、灵钛科技联合主办,区块链大本营、ETHPLANET、火星财经、Unitimes协办的「2019第二届以太坊技术及应用大会」在北京举行。来自goethereum的核心开发者GaryRongo创始人发表主题为 “深究以太坊轻客户端协议” 的演讲。期间他表示,轻节点可提高历史智能合约搜索的效率。以太坊轻节点协议包括低资源要求和数据正确性,轻节点不检测状态转换的正确性,真正需要使用时才向网络请求,本地只储存所必需的信息。轻节点会同步最近的区块头信息,此节点必须是可信且可证实历史链的正确性。他还解释称,轻节点可对布隆过滤器进行优化,提高历史智能合约搜索的效率,轻节点还可发起对服务器的付费功能。

以下为演讲全文,由火星财经APP(微信:hxcj24h)整理编辑,未经本人确认:

大家好!我是来自以太坊goethereum的GaryRong,今天我为大家带来的内容是“以太坊的轻客户端议”。

首先是协议基本概念 ,第二点是Merkle Trie & Merkle Proof,第三点是轻客户端用到的算法 ,第四点是我们的用户能够用轻节点做哪些事情,最后一点是关于流量控制和流量管理的一些内容。

以太坊轻节点协议顾名思义是为以太坊 轻节点设计的,轻节点有两个设计目标,首先要对资源要求足够低,必须能够运行在IoT或者手机这种小型终端设备上,其次,它必须有能力验证从网络中收取到数据的正确性。在我们的协议里轻节点只会同步block headers,因为它的函数很小,只有几百个字节,并且能在轻节点里设计了垃圾回收机制,使得轻节点只需要维护最近的block headers,所以存储压力非常小。

此外,block headers里有很多m root(音译),是轻客户端能够进行数据校验最关键的元数据,我们只同步block headers。此外,轻客户端本身不会做每一次区块链变更正确性的验证,因为要验证每次变更状态的准确性,必须要在本地维护全量账本,这显然不是轻客户端能接受的。从这个角度来看,轻客户端的安全性是略低于Fullnode的,工具有可能在一段时间之内推送一些其他字段都是正确,但是对应state是错误的blockheadesr。为此,lightclient只要能够最终连接到全矢的pear(音译),并且分享最长链上的最新的block headers,它就能够自动检测出这样的工具,把错误的headers回滚,通过这样的方式保证它自身的安全性。

所以综合来看,它是在block headers基础上,对其他部分的区块链数据,例如交易或回值,只需要在真正使用到时才会向网络进行请求并且进行验证,它是把P2P数据库当成 它的数据库 ,本地的数据库只是一层缓存,用于存储一些需要用到用于校验的元数据。

目前以太坊的轻节点协议可以分为两类,一类是les端实现的,第二类是在第一类基础上进行修改,PIP客户端进行实现,我们主要介绍第一类协议。

目前以太坊中的节点类别主要分为三类:第一类是Archive node,它维护全量的区块链数据,同时也会维护每个版本状态数据以及对应的proof,这个节点的体积非常大,已经超过两个T,同步这样一个需要10多天时间。第二类节点是Fullnode,它也会维护全量的区块链数据,但是不同的是它会对中间版本或过期的状态数据进行垃圾回收,所以这个节点数据库小得多,只有100多个GB。在1.9版本中我们对这个节点的同步算法进行了优化,目前最快可以在3个小时40分钟以内 完成对以太坊主网的同步。第三类是轻节点,由于它本身只维护blockheaders,并且有垃圾回收机制,可以将本地数据库控制在很小值,大约只有50兆左右。它可以选择从可信的点同步,而不必要每次都从block进行同步,同步最新的几万个header就可以同步,1分钟之内就可以完成区块链的工作。以上是这个协议基本内容。

接下来介绍merkletrie,左下角leaf1节点用来卛key=000。第二个特点是每个副节点都会存储哈希,比如3会存储1的哈希。副节点本身的哈希又是通过所有节点的哈希内容再进行一轮哈希计算得到的,所以最终merkletrie节点哈希值包含整颗树中所有节点的哈希信息。

什么是Merkleproof?这里指它拥有一个正确的root时就可以校验任意节点的正确性,当需要验证首先需要向服务器请求 一个,根据目标节点在树中路径从根节点开始收集树上所有节点,然后组成返回。Merkleproof它的安全性是攻击者很难构造假树节点,完全可以利用本地维护的正确的root校验第一个节点内容是否正确,假如第一个节点哈希内容等于本地的,我们可以证明第一个节点内容是正确的。我们可以从第一个节点的列表中拿到第二个节点的哈希,同理,可以用这个哈希校验第二个内容是否正确,以此类推,我们可以校验最后一个节点,就是目标节点的正确性。

通过这样的方式,Merkleproof是一个非常重要的内容。

第三点,它必须满足两个条件,首先,它一定是可信的,其次,必须要能够去利用这个信息去做历史数据的校验,这样它才能够真正不去同步所有历史的blockheaders。在同步时时收到来自网络的大量blockheaders,还会进行PoW校验,假设我们对全量的blockheaders进行校验,会发现本地节点的计算 带宽远远大于网络带宽,恰巧我们运行比较弱的能力下,所以我们选择以1%的概率抽取一些blockheaders校验,被校验的每一个blockheaders确认所有之前的blockheaders。

然后详细降息checkpoint,它是能够真正完成同步过程的最关键因素,checkpoint由sever或全推动者,或者处理32768blocks以后产生的元数据,元数据包含几个内容,首先是sectionsindex保证新旧程度。CHTroot,全节点将区块链最强链每个区块哈希作为数据项,去插入到本地中。这个是包含在里面的CHTroot,假设这是正确的,就能够借助这个CHT去校验任何一个被点覆盖的正确的哈希值,有了正确的哈希就能够获得正确的blockheader,就能够对历史数据进行校验了。处理了32768blocks以后可以在本地生成下一个chtroot】,一旦被产生了历史的信息已经被归纳到新的树当中了,这时我们就可以对历史的blockheaders进行垃圾回收了。

到目前为止我们对checkpoint有很强的假设,我们认为用到的这个是正确的,但是当刚进入网络时没有任何数据,很难校验这个checkpoint是否正确。暂时 我们用两种方法解决这个问题,一是我们开发者通过编码方式在代码中确认最新的checkpoint,它是较为中心化解决方案,用户限定 为开发者给定的解决方案,通常开发者发布新版本才会去更新,所以同步时用到的checkpoint是过期的信息,所以依然需要下载很多blockheaders才能够完全同步。。为了解决更新问题,第二种方案是在区块链部署一个智能合约 ,把checkpoint更新操作通过这个智能合约 完成。这种方式,只要区块链产生一个新的checkpoint,智能合约可以通过多签签名 方式注入到合约 里,这样始终用的都是最新的checkpoint,它依然没有解决中心化的问题,我个人认为这里中心化一定程度可以被接受,假设不信任开发者,理论上也就不会使用开发者交付的软件。Pow本身并没有像pos那样具有概念,所以这并不是一个特别简单的事情。

第四点,我们的用户能够轻节点做哪些事情?首先,它能够帮你做交易转积,当它收到本地交易可以把交易转积到server,不断向server查询状态,如果一旦 被确认server就给它发送一个,通过这个之后就可以去获取与之对应 的,通过本地维护的去校验收到的是否正确。第二点,,能够查询 账本服务,对于目标帐户的状态查询本质来说是对M的一次M。

第五点,轻节点能够让用户在本地进行智能合约 调用,把合约 二进制码需要用到的状态数据以及调入放到里面执行,等待它的输出。有所区别的是对于L既没有合约 二进制码也没有需要用到的状态数据,缺失的数据都是通过网络进行请求,不同通过进行验证。目前还有一个问题是缺失数据的状态在运行时才能够知道到底缺失哪些数据,所以我们发现一次合约 执行过程中可能会涉及到很多次网络的请求,这个智能合约 整体执行效率就受到本地节点网络带宽的限制了。

我们今后会把智能合约执行过程中挪到server端,收集状态数据以及对应的proof,在一个网络包进行返回,通过一次网络请求获取到所有状态数据,大幅度提高在本地执行的效率。

然后是能够让用户进行智能合约事件的订阅,但是它本身并不会去同步所有的receipts,为了完成这个功能,它只能通过每次同步得到的blockheader去猜测 里面是否包含用户感兴趣的事件。我们在里面加了bloom过滤器,把关键信息收录进来,轻节点同步得到一个新的block之后可以通过过滤器根据本地用户得到的关键字进行匹配 ,匹配通过了说明这个block有可能包含目标事件,然后它才通过去获取对应 的,在本地实现精确 的过滤,然后返回给用户。

最后一点,轻节点能够让用户进行历史智能合约事件的搜索功能。搜索跟订阅是复杂度完全不同的两件事情,最简单的是遍历blockheaders,但是显然非常低效,为了提高效率,我们对过滤器的存储进行了优化,一个过滤器也2048个比特,我们的优化是同时拿到3万个blockheaders,把对应的过滤器同时进行90度旋转 ,分别将第0位、第1位、第2047位进行整体存储。这样的好处是假设我们搜索关键字为a的事件,我们把a的进行散列,假设一个区块过滤器满足这三位同时为“1”,表明这个区块有可能包含这样一个目标事件。但是我们发现整体中我们只用到这3个信息,剩余的2045位都是无效的数据,90度旋转 很好解决这个问题,我们可以有针对性的获取这3个的过滤器的信息,同时一次验证3万个blockheaders有哪些包含目标,提高合约 搜索效率。当然,lightclient数据命中是通过网络进行请求的,所以它的效率稍微低一些。

最后一点是有关于协议中流量控制跟容量管理的一些内容。首先,流控问题,我们这里采取比较传统的流控技术,有所区别的是在中心化架构下,C需要往一个单点发送请求,server为它进行负载均衡、流量控制。但在非中心化情况下我们没有这样的单点问你的client做负载均衡。所以我们这里采取了比较特殊的机制叫“竞相令排同”(音译),server发送一些参数,这个最慢的恢复速度和一张maxcosttablle,client在本地同样维护令排同(音译),然后去判断本地令牌里面有没有这么多令牌让它发送请求,如果没有的话就不应该向server发送这个请求。在server端显得更为复杂,因为server给client都是最低配置参数 ,比如最慢恢复速度。server处理请求有较为精确 的计算公式,我们保证公式结果不会大于查询得到的结果。此外,当server发现它的资源被闲置时会给client更快令牌速度,所以同时维护两个令牌桶(音译),另外一个对应的一模一样的。

server处理完这笔请求后会根据本地的值对本地镜像令牌桶调整容量值,同样会把buffer返回。一般一个client在本地有多个server,为每个server都构建一个令牌桶,client倾向于把请求转积给更多令牌的server,server也优先处理拥有更多令牌的client的请求,实现资源的均等划分。

通过这种方式client能够借助本地令牌信息更好管理和分发它的请求,避免很低的处理优先级或者很高的响应延时。

然后是服务端的容量管理,我们提供4个参数 让server运维限制server资源使用。第一个是lightserve,它表示1秒中有多少百分比时间server可以用来处理客户端的请求,可以大于百分之百,后台有多个限权同时处理client的请求。同时,有两个关于两个网络带宽的参数性质,你的客户端网络带宽如果是珍贵 的网络资源,可以通过这两个参数进行限制。最后一个是lightpeers,表示server连接最多client的数目。

server处理请求有一个较为精确 的计算 公式,同时考虑两方面内容,首先是时间开销 ,也就是说处理这笔请求对应花费的时间,其次考虑网络带宽的因素,它会考虑这个请求对应的root包大小。最后取这三个上限值,假设你的server特别慢,这时时间开销 应该是最大的;如果你的server网络带宽被限到很小值,这时网络包的cos是最大的。

然后是buffer recharging,server端可能同时有多个client,恢复速度总和在server端有一个上限叫recharge,代表这个server所能服务的请求能力。以及你的server运维者可以通过这个限制使用。

为了最大提高服务端对客户端的服务数量,规定服务端资源闲置时它给server更快令牌恢复速度,根据当前正在恢复的速度在。

当server发现它在过去一段时间内处理的client请求累积的时间开销 ,加上本地缓存的预估时间开销,相加之和超过了恢复能力,这时表明server已经过载了,这时一定的优先级请求发送频繁的client进行冻结,通过这个方式最大程度利用server端资源,同时有严格机制限制这些资源的使用。

最后是free client和prioriity client,它不会去参与区块的验证,不会参与其他用户发起的交易,它需要server为它免费提供请求服务。但是client在用户体验确实有一定优势,它对资源要求非常低,能在非常短的时间内完成。所以我们提出了付费节点的概念,LC可以通过微支付向server进行付费,让server给它赋予更高的容量,这样它能够发送更多请求,并且这些请求有更低的响应延时。

这时我们的serve fullnode收到了对应的报酬,目前运行没有任何经济激励,但是fuunode对网络安全是非常重要的决策,我们希望通过这种方式对现状进行一定程度改善。

以上是全部内容。