以太坊区块链系统主要组成部分详解

当前位置:首页 > 币圈百科 > 以太坊区块链系统主要组成部分详解

以太坊区块链系统主要组成部分详解

2022-11-15币圈百科530

以太坊模型表明

以太坊本质上是一个基于事务的状态机。在计算机科学中,一个?状态机?它指的是能够读取一系列输入,然后根据这些输入转化为新状态的东西。

根据以太坊的状态机,我们从创世态开始。这几乎就像一张白纸,网络中没有任何交易。当事务被执行时,这种起源状态将被转换成最终状态。在任何时刻,这个最终状态都代表以太坊的当前状态。

以太坊状态下有数百万笔交易。这些事务都被“分组”到一个块中。一个块包含一系列事务,每个块都与其前一个块相链接。

为了从一个状态转换到下一个状态,交易必须有效。为了使一个交易被认为是有效的,它必须通过一个验证过程,这就是挖掘。挖掘是一组节点(即计算机),它们使用自己的计算资源来创建包含有效事务的块。

之前,我们定义区块链是一个具有共享状态的单一事务机器。利用这个定义,我们可以知道正确的当前状态是一个全局真理,每个人都必须接受它。拥有多个状态(或链)会破坏这个系统,因为在“哪个是正确的状态”这个问题上不可能得到统一的结果。如果链分支,你可能有10个硬币在一条链上,20个硬币在一条链上,40个硬币在另一条链上。在这种情况下,没有办法确定哪个链是最“有效”的。

让我们更深入的了解一下以太坊系统的主要组成部分:

账户

状态(state)

损失和费用(燃气和费用)

交易

交易执行

采矿

工作证明

在开始之前,需要注意的是,每当我说某某人的散列时,我指的是KECC CAK-256?哈希,以太坊用的就是这个哈希算法。

帐户

以太坊的全局“共享状态”是由许多小对象(帐户)组成的,这些小对象可以通过消息传递架构相互交互。每个账户都有一个州和与之相关的20字节地址。

有两种类型的帐户:

外部拥有的帐户,由私钥控制,没有与之关联的代码。

合同账户,由其合同代码控制,并有与之相关的代码。

外部拥有的账户和合同账户之间的比较

了解外部拥有的账户和合同账户之间的基本区别很重要。外部拥有的帐户可以通过用自己的私钥创建和签署交易来向另一个外部拥有的帐户或合同帐户发送消息。在两个外部拥有的帐户之间传输的消息只是简单的值传递。但是从外部拥有的账户到合同账户的消息将激活合同账户的代码,允许它执行各种动作。(比如转移令牌、写入内存、挖出一个新令牌、执行一些操作、创建一个新契约等。).

与外部拥有的账户不同,合约账户不能自己发起交易。所以以太坊的任何动作总是从外部账户发起的交易开始。

帐户状态

帐户状态有四个组成部分,无论帐户类型如何都存在:

nonce:如果帐户是外部拥有的帐户,nonce表示从此帐户地址发送的交易序列号。如果账户是合同账户,nonce表示该账户创建的合同序列号。

平衡:这个地址有魏的号码。1Ether=1018?魏.

存储根:Merkle Patricia树的根节点的哈希值(我们后面会解释Merkle树)。Merkle tree将对该帐户中存储的内容的哈希值进行编码,默认值为null。

codeHash:该账户的EVM(以太坊虚拟机,稍后详述)代码的哈希值。对于合同帐户,它是经过哈希处理并保存为codeHash的代码。对于外部拥有的帐户,codeHash字段是空字符串

的哈希值?

世界状态

好了,我们知道以太坊的全球状态是由账户地址和账户状态的映射构成的。这个映射保存在一个叫做Merkle Patricia树的数据结构中。

Merkle Tree(也称为Merkle trie)是由一系列节点组成的二叉树,包括:

大量位于树底部的包含源数据的叶节点。

