这是此前学习以太坊黄皮书的笔记,因为结合了 go-ethereum 源码,并且笔记中杂合了一些测试和脚本以加深理解,结果笔记比较混乱..
最近觉得还是稍微整理发出来,抛砖引玉~
版本基于 VERSION 80085f7 – 2021-07-11
黄皮书混用了 = = = 和 ≡ \equiv ≡ ,时而表示赋值,时而表示等价指代,注意区分
2. The Blockchain Paradigm 区块链范式
以太坊可以看作是一个交易驱动的状态机
公式 (1)
σ t + 1 ≡ Υ ( σ t , T ) \boldsymbol{\sigma}_{t+1} \equiv \Upsilon(\boldsymbol{\sigma}_{t}, T) σ t + 1 ≡ Υ ( σ t , T )
其中
Υ \Upsilon Υ 某次状态转移的函数
σ {\sigma} σ 状态
挖矿
挖矿
通过付出一定的工作量,与其他潜在区块竞争 一系列交易(一个区块) 的记账权
系统激励
公式 (2) (3) (4)
σ t + 1 ≡ Π ( σ t , B ) B ≡ ( . . . , ( T 0 , T 1 , . . . ) , . . . ) Π ( σ , B ) ≡ Ω ( B , Υ ( Υ ( σ , T 0 ) , T 1 ) . . . ) \begin{aligned}
\boldsymbol{\sigma}_{t+1} & \quad\equiv\quad {\Pi}(\boldsymbol{\sigma}_{t}, B) \\
B & \quad\equiv\quad (..., (T_0, T_1, ...), ...) \\
\Pi(\boldsymbol{\sigma}, B) & \quad\equiv\quad {\Omega}(B, {\Upsilon}(\Upsilon(\boldsymbol{\sigma}, T_0), T_1) ...)
\end{aligned} σ t + 1 B Π ( σ , B ) ≡ Π ( σ t , B ) ≡ ( ... , ( T 0 , T 1 , ... ) , ... ) ≡ Ω ( B , Υ ( Υ ( σ , T 0 ) , T 1 ) ... )
其中
Ω \Omega Ω 区块奖励状态转换函数,参考公式 (169) (170) (171) (172)
B B B 表示一个区块,包含一系列交易和一些其他组成部分
Π \Pi Π 区块状态转换函数,参考公式 (177)
2.2 Which History? 如何选择历史?
agreed-upon scheme
blocktree 区块树
去中心化
每个参与者都有机会在前一个区块后,自己创建一个新的区块
形成一棵树(blocktree)
共识
分叉
无法达成共识
各节点认可的 根节点到叶节点的路径(最佳区块链) 不同
(5)
β \beta β chain ID,参考 EIP-155: Simple replay attack protection
3. Conventions 约定
符号
σ \boldsymbol{\sigma} σ 世界状态(world-state)
μ \boldsymbol{\mu} μ 虚拟机状态(machine-state)
Υ \Upsilon Υ 状态转换函数
C C C 费用,例如C SSTORE C_\text{SSTORE} C SSTORE 是执行 SSTORE
操作的费用
KEC \texttt{KEC} KEC Keccak-256
T T T 一笔以太坊交易
n n n nonce 用于防止重放攻击
o \mathbf{o} o 消息调用的输出
B 32 \mathbb{B}_{32} B 32 长度为32的字节序列
N 256 \mathbb{N}_{256} N 256 所有比 2^256 小的正整数
μ s [ 0 ] \boldsymbol{\mu}_{\mathbf{s}}[0] μ s [ 0 ] 虚拟机栈(stack)的栈顶元素
μ m [ 0..31 ] \boldsymbol{\mu}_{\mathbf{m}}[0..31] μ m [ 0..31 ] 虚拟机内存(memory)中的前32个条目
δ \delta δ 某个 opcode 的出栈个数
状态
熟悉下面三种表示方式,对于后文理解状态转换非常关键
□ \Box □ 原始值/状态
□ ′ \Box' □ ′ 最终值/状态
□ ∗ \Box^* □ ∗ , □ ∗ ∗ \Box^{**} □ ∗∗ , ... 中间值/状态
函数
公式 (6) ℓ \ell ℓ 求序列的末尾元素
ℓ ( x ) ≡ x [ ∥ x ∥ − 1 ] \ell(\mathbf{x}) \equiv \mathbf{x}[\lVert \mathbf{x} \rVert - 1] ℓ ( x ) ≡ x [∥ x ∥ − 1 ]
4. Blocks, State and Transactions 区块,状态与交易
4.1 World Stage 世界状态
参考
世界状态
维护 账户地址 及其 账户状态 的映射
a a a
σ [ a ] \boldsymbol{\sigma}[a] σ [ a ]
账户状态
含义
编码方式 RLP
Recursive Length Prefix
递归长度前缀编码
用于序列化数据后传递到网络或存储
注意
σ [ a ] \boldsymbol{\sigma}[a] σ [ a ] 账户状态
σ [ a ] n \boldsymbol{\sigma}[a]_{\mathrm{n}} σ [ a ] n
nonce
含义
如果账户是钱包地址(非合约账户),表示由此账户发出的交易数量
如果账户是智能合约,表示由此账户创建的合约数量
σ [ a ] b \boldsymbol{\sigma}[a]_{\mathrm{b}} σ [ a ] b
σ [ a ] s \boldsymbol{\sigma}[a]_{\mathrm{s}} σ [ a ] s
storageRoot
含义
如果账户是智能合约
每个账户有自己的一棵 MRT 树,存储合约的内部状态(变量)
MPT (Merkle Patricia Tree)
Merkle Tree + Patricia Tree
storageRoot 就是树的根节点
σ [ a ] c \boldsymbol{\sigma}[a]_{\mathrm{c}} σ [ a ] c
codeHash
含义
推导
用 b b b 来表示 代码
则 KEC ( b ) = σ [ a ] c \texttt{KEC}(\mathbf{b}) = \boldsymbol{\sigma}[a]_{\mathrm{c}} KEC ( b ) = σ [ a ] c
公式 (7)
TRIE ( L I ∗ ( σ [ a ] s ) ) ≡ σ [ a ] s \texttt{TRIE}\big(L_{\mathrm{I}}^*(\boldsymbol{\sigma}[a]_{\mathbf{s}})\big) \quad\equiv\quad \boldsymbol{\sigma}[a]_{\mathrm{s}} TRIE ( L I ∗ ( σ [ a ] s ) ) ≡ σ [ a ] s
其中
σ [ a ] s {\sigma}[a]_{\mathbf{s}} σ [ a ] s 表示账户的所有内部状态组成的 TRIE 树的根节点
对这棵树的所有节点做坍塌转换,即可得到根节点的 hash 值
其中 公式 (8) (9)
L I ( ( k , v ) ) ≡ ( KEC ( k ) , RLP ( v ) ) L_{\mathrm{I}}\big( (k, v) \big) \quad\equiv\quad \big(\texttt{KEC}(k), \texttt{RLP}(v)\big) L I ( ( k , v ) ) ≡ ( KEC ( k ) , RLP ( v ) )
k ∈ B 32 ∧ v ∈ N k \in \mathbb{B}_{32} \quad \wedge \quad v \in \mathbb{N} k ∈ B 32 ∧ v ∈ N
(10) 世界状态坍塌函数 L S L_{\mathrm{S}} L S
L S ( σ ) ≡ { p ( a ) : σ [ a ] ≠ ∅ } L_{\mathrm{S}}(\boldsymbol{\sigma}) \quad\equiv\quad \{ p(a): \boldsymbol{\sigma}[a] \neq \varnothing \} L S ( σ ) ≡ { p ( a ) : σ [ a ] = ∅ }
其中 公式 (11)
p ( a ) ≡ ( KEC ( a ) , RLP ( ( σ [ a ] n , σ [ a ] b , σ [ a ] s , σ [ a ] c ) ) ) p(a) \quad\equiv\quad \big(\texttt{KEC}(a), \texttt{RLP}\big( (\boldsymbol{\sigma}[a]_{\mathrm{n}}, \boldsymbol{\sigma}[a]_{\mathrm{b}}, \boldsymbol{\sigma}[a]_{\mathrm{s}}, \boldsymbol{\sigma}[a]_{\mathrm{c}}) \big) \big) p ( a ) ≡ ( KEC ( a ) , RLP ( ( σ [ a ] n , σ [ a ] b , σ [ a ] s , σ [ a ] c ) ) )
--
函数 L S L_{\mathrm{S}} L S 和 Trie 函数一起用来提供一个世界状态的简短标识(hash)
我们假定:
公式 (12)
∀ a : σ [ a ] = ∅ ∨ ( a ∈ B 20 ∧ v ( σ [ a ] ) ) \forall a: \boldsymbol{\sigma}[a] = \varnothing \; \vee \; (a \in \mathbb{B}_{20} \; \wedge \; v(\boldsymbol{\sigma}[a])) ∀ a : σ [ a ] = ∅ ∨ ( a ∈ B 20 ∧ v ( σ [ a ]))
公式 (13) v v v 表示账户有效性的验证函数
v ( x ) ≡ x n ∈ N 256 ∧ x b ∈ N 256 ∧ x s ∈ B 32 ∧ x c ∈ B 32 v(x) \quad\equiv\quad x_{\mathrm{n}} \in \mathbb{N}_{256} \wedge x_{\mathrm{b}} \in \mathbb{N}_{256} \wedge x_{\mathrm{s}} \in \mathbb{B}_{32} \wedge x_{\mathrm{c}} \in \mathbb{B}_{32} v ( x ) ≡ x n ∈ N 256 ∧ x b ∈ N 256 ∧ x s ∈ B 32 ∧ x c ∈ B 32
其中
x n x_{\mathrm{n}} x n nonce
x b x_{\mathrm{b}} x b balance
x s x_{\mathrm{s}} x s storageRoot
x c x_{\mathrm{c}} x c codeHash
公式 (14)
E M P T Y ( σ , a ) ≡ σ [ a ] c = KEC ( ( ) ) ∧ σ [ a ] n = 0 ∧ σ [ a ] b = 0 \mathtt{EMPTY}(\boldsymbol{\sigma}, a) \equiv \boldsymbol{\sigma}[a]_{\mathrm{c}} = \texttt{KEC}\big(()\big) \wedge \boldsymbol{\sigma}[a]_{\mathrm{n}} = 0 \wedge \boldsymbol{\sigma}[a]_{\mathrm{b}} = 0 EMPTY ( σ , a ) ≡ σ [ a ] c = KEC ( ( ) ) ∧ σ [ a ] n = 0 ∧ σ [ a ] b = 0
EMPTY 账户
没有 code
且 nonce 为0
且 balance 为0
公式 (15)
D E A D ( σ , a ) ≡ σ [ a ] = ∅ ∨ E M P T Y ( σ , a ) \mathtt{DEAD}(\boldsymbol{\sigma}, a) \quad\equiv\quad \boldsymbol{\sigma}[a] = \varnothing \vee \mathtt{EMPTY}(\boldsymbol{\sigma}, a) DEAD ( σ , a ) ≡ σ [ a ] = ∅ ∨ EMPTY ( σ , a )
DEAD 账户
4.2 The Transaction 交易
两种交易类型
消息调用 message call
合约创建 contract creation
共同字段
T n T_{\mathrm{n}} T n
T p T_{\mathrm{p}} T p
T g T_{\mathrm{g}} T g
T t T_{\mathrm{t}} T t
T v T_{\mathrm{v}} T v
T w T_{\mathrm{w}} T w , T r T_{\mathrm{r}} T r , T s T_{\mathrm{s}} T s
v, r, s
含义
ECDSA 签名的3个组成部分
可以从中推导交易发起者 from address
特有字段
T i T_{\mathrm{i}} T i
init
交易类型
含义
是一段 EVM-code,它将返回 body,这是这个账户每次接收到消息调用时回执行的代码
init 代码仅在合约创建时被执行一次,然后就被丢弃
T d T_{\mathrm{d}} T d
公式 (16)
L T ( T ) ≡ { ( T n , T p , T g , T t , T v , T i , T w , T r , T s ) if T t = ∅ ( T n , T p , T g , T t , T v , T d , T w , T r , T s ) otherwise L_{\mathrm{T}}(T) \quad\equiv\quad \begin{cases}
(T_{\mathrm{n}}, T_{\mathrm{p}}, T_{\mathrm{g}}, T_{\mathrm{t}}, T_{\mathrm{v}}, T_{\mathbf{i}}, T_{\mathrm{w}}, T_{\mathrm{r}}, T_{\mathrm{s}}) & \text{if} \; T_{\mathrm{t}} = \varnothing\\
(T_{\mathrm{n}}, T_{\mathrm{p}}, T_{\mathrm{g}}, T_{\mathrm{t}}, T_{\mathrm{v}}, T_{\mathbf{d}}, T_{\mathrm{w}}, T_{\mathrm{r}}, T_{\mathrm{s}}) & \text{otherwise}
\end{cases} L T ( T ) ≡ { ( T n , T p , T g , T t , T v , T i , T w , T r , T s ) ( T n , T p , T g , T t , T v , T d , T w , T r , T s ) if T t = ∅ otherwise
在这里,我们假设除了任意长度的字节数组 T i T_{\mathrm{i}} T i 和 T d T_{\mathrm{d}} T d 以外,所有变量都是作为整数来进行 RLP 编码
公式 (17)
T n ∈ N 256 ∧ T v ∈ N 256 ∧ T p ∈ N 256 ∧ T g ∈ N 256 ∧ T w ∈ N 256 ∧ T r ∈ N 256 ∧ T s ∈ N 256 ∧ T d ∈ B ∧ T i ∈ B \begin{aligned}
& T_{\mathrm{n}} \in \mathbb{N}_{256} & \quad\wedge\quad & T_{\mathrm{v}} \in \mathbb{N}_{256} & \quad\wedge\quad & T_{\mathrm{p}} \in \mathbb{N}_{256} \quad \wedge \\
& T_{\mathrm{g}} \in \mathbb{N}_{256} & \quad\wedge\quad & T_{\mathrm{w}} \in \mathbb{N}_{256} & \quad\wedge\quad & T_{\mathrm{r}} \in \mathbb{N}_{256} \quad \wedge \\
& T_{\mathrm{s}} \in \mathbb{N}_{256} & \quad\wedge\quad & T_{\mathbf{d}} \in \mathbb{B} & \quad\wedge\quad & T_{\mathbf{i}} \in \mathbb{B}
\end{aligned} T n ∈ N 256 T g ∈ N 256 T s ∈ N 256 ∧ ∧ ∧ T v ∈ N 256 T w ∈ N 256 T d ∈ B ∧ ∧ ∧ T p ∈ N 256 ∧ T r ∈ N 256 ∧ T i ∈ B
其中
公式 (18)
N n = { P : P ∈ N ∧ P < 2 n } \mathbb{N}_{\mathrm{n}} = \{ P: P \in \mathbb{N} \wedge P < 2^n \} N n = { P : P ∈ N ∧ P < 2 n }
公式 (19)
T t ∈ { B 20 if T t ≠ ∅ B 0 otherwise T_{\mathbf{t}} \in \begin{cases} \mathbb{B}_{20} & \text{if} \quad T_{\mathrm{t}} \neq \varnothing \\
\mathbb{B}_{0} & \text{otherwise}\end{cases} T t ∈ { B 20 B 0 if T t = ∅ otherwise
对于合约创建交易,T t T_{\mathrm{t}} T t 是 空字节 的 RLP
4.3 The Block 区块
B l o c k Block Bl oc k
H H H
T \mathbf{T} T
U \mathbf{U} U
H H H (block header)
H p H_{\mathrm{p}} H p
parentHash
父区块 block header 的 hash
H o H_{\mathrm{o}} H o
ommersHash
当前区块的叔块列表的 hash
H c H_{\mathrm{c}} H c
beneficiary
因为挖到当前区块而获得奖励收益的账户地址
H r H_{\mathrm{r}} H r
stateRoot
state trie 根节点的 hash
交易被执行完且区块定稿后的状态
区块内的所有交易得到的状态,组成一棵树
H t H_{\mathrm{t}} H t
transactionsRoot
transaction trie 根节点的 hash
当前区块中所有交易组成的一棵树
H e H_{\mathrm{e}} H e
receiptsRoot
H b H_{\mathrm{b}} H b
logsBloom
当前区块中所有交易的收据数据中的可索引信息(产生日志的地址和日志主题)组成的 Bloom 过滤器
H d H_{\mathrm{d}} H d
difficulty
含义
当前区块的难度水平
根据前一个区块的难度水平和时间戳计算得到
H i H_{\mathrm{i}} H i
H l H_{\mathrm{l}} H l
gasLimit
目前每个区块的 gas 开支上限
H g H_{\mathrm{g}} H g
gasUsed
当前区块中所有交易所用掉的 gas 之和
H s H_{\mathrm{s}} H s
timestamp
当前区块初始化时的 Unix 时间戳
H x H_{\mathrm{x}} H x
extraData
含义
与当前区块相关的任意字节数据
必须在 32 字节以内
H m H_{\mathrm{m}} H m
mixHash
含义
一个 hash 值
用于与 H n H_{\mathrm{n}} H n 一起证明当前区块已经承载了足够的计算量
H n H_{\mathrm{n}} H n
nonce
含义
一个64位的随机整数
用于与 H m H_{\mathrm{m}} H m 一起证明当前区块已经承载了足够的计算量
注意
这里的 nonce 是个随机数,与账户下的 nonce 定义不同
公式 (20)
B ≡ ( B H , B T , B U ) B \quad\equiv\quad (B_{\mathrm{H}}, B_{\mathbf{T}}, B_{\mathbf{U}}) B ≡ ( B H , B T , B U )
4.3.1 Transaction Receipt 交易收据
每个交易一定会有一条对应的收据
R R R
Transaction Receipt
含义
用途
B R [ i ] B_{\mathbf{R}}[i] B R [ i ]
H e H_{\mathrm{e}} H e
receiptsRoot
含义
区块内的收据组成 receipt trie
其根节点的 hash 存储在 H e H_{\mathrm{e}} H e 中
公式 (21)
R ≡ ( R z , R u , R b , R l ) R \quad\equiv\quad (R_{\mathrm{z}}, R_{\mathrm{u}}, R_{\mathrm{b}}, R_{\mathbf{l}}) R ≡ ( R z , R u , R b , R l )
R R R 一条收据的组成
R u R_{\mathrm{u}} R u
R l R_{\mathrm{l}} R l
R b R_{\mathrm{b}} R b
256字节大小的 hash
由一系列日志构成的 Bloom 过滤器
R z R_{\mathrm{z}} R z
公式 (22)
R z ∈ N R_{\mathrm{z}} \in \mathbb{N} R z ∈ N
公式 (23)
R u ∈ N ∧ R b ∈ B 256 R_{\mathrm{u}} \in \mathbb{N} \quad \wedge \quad R_{\mathrm{b}} \in \mathbb{B}_{256} R u ∈ N ∧ R b ∈ B 256
公式 (24)
O ≡ ( O a , ( O t 0 , O t 1 , . . . ) , O d ) O \quad\equiv\quad (O_{\mathrm{a}}, ({O_{\mathbf{t}}}_0, {O_{\mathbf{t}}}_1, ...), O_{\mathbf{d}}) O ≡ ( O a , ( O t 0 , O t 1 , ... ) , O d )
只有被调用的智能合约,自身显式调用 LOG0
,LOG1
,LOG2
,LOG3
,LOG4
才会生成日志
R l R_{\mathrm{l}} R l
由一系列日志组成
( O 0 , O 1 , . . . ) (O_0,O_1,...) ( O 0 , O 1 , ... )
O O O 一条日志的组成
O a O_{\mathrm{a}} O a
当前被调用的智能合约的地址 (一定不会包括 EOA 地址)
跟随消息调用上下文变化
例子
EOA -> ContracA -> ContractB -> ContractC
O t O_{\mathrm{t}} O t
O d O_{\mathrm{d}} O d
func makeLog (size int ) executionFunc {
return func (pc *uint64 , interpreter *EVMInterpreter, scope *ScopeContext) ([]byte , error ) {
topics := make ([]common.Hash, size)
stack := scope.Stack
mStart, mSize := stack.pop(), stack.pop()
for i := 0 ; i < size; i++ {
addr := stack.pop()
topics[i] = addr.Bytes32()
}
d := scope.Memory.GetCopy(int64 (mStart.Uint64()), int64 (mSize.Uint64()))
interpreter.evm.StateDB.AddLog(&types.Log{
Address: scope.Contract.Address(),
Topics: topics,
Data: d,
BlockNumber: interpreter.evm.Context.BlockNumber.Uint64(),
})
return nil , nil
}
}
公式 (25)
O a ∈ B 20 ∧ ∀ x ∈ O t : x ∈ B 32 ∧ O d ∈ B O_{\mathrm{a}} \in \mathbb{B}_{20} \quad \wedge \quad \forall x \in O_{\mathbf{t}}: x \in \mathbb{B}_{32} \quad \wedge \quad O_{\mathbf{d}} \in \mathbb{B} O a ∈ B 20 ∧ ∀ x ∈ O t : x ∈ B 32 ∧ O d ∈ B
公式 (26)
M M M 函数
定义
输入
x ∈ { O a } ∪ O t {x \in \{O_{\mathrm{a}}\} \cup O_{\mathbf{t}}} x ∈ { O a } ∪ O t
取并集
日志地址 O a O_{\mathrm{a}} O a
转成集合 { O a } \{O_{\mathrm{a}}\} { O a }
一系列日志主题
输出
M ( O ) ≡ ⋁ x ∈ { O a } ∪ O t ( M 3 : 2048 ( x ) ) M(O) \quad\equiv\quad {\bigvee}_{x \in \{O_{\mathrm{a}}\} \cup O_{\mathbf{t}}} \big( M_{3:2048}(x) \big) M ( O ) ≡ ⋁ x ∈ { O a } ∪ O t ( M 3 : 2048 ( x ) )
理解如下
M 3 : 2048 M_{3:2048} M 3 : 2048 是个大小为256字节,共2048位的 Bloom 过滤器
对于输入数据,计算它的 Keccak-256 哈希值
取哈希值的前6个字节,两两组成一对
遍历这3对字节
取低11位,得到索引,则索引范围是 [0, 2047](2^11 == 2048)
设置 Bloom 过滤器对应索引的位为1
因此
公式 (27) (28) (29) (30)
M 3 : 2048 ( x : x ∈ B ) ≡ y : y ∈ B 256 where: y = ( 0 , 0 , . . . , 0 ) except: ∀ i ∈ { 0 , 2 , 4 } : B m ( x , i ) ( y ) = 1 m ( x , i ) ≡ K E C ( x ) [ i , i + 1 ] m o d 2048 \begin{aligned}
M_{3:2048}(\mathbf{x}: \mathbf{x} \in \mathbb{B}) & \quad\equiv\quad \mathbf{y}: \mathbf{y} \in \mathbb{B}_{256} \quad \text{where:} \\
\mathbf{y} & \quad=\quad (0, 0, ..., 0) \quad \text{except:} \\
\forall i \in \{0, 2, 4\} & \quad:\quad \mathcal{B}_{m(\mathbf{x}, i)}(\mathbf{y}) = 1 \\
m(\mathbf{x}, i) & \quad\equiv\quad \mathtt{KEC}(\mathbf{x})[i, i + 1] \bmod 2048
\end{aligned} M 3 : 2048 ( x : x ∈ B ) y ∀ i ∈ { 0 , 2 , 4 } m ( x , i ) ≡ y : y ∈ B 256 where: = ( 0 , 0 , ... , 0 ) except: : B m ( x , i ) ( y ) = 1 ≡ KEC ( x ) [ i , i + 1 ] mod 2048
其中
B \mathcal{B} B 表示位引用函数
B j ( x ) = 1 \mathcal{B}_{\mathrm{j}}(\mathbf{x}) = 1 B j ( x ) = 1 表示设置字节数组 x \mathbf{x} x 中的第 j 位(从0开始) 为1
如果仅看黄皮书中关于几个 LOG$
的 opcode 说明,会误以为过滤器仅包含日志,容易对使用场景产生困惑。实际上,在 go-ethereum 实现中,会把产生日志的合约地址 log.Address
也记录在过滤器
func CreateBloom (receipts Receipts) Bloom {
buf := make ([]byte , 6 )
var bin Bloom
for _, receipt := range receipts {
for _, log := range receipt.Logs {
bin.add(log.Address.Bytes(), buf)
for _, b := range log.Topics {
bin.add(b[:], buf)
}
}
}
return bin
}
4.3.2 Holistic Validity 整体有效性
公式 (31)
H r ≡ T R I E ( L S ( Π ( σ , B ) ) ) ∧ H o ≡ K E C ( R L P ( L H ∗ ( B U ) ) ) ∧ H t ≡ T R I E ( { ∀ i < ∥ B T ∥ , i ∈ N : p ( i , L T ( B T [ i ] ) ) } ) ∧ H e ≡ T R I E ( { ∀ i < ∥ B R ∥ , i ∈ N : p ( i , B R [ i ] ) } ) ∧ H b ≡ ⋁ r ∈ B R ( r b ) \begin{aligned}
H_{\mathrm{r}} & \quad\equiv\quad \mathtt{TRIE}(L_S(\Pi(\boldsymbol{\sigma}, B))) & \quad\quad\wedge \\
H_{\mathrm{o}} & \quad\equiv\quad \mathtt{KEC}(\mathtt{RLP}(L_H^*(B_{\mathbf{U}}))) & \quad\quad\wedge \\
H_{\mathrm{t}} & \quad\equiv\quad \mathtt{TRIE}(\{\forall i < \lVert B_{\mathbf{T}} \rVert, i \in \mathbb{N}: p (i, L_{\mathrm{T}}(B_{\mathbf{T}}[i]))\}) & \quad\quad\wedge \\
H_{\mathrm{e}} & \quad\equiv\quad \mathtt{TRIE}(\{\forall i < \lVert B_{\mathbf{R}} \rVert, i \in \mathbb{N}: p(i, B_{\mathbf{R}}[i])\}) & \quad\quad\wedge \\
H_{\mathrm{b}} & \quad\equiv\quad {\bigvee}_{\mathbf{r} \in B_{\mathbf{R}}} \big( \mathbf{r}_{\mathrm{b}} \big)
\end{aligned} H r H o H t H e H b ≡ TRIE ( L S ( Π ( σ , B ))) ≡ KEC ( RLP ( L H ∗ ( B U ))) ≡ TRIE ({ ∀ i < ∥ B T ∥ , i ∈ N : p ( i , L T ( B T [ i ]))}) ≡ TRIE ({ ∀ i < ∥ B R ∥ , i ∈ N : p ( i , B R [ i ])}) ≡ ⋁ r ∈ B R ( r b ) ∧ ∧ ∧ ∧
其中
H r H_{\mathrm{r}} H r
H o H_{\mathrm{o}} H o
H t H_{\mathrm{t}} H t
H e H_{\mathrm{e}} H e
H b H_{\mathrm{b}} H b
其中 公式 (32)
p ( k , v ) ≡ ( R L P ( k ) , R L P ( v ) ) p(k, v) \quad\equiv\quad \big( \mathtt{RLP}(k), \mathtt{RLP}(v) \big) p ( k , v ) ≡ ( RLP ( k ) , RLP ( v ) )
而且 公式 (33)
T R I E ( L S ( σ ) ) = P ( B H ) H r \mathtt{TRIE}(L_{\mathrm{S}}(\boldsymbol{\sigma})) \quad=\quad {P(B_H)_H}_{\mathrm{r}} TRIE ( L S ( σ )) = P ( B H ) H r
其中
P ( B H ) P(B_H) P ( B H )
Π ( σ , B ) ) \Pi(\boldsymbol{\sigma}, B)) Π ( σ , B ))
L S L_S L S
L H ∗ L_{\mathrm{H}}^* L H ∗
L T L_{\mathrm{T}} L T
4.3.3 Serialization 序列化
公式 (34) 定义 H 的序列化函数 L H L_{\mathrm{H}} L H 如下
L H ( H ) ≡ ( H p , H o , H c , H r , H t , H e , H b , H d , H i , H l , H g , H s , H x , H m , H n ) L_{\mathrm{H}}(H) \quad\equiv\quad (H_{\mathrm{p}}, H_{\mathrm{o}}, H_{\mathrm{c}}, H_{\mathrm{r}}, H_{\mathrm{t}}, H_{\mathrm{e}}, H_{\mathrm{b}}, H_{\mathrm{d}}, H_{\mathrm{i}}, H_{\mathrm{l}}, H_{\mathrm{g}}, H_{\mathrm{s}}, H_{\mathrm{x}}, H_{\mathrm{m}}, H_{\mathrm{n}} \; ) L H ( H ) ≡ ( H p , H o , H c , H r , H t , H e , H b , H d , H i , H l , H g , H s , H x , H m , H n )
公式 (35) 则 B 的序列化函数 L B L_{\mathrm{B}} L B 为
L B ( B ) ≡ ( L H ( B H ) , L T ∗ ( B T ) , L H ∗ ( B U ) ) L_{\mathrm{B}}(B) \quad\equiv\quad \big( L_{\mathrm{H}}(B_{\mathrm{H}}), L_{\mathrm{T}}^*(B_{\mathbf{T}}), L_{\mathrm{H}}^*({B_{\mathbf{U}}}) \big) L B ( B ) ≡ ( L H ( B H ) , L T ∗ ( B T ) , L H ∗ ( B U ) )
公式 (36)
其中
L T L_{\mathrm{T}} L T 参考公式 (16)
L H L_{\mathrm{H}} L H 参考公式 (34)
L T ∗ L_{\mathrm{T}}^* L T ∗ 和 L H ∗ L_{\mathrm{H}}^* L H ∗ 分别是它们的 reduce
函数
reduce
函数定义如下: 对集合中的每一个元素,分别执行指定函数,得到的结果组成一个集合
f ∗ ( ( x 0 , x 1 , . . . ) ) ≡ ( f ( x 0 ) , f ( x 1 ) , . . . ) for any function f {f^*}\big( (x_0, x_1, ...) \big) \quad\equiv\quad \big( f(x_0), f(x_1), ... \big) \quad \text{for any function} \; f f ∗ ( ( x 0 , x 1 , ... ) ) ≡ ( f ( x 0 ) , f ( x 1 ) , ... ) for any function f
公式 (37) 值域/约束
H p ∈ B 32 ∧ H o ∈ B 32 ∧ H c ∈ B 20 ∧ H r ∈ B 32 ∧ H t ∈ B 32 ∧ H e ∈ B 32 ∧ H b ∈ B 256 ∧ H d ∈ N ∧ H i ∈ N ∧ H l ∈ N ∧ H g ∈ N ∧ H s ∈ N 256 ∧ H x ∈ B ∧ H m ∈ B 32 ∧ H n ∈ B 8 \begin{aligned}
& {H_{\mathrm{p}}} \in \mathbb{B}_{32} & \quad\wedge\quad & H_{\mathrm{o}} \in \mathbb{B}_{32} & \quad\wedge\quad & H_{\mathrm{c}} \in \mathbb{B}_{20} & \quad\wedge\quad \\
& {H_{\mathrm{r}}} \in \mathbb{B}_{32} & \quad\wedge\quad & H_{\mathrm{t}} \in \mathbb{B}_{32} & \quad\wedge\quad & {H_{\mathrm{e}}} \in \mathbb{B}_{32} & \quad\wedge\quad \\
& {H_{\mathrm{b}}} \in \mathbb{B}_{256} & \quad\wedge\quad & H_{\mathrm{d}} \in \mathbb{N} & \quad\wedge\quad & {H_{\mathrm{i}}} \in \mathbb{N} & \quad\wedge\quad \\
& {H_{\mathrm{l}}} \in \mathbb{N} & \quad\wedge\quad & H_{\mathrm{g}} \in \mathbb{N} & \quad\wedge\quad & {H_{\mathrm{s}}} \in \mathbb{N}_{256} & \quad\wedge\quad \\
& {H_{\mathrm{x}}} \in \mathbb{B} & \quad\wedge\quad & H_{\mathrm{m}} \in \mathbb{B}_{32} & \quad\wedge\quad & {H_{\mathrm{n}}} \in \mathbb{B}_{8}
\end{aligned} H p ∈ B 32 H r ∈ B 32 H b ∈ B 256 H l ∈ N H x ∈ B ∧ ∧ ∧ ∧ ∧ H o ∈ B 32 H t ∈ B 32 H d ∈ N H g ∈ N H m ∈ B 32 ∧ ∧ ∧ ∧ ∧ H c ∈ B 20 H e ∈ B 32 H i ∈ N H s ∈ N 256 H n ∈ B 8 ∧ ∧ ∧ ∧
公式 (38)
B n = { B : B ∈ B ∧ ∥ B ∥ = n } \mathbb{B}_{\mathrm{n}} = \{ B: B \in \mathbb{B} \wedge \lVert B \rVert = n \} B n = { B : B ∈ B ∧ ∥ B ∥ = n }
公式 (39) 根据区块头 H 找到其父区块
P ( H ) ≡ B ′ : K E C ( R L P ( B H ′ ) ) = H p P(H) \equiv B': \mathtt{KEC}(\mathtt{RLP}(B'_{\mathrm{H}})) = H_{\mathrm{p}} P ( H ) ≡ B ′ : KEC ( RLP ( B H ′ )) = H p
公式 (40) 区块头 H 中的区块编号(block number)计算方式为
H i ≡ P ( H ) H i + 1 H_{\mathrm{i}} \equiv {{P(H)_{\mathrm{H}}}_{\mathrm{i}}} + 1 H i ≡ P ( H ) H i + 1
公式 (41) 根据区块头 H 计算权威难度值的公式
D ( H ) ≡ { D 0 if H i = 0 max ( D 0 , P ( H ) H d + x × ς 2 + ϵ ) otherwise D(H) \equiv \begin{dcases}
{D_0} & \text{if} \quad H_{\mathrm{i}} = 0\\
\text{max}\!\left({D_0}, {P(H)_{\mathrm{H}}}_{\mathrm{d}} + x\times\varsigma_2 + \epsilon \right) & \text{otherwise}\\
\end{dcases} D ( H ) ≡ { D 0 max ( D 0 , P ( H ) H d + x × ς 2 + ϵ ) if H i = 0 otherwise
其中
P ( H ) H d {P(H)_{\mathrm{H}}}_{\mathrm{d}} P ( H ) H d
x × ς 2 x\times\varsigma_2 x × ς 2
ϵ \epsilon ϵ
--
func makeDifficultyCalculator (bombDelay *big.Int) func (time uint64 , parent *types.Header) *big.Int;
func MakeDifficultyCalculatorU256 (bombDelay *big.Int) func (time uint64 , parent *types.Header) *big.Int;
注意两个函数,黄皮书与具体实现存在出入,主要是在 ϵ \epsilon ϵ 的处理上与公式 (41) 不同,实现为
D ( H ) ≡ { D 0 if H i = 0 max ( D 0 , P ( H ) H d + x × ς 2 ) + ϵ otherwise D(H) \equiv \begin{dcases}
{D_0} & \text{if} \quad H_{\mathrm{i}} = 0\\
\text{max}\!\left({D_0}, {P(H)_{\mathrm{H}}}_{\mathrm{d}} + x\times\varsigma_2 \right) + \epsilon & \text{otherwise}\\
\end{dcases} D ( H ) ≡ { D 0 max ( D 0 , P ( H ) H d + x × ς 2 ) + ϵ if H i = 0 otherwise
公式 (42) 创世区块的难度值
D 0 ≡ 131072 {D_0} \equiv 131072 D 0 ≡ 131072
2 17 = 131072 2^{17} = 131072 2 17 = 131072
公式 (43) 难度值调整的单位
x ≡ ⌊ P ( H ) H d 2048 ⌋ x \equiv \left\lfloor\frac{{P(H)_{\mathrm{H}}}_{\mathrm{d}}}{2048}\right\rfloor x ≡ ⌊ 2048 P ( H ) H d ⌋
公式 (44) 难度值调整的系数
ς 2 ≡ max ( y − ⌊ H s − P ( H ) H s 9 ⌋ , − 99 ) \varsigma_2 \equiv \text{max}\left(y - \left\lfloor\frac{H_{\mathrm{s}} - {P(H)_{\mathrm{H}}}_{\mathrm{s}}}{9}\right\rfloor, -99 \right) ς 2 ≡ max ( y − ⌊ 9 H s − P ( H ) H s ⌋ , − 99 )
y ≡ { 1 if ∥ P ( H ) U ∥ = 0 2 otherwise y \equiv \begin{cases}
1 & \text{if} \, \lVert P(H)_{\mathbf{U}}\rVert = 0 \\
2 & \text{otherwise}
\end{cases} y ≡ { 1 2 if ∥ P ( H ) U ∥ = 0 otherwise
其中
y y y
如果父区块中包含叔父块,则难度调整会大一个单位 (从1调整为2)
因为包含叔父块时发行的货币量大,需要适当提高难度以保持货币发行量稳定
− 99 -99 − 99
难度一次最多调整 − 99 -99 − 99 个单位
主要是应对被黑客攻击或其他目前想不到的黑天鹅事件
y − ⌊ H s − P ( H ) H s 9 ⌋ y - \left\lfloor\frac{H_{\mathrm{s}} - {P(H)_{\mathrm{H}}}_{\mathrm{s}}}{9}\right\rfloor y − ⌊ 9 H s − P ( H ) H s ⌋
H s {H_{\mathrm{s}}} H s
P ( H ) H s {P(H)_{\mathrm{H}}}_{\mathrm{s}} P ( H ) H s
规定
H s > P ( H ) H s {H_{\mathrm{s}}} \gt {P(H)_{\mathrm{H}}}_{\mathrm{s}} H s > P ( H ) H s
自适应调整
例子
出块时间在 [1,8] 之间
出块时间在 [9,17] 之间
出块时间在 [18,26] 之间
...
公式 (45) (46) (47) 难度炸弹
ϵ ≡ ⌊ 2 ⌊ H i ′ ÷ 100000 ⌋ − 2 ⌋ \epsilon \equiv \left\lfloor 2^{ \left\lfloor H'_{\mathrm{i}} \div 100000 \right\rfloor - 2 } \right\rfloor \\ ϵ ≡ ⌊ 2 ⌊ H i ′ ÷ 100000 ⌋ − 2 ⌋
其中
H i ′ ≡ max ( H i − κ , 0 ) H'_{\mathrm{i}} \equiv \max(H_{\mathrm{i}} - \kappa, 0) \\ H i ′ ≡ max ( H i − κ , 0 )
其中
κ ≡ { 3000000 if F B y z a n t i u m ⩽ H i < F C o n s t a n t i n o p l e 5000000 if F C o n s t a n t i n o p l e ⩽ H i < F M u i r G l a c i e r 9000000 if H i ⩾ F M u i r G l a c i e r \kappa \equiv \begin{cases}
3000000 & \text{if} \quad F_{\mathrm{Byzantium}} \leqslant H_{\mathrm{i}} < F_{\mathrm{Constantinople}} \\
5000000 & \text{if} \quad F_{\mathrm{Constantinople}} \leqslant H_{\mathrm{i}} < F_{\mathrm{Muir Glacier}} \\
9000000 & \text{if} \quad H_{\mathrm{i}} \geqslant F_{\mathrm{Muir Glacier}} \\
\end{cases} κ ≡ ⎩ ⎨ ⎧ 3000000 5000000 9000000 if F Byzantium ⩽ H i < F Constantinople if F Constantinople ⩽ H i < F MuirGlacier if H i ⩾ F MuirGlacier
F H o m e s t e a d ≡ 1150000 F B y z a n t i u m ≡ 4370000 F C o n s t a n t i n o p l e ≡ 7280000 F M u i r G l a c i e r ≡ 9200000 \begin{aligned}
F_{\mathrm{Homestead}} & \equiv 1150000 \\
F_{\mathrm{Byzantium}} & \equiv 4370000 \\
F_\mathrm{Constantinople} & \equiv 7280000 \\
F_{\mathrm{Muir Glacier}} & \equiv 9200000
\end{aligned} F Homestead F Byzantium F Constantinople F MuirGlacier ≡ 1150000 ≡ 4370000 ≡ 7280000 ≡ 9200000
为什么设置难度炸弹?
降低迁移到 PoS 协议时发生 fork 的风险
到时挖矿难度非常大,矿工将被迫迁移到 PoS 协议
参数
ϵ \epsilon ϵ
是2的指数函数,每十万个块扩大一倍
后期增长非常快 ("炸弹")
H i ′ H'_{\mathrm{i}} H i ′
低估了 PoS 协议的开发难度,导致一再延迟
炸弹威力显现后,通过假区块号(回退区块号)来降低难度
参考 what-is-the-difficulty-bomb
公式 (48) gasLimit 约束
H l < P ( H ) H l + ⌊ P ( H ) H l 1024 ⌋ ∧ H l > P ( H ) H l − ⌊ P ( H ) H l 1024 ⌋ ∧ H l ⩾ 5000 H_{\mathrm{l}} < {P(H)_{\mathrm{H}}}_{\mathrm{l}} + \left\lfloor\frac{{P(H)_{\mathrm{H}}}_{\mathrm{l}}}{1024}\right\rfloor \quad \wedge \\
H_{\mathrm{l}} > {P(H)_{\mathrm{H}}}_{\mathrm{l}} - \left\lfloor\frac{{P(H)_{\mathrm{H}}}_{\mathrm{l}}}{1024}\right\rfloor \quad \wedge \\
H_{\mathrm{l}} \geqslant 5000 H l < P ( H ) H l + ⌊ 1024 P ( H ) H l ⌋ ∧ H l > P ( H ) H l − ⌊ 1024 P ( H ) H l ⌋ ∧ H l ⩾ 5000
公式 (49) timestamp 约束
H s > P ( H ) H s H_{\mathrm{s}} > {P(H)_{\mathrm{H}}}_{\mathrm{s}} H s > P ( H ) H s
公式 (41)难度计算公式的设计,保证了难度根据出块间隔长短的动态平衡
如果最近的两个区块间隔较短,则会导致难度值增加,因此需要额外的计算量,大概率会延长下个区块的出块时间
相反,如果最近的两个区块间隔过长,难度值和下一个区块的预期出块时间也会减少
公式 (50) nonce / mixHash 约束
必须同时满足
n ⩽ 2 256 H d ∧ m = H m w i t h ( n , m ) = P o W ( H n , H n , d ) n \leqslant \frac {2^{256}}{H_{\mathrm{d}}} \quad \wedge \quad m = H_{\mathrm{m}} \\
with \quad (n, m) = \mathtt{PoW}(H_{\cancel{n}}, H_{\mathrm{n}}, \mathbf{d}) n ⩽ H d 2 256 ∧ m = H m w i t h ( n , m ) = PoW ( H n , H n , d )
其中
H n H_{\cancel{n}} H n
当前区块 header H H H
但不包含 nonce 和 mixHash components
d \mathbf{d} d
当前 DAG
用于计算 mixHash H m H_{\mathrm{m}} H m
P o W \mathtt{PoW} PoW
工作量证明函数
保证
除了列举所有的可能性,没有更好的其他方法来找到一个低于要求阈值的 nonce
攻击者必须拥有超过网络一半的算力,才能比其他人更快地找到 nonce
公式 (51)
综上所述,block header 的验证函数 V ( H ) V(H) V ( H ) 定义如下:
V ( H ) ≡ n ⩽ 2 256 H d ∧ m = H m ∧ H d = D ( H ) ∧ H g ≤ H l ∧ H l < P ( H ) H l + ⌊ P ( H ) H l 1024 ⌋ ∧ H l > P ( H ) H l − ⌊ P ( H ) H l 1024 ⌋ ∧ H l ⩾ 5000 ∧ H s > P ( H ) H s ∧ H i = P ( H ) H i + 1 ∧ ∥ H x ∥ ≤ 32 w h e r e ( n , m ) = P o W ( H n , H n , d ) \begin{aligned}
V(H) \equiv\quad & n \leqslant \frac{2^{256}}{H_{\mathrm{d}}} \wedge m = H_{\mathrm{m}} \quad &\wedge \\
& H_{\mathrm{d}} = D(H) \quad &\wedge \\
& H_{\mathrm{g}} \le H_{\mathrm{l}} \quad &\wedge \\
& H_{\mathrm{l}} < {P(H)_{\mathrm{H}}}_{\mathrm{l}} + \left\lfloor\frac{{P(H)_{\mathrm{H}}}_{\mathrm{l}}}{1024}\right\rfloor \quad &\wedge \\
& H_{\mathrm{l}} > {P(H)_{\mathrm{H}}}_{\mathrm{l}} - \left\lfloor\frac{{P(H)_{\mathrm{H}}}_{\mathrm{l}}}{1024}\right\rfloor \quad &\wedge \\
& H_{\mathrm{l}} \geqslant 5000 \quad &\wedge \\
& H_{\mathrm{s}} > {P(H)_{\mathrm{H}}}_{\mathrm{s}} \quad &\wedge \\
& H_{\mathrm{i}} = {P(H)_{\mathrm{H}}}_{\mathrm{i}} +1 \quad &\wedge \\
& \lVert H_{\mathrm{x}} \rVert \le 32 \\
where \quad & (n, m) = \mathtt{PoW}(H_{\cancel{n}}, H_{\mathrm{n}}, \mathbf{d})
\end{aligned} V ( H ) ≡ w h ere n ⩽ H d 2 256 ∧ m = H m H d = D ( H ) H g ≤ H l H l < P ( H ) H l + ⌊ 1024 P ( H ) H l ⌋ H l > P ( H ) H l − ⌊ 1024 P ( H ) H l ⌋ H l ⩾ 5000 H s > P ( H ) H s H i = P ( H ) H i + 1 ∥ H x ∥ ≤ 32 ( n , m ) = PoW ( H n , H n , d ) ∧ ∧ ∧ ∧ ∧ ∧ ∧ ∧
此外,extraData \textbf{extraData} extraData 最多为32字节
5. Gas and Payment Gas 与支付
一般来说,用于支付交易的 gas 费用,会被发往 beneficiary 地址,这个地址由矿工设置
6. Transaction Execution 交易执行
Υ \Upsilon Υ 交易状态转换函数
Υ \Upsilon Υ 在执行前,检查如下条件:
交易以 RLP 格式正确编码,且没有尾随多余的数据
交易签名正确
nonce 有效(即等于交易发送者账户当前的 nonce)
gas limit 不小于 g 0 g_0 g 0 (计算公式参考(55) (56) (57))
发送者账户 balance 不小于实际费用 v 0 v_0 v 0 (计算公式参考(58))
公式 (52) 交易状态转换函数
σ ′ = Υ ( σ , T ) \boldsymbol{\sigma}' = \Upsilon(\boldsymbol{\sigma}, T) σ ′ = Υ ( σ , T )
其中
σ ′ \boldsymbol{\sigma}' σ ′
Υ g \Upsilon^{\mathrm{g}} Υ g
Υ l \Upsilon^{\mathbf{l}} Υ l
Υ z \Upsilon^{\mathrm{z}} Υ z
6.1 Substrate 子状态
公式 (53) 交易执行过程中产生的子状态
A ≡ ( A s , A l , A t , A r ) A \equiv (A_{\mathbf{s}}, A_{\mathbf{l}}, A_{\mathbf{t}}, A_{\mathrm{r}}) A ≡ ( A s , A l , A t , A r )
其中
A s A_{\mathbf{s}} A s
A l A_{\mathbf{l}} A l
A t A_{\mathbf{t}} A t
A r A_{\mathbf{r}} A r
公式 (54) 空的交易子状态
A 0 ≡ ( ∅ , ( ) , ∅ , 0 ) A^0 \equiv (\varnothing,(), \varnothing, 0) A 0 ≡ ( ∅ , ( ) , ∅ , 0 )
6.2 Execution 执行
状态转换
σ \boldsymbol{\sigma} σ 原始状态
σ 0 \boldsymbol{\sigma}_0 σ 0 检查点状态
发送者 balance 扣除 T g T p {T_g}{T_p} T g T p
发送者 nonce 累加
σ P \boldsymbol{\sigma}_{\mathrm{P}} σ P 执行交易后临时状态
σ ∗ \boldsymbol{\sigma}^* σ ∗ 预备最终状态
剩余的 gas 返回给发送者
消耗的 gas 发给 beneficiary(由打包区块的矿工指定)
σ ′ \boldsymbol{\sigma}' σ ′ 最终状态
--
公式 (55) (56) (57) g 0 g_0 g 0 交易执行前预付的基础 gas
g 0 ≡ ∑ i ∈ T i , T d { G t x d a t a z e r o if i = 0 G t x d a t a n o n z e r o otherwise + { G t x c r e a t e if T t = ∅ 0 otherwise + G t r a n s a c t i o n g_0 \equiv {}
\sum_{i \in T_{\mathbf{i}}, T_{\mathbf{d}}} \begin{cases} G_{\mathrm{txdatazero}} &\text{if} \quad i = 0 \\ G_{\mathrm{txdatanonzero}} &\text{otherwise} \end{cases}
\quad + \quad \begin{cases} G_{\mathrm{txcreate}} & \text{if} \quad T_{\mathrm{t}} = \varnothing \\ 0 & \text{otherwise} \end{cases}
\quad + \quad G_{\mathrm{transaction}} g 0 ≡ i ∈ T i , T d ∑ { G txdatazero G txdatanonzero if i = 0 otherwise + { G txcreate 0 if T t = ∅ otherwise + G transaction
其中
T i T_{\mathbf{i}} T i
T d T_{\mathbf{d}} T d
G t x c r e a t e G_{\mathrm{txcreate}} G txcreate
公式 (58) v 0 v_0 v 0 交易执行前预付的费用
v 0 ≡ T g T p + T v v_0 \quad\equiv\quad T_{\mathrm{g}} T_{\mathrm{p}} + T_{\mathrm{v}} v 0 ≡ T g T p + T v
公式 (59)
S ( T ) ≠ ∅ ∧ σ [ S ( T ) ] ≠ ∅ ∧ T n = σ [ S ( T ) ] n ∧ g 0 ⩽ T g ∧ v 0 ⩽ σ [ S ( T ) ] b ∧ T g ⩽ B H l − ℓ ( B R ) u \begin{aligned}
S(T) & \quad\neq\quad \varnothing \quad \wedge \\
\boldsymbol{\sigma}[S(T)] & \quad\neq\quad \varnothing \quad \wedge \\
T_{\mathrm{n}} & \quad=\quad \boldsymbol{\sigma}[S(T)]_{\mathrm{n}} \quad \wedge \\
g_0 & \quad\leqslant\quad T_{\mathrm{g}} \quad \wedge \\
v_0 & \quad\leqslant\quad \boldsymbol{\sigma}[S(T)]_{\mathrm{b}} \quad \wedge \\
T_{\mathrm{g}} & \quad\leqslant\quad {B_{\mathrm{H}}}_{\mathrm{l}} - {\ell}(B_{\mathbf{R}})_{\mathrm{u}}
\end{aligned} S ( T ) σ [ S ( T )] T n g 0 v 0 T g = ∅ ∧ = ∅ ∧ = σ [ S ( T ) ] n ∧ ⩽ T g ∧ ⩽ σ [ S ( T ) ] b ∧ ⩽ B H l − ℓ ( B R ) u
其中
S ( T ) S(T) S ( T )
T g T_{\mathrm{g}} T g
ℓ ( B R ) u {\ell}(B_{\mathbf{R}})_{\mathrm{u}} ℓ ( B R ) u
B H l {B_{\mathrm{H}}}_{\mathrm{l}} B H l
公式 (60) (61) (62) 检查点状态 σ 0 \boldsymbol{\sigma}_0 σ 0
σ 0 ≡ σ except: σ 0 [ S ( T ) ] b ≡ σ [ S ( T ) ] b − T g T p σ 0 [ S ( T ) ] n ≡ σ [ S ( T ) ] n + 1 \begin{aligned}
\boldsymbol{\sigma}_0 & \quad\equiv\quad \boldsymbol{\sigma} \quad \text{except:} \\
\boldsymbol{\sigma}_0[S(T)]_{\mathrm{b}} & \quad\equiv\quad \boldsymbol{\sigma}[S(T)]_{\mathrm{b}} - T_{\mathrm{g}} T_{\mathrm{p}} \\
\boldsymbol{\sigma}_0[S(T)]_{\mathrm{n}} & \quad\equiv\quad \boldsymbol{\sigma}[S(T)]_{\mathrm{n}} + 1
\end{aligned} σ 0 σ 0 [ S ( T ) ] b σ 0 [ S ( T ) ] n ≡ σ except: ≡ σ [ S ( T ) ] b − T g T p ≡ σ [ S ( T ) ] n + 1
检查点状态 σ 0 \boldsymbol{\sigma}_0 σ 0 预扣了 T g T p T_{\mathrm{g}} T_{\mathrm{p}} T g T p
系统会在交易执行成功后,将剩余 gas 返还发送者
--
注意 XXX
公式 (61) 计算检查点状态 balance 时,不是扣除 v 0 v_0 v 0 ,而是只扣了 T g T p T_{\mathrm{g}} T_{\mathrm{p}} T g T p ,未扣除 T v T_{\mathrm{v}} T v
实际上,v v v 的处理,是在公式 (63) 执行交易时,在执行具体函数代码前,会从发送者 Transfer
到接收者
gas 与 value 分开处理,理解如下
gas 本身与 value 语义本质量不同,不能混为一起
转账 value 的双方 balance 的改变应该是原子的,不应拆成前后两个上下文
gas 一定是外部账户支付的,而 value 转账的扣款账户可以是外部账户,也可以是智能合约
func (evm *EVM) Call(caller ContractRef, addr common.Address, input []byte , gas uint64 , value *big.Int) (ret []byte , leftOverGas uint64 , err error ) {
evm.Context.Transfer(evm.StateDB, caller.Address(), addr, value)
}
公式 (63) 执行交易后临时状态 σ P \boldsymbol{\sigma}_{\mathrm{P}} σ P
( σ P , g ′ , A , z ) ≡ { Λ 4 ( σ 0 , S ( T ) , T o , g , T p , T v , T i , 0 , ∅ , ⊤ ) if T t = ∅ Θ 4 ( σ 0 , S ( T ) , T o , T t , T t , g , T p , T v , T v , T d , 0 , ⊤ ) otherwise (\boldsymbol{\sigma}_{\mathrm{P}}, g', A, z) \equiv \begin{cases}
\Lambda_{4}(\boldsymbol{\sigma}_0, S(T), T_{\mathrm{o}}, g, T_{\mathrm{p}}, T_{\mathrm{v}}, T_{\mathbf{i}}, 0, \varnothing, \top) & \text{if} \quad T_{\mathrm{t}} = \varnothing \\
\Theta_{4}(\boldsymbol{\sigma}_0, S(T), T_{\mathrm{o}}, T_{\mathrm{t}}, T_{\mathrm{t}}, g, T_{\mathrm{p}}, T_{\mathrm{v}}, T_{\mathrm{v}}, T_{\mathbf{d}}, 0, \top) & \text{otherwise}
\end{cases} ( σ P , g ′ , A , z ) ≡ { Λ 4 ( σ 0 , S ( T ) , T o , g , T p , T v , T i , 0 , ∅ , ⊤ ) Θ 4 ( σ 0 , S ( T ) , T o , T t , T t , g , T p , T v , T v , T d , 0 , ⊤ ) if T t = ∅ otherwise
状态转换
σ 0 \boldsymbol{\sigma}_0 σ 0 检查点状态
σ P \boldsymbol{\sigma}_{\mathrm{P}} σ P 执行交易后临时状态
操作
转换时需要区分交易类型
T t = ∅ T_{\mathrm{t}} = \varnothing T t = ∅ 未设置目标地址,说明是合约创建类型
否则,是消息调用类型
其中
σ P \boldsymbol{\sigma}_{\mathrm{P}} σ P
g ′ g' g ′
A A A
z z z
T o T_{\mathrm{o}} T o
original transactor
如果是 inner-transaction,则这里是智能合约的地址,而非 sender
Λ 4 \Lambda_{4} Λ 4
Θ 4 \Theta_{4} Θ 4
⊤ \top ⊤
数学符号,表示 bool 值
Λ 4 \Lambda_{4} Λ 4 和 Θ 4 \Theta_{4} Θ 4 的末尾参数
--
关于 ⊤ \top ⊤
OPCODE 函数 末尾参数值 含义 CREATE
Λ 4 \Lambda_{4} Λ 4 I w I_{w} I w 保持调用时的读写权限 CREATE2
Λ 4 \Lambda_{4} Λ 4 I w I_{w} I w 保持调用时的读写权限 STATICCALL
Θ 4 \Theta_{4} Θ 4 ⊥ \bot ⊥ (falsum)只读 CALL
Θ 4 \Theta_{4} Θ 4 I w I_{w} I w 保持调用时的读写权限 CALLCODE
Θ 4 \Theta_{4} Θ 4 I w I_{w} I w 保持调用时的读写权限 DELEGATECALL
Θ 4 \Theta_{4} Θ 4 I w I_{w} I w 保持调用时的读写权限
func (in *EVMInterpreter) Run(contract *Contract, input []byte , readOnly bool ) (ret []byte , err error ) {
if readOnly && !in.readOnly {
in.readOnly = true
defer func () { in.readOnly = false }()
}
for {
op = contract.GetOp(pc)
operation := in.cfg.JumpTable[op]
if in.readOnly && in.evm.chainRules.IsByzantium {
if operation.writes || (op == CALL && stack.Back(2 ).Sign() != 0 ) {
return nil , ErrWriteProtection
}
}
}
return nil , nil
}
func (evm *EVM) StaticCall(caller ContractRef, addr common.Address, input []byte , gas uint64 ) (ret []byte , leftOverGas uint64 , err error ) {
ret, err = evm.interpreter.Run(contract, input, true )
}
func (evm *EVM) Call(caller ContractRef, addr common.Address, input []byte , gas uint64 , value *big.Int) (ret []byte , leftOverGas uint64 , err error ) {
ret, err = evm.interpreter.Run(contract, input, false )
}
func (evm *EVM) CallCode(caller ContractRef, addr common.Address, input []byte , gas uint64 , value *big.Int) (ret []byte , leftOverGas uint64 , err error ) {
ret, err = evm.interpreter.Run(contract, input, false )
}
func (evm *EVM) DelegateCall(caller ContractRef, addr common.Address, input []byte , gas uint64 ) (ret []byte , leftOverGas uint64 , err error ) {
ret, err = evm.interpreter.Run(contract, input, false )
}
func (evm *EVM) create(caller ContractRef, codeAndHash *codeAndHash, gas uint64 , value *big.Int, address common.Address) ([]byte , common.Address, uint64 , error ) {
ret, err = evm.interpreter.Run(contract, nil , false )
}
--
公式 (64) 执行时最多能消耗的 gas
g ≡ T g − g 0 g \quad\equiv\quad T_{\mathrm{g}} - g_0 g ≡ T g − g 0
公式 (65) 交易执行后 refund 计数器的变化
A r ′ ≡ A r + ∑ i ∈ A s R s e l f d e s t r u c t A'_{\mathrm{r}} \quad\equiv\quad A_{\mathrm{r}} + \sum_{i \in A_{\mathbf{s}}} R_{\mathrm{selfdestruct}} A r ′ ≡ A r + i ∈ A s ∑ R selfdestruct
公式 (66) 交易执行后剩余的 gas
g ∗ ≡ g ′ + min { ⌊ T g − g ′ 2 ⌋ , A r ′ } g^* \quad\equiv\quad g' + \min \left\{ \Big\lfloor \dfrac{T_{\mathrm{g}} - g'}{2} \Big\rfloor, {A'_{\mathrm{r}}} \right\} g ∗ ≡ g ′ + min { ⌊ 2 T g − g ′ ⌋ , A r ′ }
其中
g ′ g' g ′
T g − g ′ T_{\mathrm{g}} - g' T g − g ′
g ∗ g^* g ∗
公式 (67) (68) (69) (70) 预备最终状态 σ ∗ \boldsymbol{\sigma}^* σ ∗
σ ∗ ≡ σ P except σ ∗ [ S ( T ) ] b ≡ σ P [ S ( T ) ] b + g ∗ T p σ ∗ [ m ] b ≡ σ P [ m ] b + ( T g − g ∗ ) T p m ≡ B H c \begin{aligned}
\boldsymbol{\sigma}^* & \quad\equiv\quad \boldsymbol{\sigma}_{\mathrm{P}} \quad \text{except} \\
\boldsymbol{\sigma}^*[S(T)]_{\mathrm{b}} & \quad\equiv\quad \boldsymbol{\sigma}_{\mathrm{P}}[S(T)]_{\mathrm{b}} + g^* T_{\mathrm{p}} \\
\boldsymbol{\sigma}^*[m]_{\mathrm{b}} & \quad\equiv\quad \boldsymbol{\sigma}_{\mathrm{P}}[m]_{\mathrm{b}} + (T_{\mathrm{g}} - g^*) T_{\mathrm{p}} \\
m & \quad\equiv\quad {B_{\mathrm{H}}}_{\mathrm{c}}
\end{aligned} σ ∗ σ ∗ [ S ( T ) ] b σ ∗ [ m ] b m ≡ σ P except ≡ σ P [ S ( T ) ] b + g ∗ T p ≡ σ P [ m ] b + ( T g − g ∗ ) T p ≡ B H c
状态转换
σ P \boldsymbol{\sigma}_{\mathrm{P}} σ P 执行交易后临时状态
σ ∗ \boldsymbol{\sigma}^* σ ∗ 预备最终状态
操作
剩余的 gas 返回给发送者
消耗的 gas 发给 B H c {B_{\mathrm{H}}}_{\mathrm{c}} B H c (beneficiary)
公式 (71) (72) (73) 最终状态 σ ′ \boldsymbol{\sigma}' σ ′
σ ′ ≡ σ ∗ except ∀ i ∈ A s : σ ′ [ i ] = ∅ ∀ i ∈ A t : σ ′ [ i ] = ∅ if D E A D ( σ ∗ , i ) \begin{aligned}
\boldsymbol{\sigma}' & \quad\equiv\quad \boldsymbol{\sigma}^* \quad \text{except} \\
\forall i \in A_{\mathbf{s}}: \boldsymbol{\sigma}'[i] & \quad=\quad \varnothing \\
\forall i \in A_{\mathbf{t}}: \boldsymbol{\sigma}'[i] & \quad=\quad \varnothing \quad\text{if}\quad \mathtt{DEAD}(\boldsymbol{\sigma}^*\kern -2pt, i)
\end{aligned} σ ′ ∀ i ∈ A s : σ ′ [ i ] ∀ i ∈ A t : σ ′ [ i ] ≡ σ ∗ except = ∅ = ∅ if DEAD ( σ ∗ , i )
状态转换
σ ∗ \boldsymbol{\sigma}^* σ ∗ 预备最终状态
σ ′ \boldsymbol{\sigma}' σ ′ 最终状态
操作
删除自毁集合账户
删除接触账户集合中的空账户
公式 (74) (75) (76)
Υ g ( σ , T ) ≡ T g − g ∗ Υ l ( σ , T ) ≡ A l Υ z ( σ , T ) ≡ z \begin{aligned}
\Upsilon^{\mathrm{g}}(\boldsymbol{\sigma}, T) & \quad\equiv\quad T_{\mathrm{g}} - g^* \\
\Upsilon^{\mathbf{l}}(\boldsymbol{\sigma}, T) & \quad\equiv\quad {A_{\mathbf{l}}} \\
\Upsilon^{\mathrm{z}}(\boldsymbol{\sigma}, T) & \quad\equiv\quad z
\end{aligned} Υ g ( σ , T ) Υ l ( σ , T ) Υ z ( σ , T ) ≡ T g − g ∗ ≡ A l ≡ z
其中
Υ g \Upsilon^{\mathrm{g}} Υ g
Υ l \Upsilon^\mathbf{l} Υ l
Υ z \Upsilon^{\mathrm{z}} Υ z
7. Contract Creation 合约创建
两个步骤
公式 (77) 盐
ζ ∈ B 32 ∪ B 0 \zeta \in \mathbb{B}_{32} \cup \mathbb{B}_{0} ζ ∈ B 32 ∪ B 0
如果是通过 C R E A T E 2 \small{CREATE2} CRE A TE 2 创建合约,则 ζ ≠ ∅ \zeta \neq \varnothing ζ = ∅
公式 (78) 合约创建函数 Λ \Lambda Λ
( σ ′ , g ′ , A , z , o ) ≡ Λ ( σ , s , o , g , p , v , i , e , ζ , w ) (\boldsymbol{\sigma}', g', A, z, \mathbf{o}) \equiv \Lambda(\boldsymbol{\sigma}, s, o, g, p, v, \mathbf{i}, e, \zeta, w) ( σ ′ , g ′ , A , z , o ) ≡ Λ ( σ , s , o , g , p , v , i , e , ζ , w )
函数参数
σ \boldsymbol{\sigma} σ
s s s
o o o
g g g
p p p
v v v
i \mathbf{i} i
e e e
ζ \zeta ζ
用于计算新合约地址的盐
可能不存在: ζ = ∅ \zeta = \varnothing ζ = ∅
w w w
函数输出
σ ′ \boldsymbol{\sigma}' σ ′
g ′ g' g ′
A A A
o \mathbf{o} o
执行结果
对于合约创建而言,成功的话这里得到的是合约的 body code
参考公式 (145)
公式 (79) (80) (81) 新创建合约的地址 a a a
a ≡ A D D R ( s , σ [ s ] n − 1 , ζ , i ) A D D R ( s , n , ζ , i ) ≡ B 96..255 ( K E C ( L A ( s , n , ζ , i ) ) ) L A ( s , n , ζ , i ) ≡ { R L P ( ( s , n ) ) if ζ = ∅ ( 255 ) ⋅ s ⋅ ζ ⋅ K E C ( i ) otherwise \begin{aligned}
a & \equiv \mathtt{ADDR}(s, \boldsymbol{\sigma}[s]_{\mathrm{n}} - 1, \zeta, \mathbf{i}) \\
\mathtt{ADDR}(s, n, \zeta, \mathbf{i}) & \equiv \mathcal{B}_{96..255}\Big(\mathtt{KEC}\big( L_{\mathrm{A}}(s, n, \zeta, \mathbf{i})\big) \Big) \\
L_{\mathrm{A}}(s, n, \zeta, \mathbf{i}) & \equiv \begin{cases}
\mathtt{RLP}\big(\;(s, n)\;\big) & \text{if}\ \zeta = \varnothing \\
(255) \cdot s \cdot \zeta \cdot \mathtt{KEC}(\mathbf{i}) & \text{otherwise}
\end{cases}
\end{aligned} a ADDR ( s , n , ζ , i ) L A ( s , n , ζ , i ) ≡ ADDR ( s , σ [ s ] n − 1 , ζ , i ) ≡ B 96..255 ( KEC ( L A ( s , n , ζ , i ) ) ) ≡ { RLP ( ( s , n ) ) ( 255 ) ⋅ s ⋅ ζ ⋅ KEC ( i ) if ζ = ∅ otherwise
其中
L A L_{\mathrm{A}} L A
判断合约创建方式是否为 C R E A T E 2 \small{CREATE2} CRE A TE 2
⋅ \cdot ⋅
B a . . b ( X ) \mathcal{B}_{a..b}(X) B a .. b ( X )
取二进制字节数组的第 [ a , b ] [a, b] [ a , b ] 位
σ [ x ] \boldsymbol{\sigma}[x] σ [ x ]
地址 x x x 的世界状态
不存在,则为 ∅ \varnothing ∅
注意
公式(79) 中,传给合约地址计算函数 Λ \Lambda Λ 的参数 nonce,值是 σ [ s ] n − 1 \boldsymbol{\sigma}[s]_{\mathrm{n}} - 1 σ [ s ] n − 1
理解: 在调用合约创建之前,系统已经把发送者的 nonce 加一
公式 (82) (83) (84) (85) 合约创建后的世界状态 σ ∗ \boldsymbol{\sigma}^* σ ∗
σ ∗ ≡ σ except: σ ∗ [ a ] = ( 1 , v + v ′ , T R I E ( ∅ ) , K E C ( ( ) ) ) σ ∗ [ s ] = { ∅ if σ [ s ] = ∅ ∧ v = 0 a ∗ otherwise a ∗ ≡ ( σ [ s ] n , σ [ s ] b − v , σ [ s ] s , σ [ s ] c ) \begin{aligned}
\boldsymbol{\sigma}^* & \quad\equiv\quad \boldsymbol{\sigma} \quad \text{except:} \\
\boldsymbol{\sigma}^*[a] & \quad=\quad \big( 1, v + v', \mathtt{TRIE}(\varnothing), \mathtt{KEC}\big(()\big) \big) \\
\boldsymbol{\sigma}^*[s] & \quad=\quad \begin{cases}
\varnothing & \text{if}\ \boldsymbol{\sigma}[s] = \varnothing \ \wedge\ v = 0 \\
\mathbf{a}^* & \text{otherwise}
\end{cases} \\
\mathbf{a}^* & \quad\equiv\quad (\boldsymbol{\sigma}[s]_{\mathrm{n}}, \boldsymbol{\sigma}[s]_{\mathrm{b}} - v, \boldsymbol{\sigma}[s]_{\mathbf{s}}, \boldsymbol{\sigma}[s]_{\mathrm{c}})
\end{aligned} σ ∗ σ ∗ [ a ] σ ∗ [ s ] a ∗ ≡ σ except: = ( 1 , v + v ′ , TRIE ( ∅ ) , KEC ( ( ) ) ) = { ∅ a ∗ if σ [ s ] = ∅ ∧ v = 0 otherwise ≡ ( σ [ s ] n , σ [ s ] b − v , σ [ s ] s , σ [ s ] c )
公式 (86) v ′ v' v ′ 合约地址在交易前就有的余额
v ′ ≡ { 0 if σ [ a ] = ∅ σ [ a ] b otherwise v' \equiv \begin{cases}
0 & \text{if} \quad \boldsymbol{\sigma}[a] = \varnothing\\
\boldsymbol{\sigma}[a]_{\mathrm{b}} & \text{otherwise}
\end{cases} v ′ ≡ { 0 σ [ a ] b if σ [ a ] = ∅ otherwise
到这里,新创建合约的地址的状态已经设置好了(公式(83))
公式 (87) 调用 Ξ \Xi Ξ 函数执行代码 i \mathbf{i} i 来初始化合约
( σ ∗ ∗ , g ∗ ∗ , A , o ) ≡ Ξ ( σ ∗ , g , I , { s , a } ) (\boldsymbol{\sigma}^{**}, g^{**}, A, \mathbf{o}) \quad\equiv\quad \Xi(\boldsymbol{\sigma}^*, g, I, \{s, a\}) \\ ( σ ∗∗ , g ∗∗ , A , o ) ≡ Ξ ( σ ∗ , g , I , { s , a })
Ξ \Xi Ξ 函数的输出
σ ∗ ∗ \boldsymbol{\sigma}^{**} σ ∗∗
g ∗ ∗ g^{**} g ∗∗
A A A
o \mathbf{o} o
新创建合约的 body code
由合约初始化 i \mathbf{i} i 代码得到
公式 (88) (89) (90) (91) (92) (93) (94) (95) (96) 合约初始化后的世界状态 σ ∗ \boldsymbol{\sigma}^* σ ∗
I I I 作为 Ξ \Xi Ξ 函数的输入参数
I a ≡ a I o ≡ o I p ≡ p I d ≡ ( ) I s ≡ s I v ≡ v I b ≡ i I e ≡ e I w ≡ w \begin{aligned}
I_{\mathrm{a}} & \quad\equiv\quad a \\
I_{\mathrm{o}} & \quad\equiv\quad o \\
I_{\mathrm{p}} & \quad\equiv\quad p \\
I_{\mathbf{d}} & \quad\equiv\quad () \\
I_{\mathrm{s}} & \quad\equiv\quad s \\
I_{\mathrm{v}} & \quad\equiv\quad v \\
I_{\mathbf{b}} & \quad\equiv\quad \mathbf{i} \\
I_{\mathrm{e}} & \quad\equiv\quad e \\
I_{\mathrm{w}} & \quad\equiv\quad w
\end{aligned} I a I o I p I d I s I v I b I e I w ≡ a ≡ o ≡ p ≡ ( ) ≡ s ≡ v ≡ i ≡ e ≡ w
I a I_{\mathrm{a}} I a
I o I_{\mathrm{o}} I o
I p I_{\mathrm{p}} I p
I d I_{\mathbf{d}} I d
input data
在这里为空,因为对于这个初始化调用而言没有 input
I s I_{\mathrm{s}} I s
I v I_{\mathrm{v}} I v
I b I_{\mathbf{b}} I b
I e I_{\mathrm{e}} I e
I w I_{\mathrm{w}} I w
公式 (97) 合约初始化需要支付的 gas
c ≡ G c o d e d e p o s i t × ∥ o ∥ c \quad\equiv\quad G_{\mathrm{codedeposit}} \times \lVert \mathbf{o} \rVert c ≡ G codedeposit × ∥ o ∥
出现异常
初始化代码执行过程的异常
例子
因可用 gas g ∗ ∗ g^{**} g ∗∗ 不够而导致 Out-Of-Gas 异常
成功初始化后可用 gas 不够支付 c c c
g ∗ ∗ < c g^{**} < c g ∗∗ < c
也会导致 Out-of-Gas
其他场景
导致
最终剩余 gas g ‘ g‘ g ‘ 为0
使初始化提前终止
合约初始化后的世界状态 σ ∗ ∗ \boldsymbol{\sigma}^{**} σ ∗∗ 为空,即 ∅ \varnothing ∅
最终状态与合约创建前一致
公式 (98) (99) (100) (101) 最终状态 σ ′ \boldsymbol{\sigma}' σ ′
g ′ ≡ { 0 if F g ∗ ∗ − c otherwise σ ′ ≡ { σ if F ∨ σ ∗ ∗ = ∅ σ ∗ ∗ except: σ ′ [ a ] = ∅ if D E A D ( σ ∗ ∗ , a ) σ ∗ ∗ except: σ ′ [ a ] c = KEC ( o ) otherwise z ≡ { 0 if F ∨ σ ∗ ∗ = ∅ 1 otherwise where F ≡ ( σ [ a ] ≠ ∅ ∧ ( σ [ a ] c ≠ KEC ( ( ) ) ∨ σ [ a ] n ≠ 0 ) ) ∨ ( σ ∗ ∗ = ∅ ∧ o = ∅ ) ∨ g ∗ ∗ < c ∨ ∥ o ∥ > 24576 \begin{aligned}
\quad g' \quad\equiv\quad & \begin{cases}
0 & \text{if} \quad F \\
g^{**} - c & \text{otherwise} \\
\end{cases} \\
\quad \boldsymbol{\sigma}' \quad\equiv\quad & \begin{cases}
\boldsymbol{\sigma} & \text{if} \quad F \ \lor\ \boldsymbol{\sigma}^{**} = \varnothing \\
\boldsymbol{\sigma}^{**} \quad \text{except:} & \\
\quad\boldsymbol{\sigma}'[a] = \varnothing & \text{if} \quad \mathtt{DEAD}(\boldsymbol{\sigma}^{**}, a) \\
\boldsymbol{\sigma}^{**} \quad \text{except:} & \\
\quad\boldsymbol{\sigma}'[a]_{\mathrm{c}} = \texttt{KEC}(\mathbf{o}) & \text{otherwise}
\end{cases} \\
\quad z \quad\equiv\quad & \begin{cases}
0 & \text{if} \quad F \ \lor\ \boldsymbol{\sigma}^{**} = \varnothing \\
1 & \text{otherwise}
\end{cases} \\
\text{where} \\
F \quad\equiv\quad & \big( \boldsymbol{\sigma}[a] \neq \varnothing \ \wedge\ \big(\boldsymbol{\sigma}[a]_c \neq \texttt{\small KEC}\big(()\big) \vee \boldsymbol{\sigma}[a]_n \neq 0 \big) \big) \quad \vee \\
&(\boldsymbol{\sigma}^{**} = \varnothing \ \wedge\ \mathbf{o} = \varnothing) \quad \vee \\
&g^{**} < c \quad \vee \\
&\lVert \mathbf{o} \rVert > 24576
\end{aligned} g ′ ≡ σ ′ ≡ z ≡ where F ≡ { 0 g ∗∗ − c if F otherwise ⎩ ⎨ ⎧ σ σ ∗∗ except: σ ′ [ a ] = ∅ σ ∗∗ except: σ ′ [ a ] c = KEC ( o ) if F ∨ σ ∗∗ = ∅ if DEAD ( σ ∗∗ , a ) otherwise { 0 1 if F ∨ σ ∗∗ = ∅ otherwise ( σ [ a ] = ∅ ∧ ( σ [ a ] c = KEC ( ( ) ) ∨ σ [ a ] n = 0 ) ) ∨ ( σ ∗∗ = ∅ ∧ o = ∅ ) ∨ g ∗∗ < c ∨ ∥ o ∥ > 24576
其中
g ′ g' g ′
( σ [ a ] ≠ ∅ ∧ ( σ [ a ] c ≠ KEC ( ( ) ) ∨ σ [ a ] n ≠ 0 ) ) \big( \boldsymbol{\sigma}[a] \neq \varnothing \ \wedge\ \big(\boldsymbol{\sigma}[a]_c \neq \texttt{\small KEC}\big(()\big) \vee \boldsymbol{\sigma}[a]_n \neq 0 \big) \big) ( σ [ a ] = ∅ ∧ ( σ [ a ] c = KEC ( ( ) ) ∨ σ [ a ] n = 0 ) )
目标地址已存在,且有 codeHash 或 nonce 不为0
o \mathbf{o} o
新创建合约的 body code
由合约初始化 i \mathbf{i} i 代码得到
σ ′ [ a ] c = KEC ( o ) \boldsymbol{\sigma}'[a]_{\mathrm{c}} = \texttt{KEC}(\mathbf{o}) σ ′ [ a ] c = KEC ( o )
保存新建合约的 body code 的 hash 到 σ ′ [ a ] c \boldsymbol{\sigma}'[a]_{\mathrm{c}} σ ′ [ a ] c
σ ∗ ∗ = ∅ ∧ o = ∅ \boldsymbol{\sigma}^{**} = \varnothing \ \wedge\ \mathbf{o} = \varnothing σ ∗∗ = ∅ ∧ o = ∅
含义
执行 i \mathbf{i} i 后得到的字节码,即合约代码 o \mathbf{o} o 为空
失败例子 Ropsten
SELFDESTRUCT \text{\small SELFDESTRUCT} SELFDESTRUCT
结论
根据执行结果,剩余 gas 有返还,所以不属于 F F F
代码
pragma solidity >=0.7 .0 <0.9 .0 ;
contract Storage {
constructor (address user ) payable {
address payable u = payable (address (user));
selfdestruct (u);
}
}
结论
func (in *EVMInterpreter) Run(contract *Contract, input []byte , readOnly bool ) (ret []byte , err error ) {
}
测试
结论
不满足 F F F ,因此 g ′ = g ∗ ∗ − c g' = g^{**} - c g ′ = g ∗∗ − c
满足 D E A D ( σ ∗ ∗ , a ) \mathtt{DEAD}(\boldsymbol{\sigma}^{**}, a) DEAD ( σ ∗∗ , a ) ,因此 σ ′ [ a ] = ∅ \boldsymbol{\sigma}'[a] = \varnothing σ ′ [ a ] = ∅
证明
代码 (assert 和 require 都测试过,都返还了 gas,跟参考文章结论不一样)
pragma solidity >=0.7 .0 <0.9 .0 ;
contract Storage {
uint256 number;
constructor (address user, uint256 num ) payable {
require (msg.sender == user);
number = num;
}
}
部署
发起部署的地址与构造函数的地址不同,使 require/assert 失败
根据公式(14),新创建的合约是个 EMPTY 账户
const targetContract = '0xbd83EF1a5A45b54d94895C1897aF2d00154520D5' ;
const balance = await web3.eth .getBalance (targetContract);
const nonce = await web3.eth .getTransactionCount (targetContract);
const code = await web3.eth .getCode (targetContract);
console .log (`balance: ${balance} ` );
console .log (`nonce: ${nonce} ` );
console .log (`code: ${code} ` );
8. Message Call 消息调用 (internal Transaction)
公式 (102) 消息调用函数 Θ \Theta Θ
( σ ′ , g ′ , A , z , o ) ≡ Θ ( σ , s , o , r , c , g , p , v , v ~ , d , e , w ) (\boldsymbol{\sigma}', g', A, z, \mathbf{o}) \equiv {\Theta}(\boldsymbol{\sigma}, s, o, r, c, g, p, v, \tilde{v}, \mathbf{d}, e, w) ( σ ′ , g ′ , A , z , o ) ≡ Θ ( σ , s , o , r , c , g , p , v , v ~ , d , e , w )
函数参数
σ \boldsymbol{\sigma} σ
s s s
o o o
r r r
c c c
g g g
p p p
v v v
d \mathbf{d} d
消息调用的 input data (二进制字符串)
e e e
w w w
函数输出
σ ′ \boldsymbol{\sigma}' σ ′
g ′ g' g ′
A A A
z z z
o \mathbf{o} o
注意区分
v v v
v ~ \tilde{v} v ~
D E L E G A T E C A L L {\small DELEGATECALL} D E L EG A TEC A LL 指令上下文的中的 value
公式 (103) 临时状态 σ 1 \boldsymbol{\sigma}_1 σ 1
σ 1 [ r ] b ≡ σ [ r ] b + v ∧ σ 1 [ s ] b ≡ σ [ s ] b − v u n l e s s s = r \begin{aligned}
&\boldsymbol{\sigma}_1[r]_{\mathrm{b}} \equiv \boldsymbol{\sigma}[r]_{\mathrm{b}} + v \quad\wedge\quad \boldsymbol{\sigma}_1[s]_{\mathrm{b}} \equiv \boldsymbol{\sigma}[s]_{\mathrm{b}} - v \\
& unless s = r
\end{aligned} σ 1 [ r ] b ≡ σ [ r ] b + v ∧ σ 1 [ s ] b ≡ σ [ s ] b − v u n l esss = r
意味着
公式 (104) (105) (106) (107) (108) (109) 状态转换 σ \boldsymbol{\sigma} σ -> σ 1 ′ \boldsymbol{\sigma}_1' σ 1 ′ -> σ 1 \boldsymbol{\sigma}_1 σ 1
σ 1 ≡ σ 1 ′ except: %\boxed{%
\boldsymbol{\sigma}_1 \equiv \boldsymbol{\sigma}_1' \quad \text{except:}
%}% σ 1 ≡ σ 1 ′ except:
σ 1 [ s ] ≡ { ∅ if σ 1 ′ [ s ] = ∅ ∧ v = 0 a 1 otherwise \boldsymbol{\sigma}_1[s] \equiv \begin{cases}
\varnothing & \text{if}\ \boldsymbol{\sigma}_1'[s] = \varnothing \ \wedge\ v = 0 \\
\mathbf{a}_1 &\text{otherwise} \\
\end{cases} \\ σ 1 [ s ] ≡ { ∅ a 1 if σ 1 ′ [ s ] = ∅ ∧ v = 0 otherwise
a 1 ≡ ( σ 1 ′ [ s ] n , σ 1 ′ [ s ] b − v , σ 1 ′ [ s ] s , σ 1 ′ [ s ] c ) \mathbf{a}_1 \equiv \left(\boldsymbol{\sigma}_1'[s]_{\mathrm{n}}, \boldsymbol{\sigma}_1'[s]_{\mathrm{b}} - v, \boldsymbol{\sigma}_1'[s]_{\mathbf{s}}, \boldsymbol{\sigma}_1'[s]_{\mathrm{c}}\right) a 1 ≡ ( σ 1 ′ [ s ] n , σ 1 ′ [ s ] b − v , σ 1 ′ [ s ] s , σ 1 ′ [ s ] c )
and σ 1 ′ ≡ σ except: \text{and}\quad \boldsymbol{\sigma}_1' \equiv \boldsymbol{\sigma} \quad \text{except:} and σ 1 ′ ≡ σ except:
{ σ 1 ′ [ r ] ≡ ( 0 , v , T R I E ( ∅ ) , K E C ( ( ) ) ) if σ [ r ] = ∅ ∧ v ≠ 0 σ 1 ′ [ r ] ≡ ∅ if σ [ r ] = ∅ ∧ v = 0 σ 1 ′ [ r ] ≡ a 1 ′ otherwise \begin{cases}
\boldsymbol{\sigma}_1'[r] \equiv (0, v, \mathtt{TRIE}(\varnothing), \mathtt{KEC}(())) & \text{if} \quad \boldsymbol{\sigma}[r] = \varnothing \wedge v \neq 0 \\
\boldsymbol{\sigma}_1'[r] \equiv \varnothing & \text{if}\quad \boldsymbol{\sigma}[r] = \varnothing \wedge v = 0 \\
\boldsymbol{\sigma}_1'[r] \equiv \mathbf{a}_1' & \text{otherwise}
\end{cases} ⎩ ⎨ ⎧ σ 1 ′ [ r ] ≡ ( 0 , v , TRIE ( ∅ ) , KEC (( ))) σ 1 ′ [ r ] ≡ ∅ σ 1 ′ [ r ] ≡ a 1 ′ if σ [ r ] = ∅ ∧ v = 0 if σ [ r ] = ∅ ∧ v = 0 otherwise
a 1 ′ ≡ ( σ [ r ] n , σ [ r ] b + v , σ [ r ] s , σ [ r ] c ) \mathbf{a}_1' \equiv (\boldsymbol{\sigma}[r]_{\mathrm{n}}, \boldsymbol{\sigma}[r]_{\mathrm{b}} + v, \boldsymbol{\sigma}[r]_{\mathbf{s}}, \boldsymbol{\sigma}[r]_{\mathrm{c}}) a 1 ′ ≡ ( σ [ r ] n , σ [ r ] b + v , σ [ r ] s , σ [ r ] c )
执行过程参考 #9 Execution Model
公式 (110) (111) ... (123) 最终状态 σ ′ \boldsymbol{\sigma}' σ ′
σ ′ ≡ { σ if σ ∗ ∗ = ∅ σ ∗ ∗ otherwise g ′ ≡ { 0 if σ ∗ ∗ = ∅ ∧ o = ∅ g ∗ ∗ otherwise z ≡ { 0 if σ ∗ ∗ = ∅ 1 otherwise ( σ ∗ ∗ , g ∗ ∗ , A , o ) ≡ Ξ I a ≡ r I o ≡ o I p ≡ p I d ≡ d I s ≡ s I v ≡ v ~ I e ≡ e I w ≡ w t ≡ { s , r } w h e r e Ξ ≡ { Ξ E C R E C ( σ 1 , g , I , t ) if c = 1 Ξ S H A 256 ( σ 1 , g , I , t ) if c = 2 Ξ R I P 160 ( σ 1 , g , I , t ) if c = 3 Ξ I D ( σ 1 , g , I , t ) if c = 4 Ξ E X P M O D ( σ 1 , g , I , t ) if c = 5 Ξ B N _ A D D ( σ 1 , g , I , t ) if c = 6 Ξ B N _ M U L ( σ 1 , g , I , t ) if c = 7 Ξ S N A R K V ( σ 1 , g , I , t ) if c = 8 Ξ B L A K E 2 _ F ( σ 1 , g , I , t ) if c = 9 Ξ ( σ 1 , g , I , t ) otherwise \begin{aligned}
\boldsymbol{\sigma}' & \quad\equiv\quad \begin{cases}
\boldsymbol{\sigma} & \text{if} \quad \boldsymbol{\sigma}^{**} = \varnothing \\
\boldsymbol{\sigma}^{**} & \text{otherwise}
\end{cases} \\
g' & \quad\equiv\quad \begin{cases}
0 & \text{if} \quad \boldsymbol{\sigma}^{**} = \varnothing \ \wedge \mathbf{o} = \varnothing \\
g^{**} & \text{otherwise}
\end{cases} \\
z & \quad\equiv\quad \begin{cases}
0 & \text{if} \quad \boldsymbol{\sigma}^{**} = \varnothing \\
1 & \text{otherwise}
\end{cases} \\
(\boldsymbol{\sigma}^{**}, g^{**},A, \mathbf{o}) & \quad\equiv\quad \Xi\\
I_{\mathrm{a}} & \quad\equiv\quad r \\
I_{\mathrm{o}} & \quad\equiv\quad o \\
I_{\mathrm{p}} & \quad\equiv\quad p \\
I_{\mathbf{d}} & \quad\equiv\quad \mathbf{d} \\
I_{\mathrm{s}} & \quad\equiv\quad s \\
I_{\mathrm{v}} & \quad\equiv\quad \tilde{v} \\
I_{\mathrm{e}} & \quad\equiv\quad e \\
I_{\mathrm{w}} & \quad\equiv\quad w \\
\mathbf{t} & \quad\equiv\quad \{s, r\} \\
where \\
\end{aligned} \\
\Xi \equiv \begin{cases}
\Xi_{\mathtt{ECREC}}(\boldsymbol{\sigma}_1, g, I, \mathbf{t}) & \text{if} \quad c = 1 \\
\Xi_{\mathtt{SHA256}}(\boldsymbol{\sigma}_1, g, I, \mathbf{t}) & \text{if} \quad c = 2 \\
\Xi_{\mathtt{RIP160}}(\boldsymbol{\sigma}_1, g, I, \mathbf{t}) & \text{if} \quad c = 3 \\
\Xi_{\mathtt{ID}}(\boldsymbol{\sigma}_1, g, I, \mathbf{t}) & \text{if} \quad c = 4 \\
\Xi_{\mathtt{EXPMOD}}(\boldsymbol{\sigma}_1, g, I, \mathbf{t}) & \text{if} \quad c = 5 \\
\Xi_{\mathtt{BN\_ADD}}(\boldsymbol{\sigma}_1, g, I, \mathbf{t}) & \text{if} \quad c = 6 \\
\Xi_{\mathtt{BN\_MUL}}(\boldsymbol{\sigma}_1, g, I, \mathbf{t}) & \text{if} \quad c = 7 \\
\Xi_{\mathtt{SNARKV}}(\boldsymbol{\sigma}_1, g, I, \mathbf{t}) & \text{if} \quad c = 8 \\
\Xi_{\mathtt{BLAKE2\_F}}(\boldsymbol{\sigma}_1, g, I, \mathbf{t}) & \text{if} \quad c = 9 \\
\Xi(\boldsymbol{\sigma}_1, g, I, \mathbf{t}) & \text{otherwise} \end{cases} σ ′ g ′ z ( σ ∗∗ , g ∗∗ , A , o ) I a I o I p I d I s I v I e I w t w h ere ≡ { σ σ ∗∗ if σ ∗∗ = ∅ otherwise ≡ { 0 g ∗∗ if σ ∗∗ = ∅ ∧ o = ∅ otherwise ≡ { 0 1 if σ ∗∗ = ∅ otherwise ≡ Ξ ≡ r ≡ o ≡ p ≡ d ≡ s ≡ v ~ ≡ e ≡ w ≡ { s , r } Ξ ≡ ⎩ ⎨ ⎧ Ξ ECREC ( σ 1 , g , I , t ) Ξ SHA256 ( σ 1 , g , I , t ) Ξ RIP160 ( σ 1 , g , I , t ) Ξ ID ( σ 1 , g , I , t ) Ξ EXPMOD ( σ 1 , g , I , t ) Ξ BN_ADD ( σ 1 , g , I , t ) Ξ BN_MUL ( σ 1 , g , I , t ) Ξ SNARKV ( σ 1 , g , I , t ) Ξ BLAKE2_F ( σ 1 , g , I , t ) Ξ ( σ 1 , g , I , t ) if c = 1 if c = 2 if c = 3 if c = 4 if c = 5 if c = 6 if c = 7 if c = 8 if c = 9 otherwise
Let K E C ( I b ) = σ [ c ] c \text{Let} \; \mathtt{KEC}(I_{\mathbf{b}}) = \boldsymbol{\sigma}[c]_{\mathrm{c}} Let KEC ( I b ) = σ [ c ] c
其中
I a I_{\mathrm{a}} I a
I o I_{\mathrm{o}} I o
I p I_{\mathrm{p}} I p
I d I_{\mathbf{d}} I d
消息调用的 input data (二进制字符串)
I s I_{\mathrm{s}} I s
I v I_{\mathrm{v}} I v
v ~ \tilde{v} v ~
D E L E G A T E C A L L {\small DELEGATECALL} D E L EG A TEC A LL 指令上下文的中的 value
I e I_{\mathrm{e}} I e
I w I_{\mathrm{w}} I w
注意
映射
客户端会存储映射 K E C ( I b ) \mathtt{KEC}(I_{\mathbf{b}}) KEC ( I b ) => I b I_{\mathbf{b}} I b
这样可以方便根据 σ [ c ] c \boldsymbol{\sigma}[c]_{\mathrm{c}} σ [ c ] c 索引并取出目标地址的代码 I b I_{\mathbf{b}} I b 以执行
预编译合约
9. Execution Model 执行模型
参考 go-ethereum 源码
func applyTransaction (msg types.Message, config *params.ChainConfig, bc ChainContext, author *common.Address, gp *GasPool, statedb *state.StateDB, blockNumber *big.Int, blockHash common.Hash, tx *types.Transaction, usedGas *uint64 , evm *vm.EVM) (*types.Receipt, error );
func ApplyMessage (evm *vm.EVM, msg Message, gp *GasPool) (*ExecutionResult, error );
func (st *StateTransition) TransitionDb() (*ExecutionResult, error );
func (evm *EVM) Call(caller ContractRef, addr common.Address, input []byte , gas uint64 , value *big.Int) (ret []byte , leftOverGas uint64 , err error );
func (in *EVMInterpreter) Run(contract *Contract, input []byte , readOnly bool ) (ret []byte , err error );
type (
executionFunc func (pc *uint64 , interpreter *EVMInterpreter, callContext *ScopeContext) ([]byte , error )
)
type operation struct {
execute executionFunc
}
9.1 Basics 基础
9.2 Fees Overview 费用概述
消耗
代码执行
进一步的 消息调用 或 合约创建
内存使用
refund
如果清除了一块存储,系统会免除这项操作的费用,且返还一定额度的 refund
参考 # Appendix G. Fee Schedule
R s c l e a r R_{\mathrm{sclear}} R sclear
R s e l f d e s t r u c t R_{\mathrm{selfdestruct}} R selfdestruct
9.3 Execution Environment 执行环境
I I I 执行环境
组成
I a I_{\mathrm{a}} I a
I o I_{\mathrm{o}} I o
I p I_{\mathrm{p}} I p
I d I_{\mathbf{d}} I d
消息调用的 input data (二进制字符串)
I s I_{\mathrm{s}} I s
I v I_{\mathrm{v}} I v
I b I_{\mathrm{b}} I b
I H I_{\mathrm{H}} I H
I e I_{\mathrm{e}} I e
I w I_{\mathrm{w}} I w
公式 (124) 函数 Ξ \Xi Ξ
( σ ′ , g ′ , A , o ) ≡ Ξ ( σ , g , I ) (\boldsymbol{\sigma}', g', A, \mathbf{o}) \equiv \Xi(\boldsymbol{\sigma}, g, I) ( σ ′ , g ′ , A , o ) ≡ Ξ ( σ , g , I )
其中
公式 (125) 累计子状态 A A A
A ≡ ( A s , A l , A t , A r ) A \equiv (A_{\mathbf{s}}, A_{\mathbf{l}}, A_{\mathbf{t}}, A_{\mathrm{r}}) A ≡ ( A s , A l , A t , A r )
A s A_{\mathbf{s}} A s
A l A_{\mathbf{l}} A l
A t A_{\mathbf{t}} A t
A r A_{\mathbf{r}} A r
9.4 Execution Overview 执行概述
公式 (126) (127) (128) ... (137) (138) 函数 Ξ {\Xi} Ξ 的定义
Ξ ( σ , g , I , T ) ≡ ( σ ′ , μ g ′ , A , o ) ( σ ′ , μ ′ , A , . . . , o ) ≡ X ( ( σ , μ , A 0 , I ) ) μ g ≡ g μ p c ≡ 0 μ m ≡ ( 0 , 0 , . . . ) μ i ≡ 0 μ s ≡ ( ) μ o ≡ ( ) \begin{aligned}
\Xi(\boldsymbol{\sigma}, g, I, T) & \quad\equiv\quad (\boldsymbol{\sigma}'\!, \boldsymbol{\mu}'_{\mathrm{g}}, A, \mathbf{o}) \\
(\boldsymbol{\sigma}', \boldsymbol{\mu}'\!, A, ..., \mathbf{o}) & \quad\equiv\quad X\big((\boldsymbol{\sigma}, \boldsymbol{\mu}, A^0\!, I)\big) \\
\boldsymbol{\mu}_{\mathrm{g}} & \quad\equiv\quad g \\
\boldsymbol{\mu}_{\mathrm{pc}} & \quad\equiv\quad 0 \\
\boldsymbol{\mu}_{\mathbf{m}} & \quad\equiv\quad (0, 0, ...) \\
\boldsymbol{\mu}_{\mathrm{i}} & \quad\equiv\quad 0 \\
\boldsymbol{\mu}_{\mathbf{s}} & \quad\equiv\quad () \\
\boldsymbol{\mu}_{\mathbf{o}} & \quad\equiv\quad ()
\end{aligned} Ξ ( σ , g , I , T ) ( σ ′ , μ ′ , A , ... , o ) μ g μ pc μ m μ i μ s μ o ≡ ( σ ′ , μ g ′ , A , o ) ≡ X ( ( σ , μ , A 0 , I ) ) ≡ g ≡ 0 ≡ ( 0 , 0 , ... ) ≡ 0 ≡ ( ) ≡ ( )
X ( ( σ , μ , A , I ) ) ≡ { ( ∅ , μ , A 0 , I , ∅ ) if Z ( σ , μ , I ) ( ∅ , μ ′ , A 0 , I , o ) if w = REVERT O ( σ , μ , A , I ) ⋅ o if o ≠ ∅ X ( O ( σ , μ , A , I ) ) otherwise X\big( (\boldsymbol{\sigma}, \boldsymbol{\mu}, A, I) \big) \equiv \begin{cases}
\big(\varnothing, \boldsymbol{\mu}, A^0, I, \varnothing\big) & \text{if} \quad Z(\boldsymbol{\sigma}, \boldsymbol{\mu}, I) \\
\big(\varnothing, \boldsymbol{\mu}', A^0, I, \mathbf{o}\big) & \text{if} \quad w = \text{\small REVERT} \\
O(\boldsymbol{\sigma}, \boldsymbol{\mu}, A, I) \cdot \mathbf{o} & \text{if} \quad \mathbf{o} \neq \varnothing \\
X\big(O(\boldsymbol{\sigma}, \boldsymbol{\mu}, A, I)\big) & \text{otherwise} \\
\end{cases} X ( ( σ , μ , A , I ) ) ≡ ⎩ ⎨ ⎧ ( ∅ , μ , A 0 , I , ∅ ) ( ∅ , μ ′ , A 0 , I , o ) O ( σ , μ , A , I ) ⋅ o X ( O ( σ , μ , A , I ) ) if Z ( σ , μ , I ) if w = REVERT if o = ∅ otherwise
where
o ≡ H ( μ , I ) ( a , b , c , d ) ⋅ e ≡ ( a , b , c , d , e ) μ ′ ≡ μ except: μ g ′ ≡ μ g − C ( σ , μ , I ) \begin{aligned}
\mathbf{o} & \quad\equiv\quad H(\boldsymbol{\mu}, I) \\
(a, b, c, d) \cdot e & \quad\equiv\quad (a, b, c, d, e) \\
\boldsymbol{\mu}' & \quad\equiv\quad \boldsymbol{\mu}\ \text{except:} \\
\boldsymbol{\mu}'_{\mathrm{g}} & \quad\equiv\quad \boldsymbol{\mu}_{\mathrm{g}} - C(\boldsymbol{\sigma}, \boldsymbol{\mu}, I)
\end{aligned} o ( a , b , c , d ) ⋅ e μ ′ μ g ′ ≡ H ( μ , I ) ≡ ( a , b , c , d , e ) ≡ μ except: ≡ μ g − C ( σ , μ , I )
其中
X X X
O O O
Z Z Z
o o o
H H H
检查是否正常终止
返回 ∅ \varnothing ∅ 空,表示继续执行
返回 ( ) () ( ) 空集,表示停止执行
否则,表示有意识的停止执行并附加执行结果 o o o
参考 (145)
C ( σ , μ , I ) C(\boldsymbol{\sigma}, \boldsymbol{\mu}, I) C ( σ , μ , I )
参考 (314)
Appendix H.1. Gas Cost
μ g \boldsymbol{\mu}_{\mathrm{g}} μ g
μ p c \boldsymbol{\mu}_{\mathrm{pc}} μ pc
μ m \boldsymbol{\mu}_{\mathbf{m}} μ m
μ i \boldsymbol{\mu}_{\mathrm{i}} μ i
active number of words in memory
μ s \boldsymbol{\mu}_{\mathbf{s}} μ s
μ o \boldsymbol{\mu}_{\mathbf{o}} μ o
注意
公式 (146),执行函数 Ξ \Xi Ξ 后,会丢弃 I ′ I' I ′ 并记录 μ g ′ \boldsymbol{\mu}'_{\mathrm{g}} μ g ′ 和 o o o
9.4.1 Machine State
机器状态 μ \boldsymbol{\mu} μ 组成为 ( g , p c , m , i , s ) (g, pc, \mathbf{m}, i, \mathbf{s}) ( g , p c , m , i , s )
(139) 当前待执行的指令 w w w
w ≡ { I b [ μ p c ] if μ p c < ∥ I b ∥ STOP otherwise w \equiv \begin{cases} I_{\mathbf{b}}[\boldsymbol{\mu}_{\mathrm{pc}}] & \text{if} \quad \boldsymbol{\mu}_{\mathrm{pc}} < \lVert I_{\mathbf{b}} \rVert \\
\text{{\small STOP}} & \text{otherwise}
\end{cases} w ≡ { I b [ μ pc ] STOP if μ pc < ∥ I b ∥ otherwise
func (in *EVMInterpreter) Run(contract *Contract, input []byte , readOnly bool ) (ret []byte , err error )
op = contract.GetOp(pc)
operation := in.cfg.JumpTable[op]
func (c *Contract) GetOp(n uint64 ) OpCode {
return OpCode(c.GetByte(n))
}
func (c *Contract) GetByte(n uint64 ) byte {
if n < uint64 (len (c.Code)) {
return c.Code[n]
}
return 0
}
9.4.2 Exception Halting
公式 (140) (141) 异常检查函数 Z Z Z
Z ( σ , μ , I ) ≡ μ g < C ( σ , μ , I ) ∨ δ w = ∅ ∨ ∥ μ s ∥ < δ w ∨ ( w = JUMP ∧ μ s [ 0 ] ∉ D ( I b ) ) ∨ ( w = JUMPI ∧ μ s [ 1 ] ≠ 0 ∧ μ s [ 0 ] ∉ D ( I b ) ) ∨ ( w = RETURNDATACOPY ∧ μ s [ 1 ] + μ s [ 2 ] > ∥ μ o ∥ ) ∨ ∥ μ s ∥ − δ w + α w > 1024 ∨ ( ¬ I w ∧ W ( w , μ ) ) ∨ ( w = SSTORE ∧ μ g ⩽ G c a l l s t i p e n d ) \begin{aligned}
Z(\boldsymbol{\sigma}, \boldsymbol{\mu}, I) \quad\equiv\quad
& \boldsymbol{\mu}_g < C(\boldsymbol{\sigma}, \boldsymbol{\mu}, I) \quad \vee \\
& \mathbf{\delta}_w = \varnothing \quad \vee \\
& \lVert\boldsymbol{\mu}_\mathbf{s}\rVert < \mathbf{\delta}_w \quad \vee \\
& ( w = \text{\small JUMP} \; \wedge \; \boldsymbol{\mu}_\mathbf{s}[0] \notin D(I_\mathbf{b}) ) \quad \vee \\
& ( w = \text{\small JUMPI} \; \wedge \; \boldsymbol{\mu}_\mathbf{s}[1] \neq 0 \; \wedge\boldsymbol{\mu}_\mathbf{s}[0] \notin D(I_\mathbf{b}) ) \quad \vee \\
& ( w = \text{\small RETURNDATACOPY} \; \wedge \boldsymbol{\mu}_{\mathbf{s}}[1] + \boldsymbol{\mu}_{\mathbf{s}}[2] > \lVert\boldsymbol{\mu}_{\mathbf{o}}\rVert) \quad \vee \\
& \lVert\boldsymbol{\mu}_\mathbf{s}\rVert - \mathbf{\delta}_w + \mathbf{\alpha}_w > 1024 \quad \vee \\
& ( \neg I_{\mathrm{w}} \; \wedge \; W(w, \boldsymbol{\mu}) ) \quad \vee \\
& ( w = \text{\small SSTORE} \; \wedge \; \boldsymbol{\mu}_g \leqslant G_{\mathrm{callstipend}} )
\end{aligned} Z ( σ , μ , I ) ≡ μ g < C ( σ , μ , I ) ∨ δ w = ∅ ∨ ∥ μ s ∥ < δ w ∨ ( w = JUMP ∧ μ s [ 0 ] ∈ / D ( I b )) ∨ ( w = JUMPI ∧ μ s [ 1 ] = 0 ∧ μ s [ 0 ] ∈ / D ( I b )) ∨ ( w = RETURNDATACOPY ∧ μ s [ 1 ] + μ s [ 2 ] > ∥ μ o ∥) ∨ ∥ μ s ∥ − δ w + α w > 1024 ∨ ( ¬ I w ∧ W ( w , μ )) ∨ ( w = SSTORE ∧ μ g ⩽ G callstipend )
where
W ( w , μ ) ≡ w ∈ { CREATE , CREATE2 , SSTORE , SELFDESTRUCT } ∨ LOG0 ≤ w ∧ w ≤ LOG4 ∨ w = CALL ∧ μ s [ 2 ] ≠ 0 \begin{aligned}
W(w, \boldsymbol{\mu}) \quad\equiv\quad
& w \in \{\text{\small CREATE}, \text{\small CREATE2}, \text{\small SSTORE}, \text{\small SELFDESTRUCT}\} \ \vee \\
& \text{\small LOG0} \le w \; \wedge \; w \le \text{\small LOG4} \quad \vee \\
& w = \text{\small CALL} \; \wedge \; \boldsymbol{\mu}_{\mathbf{s}}[2] \neq 0
\end{aligned} W ( w , μ ) ≡ w ∈ { CREATE , CREATE2 , SSTORE , SELFDESTRUCT } ∨ LOG0 ≤ w ∧ w ≤ LOG4 ∨ w = CALL ∧ μ s [ 2 ] = 0
其中
异常情况
var (
ErrOutOfGas = errors.New("out of gas" )
ErrCodeStoreOutOfGas = errors.New("contract creation code storage out of gas" )
ErrDepth = errors.New("max call depth exceeded" )
ErrInsufficientBalance = errors.New("insufficient balance for transfer" )
ErrContractAddressCollision = errors.New("contract address collision" )
ErrExecutionReverted = errors.New("execution reverted" )
ErrMaxCodeSizeExceeded = errors.New("max code size exceeded" )
ErrInvalidJump = errors.New("invalid jump destination" )
ErrWriteProtection = errors.New("write protection" )
ErrReturnDataOutOfBounds = errors.New("return data out of bounds" )
ErrGasUintOverflow = errors.New("gas uint64 overflow" )
ErrInvalidCode = errors.New("invalid code: must not begin with 0xef" )
ErrStackUnderflow = errors.New(fmt.Sprintf("stack underflow (%d <=> %d)" , e.stackLen, e.required))
ErrStackOverflow = errors.New(fmt.Sprintf("stack limit reached %d (%d)" , e.stackLen, e.limit))
ErrInvalidOpCode = errors.New(fmt.Sprintf("invalid opcode: %s" , e.opcode))
)
9.4.3 Jump Destionation Validity 跳转地址验证
公式 (142) (143) (144)
D ( c ) ≡ D J ( c , 0 ) D(\mathbf{c}) \equiv D_{\mathrm{J}}(\mathbf{c}, 0) D ( c ) ≡ D J ( c , 0 )
where:
D J ( c , i ) ≡ { { } if i ⩾ ∥ c ∥ { i } ∪ D J ( c , N ( i , c [ i ] ) ) if c [ i ] = JUMPDEST D J ( c , N ( i , c [ i ] ) ) otherwise D_{\mathrm{J}}(\mathbf{c}, i) \equiv \begin{cases}
\{\} & \text{if} \quad i \geqslant \lVert \mathbf{c} \rVert \\
\{ i \} \cup D_{\mathrm{J}}(\mathbf{c}, N(i, \mathbf{c}[i])) & \text{if} \quad \mathbf{c}[i] = \text{\small JUMPDEST} \\
D_{\mathrm{J}}(\mathbf{c}, N(i, \mathbf{c}[i])) & \text{otherwise} \\
\end{cases} D J ( c , i ) ≡ ⎩ ⎨ ⎧ { } { i } ∪ D J ( c , N ( i , c [ i ])) D J ( c , N ( i , c [ i ])) if i ⩾ ∥ c ∥ if c [ i ] = JUMPDEST otherwise
N ( i , w ) ≡ { i + w − PUSH1 + 2 if w ∈ [ PUSH1 , PUSH32 ] i + 1 otherwise N(i, w) \equiv \begin{cases}
i + w - \text{\small PUSH1} + 2 & \text{if} \quad w \in [\text{\small PUSH1}, \text{\small PUSH32}] \\
i + 1 & \text{otherwise} \end{cases} N ( i , w ) ≡ { i + w − PUSH1 + 2 i + 1 if w ∈ [ PUSH1 , PUSH32 ] otherwise
其中
c \mathbf{c} c
D D D TODO
计算 c \mathbf{c} c 的有效跳转地址的集合
按 J U M P D E S T {\small JUMPDEST} J U MP D EST 指令的位置来定义
N N N TODO
下一有效指令在代码 c \mathbf{c} c 中的位置
且忽略 PUSH1 \text{\small PUSH1} PUSH1 指令的数据(如果有的话)
9.4.4 Normal Halting
(145) 正常停止检查函数 H H H
H ( μ , I ) ≡ { H RETURN ( μ ) if w ∈ { RETURN , REVERT } ( ) if w ∈ { STOP , SELFDESTRUCT } ∅ otherwise H(\boldsymbol{\mu}, I) \equiv \begin{cases}
H_{\text{\tiny RETURN}}(\boldsymbol{\mu}) & \text{if} \quad w \in \{\text{\small {RETURN}}, \text{\small REVERT}\} &\\
() & \text{if} \quad w \in \{ \text{\small {STOP}}, \text{\small {SELFDESTRUCT}} \} &\\
\varnothing & \text{otherwise}
\end{cases} H ( μ , I ) ≡ ⎩ ⎨ ⎧ H RETURN ( μ ) ( ) ∅ if w ∈ { RETURN , REVERT } if w ∈ { STOP , SELFDESTRUCT } otherwise
有3种可能的输出
其中
H RETURN H_{\text{\tiny RETURN}} H RETURN
表示有意识地停止执行并附加执行结果 o o o
参考 # Appendix H. Virtual Machine Specification
H RETURN ( μ ) ≡ μ m [ μ s [ 0 ] … ( μ s [ 0 ] + μ s [ 1 ] − 1 ) ] H_{\text{\tiny RETURN}}(\boldsymbol{\mu}) \equiv \boldsymbol{\mu}_{\mathbf{m}}[ \boldsymbol{\mu}_{\mathbf{s}}[0] \dots ( \boldsymbol{\mu}_{\mathbf{s}}[0] + \boldsymbol{\mu}_{\mathbf{s}}[1] - 1 ) ] H RETURN ( μ ) ≡ μ m [ μ s [ 0 ] … ( μ s [ 0 ] + μ s [ 1 ] − 1 )]
( ) () ( ) 空集
∅ \varnothing ∅ 空
9.5 The Execution Cycle 执行循环
公式 (146) (147) (148) (149)
O ( ( σ , μ , A , I ) ) ≡ ( σ ′ , μ ′ , A ′ , I ) Δ ≡ α w − δ w ∥ μ s ′ ∥ ≡ ∥ μ s ∥ + Δ ∀ x ∈ [ α w , ∥ μ s ′ ∥ ) : μ s ′ [ x ] ≡ μ s [ x − Δ ] \begin{aligned}
O\big((\boldsymbol{\sigma}, \boldsymbol{\mu}, A, I)\big) & \quad\equiv\quad (\boldsymbol{\sigma}', \boldsymbol{\mu}', A', I) \\
\Delta & \quad\equiv\quad \mathbf{\alpha}_{w} - \mathbf{\delta}_{w} \\
\lVert\boldsymbol{\mu}'_{\mathbf{s}}\rVert & \quad\equiv\quad \lVert\boldsymbol{\mu}_{\mathbf{s}}\rVert + \Delta \\
\quad \forall x \in [\mathbf{\alpha}_{w}, \lVert\boldsymbol{\mu}'_{\mathbf{s}}\rVert): \boldsymbol{\mu}'_{\mathbf{s}}[x] & \quad\equiv\quad \boldsymbol{\mu}_{\mathbf{s}}[x-\Delta]
\end{aligned} O ( ( σ , μ , A , I ) ) Δ ∥ μ s ′ ∥ ∀ x ∈ [ α w , ∥ μ s ′ ∥) : μ s ′ [ x ] ≡ ( σ ′ , μ ′ , A ′ , I ) ≡ α w − δ w ≡ ∥ μ s ∥ + Δ ≡ μ s [ x − Δ ]
其中
δ \delta δ
α \alpha α
Δ \Delta Δ
栈的索引
公式 (150) (151)
μ g ′ ≡ μ g − C ( σ , μ , I ) μ p c ′ ≡ { J JUMP ( μ ) if w = JUMP J JUMPI ( μ ) if w = JUMPI N ( μ p c , w ) otherwise \begin{aligned}
\boldsymbol{\mu}'_{\mathrm{g}} & \quad\equiv\quad \boldsymbol{\mu}_{\mathrm{g}} - C(\boldsymbol{\sigma}, \boldsymbol{\mu}, I) \\
\boldsymbol{\mu}'_{\mathrm{pc}} & \quad\equiv\quad \begin{cases}
{J_{\text{JUMP}}}(\boldsymbol{\mu}) & \text{if} \quad w = \text{\small JUMP} \\
{J_{\text{JUMPI}}}(\boldsymbol{\mu}) & \text{if} \quad w = \text{\small JUMPI} \\
N(\boldsymbol{\mu}_{\mathrm{pc}}, w) & \text{otherwise}
\end{cases}
\end{aligned} μ g ′ μ pc ′ ≡ μ g − C ( σ , μ , I ) ≡ ⎩ ⎨ ⎧ J JUMP ( μ ) J JUMPI ( μ ) N ( μ pc , w ) if w = JUMP if w = JUMPI otherwise
其中
公式 (152) (153) (154) (155)
μ m ′ ≡ μ m μ i ′ ≡ μ i A ′ ≡ A σ ′ ≡ σ \begin{aligned}
\boldsymbol{\mu}'_{\mathbf{m}} & \quad\equiv\quad \boldsymbol{\mu}_{\mathbf{m}} \\
\boldsymbol{\mu}'_{\mathrm{i}} & \quad\equiv\quad \boldsymbol{\mu}_{\mathrm{i}} \\
A' & \quad\equiv\quad A \\
\boldsymbol{\sigma}' & \quad\equiv\quad \boldsymbol{\sigma}
\end{aligned} μ m ′ μ i ′ A ′ σ ′ ≡ μ m ≡ μ i ≡ A ≡ σ
通常我们假定内存(μ m ′ \boldsymbol{\mu}'_{\mathbf{m}} μ m ′ , μ i ′ \boldsymbol{\mu}'_{\mathbf{i}} μ i ′ ),自毁集合,世界状态不会被修改
具体参考 # Appendix H. Virtual Machine Specification
10. Blocktree to Blockchain 区块树到区块链
(156) (157) 区块难度计算函数
B t ≡ B t ′ + B d B ′ ≡ P ( B H ) \begin{aligned}
B_{\mathrm{t}} & \equiv B'_{\mathrm{t}} + B_{\mathrm{d}} \\
B' & \equiv P(B_{\mathrm{H}})
\end{aligned} B t B ′ ≡ B t ′ + B d ≡ P ( B H )
其中
B B B
B ′ B' B ′
B t B_{\mathrm{t}} B t
B d B_{\mathrm{d}} B d
11. Block Finalization 区块定稿
区块定稿要经过 4 步验证
验证叔块 Ommer Validation
验证交易 Transaction Validation
奖励发放 Reward Application
验证状态和 nonce State & Nonce Validation
11.1 Ommer Validation 验证 Ommer
(158) (159) (160)
∥ B U ∥ ⩽ 2 ⋀ U ∈ B U V ( U ) ∧ k ( U , P ( B H ) H , 6 ) \lVert B_{\mathbf{U}} \rVert \leqslant 2 \bigwedge_{\mathbf{U} \in B_{\mathbf{U}}} {V({\mathbf{U}}})\; \wedge \; k({\mathbf{U}}, P(\mathbf{B}_{\mathbf{H}})_{\mathbf{H}}, 6) \\ ∥ B U ∥ ⩽ 2 U ∈ B U ⋀ V ( U ) ∧ k ( U , P ( B H ) H , 6 )
k ( U , H , n ) ≡ { f a l s e if n = 0 s ( U , H ) ∨ k ( U , P ( H ) H , n − 1 ) otherwise k(U, H, n) \equiv \begin{cases} \mathit{false} & \text{if} \quad n = 0 \\
s(U, H) \vee \; k(U, P(H)_{\mathrm{H}}, n - 1) & \text{otherwise}
\end{cases} k ( U , H , n ) ≡ { false s ( U , H ) ∨ k ( U , P ( H ) H , n − 1 ) if n = 0 otherwise
s ( U , H ) ≡ ( P ( H ) = P ( U ) ∧ H ≠ U ∧ U ∉ B ( H ) U ) s(U, H) \equiv (P(H) = P(U)\; \wedge \; H \neq U \; \wedge \; U \notin B(H)_{\mathbf{U}}) s ( U , H ) ≡ ( P ( H ) = P ( U ) ∧ H = U ∧ U ∈ / B ( H ) U )
验证
当前区块头最多有2个叔块
叔块头列表自身有效,且表示的叔块与当前区块在6代以内
其中
11.2 Transaction Validation 交易验证
B H g = ℓ ( R ) u {B_{\mathrm{H}}}_{\mathrm{g}} = {\ell}({\mathbf{R})_{\mathrm{u}}} B H g = ℓ ( R ) u
其中
B H g {B_{\mathrm{H}}}_{\mathrm{g}} B H g
ℓ ( R ) u {\ell}({\mathbf{R})_{\mathrm{u}}} ℓ ( R ) u
11.3 Reward Application 奖励发放
公式 (162) (163) (164) (165) (166) Ω \Omega Ω 区块奖励函数
Ω ( B , σ ) ≡ σ ′ : σ ′ = σ except: σ ′ [ B H c ] b = σ [ B H c ] b + ( 1 + ∥ B U ∥ 32 ) R b l o c k ∀ U ∈ B U : σ ′ [ U c ] = { ∅ if σ [ U c ] = ∅ ∧ R = 0 a ′ otherwise a ′ ≡ ( σ [ U c ] n , σ [ U c ] b + R , σ [ U c ] s , σ [ U c ] c ) R ≡ ( 1 + 1 8 ( U i − B H i ) ) R b l o c k \begin{aligned}
\Omega(B, \boldsymbol{\sigma}) & \quad\equiv\quad \boldsymbol{\sigma}': \boldsymbol{\sigma}' = \boldsymbol{\sigma} \quad \text{except:} \\
\qquad\boldsymbol{\sigma}'[{\mathbf{B}_{\mathrm{H}}}_{\mathrm{c}}]_{\mathrm{b}} & \quad=\quad \boldsymbol{\sigma}[{\mathbf{B}_{\mathrm{H}}}_{\mathrm{c}}]_{\mathrm{b}} + \left(1 + \frac{\lVert \mathbf{B}_{\mathbf{U}}\rVert}{32}\right)R_{\mathrm{block}} \\
\forall \mathbf{U} \in \mathbf{B}_{\mathbf{U}}:\quad
\boldsymbol{\sigma}'[\mathbf{U}_{\mathrm{c}}] & \quad=\quad \begin{cases}
\varnothing &\text{if}\ \boldsymbol{\sigma}[\mathbf{U}_{\mathrm{c}}] = \varnothing\ \wedge\ R = 0 \\
\mathbf{a}' &\text{otherwise}
\end{cases} \\
\mathbf{a}' & \quad\equiv\quad (\boldsymbol{\sigma}[U_{\mathrm{c}}]_{\mathrm{n}}, \boldsymbol{\sigma}[U_{\mathrm{c}}]_{\mathrm{b}} + R, \boldsymbol{\sigma}[U_{\mathrm{c}}]_{\mathbf{s}}, \boldsymbol{\sigma}[U_{\mathrm{c}}]_{\mathrm{c}}) \\
R & \quad\equiv\quad \left(1 + \frac{1}{8} (U_{\mathrm{i}} - {B_{\mathrm{H}}}_{\mathrm{i}})\right) R_{\mathrm{block}}
\end{aligned} Ω ( B , σ ) σ ′ [ B H c ] b ∀ U ∈ B U : σ ′ [ U c ] a ′ R ≡ σ ′ : σ ′ = σ except: = σ [ B H c ] b + ( 1 + 32 ∥ B U ∥ ) R block = { ∅ a ′ if σ [ U c ] = ∅ ∧ R = 0 otherwise ≡ ( σ [ U c ] n , σ [ U c ] b + R , σ [ U c ] s , σ [ U c ] c ) ≡ ( 1 + 8 1 ( U i − B H i ) ) R block
其中
B U \mathbf{B}_{\mathbf{U}} B U
B H c {\mathbf{B}_{\mathrm{H}}}_{\mathrm{c}} B H c
当前区块头中存储的 beneficiary
即当前区块收益的归属地址
U c U_{\mathrm{c}} U c
(167) R b l o c k {R_{block}} R b l oc k 定义
R b l o c k = 1 0 18 × { 5 if H i < F B y z a n t i u m 3 if F B y z a n t i u m ⩽ H i < F C o n s t a n t i n o p l e 2 if H i ⩾ F C o n s t a n t i n o p l e R_{\mathrm{block}} = 10^{18} \times \begin{cases}
5 &\text{if}\ H_{\mathrm{i}} < F_{\mathrm{Byzantium}} \\
3 &\text{if}\ F_{\mathrm{Byzantium}} \leqslant H_{\mathrm{i}} < F_{\mathrm{Constantinople}} \\
2 &\text{if}\ H_{\mathrm{i}} \geqslant F_{\mathrm{Constantinople}} \\
\end{cases} \\ R block = 1 0 18 × ⎩ ⎨ ⎧ 5 3 2 if H i < F Byzantium if F Byzantium ⩽ H i < F Constantinople if H i ⩾ F Constantinople
11.4 State & Nonce Validation 状态和 nonce 验证
(168) 映射 Block 到世界状态的函数 Γ \Gamma Γ
Γ ( B ) ≡ { σ 0 if P ( B H ) = ∅ σ i : T R I E ( L S ( σ i ) ) = P ( B H ) H r otherwise \Gamma(B) \equiv \begin{cases}
\boldsymbol{\sigma}_0 & \text{if} \quad P(B_{\mathrm{H}}) = \varnothing \\
\boldsymbol{\sigma}_{\mathrm{i}}: \mathtt{{TRIE}}(L_{\mathrm{S}}(\boldsymbol{\sigma}_{\mathrm{i}})) = {P(B_{\mathrm{H}})_{\mathrm{H}}}_{\mathrm{r}} & \text{otherwise}
\end{cases} Γ ( B ) ≡ { σ 0 σ i : TRIE ( L S ( σ i )) = P ( B H ) H r if P ( B H ) = ∅ otherwise
其中
L S L_S L S
T R I E ( L S ( σ i ) ) = P ( B H ) H r \mathtt{{TRIE}}(L_{\mathrm{S}}(\boldsymbol{\sigma}_{\mathrm{i}})) = {P(B_{\mathrm{H}})_{\mathrm{H}}}_{\mathrm{r}} TRIE ( L S ( σ i )) = P ( B H ) H r
判断 state TRIE 根节点的内容 等于 区块头的 stateRoot
理解
不像 Block 存储在区块链上,TRIE 树结构是通过存储在客户端数据库中的数据构造出来的
因此需要比较区块头存储中的 stateRoot hash,是否与构造 TRIE 树时层层计算出来的根节点 hash 相等
(169) (170) (171) (172) 区块级别状转换函数 Φ \Phi Φ
Φ ( B ) ≡ B ′ : B ′ = B ∗ except: B n ′ = n : x ⩽ 2 256 H d B m ′ = m with ( x , m ) = P o W ( B n ∗ , n , d ) B ∗ ≡ B except: B r ∗ = r ( Π ( Γ ( B ) , B ) ) \begin{aligned}
\Phi(B) & \quad\equiv\quad B': \quad B' = B^* \quad \text{except:} \\
B'_{\mathrm{n}} & \quad=\quad n: \quad x \leqslant \frac{2^{256}}{{H_{\mathrm{d}}}} \\
B'_{\mathrm{m}} & \quad=\quad m \quad \text{with } (x, m) = \mathtt{PoW}(B^*_{{\cancel{n}}}, n, \mathbf{d}) \\
B^* & \quad\equiv\quad B \quad \text{except:} \quad {{B^*_{\mathrm{r}}}} = {r}({\Pi}(\Gamma(B), B))
\end{aligned} Φ ( B ) B n ′ B m ′ B ∗ ≡ B ′ : B ′ = B ∗ except: = n : x ⩽ H d 2 256 = m with ( x , m ) = PoW ( B n ∗ , n , d ) ≡ B except: B r ∗ = r ( Π ( Γ ( B ) , B ))
Φ \Phi Φ 函数计算 nonce 和 mixHash 后分别设置到 B n ′ B'_{\mathrm{n}} B n ′ 和 B m ′ B'_{\mathrm{m}} B m ′
其中
d \mathbf{d} d
Π \Pi Π
Ω \Omega Ω
(173) 第 n 个状态 σ [ n ] \boldsymbol{\sigma}[n] σ [ n ]
σ [ n ] = { Γ ( B ) if n < 0 Υ ( σ [ n − 1 ] , B T [ n ] ) otherwise \boldsymbol{\sigma}[n] = \begin{cases} {\Gamma}(B) & \text{if} \quad n < 0 \\ {\Upsilon}(\boldsymbol{\sigma}[n - 1], B_{\mathbf{T}}[n]) & \text{otherwise} \end{cases} σ [ n ] = { Γ ( B ) Υ ( σ [ n − 1 ] , B T [ n ]) if n < 0 otherwise
(174) (175) (176) Υ u \Upsilon^{\mathbf{u}} Υ u Υ l \Upsilon^{\mathbf{l}} Υ l Υ z \Upsilon^{\mathbf{z}} Υ z 的定义/赋值
R [ n ] u = { 0 if n < 0 Υ g ( σ [ n − 1 ] , B T [ n ] ) + R [ n − 1 ] u otherwise \begin{aligned}
\mathbf{R}[n]_{\mathrm{u}} = \begin{cases} 0 & \text{if} \quad n < 0 \\
\Upsilon^g(\boldsymbol{\sigma}[n - 1], B_{\mathbf{T}}[n]) \quad + \mathbf{R}[n-1]_{\mathrm{u}} & \text{otherwise} \end{cases}
\end{aligned} R [ n ] u = { 0 Υ g ( σ [ n − 1 ] , B T [ n ]) + R [ n − 1 ] u if n < 0 otherwise
R [ n ] l = Υ l ( σ [ n − 1 ] , B T [ n ] ) \mathbf{R}[n]_{\mathbf{l}} =
\Upsilon^{\mathbf{l}}(\boldsymbol{\sigma}[n - 1], B_{\mathbf{T}}[n]) R [ n ] l = Υ l ( σ [ n − 1 ] , B T [ n ])
R [ n ] z = Υ z ( σ [ n − 1 ] , B T [ n ] ) \mathbf{R}[n]_{\mathrm{z}} =
\Upsilon^{\mathrm{z}}(\boldsymbol{\sigma}[n - 1], B_{\mathbf{T}}[n]) R [ n ] z = Υ z ( σ [ n − 1 ] , B T [ n ])
其中
R u R_{\mathrm{u}} R u
R l R_{\mathrm{l}} R l
R z R_{\mathrm{z}} R z
R b R_{\mathrm{b}} R b
由一系列日志构成的 Bloom 过滤器
参考公式 (26) (27) (28) (29) (30)
公式 (177) 区块级状态转换函数 Π \Pi Π
Π ( σ , B ) ≡ Ω ( B , ℓ ( σ ) ) \Pi(\boldsymbol{\sigma}, B) \equiv {\Omega}(B, \ell(\boldsymbol{\sigma})) Π ( σ , B ) ≡ Ω ( B , ℓ ( σ ))
对区块应用区块奖励函数 Ω {\Omega} Ω ,可以得到最新的世界状态,即最终的区块级状态转换
Appendix B. Recursive Length Prefix
参考 eth wiki: RLP
Appendix C. Hex-Prefix Encoding
公式 (189) (190)
H P ( x , t ) : x ∈ Y ≡ { ( 16 f ( t ) , 16 x [ 0 ] + x [ 1 ] , 16 x [ 2 ] + x [ 3 ] , . . . ) if ∥ x ∥ is even ( 16 ( f ( t ) + 1 ) + x [ 0 ] , 16 x [ 1 ] + x [ 2 ] , 16 x [ 3 ] + x [ 4 ] , . . . ) otherwise \begin{aligned}
\mathtt{HP}(\mathbf{x}, t): \mathbf{x} \in \mathbb{Y} \equiv \begin{cases}
(16f(t), 16\mathbf{x}[0] + \mathbf{x}[1], 16\mathbf{x}[2] + \mathbf{x}[3], ...) &
\text{if} \lVert \mathbf{x} \rVert \; \text{is even} \\
(16(f(t) + 1) + \mathbf{x}[0], 16\mathbf{x}[1] + \mathbf{x}[2], 16\mathbf{x}[3] + \mathbf{x}[4], ...) & \text{otherwise}
\end{cases} \\
\end{aligned} HP ( x , t ) : x ∈ Y ≡ { ( 16 f ( t ) , 16 x [ 0 ] + x [ 1 ] , 16 x [ 2 ] + x [ 3 ] , ... ) ( 16 ( f ( t ) + 1 ) + x [ 0 ] , 16 x [ 1 ] + x [ 2 ] , 16 x [ 3 ] + x [ 4 ] , ... ) if ∥ x ∥ is even otherwise
f ( t ) ≡ { 2 if t ≠ 0 0 otherwise \begin{aligned}
f(t) & \equiv & \begin{cases} 2 & \text{if} \quad t \neq 0 \\ 0 & \text{otherwise} \end{cases}
\end{aligned} f ( t ) ≡ { 2 0 if t = 0 otherwise
参考
func hexToCompact (hex []byte ) []byte {
terminator := byte (0 )
if hasTerm(hex) {
terminator = 1
hex = hex[:len (hex)-1 ]
}
buf := make ([]byte , len (hex)/2 +1 )
buf[0 ] = terminator << 5
if len (hex)&1 == 1 {
buf[0 ] |= 1 << 4
buf[0 ] |= hex[0 ]
hex = hex[1 :]
}
decodeNibbles(hex, buf[1 :])
return buf
}
输入
hex
16进制明文字符串 path
每个字符占用一个字节,取值范围是 [0-9, a-f]
可能在 path 尾部追加最后一个字节,值为 0x10,表示 terminator
即 hex 是个叶子节点(包含 value),而非中间节点
输出
buf (Hex-Prefix 编码得到的二进制字符串 )
添加半个字节(一个hex编码)到 hex 前面,用于表示
hex 是否包含 terminator
hex 移除 terminator 后(如果有的话),长度是奇数还是偶数
确保 buf 的长度是偶数
例子
Row Node Type Path Length Path Before Encoding(In HEX) Path After Encoding(In HEX) 0 Extension EVEN [0, 1, 2, 3, 4, 5] '00 01 23 45' 1 Extension ODD [1, 2, 3, 4, 5] '11 23 45' 2 Leaf(has terminator(10)) EVEN [0, f, 1, c, b, 8, 10] '20 0f 1c b8' 3 Leaf(has terminator(10)) ODD [f, 1, c, b, 8, 10] '3f 1c b8'
Appendix D. Modified Merkle Patricia Tree
参考
(191) (192) 数据集合 I \mathfrak{I} I
I = { ( k 0 ∈ B , v 0 ∈ B ) , ( k 1 ∈ B , v 1 ∈ B ) , . . . } ∀ I ∈ I : I ≡ ( I 0 , I 1 ) \mathfrak{I} = \{ (\mathbf{k}_0 \in \mathbb{B}, \mathbf{v}_0 \in \mathbb{B}), (\mathbf{k}_1 \in \mathbb{B}, \mathbf{v}_1 \in \mathbb{B}), ... \} \\
\forall I \in \mathfrak{I}: I \equiv (I_0, I_1) I = {( k 0 ∈ B , v 0 ∈ B ) , ( k 1 ∈ B , v 1 ∈ B ) , ... } ∀ I ∈ I : I ≡ ( I 0 , I 1 )
(193) (194)
任何 bytes 都可以看为半字节(nibbles 4bit)组成的序列
y ( I ) = { ( k 0 ′ ∈ Y , v 0 ∈ B ) , ( k 1 ′ ∈ Y , v 1 ∈ B ) , . . . } ∀ n : ∀ i < 2 ∥ k n ∥ : k n ′ [ i ] ≡ { ⌊ k n [ i ÷ 2 ] ÷ 16 ⌋ if i is even k n [ ⌊ i ÷ 2 ⌋ ] m o d 16 otherwise \begin{aligned}
y(\mathfrak{I}) & = \{ (\mathbf{k}_0' \in \mathbb{Y}, \mathbf{v}_0 \in \mathbb{B}), (\mathbf{k}_1' \in \mathbb{Y}, \mathbf{v}_1 \in \mathbb{B}), ... \} \\
\forall n: \quad \forall i < 2\lVert\mathbf{k}_{n}\rVert: \quad \mathbf{k}_{n}'[i] & \equiv
\begin{cases}
\lfloor \mathbf{k}_{n}[i \div 2] \div 16 \rfloor & \text{if} \; i \; \text{is even} \\
\mathbf{k}_{n}[\lfloor i \div 2 \rfloor] \bmod 16 & \text{otherwise}
\end{cases}
\end{aligned} y ( I ) ∀ n : ∀ i < 2 ∥ k n ∥ : k n ′ [ i ] = {( k 0 ′ ∈ Y , v 0 ∈ B ) , ( k 1 ′ ∈ Y , v 1 ∈ B ) , ... } ≡ { ⌊ k n [ i ÷ 2 ] ÷ 16 ⌋ k n [⌊ i ÷ 2 ⌋] mod 16 if i is even otherwise
公式 (195) 根节点函数 TRIE \texttt{TRIE} TRIE
TRIE ( I ) ≡ KEC ( RLP ( c ( I , 0 ) ) ) \texttt{TRIE}(\mathfrak{I}) \equiv \texttt{KEC}\big(\texttt{RLP} (c(\mathfrak{I}, 0))\big) TRIE ( I ) ≡ KEC ( RLP ( c ( I , 0 )) )
公式 (196)
n ( I , i ) ≡ { ( ) if I = ∅ c ( I , i ) if ∥ RLP ( c ( I , i ) ) ∥ < 32 KEC ( RLP ( c ( I , i ) ) ) otherwise n(\mathfrak{I}, i) \equiv \begin{cases}
() & \text{if} \quad \mathfrak{I} = \varnothing \\
c(\mathfrak{I}, i) & \text{if} \quad \lVert \, \texttt{RLP} \big( c(\mathfrak{I}, i) \big) \rVert < 32 \\
\texttt{KEC}\big(\texttt{RLP}( c(\mathfrak{I}, i)) \big) & \text{otherwise}
\end{cases} n ( I , i ) ≡ ⎩ ⎨ ⎧ ( ) c ( I , i ) KEC ( RLP ( c ( I , i )) ) if I = ∅ if ∥ RLP ( c ( I , i ) ) ∥ < 32 otherwise
公式 (197)
c ( I , i ) ≡ { ( HP ( I 0 [ i . . ( ∥ I 0 ∥ − 1 ) ] , 1 ) , I 1 ) if ∥ I ∥ = 1 where ∃ I : I ∈ I ( HP ( I 0 [ i . . ( j − 1 ) ] , 0 ) , n ( I , j ) ) if i ≠ j where j = max { x : ∃ l : ∥ l ∥ = x ∧ ∀ I ∈ I : I 0 [ 0.. ( x − 1 ) ] = l } ( u ( 0 ) , u ( 1 ) , . . . , u ( 15 ) , v ) otherwise where u ( j ) ≡ n ( { I : I ∈ I ∧ I 0 [ i ] = j } , i + 1 ) v = { I 1 if ∃ I : I ∈ I ∧ ∥ I 0 ∥ = i ( ) otherwise \begin{aligned}
c(\mathfrak{I}, i) \equiv \begin{cases}
\big(\texttt{HP}(I_0[i .. (\lVert I_0\rVert - 1)], 1), I_1 \big) & \text{if} \ \lVert \mathfrak{I} \rVert = 1 \text{where} \ \exists I: I \in \mathfrak{I} \\
\big(\texttt{HP}(I_0[i .. (j - 1)], 0), n(\mathfrak{I}, j) \big) & \text{if} \ i \ne j \ \text{where} \ j = \max \{ x : \exists \mathbf{l}: \lVert \mathbf{l} \rVert = x \wedge \forall I \in \mathfrak{I}: I_0[0 .. (x - 1)] = \mathbf{l} \} \\
(u(0), u(1), ..., u(15), v) & \text{otherwise} \ \text{where} \\
& u(j) \equiv n(\{ I : I \in \mathfrak{I} \wedge I_0[i] = j \}, i + 1) \\
& v = \begin{cases}
I_1 & \text{if} \ \exists I: I \in \mathfrak{I} \wedge \lVert I_0 \rVert = i \\
() & \text{otherwise}
\end{cases}
\end{cases}
\end{aligned} c ( I , i ) ≡ ⎩ ⎨ ⎧ ( HP ( I 0 [ i .. (∥ I 0 ∥ − 1 )] , 1 ) , I 1 ) ( HP ( I 0 [ i .. ( j − 1 )] , 0 ) , n ( I , j ) ) ( u ( 0 ) , u ( 1 ) , ... , u ( 15 ) , v ) if ∥ I ∥ = 1 where ∃ I : I ∈ I if i = j where j = max { x : ∃ l : ∥ l ∥ = x ∧ ∀ I ∈ I : I 0 [ 0.. ( x − 1 )] = l } otherwise where u ( j ) ≡ n ({ I : I ∈ I ∧ I 0 [ i ] = j } , i + 1 ) v = { I 1 ( ) if ∃ I : I ∈ I ∧ ∥ I 0 ∥ = i otherwise
其中
叶子节点 Lea
包含两个字段
第一个字段是剩下的 Key 的 HP 编码(HP 的第二个参数为1)
第二个字段是 Value
扩展节点 Extension
包含两个字段
第一个字段是剩下的 Key 的可以至少被两个剩下节点共享的最大公共前缀((HP 的第二个参数为0)
第二个字段是 n ( I , j ) n(\mathfrak{I}, j) n ( I , j )
分支节点 Branch
包含17个字段
前16个项目对应于 [0-9,a-f]
第17个字段是存储在当前结点结束的节点
例如
有三个key,分别是 abc,abd,ab
第17个字段储存了ab节点的值
图片来源 ELI5 How does a Merkle-Patricia-trie tree work?
Appendix H. Virtual Machine Specification
注意区分单位
μ s \boldsymbol{\mu}_{\mathbf{s}} μ s / σ [ a ] s \boldsymbol{\sigma}[a]_{\mathbf{s}} σ [ a ] s 以 32 字节为单位
μ m \boldsymbol{\mu}_{\mathbf{m}} μ m 以 1 字节为单位
参考 SSTORE
/SLOAD
, MSTORE
/MLOAD
H.2. Instruction Set
参考 Difference between CALL, CALLCODE and DELEGATECALL
DELEGATECALL was a new opcode that was a bug fix for CALLCODE which did not preserve msg.sender and msg.value. If Alice invokes Bob who does DELEGATECALL to Charlie, the msg.sender in the DELEGATECALL is Alice (whereas if CALLCODE was used the msg.sender would be Bob).