编者注:本译文的首个版别见于此处,本次再版已经过校正。在此对原译者 kim 表明感谢。

原文的写作时刻不确定,但可将其视为一个原点,反思以太坊的规划理念以及以太坊在这几年间的演化。既是反思其立异,也是反思其有欠考虑的当地。

虽然以太坊的许多理念在新近的密码学钱银(如比特币)上现已运用并测试了5年之久,但从某些协议功用的处理办法上来说,以太坊与常见办法仍有许多不同。并且,以太坊可用于开发全新的经济东西,由于它具有其他体系不具有的许多功用。本文会详细描绘以太坊一切的潜在长处,以及在构建以太坊协议过程中某些有争议的当地。别的,也会指出咱们的计划及替代计划的潜在危险。

准则

以太坊协议的规划遵从以下几点准则:

  1. 三明治杂乱模型(亦可译为 “杂乱度分层模型” ):咱们以为以太坊的底层协议应尽或许的简略,接口规划应易于了解(不论是面向开发者的高档编程言语接口,仍是面向用户的运用接口)。那些不行避免的杂乱部分应放入中间层。中间层不作文核心一致的一部分,且对最终用户不行见,它包括:高档言语编译器、参数序列化和反序列化脚本、存储数据结构模型、leveldb 存储接口以及联网协议等。当然,差异的界线不是肯定明确的,有时候需求酌情调整。

  2. 自在:不该束缚用户运用以太坊协议,也不该试图优先支撑或不支撑某些以太坊合约或买卖。这一点与 “网络中立” 概念背面的指导准则类似。比特币买卖协议就 没有 遵从这一准则:比特币买卖协议并不鼓励区块链的 “十分规用处(off-labal purpose)” (如,数据存储,元协议)(校正注:off-labal 的原意为将药物用在其经过批准的适应症之外的症状上,例如运用止咳药来医治头痛。此处意译为 “十分规用处” );并且,有时候还有人用 准-协议层 的改变(例如将 OP_RETURN 字段的长度束缚在 40 字节)来进犯以 “未经授权” 的办法运用区块链的运用(校正注:此处是在挖苦比特币的社区有检查比特币区块链用法的倾向)。因而,在以太坊,咱们坚定支撑仅运用买卖手续费来达到大体鼓励相容的办法 —— 用户耗费整个网络越多资源,需求支付的价值就越高,也即使其自己承当本钱(即庇古税)。

  3. 泛化:以太坊协议的特性和操作码应最大极限地体现低层次的概念(就像基本粒子一样),以便它们能够随意组合,包括组合出今天看来没什么用、但未来或许有用的东西。并且,经过剥离那些不需求的功用,低层次的概念能够愈加高效。遵从这一准则的例子是,咱们挑选 LOG 操作码作为向 dapp 供给信息的办法,而不是像之前那样记录下一切买卖和音讯。在新近,“音讯(message)” 的概念完完全全是多种概念的调集,它包括 “函数调用(function call)” 和 “外在观察者感兴趣的事情信息(event)” ,而两者是完全能够别离开来的。

  4. 没有特色便是最大的特色:为了遵从泛化准则,咱们拒绝将那些高档用例内嵌为协议的一部分,哪怕是经常运用的用例,也绝不这么做。假如人们真的想完成这些用例,能够在合约内创立子协议(如,根据以太坊的子钱银,比特币/莱特币/狗币的侧链等)。比方,在以太坊中就短少类似比特币中的 “时刻锁” 功用。可是,经过以下协议能够模拟出这个功用:用户发送签名数据包到特定的合约中处理,假如数据包在特定合约中有用,则履行相应的函数。

  5. 不厌恶危险:假如危险的添加带来了可观的优点,咱们乐意承当更高的危险(例如,通用的状况转换,出块时刻减低 50 倍,一致功率,等等)。

这些准则指导着以太坊的开发,但它们并不是肯定的;某些情况下,为了削减开发时刻或许不希望一次作出过多改动,也会使咱们推延作出某些修正,把它留到将来的版别中去修正。

区块链层协议

