尽管以太坊的许多理念在早先的加密货币(如比特币)上已经运用并测试了5年之久,但从处理某些协议功能上来说,以太坊的处理方式与常见方式仍有许多不同。很多时候,以太坊会被用来建立全新的经济方法,因为它具有许多其他系统不具备的功能。本文会详细描述以太坊所有潜在的优点以及在构建以太坊协议过程中某些有争议的地。另外,也会指出我们的方案及替代方案潜在的风险。
原则
以太坊协议的设计遵循以下几点原则:
1.三明治复杂模型
我们认为以太坊的底层协议应尽可能的简单,接口设计应易于理解,那些不可避免的复杂部分应放入中间层。中间层不是核心共识的一部分,且对最终用户不可见,它包含:高级语言编译器、参数序列化和反序列化脚本、存储数据结构模型、leveldb存储接口以及线路协议等。当然,这样的设置也并非绝对。
2.自由
不应限制用户使用以太坊协议,也不应试图优先支持或不支持某些以太坊合约或交易。这一点与“网络中立”概念背后的指导原则相似。比特币交易协议就没有遵循这一原则。在比特币交易协议中,并不鼓励为了“去除标签”而使用区块链(如,数据存储,元协议)。某些情况下,对准协议进行明显修改会引起不法分子以未经授权方式使用区块链来攻击应用。因此,在以太坊,我们强烈建议设置交易费用,且用户使用区块链的步骤越多,交易费用也就越多(类似庇古税)。这样,既可以将交易费用作为合法矿工的奖励,又能让那些不法分子付出代价,一举两得。
3.泛化
以太坊协议的特性和操作码应最大限度地体现低层次的概念(就像基本粒子一样),以便它们可以随意组合。因此,通过剥离那些不需要的功能,使低层次的概念更加高效。遵循这一原则的例子是,我们选择LOG操作码作为向dapps提供信息的方式,而不是像之前那样记录下所有交易和消息信息。在早先,“消息(message)”的概念完完全全是多种概念的集合,它包含“函数调用(function call)”和“外在观察者感兴趣的事情(event interesting to outside watchers)”,而两者是完全可以分离开来的。
4.没有特点就是最大的特性点
为了遵循泛化原则,我们拒绝将那些高级用例内嵌为协议的一部分,哪怕是经常使用的用例,也绝不这么做。如果人们真的想实现这些用例,可以在合约内创建子协议(如,基于以太坊的子货币,比特币/莱特币/狗币的侧链等)。比如,在以太坊中就缺少类似比特币中的“时间锁定”功能。但是,通过以下协议可以模拟出这个功能:用户发送签名数据包到特定的合约中处理,如果数据包在特定合约中有效,则执行相应的函数。
5.没有风险规避机制
如果风险的增加带来了可观的好处,我们愿意承担更高的风险(例如,广义状态转换,区块时间提升50倍,共识效率)。
这些原则指导着以太坊的发展,但它们并不是绝对的;某些情况下,为了减少开发时间或者不希望一次作出过多改变,也会使我们推迟作出某些修改,把它留到将来的版本中去修改。
区块链层协议
本节对以太坊中区块链层协议的改变进行了描述,包括区块和交易是如何工作的、数据如何序列化及存储、账户背后的机制。
账户 ,而非UTXO①
比特币及其许多衍生品,都将用户的余额信息存储在UTXO结构中,系统的整个状态由一系列的“有效的输出”组成(可以将这些“有效的输出”想象成钱币)。每个UTXO都有拥有者和自身的价值属性。一笔交易在消费若干个UTXO同时也会生成若干个新的UTXO。“有效的输出”中有效需满足下面几点约束:
1.每个被引用的输入必须有效,且未被使用过;
2.交易的签名必须与每笔输入的所有者签名匹配;
3.输入的总值必须等于或大于输出的总值。
因此,比特币系统中,用户的“余额”是该用户的私钥能够有效签名的所有UTXO的总和。下图展示了比特币系统中交易输入输出过程:
但是,以太坊抛弃了UTXO的方案,转而使用更简单的方法:采用状态(state)的概念存储一系列账户,每个账户都有自己的余额,以及以太坊特有的数据(代码或内部存储器)。如果交易发起方的账户余额足够支付交易费用,则交易有效,那么发起方账户会扣除相应金额,而接受账户则计入该金额。某些情况下,接受账户内有需要执行的代码,则交易会触发该代码的执行,那么账户的内部存储器可能就会发生变化,甚至可能会创建额外的信息发送给其他账户,从而导致新的交易发生。
尽管以太坊没有采用UTXO的概念,但UTXO也不乏有一些优点:
1.较高程度的隐私保护
如果用户每次交易都使用一个新的地址,那么账户之间的相互关联就很困难。这样做适用于对安全性要求高的货币系统,但对任何dapp应用来说就不合适了。因为dapp通常需要跟踪用户复杂的绑定状态,而dapp的状态并不能像货币系统中的状态那样简单地划分。
2.潜在地可扩展性
UTXO在理论上可扩展性更好。因为我们只能依靠那些金融货币拥有者来维护能够证明货币所有权的默克尔树,即使所有的人(包括数据的拥有者)都遗忘了某一数据,真正受损也只有数据的拥有者,其他人不受影响。
在以太坊账户系统中,如果一个账户对应在默克尔树中信息被所有人都丢失了,那么该账户将无法处理任何能够影响它的消息,包括发送给它的消息,它也无法处理。
不过,并非只有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②字节数)
但实际节约并没有这么大,因为账户需要被存储在帕特里夏树中。另外以太坊中交易也比比特币中的更小(以太坊中100字节,比特币中200-250字节),因为每次交易只需要生成一次引用,一次签名,以及一个输出。
2.可替代性更高
在UTXO结构中,“有效输出”的源码实现中没有区块链层的概念,所以不管是在技术还是法律上,通过建立一个红名单/黑名单,并依据的这些“有效输出”的来源区分它们并不是很实际。
3.简单
以太坊编码更简单、更易于理解,尤其是在涉及到复杂脚本时。尽管任何去中心化应用都可以用UTXO方式来实现,但这种方式实质上是通过赋予一个脚本限制给定的UTXO能够使用以及请求的UTXO的种类的方式来实现,包括脚本评估的应用更改根状态的默克尔树证明。因此,UTXO实现方式比以太坊使用账户的方式要复杂的多。
4.轻客户端
轻客户端可以随时通过沿指定方向扫描状态树来访问与账户相关的所有数据。在UTXO方式中,引用随着每个交易的变化而变化,这对于长时间运行并使用了上文提到的UTXO根状态传播机制的dapp应用来说,无疑是繁重的。
我们认为,账户的好处大大超过了其他方式,尤其是对于我们正在处理的包含任意状态和代码的dapp应用而言。另外,本着“没有特点就是最大的特点”的指导原则,我们认为如果用户真的关心私密性,则可以通过合约中的签名数据包协议来建立一个加密“混合器”进行加密。
账户方式的一个弱点是:为了阻止重播攻击,每笔交易必须有nonce,这就使得账户需要跟踪nonce的使用情况,并且只有在nonce最后使用后且值为1时才接受交易。这就意味着,即使不再使用的账户,也不能从账户状态中移除。解决这个问题的一个简单方法是让交易包含一个区块号,使它们在几个时间段内不重复,并且每个时间段重置nonce。由于完全扫描账户的开销太大,所以为了删除未使用的账户,矿工或用户需要通过“Ping”操作来实现。在1.0上我们没有实现这个机制,1.1及以上版本可能会使用这个机制。
默克尔帕特里夏树
默克尔帕特里夏树(Merkle Patricia tree/trie),由Alan Reiner提出设想,并在瑞波协议中得到实现,是以太坊的主要数据结构,用于存储所有账户状态,以及每个区块中的交易和收据数据。MPT是默克尔树和帕特里夏树的结合缩写,结合这两种