主页 > 下载imtoken钱包官方 > 以太坊的区块结构是怎样的?默克尔树在以太坊中是如何工作的

以太坊的区块结构是怎样的?默克尔树在以太坊中是如何工作的

下载imtoken钱包官方 2023-11-30 05:13:38

大家好! 本文旨在介绍以太坊黄皮书中的一些概念。 通过这篇文章,我们将了解以太坊的一些主要组成部分以及它们在整个系统中的作用,同时也会简要讨论一下以太坊中默克尔树的工作原理。

希望屏幕前的你看完后能明白什么是默克尔树,以及它在以太坊中的作用; 能够理解“世界状态”和“账户状态”的概念; 可以勾勒出您心中的交易和领域。 块的结构。

默克尔树

在讨论以太坊的主要数据对象之前,我想先简单介绍一下什么是 Merkle 树,以及使其发挥作用的属性。

黄皮书假设世界状态和交易由自定义的 Merkle-Patricia 树维护。 附录 D 描述了这个数据结构。

Merkle-Patricia 树有许多有趣的特性,如果您想了解更多关于它们在以太坊中的用途,我推荐阅读这篇文章。

在 Merkle 树中,叶节点保存块数据的哈希值,而非叶节点保存其子节点的哈希值。

image.png

-Merkle树示意图(包括节点及节点之间的关系)-

Merkle 树指向的数据的任何变化都会引起节点哈希的变化。 由于每个父节点存储的哈希值依赖于子节点包含的数据,所以子节点中数据的变化会引起父节点哈希的变化。 而这样的影响是一个连锁反应,从叶节点到根节点。 因此,叶节点指向的数据发生变化,就会引起根节点存储的哈希发生变化。 从以上结构特征中,我们可以推导出两个重要的属性:

1、判断两棵Merkle树指向的数据是否完全相同时,不需要比较每个叶子节点,只需要比较根节点存储的hash即可。

2.判断一个特定的数据是否被一棵树指向时,我们可以使用Merkle证明技术。 无需在此详细介绍该技术,只要知道这是证明数据存在于 Merkle 树中的一种简单、有效的方法即可。

第一个属性重要的是,我们可以只用根节点的哈希值来标记某一时刻整棵树指向的数据。 这意味着只需要保存根节点的哈希值就可以标记区块(不需要存储区块链中的所有数据),数据不可篡改。

至此我们已经明确了根节点hash在Merkle树中的作用,下面来介绍一下以太坊中的主要对象。

世界状况

世界状态是从地址(账户)到账户状态的映射。 虽然世界状态没有存储在区块链上,但在黄皮书的描述中,世界状态也是由一棵树保存的(这棵树也叫状态数据库或状态树)。 世界状态可以看作是一个全局状态,随着交易的执行而不断更新。 以太坊就像一台去中心化的计算机,世界的状态就是这台计算机的硬盘。

以太坊中的所有账户信息都反映在世界状态中,并由世界状态树保存。 如果你想知道一个账户的余额,或者智能合约的当前状态,你需要查询世界状态树来获取账户的具体状态信息。 我还将在下面简要描述这些信息是如何存储的。

image.png

-世界状态树和账户存储-

帐户状态

以太坊 挖矿 划算_以太坊挖矿原理_n卡以太坊挖矿教程

以太坊中有两种类型的账户:外部拥有账户(EOA)和合约账户。 我们用来收发以太币和部署智能合约的账户是EOA账户,部署智能合约时自动生成的账户是合约账户。 每个智能合约都有自己独特的以太坊账户。

账户状态反映了以太坊账户的各种信息。 例如,它存储了当前账户的以太坊余额信息,当前账户发送的交易数量……每个账户都有一个账户状态。

让我们看看帐户状态中包含的内容:

随机数

从这个地址发送的交易数量(如果当前是 EOA 账户)或者这个账户产生的合约创建操作(暂时先不管合约创建操作是什么)。

平衡

该账户拥有的以太币数量(以 Wei 为单位)。

存储根

账户存储树根节点的哈希值(后面会介绍什么是账户存储)。

