02.以太坊架構和組成
01.以太坊整體架構
以太坊是一個區塊鏈應用平臺。
分為三層:
- 底層服務
- 核心層
- 頂層應用
02.區塊
-
區塊鏈是比特幣使用的底層技術架構。
-
他本身是一串連續的資料區塊,區塊之間的連線指標是區塊頭雜湊指標,他們是使用密碼學雜湊演算法生成的。
-
區塊本質上就是一個數據包,比特幣的交易記錄會儲存在區塊中,大約每10分鐘生成一個新的區塊。
-
所謂區塊:可以定義為記錄一段時間內發生的交易和狀態的結果的資料結構。是對當前賬本狀態的一次共識。
-
比特幣的每個資料區塊一般包含區塊頭(Header)和區塊體(Body)兩部分。
- 區塊頭封裝了前一個區塊的雜湊值(Prev_Hash),時間戳(Timestamp),隨機數(Nonce),Merkle樹的根值(Tx_Root)和當前區塊的雜湊值等資訊。
- 區塊體中則主要包含交易技術和交易詳情。 -
-
每筆交易都被永久的記錄在區塊中,任何人都可以查詢。交易是通過Merkle樹的資料結果記錄的。其中沒儀表交易都包含了數字簽名,如此可以保證每一筆交易都不偽造,不能篡改。所有的交易過程都將通過Merkle樹的hash過程生成一個唯一的Tx-Root記錄到區塊中。
-
使用者在驗證區塊的有效性時,只需根據Merkle樹的Hash方法計算出根值並且與區塊中Tx_Root進行比較,即可驗證真偽,若相同及有效,若不同則無效。
03.區塊 ——以太坊
-
去開主要由區塊頭,交易列表,和叔區塊三部分組成。
- 區塊頭:
- 父塊的雜湊值(PrevHash)
- 叔區塊的雜湊值(Uncles Hash)
- 狀態樹根雜湊值(stateRoot)
- 交易樹根雜湊值(Transaction Root)
- 收據樹根雜湊值(Receipt Root)
- 時間戳(Timestamp)
- 隨機數(Nonce)
- 以太坊區塊鏈上區塊資料結構的一個重要改變就是儲存了三棵Merkle樹根
- 狀態樹
- 交易樹
- 收據樹
- 區塊頭:
-
儲存三棵樹可以方便賬戶做更多查詢
-
交易列表是由礦工從交易池選擇收入區塊中的一系列交易
-
區塊鏈上的第一個區塊稱為“創世區塊”
-
區塊鏈上除了創世區塊意外每個區塊都有他的父區塊,這些區塊連線起來組成一個區塊鏈
-
以太坊大約每15s可以挖出一個新的區塊
-
以太坊區塊結構中狀態樹的更新
04.賬戶
- 賬戶以地址為索引,地址由公鑰衍生而來,取公鑰的最後20位元組
- 兩種型別的賬戶
- 外部賬戶
- 簡稱賬戶,他們都是由人建立,可以儲存以太幣
- 合約賬戶
- 合約賬戶是由外部賬戶建立的賬戶
- 以太坊中這兩中賬戶統稱為“狀態物件”(儲存狀態)
- 外部賬戶儲存以太幣餘額狀態
- 合約莊戶除了餘額還有智慧合約以及其變數的狀態 通過交易的執行,這行狀態物件發生變化,而Merkle樹使用者索引和狀態物件的更新。
- 外部賬戶
一個以太坊的賬戶包含四個部分
- 該地址交易的次數,他是用於保障被一筆交易能且被處理一次的計數器,有效避免重放攻擊
- 賬戶目前的以太幣餘額
- 賬戶的合約二進位制程式碼(合約賬戶)
- 賬戶的儲存(預設為空)
4.1 外部賬戶
- 外部賬戶(EOA)由私鑰來控制,是由使用者實際控制的賬戶
- 每個外部賬戶擁有一對公私鑰,這對金鑰用於簽署交易,他的地址由公鑰決定。
- 外部賬戶不能包含以太坊虛擬機器(EVM)程式碼
我們可以做一個簡單的對比,把外部賬戶看做使用者在某個銀行辦理的一個賬戶,公鑰就是使用者為該賬戶設定的卡號,而私鑰則是使用者設定的密碼。 一個外部賬戶具有以下特性:
-
擁有一定的賬戶餘額
-
可以傳送交易
-
通過私鑰控制
-
以及沒有相關的程式碼
-
使用者在建立好戰鼓後一定要記住私鑰!如果使用者忘記了,那你就滾吧。不可能不滾的。
-
祕鑰通常儲存在keystore目錄下, 使用者可以經常性的備份金鑰檔案,以防止忘記或者丟失
-
在以太坊節點之間傳遞整個目錄後者金鑰檔案是安全的。但是賬戶的順序可能會發生比改變。
-
使用者需確保不要依賴或者更改指令碼和程式碼段中的索引。使用者自己列出自己建立的賬戶時,賬戶匯按字典排序,並且按照賬戶的建立時間先後排序
4.2 合約賬戶
- 合約賬戶是一個包含合約程式碼的賬戶
- 合約賬戶不是由私鑰檔案直接控制,而是由合約程式碼控制的
- 合約賬戶的地址是由合約建立時合約建立者的地址,以及該地址發出的交易共同計算得出
- 一個合約賬戶具有下列特性:
- 擁有一定的以太幣餘額
- 有相關聯的程式碼
- 程式碼通過交易或者其他合約傳送的呼叫來啟用。
- 當合約被執行時候,智慧操作合約莊戶擁有的特定儲存。
- 合約賬戶和普通賬戶最大的不同就是他還存有智慧合約
- 以太坊區塊鏈上的所有操作都是根據都是根據從賬戶發出的交易來執行的。
- 每當合約賬戶收到一條交易訊息時,其他合約程式碼將被交易輸入的引數呼叫執行。
- 而合約程式碼將會在參與到網路中的每一個節點上執行,並將執行結果作為新區塊驗證的一部分
4.3 私鑰和公鑰
- 公鑰加密
-公鑰認證 私鑰的三種形態:
- Private key就是一份隨機生成的256位二進位制數字,該256位二進位制數字就是私鑰最初始的狀態
- 而2以太坊錢包中,私鑰和公鑰將會以加密的方式儲存一份JSON檔案,存在keystore子目錄下,這份JSON檔案就是Keystore,所以使用者需要同時備份Keystore和對應的Password
- 最後一種Memonic code是由BIP39方案,隨機生成12-24個容易幾乎記住的單詞,隨機種子,通過提案的方式生成確定性錢包
4.4 錢包
錢包就是一個比較形象的概念,一個外部賬戶通常由私鑰檔案來控制,擁有私鑰的而使用者就可以擁有對應地址的賬戶裡的以太幣使用權。 我們通常把管理這些數字金鑰的軟體成為錢包,而我們所所的備份錢包其實就是備份賬戶的私鑰檔案
-以太幣錢包分類
-
Mist錢包
-
Parity錢包
-
Etherwall錢包
-
Brain錢包
-
錢包備份
- 防盜:分離備份
- 防丟:多處本分
- 分散風向:將資金適當的分散開
-
常見的錢包備份方式:
- 多處和分離備份
- 紙錢包 預防方案:使用者可以痛死使用多重簽名和多處分離備份,設定一個金額閾值,當用戶提取超過該閾值的金額時需要多個私鑰,另外把這些私鑰多處分離備份,大大降低了資金被盜的風險
05.資料結構與儲存
- 包括以太坊和比特幣在內的大多是都是區塊鏈專案,會使用Merkle樹或者基於Merkle樹的資料結構,比特幣- 中儲存了一顆Merkle樹,而以太坊針對物件設計了三棵Merkle樹,分別是狀態樹,交易樹和收據叔,這三種樹可以幫助以太坊客戶端做一些簡易的查詢,查詢某個賬戶的餘額,某筆交易是否被包含在區塊中。
- 區塊,交易等資料最終都是存在LevelDB資料庫中,LevelDB資料庫是一個鍵值對資料庫,key一般與雜湊相關,value則是存在儲存內容的RLP編碼
5.1 資料組織形式
- 以太坊使用Merkle Patricia樹,(MPT),作為資料組織形式,用來組織管理使用者的賬戶狀態,交易資訊等重要資料。
- MPT是一種加密認證的資料結構,他融合了Merkle樹和Tire樹(字首樹)兩種資料型別的優點
- Merkle樹
-
Merkle樹是一種樹行資料結構,可以是二叉樹,也可以是多叉樹
-
由一組葉節點,一組中間節點和一個根節點構成
-
最下面的葉節點包含基礎資料,每個中間節點是他的子節點的雜湊,根節點是他的子節點的雜湊,代表了Merkle樹的根部。
-
建立Merkle樹的目的是語序區塊的資料可以零散的傳送
-
節點可以從一個節點下載區塊頭,從另外的源下載與其相關的樹的其他部分,而依然能夠確認所有的資料都是正確的。之所以如此是因為雜湊向上擴散,如果一個惡意使用者嘗試在樹的下部加入一個偽造的交易,所引起的改動將導致樹上的上層節點以及更上層節點的改動,最終導致根節點的改動以及區塊雜湊的改動,這樣協議就會將其記錄為一個完全不同的區塊(幾乎可以坑定帶著不確定的工作量證明)
-
如果底層的交易被篡改了,那麼其對應的葉節點雜湊值也會改變,這件最終導致其Merkle樹根值變化
-
Merkle樹可以用來儲存所有鍵值對
- 這顆樹的建立從每個節點開始,將節點兩兩分成多達16個組,並對每個組求雜湊值,接著對雜湊結果繼續求雜湊值,如此遞迴下去,知道整顆樹有一個最後的根雜湊值。
-
Merkle樹具有下列特性
- 每個資料集對應一個唯一合法的根雜湊值
- 很不容易更新,新增, 或者刪除樹節點,以及生成新的根雜湊值
- 不改變根雜湊值的話就沒有辦法修改樹的任何部分,所以如果跟雜湊值被包括在簽名的文件或者有效區塊中,就可以保證這棵樹的正確性
- 任何人都可以只提供一個到特定節點的分支,並且通過密碼學方法證明擁有對應內容的節點確實在樹裡
-
- Merkle樹
5.2 Trie樹
- Trie樹也叫做Radix樹
- 在Radic樹中,key代表的是從樹根到對應value的一條真實的路徑
- 即從根節點開始,key中的每個字元(從前到後)都代表著從根節點觸發尋找相應value所要經過的子節點
- value儲存在葉節點中,是每個路徑的最終節點。
- 假如key中的每個字元都來自一個容量為N且包含的字母都互不相識的字母表,那麼樹中的每個節點最多會有N個孩子,樹的最大深度便是Key的最大程度
- 優點如果有兩個value,他們有著基於相同字首的key,他們的相同字首的長度佔自身比例越大,則代表著兩個value在樹中的位置越靠近,並且Trie樹中不會有像散列表一樣的衝突,也就是說一個key只對應一個value,但是也存在著不平衡的
5.3 Merkle Patricia樹
- 為了保證樹的加密安全,每個節點通過他的雜湊值被引用,對於儲存在LEVELDB資料庫中的非葉節點,其中資料庫中的表現形式:key代表著節點的RLP編碼的SHA3雜湊值,value是節點的RLP編碼。想要獲得一個節點的內容,只需要根據該節點的雜湊值訪問資料庫以獲得節點的RLP編碼,然後解碼即可。
- 在該方案中,根節點被稱為整棵樹的加密簽名,如果一棵樹給定Trie樹的根雜湊值是公開的,那麼所有人都可以提供一種證明,即通過提供每步向上的路徑證明特定的key是否含有特定的值
- 引入很多節點型別來提供效率,MPT中節點包括以下4種:
- 空節點:簡單的表示空,在程式碼中就是一個空串
- 葉節點:鍵值對的一個列表,其中key是一種特殊的十六進位制編碼,value是RLP編碼
- 擴充套件節點:鍵值對的列表,但是這裡的value是其他接待的雜湊值,通過這個雜湊值可以連線到其他節點
- 分支節點:一個節點為17的列表,MPT中的key被編碼成一種特殊的十六進位制的表示,再加上最後的value,前16個元素對應的key中的16個可能的十六進位制字元,如果有一個鍵值對在這個分支節點終止,則最後一個元素代表一個值,即分支節點既然可以是搜尋路徑的終止,也可能是路徑的中間節點
MPT還有一個重要的概念:使用者對key進行編碼的特殊十六進位制字首編碼(HP),因為字母表中的字元都是十六進位制表示的,所以每個節點最多隻能由16個孩子,因為鍵值對有兩個表示形式的節點,所以必須引用一中特殊的終止符表示,用來標示key所對應的值是真實的值還是其他節點的雜湊值。通過對終止符標識進行賦值,可以區分key所對應的節點的種類,無論key的長度是奇數還是偶數,HP都可以對其進行編碼。
以太坊區塊鏈系統中使用MPT樹結構,但是每個以太坊區塊頭不是隻包括一顆MPT樹,而是為了三種物件設計了三棵樹。
5.4 狀態樹
- 狀態樹中的每個節點16個孩子節點,每個葉節點表示一個賬戶,這些葉節點的父節點由葉節點的雜湊組成,而這些父節點再組成更高一層的父節點,直至到形成根節點。
- 狀態樹包含一個鍵值對映,其中鍵是賬戶地址,值是賬戶內容 {nonce,balance,codeahash,storageRoot}
- nonce是賬戶交易的序數
- balance是賬戶餘額
- codeHash是程式碼的雜湊值
- storageRoot是另一棵樹的根節點
- 狀態樹代表訪問區塊後的整個狀態
- 賬戶的狀態不是直接儲存在每個區塊中,所有的賬戶狀態都是以狀態資料的形式存在以太坊的節點中
- 狀態資料是一種隱式的資料,意味著他需要從實際的區塊鏈資料中計算出來,交易包含決定新狀態資料的所有欄位內容。與比特幣不同的是,以太坊區塊包含了整個狀態樹的Merkle樹根雜湊和交易列表
- 狀態樹是用來記錄各個賬戶的狀態的樹,他需要經常更新
5.5 交易樹
- 每個區塊都有一棵獨立的交易樹。
- 區塊中交易的順序主要由礦工決定,在這個塊被挖出來前這些資料都是未知的。不過礦工一般會根據交易的GasPrice和Nonce對交易進行排序。
- 首先會將交易列表中的交易劃分到各個傳送賬戶,每個賬戶的交易根據這些交易的nonce來排序,每個賬戶的交易排序完成後,再通過比較每個賬戶的第一條交易,選擇最高價格的交易,這寫是通過一個堆來實現的、
- 每挖出一個新塊,更新一次交易樹
- 在交易樹包含的鍵值對中,其中每個鍵是交易的編號,值是交易內容
5.6 收據樹
- 每個區塊都有自己的收據樹,收據樹不需要更新
- 收據樹代表每個交易相應的收據
- 收據樹也包含了一個鍵值對映,其中鍵是索引編號,用來指引這個收據相關的交易的位置,值是收據的內容
- 交易的收據是一個RLP編碼的資料結構[medstate,Gas_used,logbloom,logs],其中 medstate是交易處理後樹根的狀態,Gas_used是交易處理後Gas的使用量,logs是表格元素的列表,表格有交易執行期間呼叫的操作碼,address是生成日誌的合約地址,topicn是最多4個32位元組的值,data是任意位元組大小的資料,logbllom是交易所有logs的布隆過濾器。