本文简要比较了以太坊和比特币在数据结构五方面的差异:数据结构、区块结构、交易、交易费、状态与账户类型。

原文标题:《引介 | 简要比较以太坊和比特币的数据结构》
作者:Eman Herawy
翻译 & 校对:stormpang & 阿剑

引介:以太坊为什么是第二代区块链?

2017 年末,当我开始了解区块链的时候,我注意到以太坊非常受关注。 我总是看到别人说:比特币是第一代区块链,而以太坊是第二代区块链。读了许多关于比特币与以太坊间对比的文章之后,我明白了 「为什么」:比特币是一种使用有限脚本语言来构建去中心化支付系统的加密货币,但是以太坊不仅如此。

以太坊不仅仅是一种加密货币,还是一种全球化去中心计算基础设施,能够执行智能合约与程序代码(使用多种编程语言编写)进而控制数字资产。在以太坊平台之上,开发者可以自行构建去中心化应用(dApp)。我对去中心化应用开发(dApp)非常感兴趣,因此我并没有花很多时间阅读以太坊黄皮书,去理解其具体构建原理(「How」)。

我在 Devcon v 期间开始阅读以太坊黄皮书的时候,我不仅明白了为什么以太坊是第二代区块链,而且被这些最终将奇妙观念化为现实的伟大思想打动。

让我们深入了解一下几个主要的部分:

  • 数据结构
  • 区块结构
  • 交易
  • 以太坊中 Gas & 比特币中交易费
  • 状态 & 账户类型

数据结构

比特币使用了 Merkel 树(由密码学哈希值组成的二叉树),而以太坊使用了改良的 Merkel Patricia 树。如果你想更深入地了解,可以 观看 该视频。

插播:Medium 不支持下标格式,如果你想阅读本文含有黄皮书中某些符号的版本,请 查看 该文档。

区块

让我们来看一下以太坊区块结构。

引介 | 简要比较以太坊和比特币的数据结构来源:解读以太坊黄皮书

区块包含:

区块头

请注意,比特币区块头中只有 1 棵 Merkel 树,以太坊区块头中有 4 棵(State Trie - 状态树,Storage Trie - 存储树,Transaction Trie - 交易树 & Receipts Trie - 收据树)。以太坊区块头包含:

  1. parentHash:父块区块头哈希值。
  2. ommersHash:当前区块的叔块列表的哈希值。
  3. beneficiary:矿工用于接收交易费的以太坊的地址。
  4. stateRoot:在本区块及其交易执行完成后,状态树的根节点哈希值。
  5. transactionsRoot:由区块交易列表中全部交易构成的交易树的根节点哈希值。
  6. receiptsRoot:由交易列表中每笔交易的收据构成的收据树的根节点哈希值。每一条交易收据(BR 数组中的第 i 项对应第 i 笔交易的收据)都存储在键值索引的收据树中,树的根节点哈希值存储在区块头中。这对生成零知识证明或是索引与搜索都非常有用。交易收据 R 是以下四项的元组:
    1. Ru:交易执行后包含该交易收据的区块累计消耗 gas 量。
    2. Rl:交易执行期间所产生的日志集合。
    3. Rb:依据日志信息构建的 Bloom 过滤器。
    4. 交易状态码。
  7. logsBloom:该字段用于存储以太坊事件(Event),可依据日志记录器地址或日志主题进行索引。
  8. difficulty:本区块的难度水平,根据前一个区块难度水平及时间戳计算得来。
  9. number:所有先前区块的个数(即本区块区块号),创世区块的 number 字段为 0;
  10. gasLimit:当前区块允许的最大 gas 消耗量。
  11. gasUsed:当前区块内所有交易所消耗的 gas 总量。
  12. timestamp:区块初始化时的 Unix 时间。
  13. extraData:可供矿工添加任意数据的字节数组
  14. mixHash:用于验证区块是否被正确处理的哈希值。
  15. nonce:用于验证区块是否被正确处理的哈希值。(功能与 mixHash 相同)

区块体

  1. 叔区块头(Ommer Block Header)列表
  2. 交易序列:本区块中交易列表。