一系列中间节点,是两个子节点的哈希值。

一个根节点,也是两个子节点的哈希值,代表整个树。

树底的数据是这样生成的:把我们要保存的数据分成块,然后把块分成桶,然后获取每个桶的hash值,重复这个过程,直到只剩下一个Hash:根Hash。

这个树要求树中存在的所有值都有一个对应的键。从树的根节点开始,key会告诉你跟随哪个子节点得到对应的值,这个值存在于叶节点中。在以太坊中,key/value是地址和与地址关联的账户之间的映射,包括每个账户的余额、nonce、codeHash和storage root(storage root本身就是一棵树)。

同样的树结构也用于存储交易和收据。更具体地,每个块散列一个头部,该头部保存三个不同Merkle trie结构的根节点的散列,包括:

状态树

事务树

收据树

Merkle tries存储所有信息的高效率在以太坊的“轻客户端”和“轻节点”中相当有用。

燃气和费用

以太坊中比较重要的一个概念是费用,以太坊网络上的每一笔交易都会产生费用,因为没有免费的午餐。这笔费用由“煤气”支付。

气是用来衡量交易中所需手续的单位。汽油价格你愿意在每种汽油上花费的乙醚量,用“gwei”来衡量。“卫”是乙醚的最小单位,1Ether的意思是1018?魏。1gw为10亿魏。

对于每笔交易,发送方设置燃气限额和燃气价格。气体限制和气体价格表示发送者愿意为执行交易支付的最大值。

例如,假设发送方设置气限为50000,气价为20g魏。这意味着发送者愿意支付高达50,000 * 20g魏=1,000,000,000,000魏=0.001乙醚来执行该交易。

记住,气限代表的是用户愿意花在气上的最大金额。如果他们的账户余额足够支付这笔最高费用,那就没问题。在交易结束时,任何未使用的气体将被返还给发送者,并按照原始价格进行交换。

如果发送方没有提供足够的gas来执行交易,那么交易执行会出现“gas不足”的情况,然后会被认为无效。在这种情况下,事务处理将被终止,所有已更改的状态将被恢复。最后,我们将返回到事务前的状态——事务前的完整状态,就好像这个事务从未发生过一样。因为机器在气体耗尽之前已经为计算做出了努力,所以理论上没有气体会返回给发送者。

这些油钱到底去哪了?寄件人花在煤气上的所有钱都寄到“受益人”地址,这个地址通常是矿工的地址。因为矿工已经努力计算和核实交易,所以矿工收到作为报酬的天然气费。

通常情况下,发送方愿意支付更高的气价,而矿工总能从这笔交易中获得更多的价值。所以矿商更愿意选择这种交易。通过这种方式,矿商可以自由选择他们愿意核实或忽略的交易。 为了指导发送方应该设置多少天然气价格,矿工可以选择建议最低天然气价格,并且他们愿意执行交易。

仓储也有费用

气不仅仅是用来支付这一步的计算,还有仓储。总存储成本与所用32位字节的最小倍数成正比。

费用的作用是什么?

以太坊运行的一个重要方面是,每个网络执行的操作也受到所有节点的影响。但是,以太坊虚拟机上的计算操作非常昂贵。因此,以太坊智能合约最好用于执行最简单的任务,如运行简单的业务逻辑或验证签名和其他加密对象,而不是复杂的操作,如文件存储、电子邮件或机器学习,这些操作会给网络带来压力。征收费用可以防止用户使网络超载。

以太坊是一种图灵完全语言(简而言之,图灵机就是可以模拟任何计算机算法的机器。)。这让流通,让以太坊遭遇宕机?这个问题让你不确定程序是否无限期运行。如果没有成本,恶意执行者可以通过执行一个包含无限循环的事务来轻易地使网络瘫痪,而不会产生任何影响。因此,开销可以保护网络免受蓄意攻击。

您可能会想,“为什么我们仍然要为存储付费?”其实就像计算一样,以太坊网络上的存储是整个网络必须承担的成本。

