以太坊运行原理笔记:
(参考以太坊黄皮书)
交易收据:
在交易执行过程中,把一些特殊的信息编码为交易收据,并把收据信息保存在一个以索引为键的树种,树的根节点保存在区块头中。
那么交易收据组成:
区块中交易发生累积的Gas
交易过程中日志的集合
这些日志信息构成的Bloom过滤器和交易的状态代码
处理:
通过函数把交易收据转化为RLP序列化字节数组
转换交易前状态根,要求状态代码值是一个整数
累积的Gas使用量也为一个正整数,且日志的Bloom过滤器为一个256字节数据的hash值
日志记录包括日志产生者的地址,32字节的日志主题和一些字节数据组成元组
Bloom过滤器函数把日志项精简为一个256字节的hash
整体有效性:
区块需要同时满足要求才能确认是有效的。
内部一致的ommers和交易区块Hash值,且这个基于初始状态按照顺序执行所有的给定交易后所达到的一个新的状态
区块头验证那么就涉及到难度算法
难度算法:
区块的难度是被用来在验证区块时加强一致性。创世纪区块的难度是131,072,有一个特殊的公式用来计算之后的每个块的难度。如果某个区块比前一个区块验证的更快,以太坊协议就会增加区块的难度。(算法详见黄皮书-中文版第5页)
区块难度影响的是nonce,通过POW算法来计算一个hash值,关系为:n<或等于2的256次/Hd(Hd为难度)
找到符合难度阈值的nonce唯一方法就是使用POW算法来列举所有的可能性。找到解决方案预期时间与难度成正比—难度越高,找到nonce就越困难,因此验证一个区块也就越难,这又相应地增加了验证新块所需的时间。所以,通过调整区块难度,协议可以调整验证区块所需的时间。
如果验证时间变的越来越慢,协议就会降低难度。这样的话,验证时间自我调节以保持恒定的速率—平均每15s-17s一个块。
gas
Gas Price:字面理解汽油价格,这个就像你去加油站,95#汽油今天是什么价格。一个Gas Price就是单价,那么你的交易费用=Gas*Gas Price,然后以以太币来ether来支出。当然你觉得我不想支付费用,你可以设置Gas Price为0,但是选择权在矿工手中,矿工有权选择收纳交易和收取费用,那么最简单的想想很难让一个矿工去接收一个价格很低的交易吧。另外提一句,以太坊默认的Gas Price是1wei。
Gas Limit:字面理解就是Gas的限制,限制是必要的,没有限制就没有约束。这个Gas Limit是有两个意思的。首先针对单个交易,那么这个表示交易的发起者他愿意支付最多是多少Gas,这个交易发起者在发起交易的时候需要设置好。还有一个是针对区块的Gas Limit,一个单独的区块也有Gas的限制。
执行交易
交易执行前要有一个基本的验证
交易是RLP格式
交易的签名有效
交易的nonce,也就是当前发送者账户的nonce有效
gas足够
发送者拥有足够以太币
那么在交易过程中有一个子状态,是交易执行过程中累积的特定的信息,元组表示。这个元组内包括:
一组在交易完成后删除的账户
一系列的日志,针对VM代码执行的归档,用于索引检查点,允许外部旁观者来简单跟踪合约调用
交易接触的过账户集合,空账户在交易结束后删除
应该返回余额
交易的gas limit 一定要等于或者大于交易使用的intrinsic gas,intrinsic gas包括:
执行交易预订费用
随交易发送的数据的gas费用
交易是合约创建交易,还需要额外的gas
发送账户余额必须有足够的Ether来支付”前期”gas费用。前期gas费用的计算比较简单:首先,交易的gas limit乘以交易的gas价格得到最大的gas费用。然后,这个最大gas费用被加到从发送方传送给接收方的总值。
开始执行交易。在交易执行的整个过程中,以太坊保持跟踪“子状态”。子状态是记录在交易中生成的信息的一种方式,当交易完成时会立即需要这些信息。
交易所需的各种计算开始被处理。
当交易所需的步骤全部处理完成,并假设没有无效状态,通过确定退还给发送者的未使用的gas量,最终的状态也被确定。除了未使用的gas,发送者还会得到上面所说的“退款余额”中退还的一些津贴。
一旦发送者得到退款之后:
gas的Ether就会矿工
交易使用的gas会被添加到区块的gas计数中
所有在自毁集中的账户都会被删除
最终形成新的状态以及交易创建的一系列日志。
简单理解:
首先交易发起者A发起一笔转账交易,那么发送的格式如下:
代码具体内容
from交易发起者的地址
to交易接收者的地址
value转移的以太币数量
GasGas的量
Gas PriceGas的单价
data发送给接收者的消息
nonce交易编号
节点验证
以太坊网络中会有节点收到A发送出来的消息,那么会去检查这个消息格式时候有效,然后计算Gas Limit。这个时候回去验证A的以太坊余额,如果余额不足,那么就返回错误,不予处理。一旦A发送的消息通过了节点的验证,那么节点就会把这个交易放到交易存储池中。并广播到区块链网络。
矿工验证
那么写入区块链必须要矿工打包,矿工在接收到A发出的交易,会和其他交易一块打包,普通转账交易打包即可,那么合约调用的交易则需要在矿工本地的EVM上去执行调用的合约代码,代码执行过程中检查Gas的消耗。一旦Gas消耗完了,那么就回滚,如果Gas足够那么返回多余的Gas。并广播到区块链网络。
其余节点
重复节点验证步骤,然后合约也会在本地EVM上执行验证。通过验证后同步区块链。