賬戶
與BTC不同,ETH使用的是基于賬戶的賬本(account-based ledger),賬本中記錄了各個用戶的的余額,交易時不必追溯幣的來源,
基于賬戶的賬本對雙花攻擊(duoble spending attack)有著天然的防御作用,賬戶余額是系統中全節點維護的一個狀態,稱為balance,交易發生時余額隨機改變,但與之而來的問題便是重放攻擊(reply attack):若將已發布的交易再一次進行廣播發布,造成支付者多次支付,接收者將因此獲利,
ETH中使用nonce解決這一問題,nonce作為賬戶狀態中的一個欄位,有著計數器的功能,記錄了賬戶有史以來交易的次數,轉賬時,nonce成為交易內容的一部分,受支付者的簽名保護,
ETH有兩類賬戶:
- 外部賬戶(externally owned account)
也稱普通賬戶,由公私鑰對進行控制,包含之前所述的balance和nonce;另外一類賬戶為合約賬戶; - 合約賬戶(smart contract account)
合約賬戶不是通過公私鑰對進行控制,在創建合約時,合約將回傳一個地址,由此地址可呼叫合約,但合約賬戶不能主動發起一次交易,所有的交易只能由外部賬戶發起,之后可能會引起合約間的相互呼叫,另外,除了balance和nonce,合約賬戶還有代碼code和存盤storage,
由于ETH支持智能合約,要求參與者有比較穩定的身份,這與BTC的設計有所不同,
狀態樹
ETH的賬戶地址是160bits,共20個位元組,賬戶地址到賬戶狀態為一對映射,賬戶狀態為前述的包括balance,nonce,code,storage等,所有的賬戶組織成一個改進的Merkle Patricia Tree,
存盤賬戶狀態的結構為狀態樹,其基本資料結構為Merkle Patricia Tree,MPT是一種融合了merkle tree和patricia tree兩種樹結構優點的資料結構,用路徑壓縮提高效率,可計算出一個賬戶狀態的根哈希值, 保存于block header中,
MPT豐富了節點型別,共有如下4個型別的節點:
- 擴展節點 extension Node: [key, value],只能有一個子節點,這里的value值存盤的是孩子節點的哈希值;
- 分支節點 branch Node [0,1,…,16,value],可以有多個節點,因為MPT樹中的key被編碼成一種特殊的16進制的表示,再加上最后的value,所以分支節點是一個長度為17的list,前16個元素對應著key中的16個可能的十六進制字符,如果有一個[key, value]對在這個分支節點終止,最后一個元素為value值,存盤的是剛好在分支節點結束時的值,若沒有節點在分支節點中結束時,value值沒有存盤資料,即分支節點既可以搜索路徑的終止也可以是路徑的中間節點,分支節點的父親必然是extension node;
- 葉子節點 leaf Node : [key, value],這里的key都是16編碼出來的字串,每個字符只有0-f 16種,value是RLP編碼的資料;
- 空白節點 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:指向叔塊的header的指標陣列
- transactions:交易串列
extblock
// "external" block encoding. used for eth protocol, etc.
type extblock struct {
Header *Header
Txs []*Transaction
Uncles []*Header
}
extblock為真正發布的區塊資訊,即為block結構的前三項,
新區塊發布
多個區塊的狀態樹共享節點,每次發布新區塊,MPT樹中部分節點狀態會改變,但改變并非在原地修改,而是新建一些分支,保留原本狀態,當僅僅有新發生改變的節點才需要修改,其他未修改節點直接指向前一個區塊中的對應節點,而交易樹與收據樹只將當前區塊內發布的交易組織起來,如圖所示:

由于以太坊中出塊時間15s左右,會產生很多的分叉,保持歷史記錄的一個好處是,當某些分叉需要回滾時可以更好的查看歷史記錄,
交易驅動的狀態機 transaction-drived state machine
ETH為一個交易驅動的狀態機,其狀態為狀態樹中賬戶的狀態,通過執行交易樹的交易,可驅動系統由當前狀態轉移到下一個狀態,其狀態轉移時確定性的,即通過給定的當前狀態和交易,能確定性的轉移到下一個狀態,
轉載請註明出處,本文鏈接:https://www.uj5u.com/qukuanlian/273280.html
標籤:區塊鏈
上一篇:CSS入門
