《区块链原理与技术》学习笔记 第五部分
以太坊中,交易承载了账户转账和合约创建、调用合约等功能。
交易中的数据大体分为基本的交易、交易的执行参数、交易的签名三个部分。
基本交易内容
交易的执行参数
交易的签名
以太坊中交易的的手续费由Gas机制计算,主要包括以下概念:
其中交易的Gas由基础的交易Gas加上EVM运行时消耗的Gas值累加得到。当GasUsed超过GasLimit,交易执行失败。
交易的GasUsed*GasPrice就是用户为交易支付的手续费。
1.发起
2.广播
3.打包与执行
4.验证与执行
根据to值的不同,交易的执行分为以下3种:
1.创建合约交易
to为空的交易,交易根据from和nonce值生成合约地址,并执行data中的智能合约代码。EVM会将代码存储到合约地址中。
2.调用合约交易
to为合约账户的交易。EVM获取to地址中的代码,并执行data中的代码。
本质上来说。对合约的调用就是对合约状态的修改。
3.普通转账交易
to为人控制的账户(外部账户),交易直接将以太币从from转到to
叔块
指不在主链但被主链记录的满足难度的区块。矿工在打包区块时,可以自主选择合法的0-2个叔块。
以太坊中规定,7代以内的有共同祖先的都可以认为是叔父块。
叔父块的接纳和奖励规则
叔父块可以尽量收缩和统一整个区块链的主链,同时维护矿工的积极性。
权益证明(Proof-of-Stake):持有币的数量和占有币数的时间来决定你获得本次记账权利的概率。持有越多,获得记账概率越大。
相比PoW缩短了达成共识时间,节省能源,但是容易分叉和中心化。
挖矿难度的公式为:
H = 0 , D ( H ) = 0 D ( H ) = m a x ( D 0 , P ( H ) H d + x × ζ 2 ) + ϵ H=0,D(H)=0 \\ D(H)=max(D_0,P(H)_{H_d}+x × \zeta_2)+\epsilon H=0,D(H)=0D(H)=max(D0,P(H)Hd+x×ζ2)+ϵ
其中 P ( H ) H d P(H)_{H_d} P(H)Hd是父区块的难度, x × ζ 2 x×\zeta_2 x×ζ2 用于自适应调节出块难度, ϵ \epsilon ϵ表示设定的难度炸弹
基础部分有下界,最小值为 D 0 = 131072 D_0=131072 D0=131072
x = ⌊ P ( H ) H d 2048 ⌋ , ζ 2 = m a x ( y − ⌊ H s − P ( H ) H s 9 ⌋ , − 99 ) x= \left\lfloor \frac{P(H)_{H_d}}{2048} \right\rfloor, \ \zeta_2=max \left( y-\left\lfloor \frac{H_s-P(H)_{H_s}}{9} \right\rfloor, -99 \right) x=⌊2048P(H)Hd⌋, ζ2=max(y−⌊9Hs−P(H)Hs⌋,−99)
x为调整的单位, ζ 2 \zeta_2 ζ2 为调整的系数
如果父区块中包含uncle,y为2,否则为1
H s H_s Hs是本区块的时间戳, P ( H ) H s P(H)_{H_s} P(H)Hs是父区块的时间戳,并规定 H s > P ( H ) H s H_s > P(H)_{H_s} Hs>P(H)Hs
ϵ = ⌊ 2 ⌊ H i ′ / 100 , 000 ⌋ − 2 ⌋ , H i ′ = m a x ( H i − 30 , 000 , 000 ) \epsilon = \left\lfloor 2^{\lfloor H'_i / 100,000 \rfloor -2} \right\rfloor, \ H'_i=max(H_i-30,000,000) ϵ=⌊2⌊Hi′/100,000⌋−2⌋, Hi′=max(Hi−30,000,000)
ϵ \epsilon ϵ 是2的指数函数。每100000块扩大一倍
设置难度炸弹是为了降低迁移到PoS协议时发生fork的风险,引导矿工有意愿迁移到PoS。
以太坊区块的区块头包括:
以太坊区块体的内容:
世界状态
以太坊中所有账户的状态的汇总,也就是区块头的状态根,通过一个特殊的树状哈希数据结构实现。
收据
对应交易的数据结构,代表交易执行的一些中间状态写入和交易的执行结果等信息。
收据的内容包括:
由于以太坊潜在的账户数量巨大,单使用Merkle Tree无法存储数据,且修改成本高,因此以太坊使用了十六叉压缩前缀树,作为地址到账户的索引,然后利用Merkle Tree将每一层节点合并计算节点的哈希值,最后得到根哈希值。
压缩前缀树
普通的字典树(Trie)为每一个字母作为树的节点,这样导致树的高度太高,浪费存储空间;压缩前缀树(Patricia Trie)将共同的前缀部分组成一个子树,逐级向下划分,提高了查找效率。
MPT
在MPT中,“单词”对应账户的哈希值,“指针”对应哈希指针。叶子节点记录(前缀+账户哈希值)的哈希值,父节点的哈希值为(前缀+子分支)的哈希值。
以下图为例:
H1=H(“”+账户1的哈希值),H3=H(d+账户3的哈希值)
H5=H(bc+H1+H2+“”+“”+…+“”)
H6=H(b+H4+…+“”+H3+“+”“)
H_root=H(”“+…+”“+H5+…+”“+H6+”")
状态树
以太坊的状态树记录各个账号的状态,当状态改变后只会影响对应分支的状态,区块存储对应状态树的状态根。
合约存储树
合约账户存储树也使用了MPT来记录存储地址到存储值的映射,映射表的哈希值叫做存储根(storage root)。
由于合约存储空间中的一个单位刚好为256位,所以可以直接当叶子节点
交易树和收据树
这两棵树通过交易/收据在区块中的序号来构建MPT,收据和交易的信息一一对应。
布隆过滤器可以检索一个值是否在一个集合中,以太坊用来对收据的日志进行索引、查找。
在容忍一定错误率的情况下,它的效率很高。
原理:用多个哈希函数将键值映射到一个位图中。对于一个键值,若在同样的哈希函数映射下,没有在位图中出现标记位,则键值一定不在集合中。