代码哈希

对于合约账户,正是这个账户存储了 EVM 代码的哈希值。 对于 EOA 帐户以太坊挖矿原理,将此留空。

账户状态中一个不可忽视的细节是所有对象,包括上述对象,都是可变的(除了codeHash)。 例如,当一个账户向另一个账户发送以太币时,除了nonce增加外,该账户的余额也会相应发生变化。

codeHash 的不变性使得一旦部署有漏洞的智能合约就无法修复和更新。 相应地,只能部署一个新合约(易受攻击的版本将始终存在于区块链上)。 这就是为什么有必要使用 Truffle 进行智能合约开发和部署,并在使用 Solidity 编程时遵循最佳实践。

帐户存储树是一种保存与帐户关联的数据的结构。 此项仅适用于合约账户,而在EOA中,storageRoot留空,codeHash为一串空字符串的hash值。 所有智能合约数据以 32 字节映射的形式存储在账户存储树中。 账户状态树如何维护合约数据这里不再赘述。 如果读者对其内部实现感兴趣,强烈推荐阅读本文。 账户状态中的storageRoot区域负责维护账户存储树根节点的哈希值。

image.png

-账户状态和账户存储树-

贸易

事务驱动从当前状态到下一个状态的转换。 以太坊中存在三种交易:

1. 在 EOA 之间转移价值的交易(例如,改变发送者和接收者的余额大小)。

以太坊挖矿原理_以太坊 挖矿 划算_n卡以太坊挖矿教程

2. 发送消息调用合约的事务(例如通过发送消息调用触发setter方法在合约中设置一个值)。

3.部署合约的交易(从而创建合约账户)。

(从技术角度来说,前两笔交易是一样的……都是通过消息调用改变账户状态的交易,只不过一个是EOA账户,一个是合约账户。这里,交易分为三种,方便读者理解。)

一个事务由以下部分组成:

随机数

该账户发出的交易号数(校对注:可以大致理解为“这是该账户的第一笔交易”)。

汽油价格

在执行此交易、执行计算时每单位天然气支付的费用(以 Wei 为单位)。

气体限制

执行此交易时可以使用的最大气体量。

如果此交易是为了发送以太币,这里是接收以太币的 EOA 地址。

如果此交易用于向合约发送消息(例如,调用智能合约中的方法),则这里是合约的地址。

如果此交易用于创建合约,则此处的值为空。

价值

如果交易是发送或接收以太币,这里是接收账户中以 Wei 为单位的代币数量。

如果此交易用于向合约发送消息调用,则这里是支付给接收此消息的智能合约的 Wei 金额。

如果此交易用于创建合约,则这里是合约初始化时存储在帐户中的 Wei 中的以太币数量。

v, r, s

以太坊 挖矿 划算_以太坊挖矿原理_n卡以太坊挖矿教程

交易加密签名中使用的值,可用于确定交易的发送方。

数据(仅用于价值传输和向智能合约发送消息)

消息调用附带的输入数据(比如你要执行智能合约中的setter方法,数据区要包含setter方法的标识和你要设置的参数值)。

init(仅用于合约创建)

用于初始化合约的 EVM 代码。

不要想着一下子消化这些概念……你必须对以太坊的内部机制有更深入的了解,才能真正理解和使用数据区和初始化区等概念。

正如您所料,区块中的所有交易也存储在默克尔树中。 而这棵树的根节点的hash值就是由区块头保存的! 让我们分析一下以太坊区块结构。

堵塞

一个区块分为区块头和区块体两部分。

区块头是以太坊区块链的一部分。 它保存了前一个区块(也称为父区块)的哈希值,通过区块头的连接形成密码学背书的链。

区块体包含记录在该区块中的一系列交易,以及叔块(ommer)区块头的列表。 如果你想了解更多关于叔块的知识,我推荐阅读这篇文章。

640 (1).png

-以太坊区块抽象示意图-

下面介绍一下区块头包括哪些部分

父哈希