事务和消息

之前说过以太坊是基于事务的状态机。换句话说,两个不同账户之间的交易使得以太坊的全局状态从一种状态变为另一种状态。

最基本的概念是,交易是由外部拥有的帐户加密和签名、序列化然后提交给区块链的指令。

有两种类型的事务:消息通信和契约创建(即事务生成一个新的以太坊契约)。

无论何种类型的交易,都包含:

nonce:发送方发送的交易次数

gasPrice:发送方愿意支付执行交易所需的每种气体的Wei量

gasLimit:发送方愿意支付执行交易的气体量的最大值。此数量设置后,在完成任何计算之前会提前扣除

到:接收方地址。在合同创建交易中,合同账户的地址还不存在,所以值为空

值:发送方转给接收方的魏数。在合同创建事务中,value用作新合同帐户的起始余额

v,r,s:用于生成签名

init(仅存在于合同创建事务中):用于初始化新合同帐户的EVM代码片段。init值被执行一次,然后被丢弃。当init第一次执行时,它返回一个帐户代码体,即一段与合同帐户永久关联的代码。

data(可选域,只存在于消息通信中):消息调用中的输入数据(即参数)。例如,如果智能合约是域名注册服务,则调用合约可能期望输入域名和IP地址

等域?

在“帐户”一章中,我们了解了事务—消息传递和合同创建事务总是由外部拥有的帐户触发并提交给区块链。另一种思路是,交易是连接外界和以太坊内部状态的桥梁。

但不代表一个契约不能和另一个契约沟通。以太坊状态全局范围内的契约可以与同一范围内的契约进行通信。他们通过“消息”或“内部交易”进行交流。我们可以认为消息或内部事务类似于事务,但最大的区别是它们不是由外部拥有的帐户生成的。相反,它们是通过合同生产的。它们是虚拟对象,与事务不同,不序列化,只存在于带有以太坊的执行环境中。

当一个合同向另一个合同发送内部交易时,将执行接收方合同账户中存在的关联代码。

需要注意的一点是,内部交易或消息不包含gasLimit。因为gas限制是由原始交易的外部创建者(即外部所有者帐户)决定的。外部自有账户设置的gas限额必须足够高,以完成交易,包括由该交易引起的任何“子执行”,如合同到合同消息。如果在一个事务或信息链中,一个消息的执行使gas不足,那么这个消息的执行将被恢复,包括由这个执行触发的任何子消息。然而,不需要恢复父执行。

块头

让我们回到块的问题。我们前面提到每个块都有一个“块头”,但这到底是什么呢?

块头是块的一部分, 它包含:

括号:父块头的Hash值(这也是块成为区块链的原因)

ommerHash:当前块ommers列表的Hash值

好处:接收挖这个块的费用的账户的地址

StateRoot:状态树的根节点的哈希值(回想一下我们之前说过的关于存储在头中的状态树的内容,它使得轻型客户端验证关于状态的任何内容变得非常简单)

transactionsRoot:包含此块中列出的所有事务的树的根节点的哈希值

ReceiptsRoot:包含此块中列出的所有事务的树的根节点哈希值

logs Bloom:Bloom过滤器(数据结构) 由日志信息组成

难度:该块的难度级别

编号:当前块的计数(Genesis块的块号为0,对于每个后续块,块号都增加1)

gasLimit:每个块的当前气体限制

gas used:该块使用的总气体

timestamp:该块建立时的unix时间戳

extraData:与该块相关的附加数据

与nonce结合时, 证明这个块已经执行了足够多的计算

nonce:一个Hash值,当与mixHash结合时,证明这个块已经执行了足够多的计算

注意每个块是如何包含三个树形结构的,分别对应于

state root)

]

transactions

receiptsRoot

这三个树形结构是

另外,上面描述的有几个术语值得解释一下。下面我们就来看看他们。

日志

