交易树与收据树 #
上篇文章中讲了数据结构MPT及状态树,这篇文章再来讲交易树与收据树。交易树与收据树同样基于MPT,分别用于存储区块内的交易信息与交易执行结果,是保证以太坊数据可验证性和透明性的关键组件。二者均与区块一一对应,其根哈希会被记录在区块头中,确保数据不可篡改。
交易树 #
交易树是每个区块内所有交易的结构化存储载体,本质是一棵以交易在区块中的序号为键的 MPT。
其核心作用:
- 记录区块内所有交易的完整信息,包括发送方、接收方、转账金额、Gas 设置、智能合约调用数据等。
- 生成交易根哈希并写入区块头,任何人可通过该哈希验证区块内交易是否被篡改,也可通过Merkle Proof快速验证某笔交易是否存在于区块中。
结构特点:
- 交易的索引(在区块中的序号)会被 RLP 编码后作为 MPT 的键,由于交易序号是连续的数字,其路径前缀共享的概率极低,因此交易树的 MPT 路径压缩特性几乎无法体现,但仍保留 MPT 的密码学验证能力。
- 与状态树不同,每个区块的交易树仅包含相关的交易,不同区块的交易树不会共享节点。
收据树 #
收据树也叫回执树,存储每笔交易执行后的结果信息,同样是基于 MPT 构建,且与交易树的节点一一对应。
核心作用:
- 记录交易执行的最终状态,包括交易是否成功、消耗的 Gas 量、智能合约触发的事件日志(Log)、区块哈希与交易哈希关联信息等。
- 生成收据根哈希写入区块头,为轻节点验证交易执行结果提供依据,比如钱包可通过收据树验证转账是否到账、智能合约事件是否触发。
结构特点:
- 键为对应交易在区块中的序号,与交易树的键完全一致,保证交易与收据的一一映射。
- 收据中包含布隆过滤器(Bloom Filter),用于快速检索交易类型、涉及地址等信息,区块头也会聚合所有收据的布隆过滤器,提升全网的事件查询效率。
源码 #
以太坊的客户端比较著名的一个实现**go-ethereum**由go语言实现,下面贴了以太坊Header的源码,还有其他的一些实现细节可以从继续读一下整个源码(有50k+的start)。
// Header represents a block header in the Ethereum blockchain.
type Header struct {
ParentHash common.Hash `json:"parentHash" gencodec:"required"`
UncleHash common.Hash `json:"sha3Uncles" gencodec:"required"`
Coinbase common.Address `json:"miner"`
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 uint64 `json:"timestamp" gencodec:"required"`
Extra []byte `json:"extraData" gencodec:"required"`
MixDigest common.Hash `json:"mixHash"`
Nonce BlockNonce `json:"nonce"`
// BaseFee was added by EIP-1559 and is ignored in legacy headers.
BaseFee *big.Int `json:"baseFeePerGas" rlp:"optional"`
// WithdrawalsHash was added by EIP-4895 and is ignored in legacy headers.
WithdrawalsHash *common.Hash `json:"withdrawalsRoot" rlp:"optional"`
// BlobGasUsed was added by EIP-4844 and is ignored in legacy headers.
BlobGasUsed *uint64 `json:"blobGasUsed" rlp:"optional"`
// ExcessBlobGas was added by EIP-4844 and is ignored in legacy headers.
ExcessBlobGas *uint64 `json:"excessBlobGas" rlp:"optional"`
// ParentBeaconRoot was added by EIP-4788 and is ignored in legacy headers.
ParentBeaconRoot *common.Hash `json:"parentBeaconBlockRoot" rlp:"optional"`
// RequestsHash was added by EIP-7685 and is ignored in legacy headers.
RequestsHash *common.Hash `json:"requestsHash" rlp:"optional"`
}