整体有效性:要确定一个区块的有效性,当且仅当其满足以下几个条件:区块的叔区块列表哈希、交易区块哈希以及给定交易内部一致打包区块的过程包括四个阶段:

  • 验证(或确定,如果正在挖矿的话)叔区块列表:
    1. 一个区块必须指定一个父区块,并且必须指定 0 个或多个叔区块
    2. 区块 B 中包含的叔区块必须具有以下性质:
      a. 区块 B 的叔区块必须是区块 B 第 k 代祖先区块的直接子块,其中 2 <= k <= 7。
      b. 区块 B 的叔区块不能是区块 B 的祖先。
      c. 叔区块的区块头必须有效,但是无需被验证也无需是有效区块。
      d. 叔区块必须与先前区块打包的叔区块以及本区块的其他叔区块不同(防止重复打包)。
  • 交易验证(或确定,如果正在挖矿的话):区块头中 gasUsed 的数值必须与最后一笔交易打包后区块累计的 gas 消耗量一致。
  • 申请奖励:如果存在叔区块,则叔区块可用于增加本区块受益人与产生叔区块的受益人的账户余额。当同一区块高度有多个有效区块时,叔区块机制(Ommer Block)有助于激励矿工维护网络正常运行。叔区块奖励划分规则:叔区块获得其基础奖励的 87.5%,包含该叔区块的主链区块获得基础奖励的 3.125%。不过,叔块受益人和侄块受益人都不能得到叔块中的交易手续费(译者注:因为叔块中的交易会被视为无效,回到交易池中等待打包)。
  • 验证(或如果正在挖矿的话,计算出有效的)状态以及区块 nonce。通过检查最终状态是否与区块头中 stateRoot 一致即可检验。

比特币中区块结构

引介 | 简要比较以太坊和比特币的数据结构来源:5minuteblockchain

区块包含:

区块头

  1. timestamp:区块初始化时的 Unix 时间。
  2. nonce:用于 PoW 算法的计数器。
  3. Version:用于追踪软件或协议升级的版本号。
  4. Previous:链上父区块哈希值。
  5. Merkel Root:本区块中交易所构造的 Merkel 树树根的哈希值。
  6. Difficulty:产生该区块所必须的难度值,该值在挖矿过程中根据该区块前一定数量的区块产生所用时间动态调整。

区块体

  1. 交易序列:本区块中包含交易的列表

交易

以太坊交易

以太坊中包含两类交易(事务):消息调用与合约创建。每笔交易的执行都将引起机器状态 μ (μ 是一种临时状态,包括了在区块添加至世界状态前所有计算中必须的变化)的变化。每笔交易包括以下字段:

  1. nonce:发送方先前发出的交易总数量。
  2. gasPrice:单位 gas 消耗需支付给网络的以太币(单位:Wei)数量。
  3. gasLimit:该交易执行过程中能够消耗的最大 gas 数量。
  4. to:消息调用接收方地址。
  5. value:发送方转移给消息接收方的以太币数量(单位:Wei)。
  6. v, r, s:交易签名相关字段。
  7. Init:(仅用于合约创建交易)不限制大小的字节数组,包含合约创建所需的 EVM 字节码。
  8. data:不限制大小的字节数组,用于指定消息调用交易的输入数据。

比特币交易

引介 | 简要比较以太坊和比特币的数据结构来源:gomedici

  • 交易头
    • 比特币协议版本
    • 输入数量
    • 输出数量
    • 区块锁定时间(不想让交易被立即打包时设置)
  • 一个或多个输入(UTXO)
    • 先前交易的哈希值(UTXO 输入即为为先前交易的 UTXO 输出)
    • 先前交易的输出的索引号。
    • 解锁脚本(称为 ‘scriptSig’)以及解锁脚本长度,用于证明该 UTXO 的所有权。
  • 一个或多个输出(UTXO)
    • 发送方给接收方发送的比特币数量。
    • 锁定脚本(称作 ‘scriptPubKey’)以及锁定脚本长度。‘scriptPubKey’ 是一个条件公钥脚本。任何可以满足公钥脚本条件的人都可以花费该 UTXO 中的比特币。

以太坊的 Gas & 比特币的交易费

Ethereum Gas