本节对以太坊中区块链层协议的改动进行了描绘,包括区块和买卖是如何工作的、数据如何序列化及存储、账户背面的机制。

账户 ,而非 UTXO 1

比特币及其许多变种,都将用户的余额信息存储在 UTXO 结构中,体系的整个状况由一系列的 “未花费的输出” 组成(能够将这些 “未花费的输出” 想象成钱币)(校正注:更好的一个比喻或许是 “支票”。)。每个 UTXO 都有具有者和本身的价值特色。一笔买卖在消费若干个 UTXO 一起也会生成若干个新的 UTXO;而买卖受到下列有用性要求的束缚:

1.每个被引证的输入有必要有用,且未被运用过;2.买卖的签名有必要与每笔输入的一切者签名匹配;3.输入的总值有必要等于或大于输出的总值。

因而,比特币体系中,用户的 “余额” 是该用户的私钥能够有用签名的一切 UTXO 的总和。下图展示了比特币体系中买卖输入输出过程:

Vitalik:以太坊的设计理念(一)

比特币所用的三式记账法 

可是,以太坊抛弃了 UTXO 的计划,转而运用更简略的办法:选用状况(state)的概念存储一系列账户,每个账户都有自己的余额,以及以太坊特有的数据(代码和内部存储器)。假如买卖主张方的账户余额满足支付买卖费用,则买卖有用,那么主张方账户会扣除相应金额,而接纳账户则计入该金额。某些情况下,接纳账户内有需求履行的代码,则买卖会触发该代码的履行,那么账户的内部存储器或许会发生变化,甚至或许会创立额定的音讯发送给其他账户,然后导致新的买卖发生。

虽然以太坊没有选用 UTXO 的概念,但 UTXO 也不乏有一些长处:

  1. 较高程度的隐私保护:假如用户每次买卖都运用一个新的地址,那么账户之间的相互关联就很困难。这样做适用于对安全性要求高的钱银体系,但不是对任何 dapp 都适宜。由于 dapp 通常需求跟踪用户杂乱的绑定状况,而 dapp 的状况并不能像钱银体系中的状况那样简略地划分。

  2. 潜在的可扩展性:理论上来说,UTXO 与某些类型的可扩展性计划(scalability paradigm)更契合,由于只需持币者具有能够证明自己钱银一切权的默克尔证明即可,即使一切的人(包括 TA 自己)都遗忘了这一数据,真正受损也这个人,其他人不受影响。在以太坊账户体系中,假如一切人都丢失了某个账户对应的默克尔树部分,那么该账户将无法处理任何能够影响它的音讯,包括发送给它的音讯,它也无法处理。不过,并非只要 UTXO 能够可扩展,也存在不依赖 UTXO 就能扩展的办法(此处没有扩展开来讲,译者注)。

账户的优点有以下几点:

  1. 节约大量空间:假如一个账户有 5 个 UTXO,则从 UTXO 形式转成账户形式,所需空间会从 300 字节降到 30 字节。详细计算如下:300 = (20+32+8)* 5 (20 是地址字节数,32 是 TX 的 id 字节数,8 是面额占用的字节数); 30 = 20 + 8 + 2 (20 是地址字节数,8 是账户余额值字节数,2 是 nonce 2 字节数);但实践节约并没有这么大,由于账户需求被存储在帕特里夏树中。别的以太坊中买卖也比比特币中的更小(以太坊中 100 字节,比特币中 200-250 字节),由于每次买卖只需求生成一次引证,一次签名,以及一个输出。

  2. 可互换性更强:UTXO 结构并没有区块链层的概念,所以不管是在技能仍是法律上,经过树立一个红名单/黑名单,并根据的这些 “有用输出” 的来源差异它们并不是很实践。

  3. 简略:以太坊编码更简略、更易于了解,尤其是在涉及到杂乱脚本时。虽然任何去中心化运用都能够用 UTXO 办法来(勉强)完成,但这种办法实质上是赋予脚本束缚给定的 UTXO 所能输出的 UTXO 的种类及其运用条件(比方需求包括默克尔树证明来帮助脚本所对应的运用更改状况根)的才能。因而,UTXO 完成办法比以太坊运用账户的办法要杂乱的多。

  4. 轻客户端:轻客户端能够随时经过沿指定方向扫描状况树来拜访与账户相关的一切数据。在 UTXO 范式中,每笔买卖需求用到的引证都不同,这关于长时刻运转并运用了上文提到的 UTXO 根状况传达机制的 dapp 运用来说,无疑是深重的。

