【区块链基础】4——ETH区块结构
账户
不同于BTC这种直接记录交易金额的方式,ETH采用了基于账户记录的交易系统。其特点在于每位用户的个人资金余额在账本中被详细记录,并且在每笔交易完成后无需追踪资金来源路径。
针对双花攻击 (duoble spending attack),账户账本具有固有的抵御能力。账户余额属于系统中全节点维护的一个重要状态,并称为balance。在交易发生时,余额会随机变化。然而伴随这一现象的是重放攻击 (reply attack):若将已发布的交易再一次进行广播发布,则会导致支付者进行多重支付行为,并使接收方从中获得利益。
在以太坊区块链中، 通过采用Nonce来解决此问题. 其中,Nonce被用作账户状态中的一个字段, 其功能类似于计数器, 记录了账户历史上所有交易的数量. 在转账过程中,Nonce被包含在交易信息中, 并受到支付者签名的有效保护.
ETH有两类账户:
也可称为普通账户(Ordinary Account),它基于公私钥对进行管理,并包含如前文所述的balance和nonce;而另一类账户则为合约账户(Contract Address)
在创建该智能合约时,默认返回一个唯一地址。该地址可被用来触发特定操作,并具有执行功能;然而需要注意的是,并非所有操作都允许自动触发;具体而言,在初始状态下只有两种操作是可以自动触发的:一个是查看当前余额(balance),另一个是验证哈希校验码(nonce)。值得注意的是,在初始状态下,并非所有的功能都是自动可用的;只有当智能合同达到特定条件时才能开始执行这些预先设置好的逻辑功能;此外还需要注意的是,在某些情况下即使拥有指定权限也无法执行预设逻辑;这种设计是为了防止未经授权的操作并保障系统的安全性。
由于ETH基于支持智能合约的功能设计,它要求各方在参与过程中拥有稳定的角色配置。这种架构与Bitcoin的设计存在明显的差异。
状态树
该智能合约地址由160位二进制数据构成,并占据了20个字节的空间;每个账户地址对应唯一的状态信息;具体包括交易余额(balance)、交易哈希(nonce)、程序代码(code)以及存储数据(storage)等多个关键字段;所有这些账户被组织成一种优化版的Merkle Patricia树结构
记录账户状态的结构构成是状態樹 ,其基本數據結構為\text{Merkle Patricia Tree}。\text{MPT}是一種結合\text{merkle tree}和\text{patricia tree}兩種樹結構優勢的数据结构调整体,在使用路径压缩来提升效率的同时,能够计算出一个账户状态对应的根哈希值并存放在block header中。
区块链基础
区块链基础
Merkle树可用于参考详细解析,请参见[【区块链基础
MPT丰富了节点类型,共有如下4个类型的节点:
- 扩展型结点(extension Node):其结构为[key, value]列表,并且只能包含单一子列表。
- 分支型结点(branch Node)基于索引列表[0, 1,…, 16]和一个value字段;该字段用于指示结点终止的位置。
- 叶子型结点(leaf Nodes)采用双字节编码的方式表示关键信息,并且每个叶子包含唯一标识符以及相关数据。
- 空白结点(NULL)
ETH对MPT做了略微的改进:
Extension Node 和 Branch Node 与原生的MPT有所区别。prefix 可以按奇偶数目分割 nibbles(16进制数值)。
具体以官方的下图为例:

MPT作用如下:
该系统通过计算根哈希值来确保数据不可篡改。只有当哈希值未发生变化时才能保证整个系统的任意一部分都不会受到修改操作的影响;同时各个用户账户的信息也不会受到影响。
账户所在的分支从下往上包含merkle proof,并被发送给轻节点进行验证过程。
交易树
用来记录交易数据的信息这一数据结构同样遵循MPT规范,其中键值字段则表示交易在所在区块中的序列号
收据树
完成一笔交易后会生成一张收据, 该收据主要用于记录有关交易的信息以及其执行成果, 其数据架构同样遵循MPT模式, 其中键值对应于在已发布区块中进行的交易编号, 并与该区块内的相应节点一一对应. 为了提高以ETH为基础的智能合约系统的运行效率, 构建相应的收据索引能够显著提高对系统运行结果进行快速检索的能力.
布隆过滤器 bloom filter
bloom filter可以比较高效的查找某个元素是否包含在比较大的集合之内。直观的说,bloom算法类似一个hash set,用来判断某个元素(key)是否在某个集合中。和一般的hash set不同的是,这个算法无需存储key的值,对于每个key,只需要k个比特位,每个存储一个标志,用来判断key是否在集合中。
算法:
- 首先需要k个hash函数,每个函数可以把key散列成为1个整数
- 初始化时,需要一个长度为n比特的数组,每个比特位初始化为0
- 某个key加入集合时,用k个hash函数计算出k个散列值,并把数组中对应的比特位置为1
- 判断某个key是否在集合时,用k个hash函数计算出k个散列值,并查询数组中对应的比特位,如果所有的比特位都是1,认为在集合中。
在查找某一交易时可快速过滤掉大量无关的区块
区块
header
// Header represents a block header in thr Ethereum blockchain.
type Header struct {
ParentHash common.Hash `json:"parentHash" gencodec:"required"`
UncleHash common.Hash `json:"sha3Uncles" gencodec:"required"`
Coinbase common.Address `json:"miner" gencodec:"required"`
Root common.Hash `json:"stateRoot" gencodec:"required"`
TxHash common.Hash `json:"transactionsRoot" gencodec:"required"`
ReceiptHash common.Hash `json:"receiptsRoot" gencodec:"required"`
Bloom Bloom `json:"logsBloom" gencodec:"required"`
Difficulty *big.Int `json:"difficulty" gencodec:"required"`
Number *big.Int `json:"number" gencodec:"required"`
GasLimit uint64 `json:"gasLimit" gencodec:"required"`
GasUsed uint64 `json:"gasUsed" gencodec:"required"`
Time *big.Int `json:"timestamp" gencodec:"required"`
Extra []byte `json:"extraData" gencodec:"required"`
MixDigest common.Hash `json:"mixHash" gencodec:"required"`
Nonce BlockNonce `json:"nonce" gencodec:"required"`
}
- ParentHash:父区块header的哈希值
- UncleHash:叔块的哈希(可能比Parent大好几辈)
- Coinbase:挖矿地址
- Root:状态树根节点对应的哈希值
- TxHash:交易树根节点对应的哈希值(类似于比特币中的merkle root)
- ReceiptHash:收据树根节点对应的哈希值
- Bloom:布隆过滤器(与收据树相关),提供高效查询符合条件交易执行结果的数据结构
- Difficulty:挖矿难度参数
- GasLimit/GasUsed:智能合约执行时消耗的汽油费参数(类似于比特币中的交易费用)
- Time:区块产生的时间戳
- MixDigest:nonce字段经过计算得到的最终摘要值
- Nonce:满足难度约束条件下的随机数字段
block
// Block represents an entire block in the Ethereum blockchain.
type Block struct {
header *Header //区块头
uncles []*Header //叔块
transactions Transactions //区块打包的一批交易数据
// caches
hash atomic.Value
size atomic.Value
// Td is used by package core to store the total difficulty
// of the chain up to and including the block.
td *big.Int //总难度值
// These fields are used by package eth to track
// inter-peer block relay.
ReceivedAt time.Time
ReceivedFrom interface{}
}
- header:头部是一个指向header部分的指针。
- uncles:parent nodes是一个指向叔块header部分的指针数组。
- transactions:transactions是一个存储所有交易记录的数据集合。
extblock
// "external" block encoding. used for eth protocol, etc.
type extblock struct {
Header *Header
Txs []*Transaction
Uncles []*Header
}
extblock为真正发布的区块信息,即为block结构的前三项。
新区块发布
多个区块的状态_tree共享一些节点,在每次发布一个新的新区块时,在MPT_tree中有一些节点的状态会发生变化。这些变化并不是直接修改已有的节点状态,而是创建了一些新的分支结构,并保留原有状态信息。只有那些发生更改的节点才需要进行修改操作;而那些未发生变化的节点可以直接指向前一个区块中的对应位置。需要注意的是,在这个过程中仅涉及到了交易_tree与收据_tree的内容,并以图示的形式展示了当前区块内的交易记录。

每隔15秒左右,在以太坊网络中会出现分支现象。其中一个优点是在某些分叉发生需要回滚的情况下能够更清晰地查看历史记录信息。
交易驱动的状态机 transaction-drived state machine
以交易驱动的 ETH 是一种状态机,其状态对应于状态树中的账户状态。通过基于对交易树中交易的处理,可以使系统从当前到下一个确定性地转移。其在转移过程中具有确定性,即当前状态下配合相应交易即可实现下一步骤的状态转换。
参考资料
区块链基础系列
区块链基础
区块链基础
区块链基础
区块链基础
区块链基础
区块链基础
区块链基础
blockchain 基础
欢迎打赏Σ(っ°Д°;)っ