由于以太坊是图灵完备的系统,为了避免计算资源被滥用,以太坊中所有编程计算操作都要收取交易费。计算就要投入成本,需要的计算资源越多则与之对应的交易费就越高。用于购买 gas 的以太币被转入受益者地址。如果(交易发送方)账户余额地址不能支付 gas 的费用,那么该交易就被认为是无效的。在以太坊平台中,只有执行交易的过程中才涉及 gas 消耗。每笔交易都有一个与之关联的具体 gas 消耗量。gasLimit 与 gasPrice 也在交易中指定。

  • gasLimit:发送方愿意支付用于交易执行的 gas 最大数量。gasLimit 的存在,有助于解决交易陷入无限循环而无法退出的情况。在交易执行之后,如果仍有 gas 剩余,那么这些 gas 将返回给发送方。但是,如果交易因为某种原因执行失败,gas 就不再退回。
  • gasPrice:gasPrice 是指 「你想支付多少以太币来购买一单位 gas」。交易发送方可以任意指定 gasPrice 的具体数值,然而,矿工也可以自由忽略一些 gasPrice 不符合他们需求的交易。

比特币交易费

比特币交易费是由矿工收取的一小笔款项。比特币交易费并不是必须的,但由于矿工可以自由忽略任意交易,添加手续费则可以激励矿工将你的交易打包进区块链中。比特币交易费的数值等于交易输入减去输出所得到的差值。

状态 & 账户类型

比特币

比特币地址是一个 ECDSA 公钥,该地址的余额并不保存在比特币区块链中。如果你想要知道如何查看比特币余额,个人钱包应用通过扫描区块链数据库,计算出与某一具体地址相关的所有 UTXO,进而求出该地址的比特币余额。

以太坊

以太坊区块链始终维护一个世界状态σ,其中包含了地址与账户状态的映射。

  • 以太坊包含两种类型的账户:
  1. 由私钥控制的外部持有账户(EOA)
  2. 由智能合约控制的合约账户(Contract Account)。
  • 账户状态σ [a]:账户状态存储在区块链之外的改良版 Merkle Patricia Trie 树中。如果你想更深入的了解状态数据库中 MPT 树是如何存储的,请观看该视频。账户状态包含四个字段:
    1. nonce:包含合约创建交易在内的由该地址发出的所有交易数量。
    2. balance:该地址持有的以太币数量(单位:Wei)。
    3. storageRoot:编码账户存储内容的 Merkel Patricia 树的根节点哈希。
    4. codeHash:(仅针对合约账户)存储在状态数据库中 EVM 字节码的哈希值。与其他字段不同,该字段是不可变的。

有兴趣看看黄皮书么

我确信你一定非常希望通过阅读黄皮书了解更多有关以太坊的设计细节,上文所提到的比特币与以太坊的不同仅是我的个人观点。但是,如果你真的下决心去读,可以参考我的经验,因为这并不是一件容易的事情。我记得当我告诉一个朋友我要开始阅读黄皮书并写一些相关博客的时候,他跟我说:

天呐!不可能的 :D。虽然很有教育意义,但是依旧是不可能的!

他是对的,我阅读以太坊黄皮书的目的是写一篇总结,就像我读完比特币白皮书一样,但是当我第一遍读完黄皮书的时候,写总结简直太难了。为了写一篇黄皮书总结,我断断续续读了 4 遍 :D

我第一遍读完黄皮书之后,我只能掌握大概 50%-60% 的内容,因为在阅读数学推导的时候我遇到了很大困难(「就像我朋友告诉的我那样 :D」)。但是,通过多次阅读黄皮书,我更深入地理解了以太坊的设计原理以及我先前在以太坊上开发去中心化应用时所遇到的一些 Bug。总的来说,我还是非常满意的。

以下是当时对我帮助很大的一些文章链接:

  • 这是我读过的最棒的解释黄皮书的文章(编者注:中译本在此《以太坊的工作原理》)。
  • 特别感谢我在 devcon 学者项目的同事 @shaqueilla.seale,她发给我了解读以太坊黄皮书系列 文章 [但这些文章并不完整,蓝过]
  • 以太坊中数据是如何 存储
  • 对我而言,黄皮书中最难理解的部分是:
    1. 代数符号,这个 答案 给了我很多帮助
    2. 约定部分,这个 gist 给了我很多帮助

来源链接:mp.weixin.qq.com