咱们以为,账户的优点大大超过了其他办法,尤其是关于咱们想要支撑的、可包括恣意状况和代码的 dapp 运用而言。别的,本着 “没有特色便是最大的特色” 的指导准则,咱们以为假如用户真的关心私密性,则能够经过合约中的签名数据包协议来树立一个加密 “混币器(mixer and coinjoin)” 混杂支付途径。

账户办法的一个弱点是:为了阻挠重放进犯(replay attack,指让同一笔买卖重复履行),每笔买卖有必要有一个 “nonce”(流水号)。因而,每个账户都要有一个实时更新的 nonce 值,每一笔新买卖都在账户 nonce 值上递增 1 作为自己的 nonce(并在买卖处理之后按此值更新账户的 nonce 值)(校正注:在账户形式下,假如买卖不附带这种耗费性的标识符,买卖就可被重复处理,这样接纳账户能够一遍又一遍地收账且不必支付任何价值,而发账的账户会被吸干;以太坊账户的 nonce 随所主张的买卖得到处理而递增,就处理了这个问题)。这就意味着,即使不再运用的账户,也不能从账户状况中移除。处理这个问题的一个简略办法是让买卖包括一个区块号,使它们在一段时刻后就无法再被重放,并且每隔一段时刻段重置 nonce。

若要在状况中删除某个账户(比方长期不运用的账户),就有必要先 “ping” 出它们来,而完好扫描区块链协议的开销是十分大的。在1.0上咱们没有完成这个机制,1.1及以上版别或许会运用这个机制。

校正注:这便是以太坊日后面对的 “状况爆破” 问题的技能原因:一切状况数据有必要完好保存,无法合理地删除账户。作为一种区块链协议,以太坊的节点不仅要对业务(买卖)的次序达到一致,还要对大局状况达到一致(表现形式便是区块头里需求包括状况根。因而,若要删除状况,也需求全网的一致,否则会陷入分裂。

校正注:这种以 nonce 来符号账户买卖次序的做法,也使得用户的买卖有必要次序履行,假如一笔买卖无法得到处理,运用后续 nonce 的买卖也无法得到处理。关于 “加速” 已发出的买卖的上链进展,见这篇文章。

默克尔帕特里夏树(MPT)

默克尔帕特里夏树(Merkle Patricia tree/trie),由 Alan Reiner 提出设想,并在瑞波协议中得到完成,是以太坊的首要数据结构,用于存储一切账户状况,以及每个区块中的买卖和收据数据。MPT 是默克尔树和帕特里夏树的结合,结合这两种树创立的结构具有以下特色:

  1. 任一组 键-值对 所对应的根哈希值都是仅有的,想要谎报某个 键值对 存在于某棵树上是必定会被识破的(除非进犯者具有约 2^128 的算力)。

  2. 增、删、改 一个键值对的时刻杂乱度是对数等级。

MPT为咱们供给了一个高效、易更新、且代表整个状况树的 “指纹” 。关于MPT更详细描绘:https://github.com/ethereum/wiki/wiki/Patricia-Tree。

MPT的详细规划决议计划如下:

  1. 有两类节点:KV 节点和离散节点。KV节点的存在提高了功率,由于假如在特定区域树是稀少的,KV节点可作为一个 “捷径” 来紧缩树的高度(阅览 MPT 的胪陈可了解更多细节)。

  2. 离散节点是十六进制,不是二进制:这样让查找更有功率,咱们现在认识到这种挑选并不理想,由于十六进制树的查找功率在二进制中能够经过批次存储节点来模拟。可是,MPT 树结构的完成是十分容易出错的,最终至少会造成状况根不匹配,所以咱们决议搁置改变,比及 1.1 版别再说。

  3. 空值(empty value)与非成员(non-membership)之间没有差异:这样做是为了简化逻辑,以太坊中未启用的账户的值(余额)默以为 0,空字符串也用 0 表明。但是,需求着重的是,这样做牺牲了一些通用性,因而也不是最优的。

  4. 终节点(terminating)和非终节点的差异:技能上,标识一个节点 “是否是终节点” 是没必要的,由于以太坊中一切的树都被用于存储固定长度(即键的长度)的数据,但为了添加通用性,咱们仍是会添加这个标识,以希望以太坊的 MPT 的完成办法能够被其他密码学钱银原样选用。

  5. 在 “安全树”(状况树和账户存储树)中选用 SHA3(k) 作为键:运用 SHA3(k),想要经过生成许多的账户(账户最多可让状况树高达 64 层!)并重复调用 SLOAD 和 SSTORE 操作码来 DoS 进犯的难度会大大提高。留意,这也让枚举树变得更困难;假如要使你的客户端具有枚举的功用,最简略的办法便是保护一个映射 sha3(k) -> k 的数据库。

校正注:这儿的意思是,假如运用 k 作为默克尔树存储数据的键,其散布或许很稀少,而进犯者能够容易地规划出需求很深的树途径来存储的账户,并对这些账户重复调用状况拜访操作,以此造成网络中的节点超负荷运转,可是,哈希函数的结果是随机散布的,以 sha3(k) 作为键能够使键的散布较为均匀,树高也会较矮)。