以太坊允许日志可以跟踪各种交易和信息。一个合约可以通过定义“事件”来显示的生成日志。

一个日志的实体包含:

记录器的账户地址

代表本次交易执行的各种事件的一系列主题以及与这些事件相关的任何数据

日志被保存在bloom过滤器?中,过滤器高效的保存了无尽的日志数据。

交易收据

自于被包含在交易收据中的日志信息存储在头中。就像你在商店买东西时收到的收据一样,以太坊为每笔交易都产生一个收据。像你期望的那样,每个收据包含关于交易的特定信息。这些收据包含着:

区块序号

区块Hash

交易Hash

当前交易使用了的gas

在当前交易执行完之后当前块使用的累计gas

执行当前交易时创建的日志

等等

区块难度

区块的难度是被用来在验证区块时加强一致性。创世纪区块的难度是131,072,有一个特殊的公式用来计算之后的每个块的难度。如果某个区块比前一个区块验证的更快,以太坊协议就会增加区块的难度。

区块的难度影响nonce,它是在挖矿时必须要使用proof-of-work算法来计算的一个hash值。

区块难度和nonce之间的关系用数学形式表达就是:

Hd代表的是难度。

找到符合难度阈值的nonce唯一方法就是使用proof-of-work算法来列举所有的可能性。找到解决方案预期时间与难度成正比—难度越高,找到nonce就越困难,因此验证一个区块也就越难,这又相应地增加了验证新块所需的时间。所以,通过调整区块难度,协议可以调整验证区块所需的时间。

另一方面,如果验证时间变的越来越慢,协议就会降低难度。这样的话,验证时间自我调节以保持恒定的速率—平均每15s一个块。

交易执行

我们已经到了以太坊协议最复杂的部分:交易的执行。假设你发送了一笔交易给以太坊网络处理,将以太坊状态转换成包含你的交易这个过程到底发生了什么?

蓑衣网小编2022

首先,为了可以被执行所有的交易必须都要符合最基础的一系列要求,包括:

交易必须是正确格式化的RLP。”RLP”代表Recursive Length Prefix,它是一种数据格式,用来编码二进制数据嵌套数组。以太坊就是使用RLP格式序列化对象。

有效的交易签名。

有效的交易序号。回忆一下账户中的nonce就是从此账户发送出去交易的计数。如果有效,那么交易序号一定等于发送账户中的nonce。

交易的gas limit 一定要等于或者大于交易使用的intrinsic gas,intrinsic gas包括:——-1.执行交易预订费用为21,000gas——-2.随交易发送的数据的gas费用(每字节数据或代码为0的费用为4gas,每个非零字节的数据或代码费用为68gas)——-3.如果交易是合约创建交易,还需要额外的32,000gas

发送账户余额必须有足够的Ether来支付”前期”gas费用。前期gas费用的计算比较简单:首先,交易的gas limit乘以交易的gas价格得到最大的gas费用。然后,这个最大gas费用被加到从发送方传送给接收方的总值。

蓑衣网小编2022

怎么样交易符合上面所说的所有要求,那么我们进行下面步骤。

第一步,我们从发送者的余额中扣除执行的前期费用,并为当前交易将发送者账户中的nonce增加1。此时,我们可以计算剩余的gas,将交易的总gas减去使用的intrinsic gas。

第二步,开始执行交易。在交易执行的整个过程中,以太坊保持跟踪“子状态”。子状态是记录在交易中生成的信息的一种方式,当交易完成时会立即需要这些信息。具体来说,它包含:

自毁集:在交易完成之后会被丢弃的账户集(如果存在的话)

日志系列:虚拟机的代码执行的归档和可检索的检查点

退款余额:交易完成之后需要退还给发送账户的总额。回忆一下我们之前提到的以太坊中的存储需要付费,发送者要是清理了内存就会有退款。以太坊使用退款计数进行跟踪退款余额。退款计数从0开始并且每当合约删除了一些存储中的东西都会进行增加。