前一个区块的区块头哈希。 每个区块都包含之前区块的哈希值,一直追溯到链上的创世区块。 这也是维护数据不可篡改的结构设计(对前一个区块的任何篡改都会影响后续所有区块的哈希值)。

哈希表

叔块头和部分块体的哈希值。

受益人

以太坊挖矿原理_以太坊 挖矿 划算_n卡以太坊挖矿教程

开采该区块赚取收入的以太坊账户。

状态根

世界状态树根节点的哈希值(在所有交易执行后)。

交易根

交易树根节点的哈希值。 这棵树包含了区块体的所有交易。

收据根

每当执行交易时,以太坊都会生成与结果对应的交易收据。 这是交易收据树根节点的哈希值。

原木绽放

Bloom filter,用于判断某条日志是否已经由某个区块的交易产生(如果你对这方面感兴趣,可以参考Stack Overflow上的这个回答)。 这避免了将日志信息存储在块中(节省了大量空间)。

困难

该区块的难度值。 这是衡量当前区块挖掘难度的指标(这里不介绍这个概念的细节和计算)。

数字

前导块的总数。 这表示区块链的高度(即区块链上有多少块)。 创世块的编号为0。

气体限制

每笔交易都需要消耗 gas。 gas limit 表示该区块记录的所有交易可以使用的gas总量。 这是一种限制区块内交易数量的方法。

使用的气体

区块中每笔交易实际消耗的gas总量。

时间戳

区块创建时的 Unix 时间戳。 请记住,由于以太坊网络的去中心化性质,我们不能相信这个值,尤其是在编写涉及与时间相关的业务逻辑的智能合约时。

以太坊挖矿原理_n卡以太坊挖矿教程_以太坊 挖矿 划算

额外数据

可以输入任何内容的可变长度字节数组。 当矿工创建区块时,他们可以在这个区域添加任何东西。

混合哈希

用于验证一个区块是否真正记录在链上的哈希值(如果你想真正理解这个概念,推荐阅读这篇文章 Ethash 工作量证明函数)。

随机数

和mixHash一样,用来验证区块是否真的记录在链上。

哎呀……弄得我嘴巴都疼了……建议大家慢慢吸收吧! 但还是那句话,读这篇文章不应该以记住每一个名词和它的作用为目的(这些你在google上都能找到)。 我写这篇文章的初衷是想通俗易懂(至少比黄皮书简单)介绍以太坊对象的方方面面,帮助新手理解那些专业术语代表什么。 将本文视为“以愚蠢的方式学习以太坊对象”!

综上所述

让我们简要回顾一下我们学到了什么! 总的来说,以太坊中有四种前缀树:

世界状态树包括从地址到账户状态的映射。 世界状态树根节点的哈希值由区块保存(在stateRoot字段中),表示区块创建时的当前状态。 全网只有一棵世界状态树。

账户存储树存储与某个智能合约相关的数据信息。 账户存储树根节点的哈希值(在storageRoot字段中)由账户状态保存。 每个账户都有一个账户存储树。

交易树包含一个区块中的所有交易信息。 交易树根节点的哈希值由区块头保存(在transactionsRoot区域)。 每个区块都有一个交易树。

交易回执树包含一个区块中所有交易的回执信息。 交易回执树根节点的哈希值也由区块头保存(在receiptsRoot区); 每个区块都有对应的交易收据树。

我们今天讨论的对象是:

世界现状:分布式计算机以太坊的硬盘。 它是从地址到帐户状态的映射。

账户状态:存储每个以太坊账户的状态信息。 账户状态还持有账户状态树的 storageRoot,其中包含账户的存储数据。

事务:标记系统中的状态转换。 它可以是资金转移、消息调用或合约部署。

块:包含指向前一个块(parentHash)的链接以太坊挖矿原理,并保存在执行时会在系统中产生新状态的交易。 区块中还保存了stateRoot、transactionRoot、receiptsRoot、世界状态树的根节点hash、交易树和对应的交易收据树。

我想用一张图来表示文章中提到的各种概念信息。

image.png

-以太坊的区块、交易、账户状态对象和默克尔树-