这种特性也是有得有失,这一方面意味着 DoS 进犯会变得更困难,另一方面,也使得一个区块中的买卖的状况树拜访途径,很少有重合的,因而每次查找都是杂乱度最差的情形。

此外,这也使得 MPT 不宜完成 “无状况性”(区块本身带着验证所需的数据、验证者无需具有大局状况),由于状况拜访的途径不重合,依据的空间功率也是最差情形。当然,也能够说,默克尔树依据的空间功率本身也不够高

RLP

RLP(recursive length prefix):递归长度前缀。

RLP 编码是以太坊中首要的序列化格局,它的运用无处不在:区块、买卖、账户状况以及网络协议音讯。详见 RLP 正式描绘: https://github.com/ethereum/wiki/wiki/RLP

RLP 旨在成为高度简化的序列化格局,它仅有的目的是存储嵌套的字节数组 3。不同于 protobuf、BSON 等现有的处理计划,RLP并不界说任何指定的数据类型,如 Boolean(布尔值)、float(浮点数)、double 或许 integer(整数)。它只是是以嵌套数组的形式存储结构体,由协议来确定数组的含义。RLP 也没有显式支撑 map 调集,半官方的主张是选用 [[k1, v1], [k2, v2], ...] 的嵌套数组来表明键值对调集,k1,k2 ... 按照字符串的规范排序。

与 RLP 具有相同功用的计划是 protobuf 或 BSON,它们是一向被运用的算法。但是,以太坊中,咱们更偏向于运用 RLP,由于:(1)它易于完成;(2)肯定保证字节的一致性。

许多言语的键值对调集没有明确的排序,并且浮点格局有许多特殊情况,这或许造成相同数据却发生不同编码和不同哈希值。经过内部开发协议,咱们能保证它是带着这些方针规划的(这是一般准则,也适用于代码的其他部分,如虚拟机)。BitTorrent 运用的编码办法 bencode 也许能够替代 RLP。不过它选用的是十进制的编码办法,与选用二进制的 RLP 比较,略微差劲了点。

紧缩算法

网络协议和数据库都选用了一个自界说的紧缩算法来存储数据。该算法可描绘为:对 0 运用行程编码 4 并一起保留其他值(除了一些特殊情况如 sha3(' ') ),举例如下:

>>> compress('horse')'horse'>>> compress('donkey dragon 1231231243')'donkey dragon 1231231243'>>> compress('\xf8\xaf\xf8\xab\xa0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xbehttps://bicoin8.com/wp-content/uploads/2023/04/202304211cHpE0.jpgb\xd5\xcd\x8d\x87\x97')'\xf8\xaf\xf8\xab\xa0\xfe\x9e\xbehttps://bicoin8.com/wp-content/uploads/2023/04/202304211cHpE0.jpgb\xd5\xcd\x8d\x87\x97'>>> compress("\xc5\xd2F\x01\x86\xf7#<\x92~}\xb2\xdc\xc7\x03\xc0\xe5\x00\xb6S\xca\x82';https://bicoin8.com/wp-content/uploads/2023/04/202304211cHpE0.jpg\xfa\xd8\x04]\x85\xa4p")‘\xfe\x01'

紧缩算法存在之前,以太坊协议的许多当地都有一些特殊情况,例如,sha3 经常被重界说使得 sha3(' ')=' ',这样不需求在账户中存储代码,能够节约 64 字节。但是,最近一切这些使得以太坊数据结构变得臃肿的特殊情况都被删除了,取而代之的是将数据保存函数添加到区块链协议之外的层,也便是将其放入网络协议以及将其插入用户数据库完成。这样添加了模块化才能,简化了一致层,使得对紧缩算法的继续更新布置起来相对简略(例如:可经过网络协议的版别号来差异、布置)。

树(trie)的运用

提示:了解这部分的知识需求读者了解布隆过滤器 5 的原理。简介可见:http://en.wikipedia.org/wiki/Bloom_filter

以太坊区块链中每个区块头都包括指向三个树的指针:状况树、买卖树、收据树。

  • 状况树代表处理完该区块后的整个状况;

  • 买卖树代表区块中一切买卖,这些买卖由 index 索引作为key;(例如,k0:第一个履行的买卖,k1:第二个履行的买卖)

  • 收据树代表每笔买卖相应的收据。

买卖的收据是一个 RLP 编码的数据结构:

[ medstate, gas_used, logbloom, logs ]其中:
  • medstate:买卖处理后,状况树的根;

  • gas_used:买卖处理后,gas 的运用量;

  • logs:是许多 [address, [topic1, topic2...], data] 元素的列表。这些元素由买卖履行期间调用的操作码 LOG0 ... LOG4 生成(包括主调用和子调用);address 是生成日志的合约的地址;topics 是最多 4 个 32 字节的值;data 是恣意巨细的字节数组;

  • logbloom:买卖中一切 logs 的 address 和 topics 组成的布隆过滤器。

区块头中也存在一个布隆过滤器,它是区块中买卖的一切布隆过滤器的或运算(OR)结果。这样的构造使得以太坊协议对轻客户端友好得无以复加。

注释

  1. UTXO:unspent transaction outputs,字面了解是:未花费的买卖输出,也即未被任何买卖引证为输入的买卖输出。它是比特币协议中用于存储价值(一切权)信息的数据结构。—— 校正注

  2. Nonce,Number used once 或 Number once 的缩写,在密码学中 Nonce 是一个只被运用一次的恣意或非重复的随机数值,在加密技能中的初始向量和加密哈希函数都发挥着重要作用,在各类验证协议的通信运用中保证验证信息不被重复运用以对抗重放进犯(Replay Attack)。—— 译者注

  3. 嵌套数组:创立一个数组,并运用其他数组填充该数组。如数组 pets:

    var cats : String[] = ["Cat","Beansprout", "Pumpkin", "Max"];
    var dogs : String[] = ["Dog","Oly","Sib"];
    var pets : String = [cats, dogs];

    —— 译者注

  4. 行程编码(run-length-encoding):一种计算编码。首要技能是检测重复的比特或字符序列,并用它们的呈现次数取而代之。(百度百科)—— 译者注

  5. 布隆过滤器:由 Howard Bloom 在 1970 年提出的二进制向量数据结构,它具有很好的空间和时刻功率,被用来检测一个元素是不是调集中的一个成员。(百度百科)—— 译者注

视野开拓

地主不可能区别对待不同生产效率的佃农,即使这种区别对待不花任何成本,因为雇用边际外的佃农(生产力较低的佃农)的地主将会把生产力较高的佃农从实行区别对待的地主那里争取过来。-《佃农理论》

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注