1. 程式人生 > >以太坊原始碼解讀(4)Block類及其儲存

以太坊原始碼解讀(4)Block類及其儲存

一、Block類

type Block struct {
        /******header*******/
	header       *Header
        /******header*******/

        /******body*********/
	uncles       []*Header
	transactions Transactions
        /******body*********/

	// 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{}
}

block類實際上就只有兩個部分,header和body。其他的如hash、size、td等都是在接受和驗證區塊後產生的內容,實際上向全網公佈的時候block就只有header和body(uncles和transactions)。

Header裡有哪些內容呢?


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"`
}

1)ParentHash:前一個區塊的hash
2)UncleHash:叔區塊hash,如果有多個叔區塊就加到一起
3)Coinbase:礦工賬戶
4)Root:StateDB中的“state Trie”的根節點的RLP雜湊值。
5)TxHash:“tx Trie”的根節點的RLP雜湊值。
6)ReceiptHash: "Receipt Trie”的根節點的RLP雜湊值。
7)Bloom:Bloom過濾器(Filter),用來快速判斷一個引數Log物件是否存在於一組已知的Log集合中。
8)Difficulty:難度值
9)Number:區塊號
10)GasLimit:區塊內所有Gas消耗的理論上限。該數值在區塊建立時設定,與父區塊的GasUsed有關。
11)GasUsed:

區塊內所有Transaction執行時所實際消耗的Gas總和。
12)Time:時間戳
13)Extra:額外資訊
14)Nonce:pow產生的數值,也可以用於驗證礦工的工作

二、Root、TxHash、ReceiptHash

在比特幣中,區塊body中的交易通過merkle tree的形式組織,然後將merkle root存在block header中。

而在以太坊中不是merkle-tree,而是Merkle-PatricaTrie(MPT)結構,而且存在三棵樹:state Trie、tx Trie、Receipt Trie。

首先,在StateDB中,每個賬戶以stateObject物件表示,所有賬戶物件可以逐個插入一個Merkle-PatricaTrie(MPT)結構裡,形成“state Trie”。其次,Block的transactions中所有的tx物件,被逐個插入一個MPT結構,形成“tx Trie”。最後,所有Transaction執行完後會生成一個Receipt陣列,這個陣列中的所有Receipt被逐個插入一個MPT結構中,形成"Receipt Trie"

上圖中表示的意思是,首先一個區塊的幾個重要部分分開儲存在leveldb中,header、body、receipts以RLP編碼的形式儲存在資料庫中,key都是用num+key構成的。另外,我們可以通過‘h’+num+hash+'t'查詢區塊鏈的總難度td;‘H’+hash可以查詢到blocknumber;在知道num的情況下可以查詢‘h’+num+‘n’對應的區塊鏈上的hash(即不在規範鏈上的區塊可能也有該num,但是無法通過這個key查詢到);在僅僅知道hash的情況下,通過‘l’+hash來查詢區塊hash+區塊號+交易編碼的編碼值,這樣的值僅僅儲存規範鏈上的區塊,所以我們可以快速的檢視某hash對應的區塊是否在規範鏈上。

key value
'h' + num +hash header的RLP編碼值
'b' + num +hash body的RLP編碼值
'r' + num +hash receipt的RLP編碼值
'h' + num + hash + 't' 截止該區塊的總難度值
'h' + num + 'n' 區塊號對應的規範鏈上的區塊的hash(規範鏈 )
'H' + hash Header對應的block number(規範鏈)
'l' + hash 【區塊hash、區塊號num、交易編號】的編碼值,是交易查詢入口(規範鏈)

這些資訊都在強烈的暗示,num(Number)和hash是Block最為重要的兩個屬性:num用來確定Block在整個區塊鏈中所處的位置,hash用來辨識惟一的Block/Header物件。

通過以上的設計,Block結構體的所有重要成員,都被儲存進了底層資料庫。當所有Block物件的資訊都已經寫進資料庫後,我們就可以使用BlockChain結構體來處理整個塊鏈。