第三步,交易所需的各种计算开始被处理。

当交易所需的步骤全部处理完成,并假设没有无效状态,通过确定退还给发送者的未使用的gas量,最终的状态也被确定。除了未使用的gas,发送者还会得到上面所说的“退款余额”中退还的一些津贴。

一旦发送者得到退款之后:

gas的Ether就会矿工

交易使用的gas会被添加到区块的gas计数中(计数一直记录当前区块中所有交易使用的gas总量,这对于验证区块时是非常有用的)

所有在自毁集中的账户(如果存在的话)都会被删除

蓑衣网小编2022

最后,我们就有了一个新的状态以及交易创建的一系列日志。

现在我们已经介绍了交易执行的基本知识,让我们再看看合约创建交易和消息通信的一些区别。

合约创建(Contract creation)

回忆一下在以太坊中,有两种账户类型:合约账户和外部拥有账户。当我们说一个交易是“合约创建”,是指交易的目的是创建一个新的合约账户。

为了创建一个新的合约账户,我们使用一个特殊的公式来声明新账户的地址。然后我们使用下面的方法来初始化一个账户:

设置nonce为0

如果发送者通过交易发送了一定量的Ether作为value,那么设置账户的余额为value

将存储设置为0

设置合约的codeHash为一个空字符串的Hash值

一旦我们完成了账户的初始化,使用交易发送过来的init code(查看”交易和信息”章节来复习一下init code),实际上就创造了一个账户。init code的执行过程是各种各样的。取决于合约的构造器,可能是更新账户的存储,也可能是创建另一个合约账户,或者发起另一个消息通信等等。

当初始化合约的代码被执行之后,会使用gas。交易不允许使用的gas超过剩余gas。如果它使用的gas超过剩余gas,那么就会发生gas不足异(OOG)常并退出。如果一个交易由于gas不足异常而退出,那么状态会立刻恢复到交易前的一个点。发送者也不会获得在gas用完之前所花费的gas。

不过,如果发送者随着交易发送了Ether,即使合约创建失败Ether也会被退回来。

如果初始化代码成功的执行完成,最后的合约创建的花费会被支付。这些是存储成本,与创建的合约代码大小成正比(再一次,没有免费的午餐)。如果没有足够的剩余gas来支付最后的花费,那么交易就会再次宣布gas不足异常并中断退出。

如果所有的都正常进行没有任何异常出现,那么任何剩余的未使用gas都会被退回给原始的交易发送者,现在改变的状态才被允许永久保存。

消息通信(Message calls)

消息通信的执行与合约创建比较类似,只不过有一点点区别。

由于没有新账户被创建,所以消息通信的执行不包含任何的init code。不过,它可以包含输入数据,如果交易发送者提供了此数据的话。一旦执行,消息通信同样会有一个额外的组件来包含输出数据,如果后续执行需要此数据的话就组件就会被使用。

就像合约创建一样,如果消息通信执行退出是因为gas不足或交易无效(例如栈溢出,无效跳转目的地或无效指令),那么已使用的gas是不会被退回给原始触发者的。相反,所有剩余的未使用gas也会被消耗掉,并且状态会被立刻重置为余额转移之前的那个点。

没有任何方法停止或恢复交易的执行而不让系统消耗你提供的所有gas,直到最新的以太坊更新。例如,假设你编写了一个合约,当调用者没有授权来执行这些交易的时候抛出一个错误。在以太坊的前一个版本中,剩余的gas也会被消耗掉,并且没有任何gas退回给发送者。但是拜占庭更新包括了一个新的“恢复”代码,允许合约停止执行并且恢复状态改变而不消耗剩余的gas,此代码还拥有返回交易失败原因的能力。如果一个交易是由于恢复而退出,那么未使用的gas就会被返回给发送者。

以太坊区块链系统主要组成部分详解 | 分享给朋友: