以太坊原始碼分析(1)go-ethereum的設計思路及模組組織形式

尹成發表於2018-05-13
go-ethereum的設計思路及模組組織形式
===================================

以太坊的目標是基於區塊鏈技術打造一個執行智慧合約的去中心化平臺。

## 一. 區塊鏈技術
區塊鏈屬於一種去中心化的數字記賬技術,區塊鏈資料由彼此互不信任的節點共同維護,每個節點複製一份完整的記錄。

## 二. 以太坊核心概念
* EVM: 以太坊虛擬機器,輕量級的虛擬機器環境,是以太坊智慧合約的執行環境。
* Account: 賬戶分為兩類,合約賬戶和外部賬戶。合約賬戶主要儲存執行的合約程式碼,外部賬戶儲存以太幣,對應具體共鑰。
* Transaction: 以太坊網路上的交易,從一個賬戶到另一個賬戶的訊息,包括以太幣或這智慧合約引數。
* Gas: 以太坊網路執行的燃料,每執行一條智慧合約,都會消耗一定的燃料。
* Mine: 挖礦,以太坊網路通過工作量證明演算法來保證網路的安全執行。
* P2P網路: 以太坊分散式網路中的所有節點都地位平等,沒有中心伺服器。

## 三. 以太坊模型
以太坊本質是一個基於交易的狀態機(transaction-based state machine),以太坊的狀態中有百萬個交易,
這些交易被打包到一個區塊(Block)中,每個區塊都和之前的區塊連結起來,形成一個反向連結串列,所以叫區塊鏈。在區塊鏈的基礎上增加了智慧合約打造出以太坊。



為了讓一筆交易被認為是有效的,它必須要經過一個驗證過程,也就是挖礦(Mine)。 任何一個以太坊網路上的礦工都可以嘗試建立和驗證區塊,
如果一個區塊被認為是有效的,並且是最快完成驗證的,那麼就會新增到主鏈上,主鏈是以太坊網路上最長的一條鏈。如果同時有多個礦工打包了一個區塊,加上區塊在網路中傳播需要一定時間,
難免會產生多條路徑,就是所謂的分叉。
為了防止多條鏈的產生,以太坊使用了 **GHOST 協議** (Greedy Heaviest Observed Subtree),也就是選擇一條完成計算最多的路徑,區塊號越大, 路徑就越長,說明挖礦消耗的算力越多。
因為成功證實了一個新區塊會得到一定以太幣的獎勵,所以從經濟學和博弈論的角度,選擇主鏈是最優的。



## 四. 以太坊的架構
以太坊的架構設計可以簡單的分為三個層次,協議層、介面層和應用層。而協議層又可以分為網路層和儲存層。


從技術角度看,協議層主要包括P2P網路通訊,分散式演算法,加密簽名和資料儲存技術。資料儲存底層,比特幣和以太坊都選用了Google開源的LevelDB資料庫。

介面層與協議層完全分離,除了交易時與協議層進行互動,保證開發各種基於區塊鏈的應用層業務不受約束,包括分散式儲存業務,機器學習,物聯網等。

應用層主要是從區塊鏈自身的特性出發,在不引用第三方機構的前提下,提供去中心化,不可篡改,安全可靠的場景應用。
主要包括金融服務,徵信和權屬管理,資源共享,投資管理以及物聯網和供應鏈等。

## 五. 以太坊核心資料結構

#### 1. 區塊(Block)是以太坊的核心資料結構之一,Block包含Header和Body兩部分。


#### 2. Blockchain和HeaderChain, Blockchain管理所有的Block, 讓其組成一個單向連結串列。Headerchain管理所有的Header,也形成一個單向連結串列, Headerchain是Blockchain裡面的一部分。

#### 3. Transaction是Body的重要資料結構,一個交易就是被外部擁有賬戶生成的加密簽名的一段指令,序列化,然後提交給區塊鏈。


#### 4. 以太坊的資料庫體系-Merkle-Patricia Trie(MPT), 它是由一系列節點組成的二叉樹,在樹底包含了源資料的大量葉子節點, 父節點是兩個子節點的Hash值,一直到根節點。


## 六. go-ethereum原始碼的目錄結構

``` golang
|---accounts 以太坊賬戶管理
|---bmt 二進位制Merkle-Patricia Trie的實現
|---build 主要是編譯和構建的一些指令碼和配置
|---cmd 命令列工具
| |---abigen 合約介面生成工具
| |---bootnode 實現網路發現的節點
| |---evm 以太坊虛擬機器
| |---faucet
| |---geth 以太坊命令列客戶端
| |---p2psim 提供了一個工具來模擬http的API
| |---puppeth 建立一個新的以太坊網路的嚮導
| |---rlpdump 提供RLP資料的格式化輸出
| |---swarm swarm網路的接入點
| |---util 公共的元件
| |---wnode 這是一個簡單的Whisper節點。 它可以用作獨立的引導節點。此外,可以用於不同的測試和診斷目的。
|---common 提供了一些公共的工具類
|---consensus 以太坊的共識演算法,包括ethhash, clique
|---core 以太坊的核心資料結構和演算法(虛擬機器,狀態,區塊鏈,布隆過濾器)
|---crypto 加密,數字簽名和hash演算法
|---eth 實現了以太坊的協議
|---ethclient 以太坊的RPC客戶端
|---ethdb eth的資料庫,主要是LevelDB及相應介面
|---event 實時事件處理
|---light 實現為以太坊輕量級客戶端提供按需檢索的功能
|---metrics 提供磁碟計數器
|---miner 以太坊的挖礦和共識演算法
|---mobile 移動端使用的一些warpper
|---node 以太坊的多種型別的節點
|---p2p 以太坊p2p網路協議
|---rlp 以太坊序列化和反序列化處理
|---rpc 遠端方法呼叫
|---swarm swarm網路處理
|---trie 以太坊重要的資料結構MPT的實現
|---whisper whisper節點的協議
```

## 七. 資料

[以太坊官方文件](http://ethdocs.org/en/latest/index.html)

[以太坊設計原理](https://github.com/ethereum/wiki/wiki/Design-Rationale)

[以太坊白皮書](https://github.com/ethereum/wiki/wiki/White-Paper)

[以太坊黃皮書](https://ethereum.github.io/yellowpaper/paper.pdf)

# go-ethereum原始碼解析
因為go ethereum是最被廣泛使用的以太坊客戶端, 所以後續的原始碼分析都從github上面的這份程式碼進行分析。 然後我使用的是windows 10 64位的環境。

### 搭建go ethereum除錯環境
首先下載go安裝包進行安裝,因為GO的網站被牆,所以從下面地址下載。

    https://studygolang.com/dl/golang/go1.9.1.windows-amd64.msi

安裝好之後,設定環境變數,把C:\Go\bin目錄新增到你的PATH環境變數, 然後增加一個GOPATH的環境變數,GOPATH的值設定為你的GO語言下載的程式碼路徑(我設定的是C:\GOPATH)


安裝git工具,請參考網路上的教程安裝git工具, go語言從github自動下載程式碼需要git工具的支援

開啟命令列工具下載 go-ethereum的程式碼
    
    go get github.com/ethereum/go-ethereum

命令執行成功之後,程式碼就會下載到下面這個目錄,%GOPATH%\src\github.com\ethereum\go-ethereum
如果執行過程中出現

    # github.com/ethereum/go-ethereum/crypto/secp256k1
    exec: "gcc": executable file not found in %PATH%

則需要安裝gcc工具,我們從下面地址下載並安裝

    http://tdm-gcc.tdragon.net/download

接下來安裝IDE工具。 我是用的IDE是JetBrains的Gogland。 可以在下面地址下載

    https://download.jetbrains.com/go/gogland-173.2696.28.exe

安裝完成後開啟IDE. 選擇File -> Open -> 選擇GOPATH\src\github.com\ethereum\go-ethereum目錄開啟。

然後開啟go-ethereum/rlp/decode_test.go. 在編輯框右鍵選擇執行, 如果執行成功,代表環境搭建完成。


### go ethereum 目錄大概介紹
go-ethereum專案的組織結構基本上是按照功能模組劃分的目錄,下面簡單介紹一下各個目錄的結構,每個目錄在GO語言裡面又被成為一個Package,我理解跟Java裡面的Package應該是差不多的意思。


    accounts     實現了一個高等級的以太坊賬戶管理
    bmt         二進位制的默克爾樹的實現
    build           主要是編譯和構建的一些指令碼和配置
    cmd         命令列工具,又分了很多的命令列工具,下面一個一個介紹
        /abigen     Source code generator to convert Ethereum contract definitions into easy to use, compile-time type-safe Go packages
        /bootnode   啟動一個僅僅實現網路發現的節點
        /evm        以太坊虛擬機器的開發工具, 用來提供一個可配置的,受隔離的程式碼除錯環境
        /faucet     
        /geth       以太坊命令列客戶端,最重要的一個工具
        /p2psim     提供了一個工具來模擬http的API
        /puppeth    建立一個新的以太坊網路的嚮導
        /rlpdump    提供了一個RLP資料的格式化輸出
        /swarm      swarm網路的接入點
        /util       提供了一些公共的工具
        /wnode      這是一個簡單的Whisper節點。 它可以用作獨立的引導節點。此外,可以用於不同的測試和診斷目的。
    common          提供了一些公共的工具類
    compression     Package rle implements the run-length encoding used for Ethereum data.
    consensus       提供了以太坊的一些共識演算法,比如ethhash, clique(proof-of-authority)
    console         console類
    contracts   
    core            以太坊的核心資料結構和演算法(虛擬機器,狀態,區塊鏈,布隆過濾器)
    crypto          加密和hash演算法,
    eth         實現了以太坊的協議
    ethclient       提供了以太坊的RPC客戶端
    ethdb           eth的資料庫(包括實際使用的leveldb和供測試使用的記憶體資料庫)
    ethstats        提供網路狀態的報告
    event           處理實時的事件
    les         實現了以太坊的輕量級協議子集
    light           實現為以太坊輕量級客戶端提供按需檢索的功能
    log         提供對人機都友好的日誌資訊
    metrics         提供磁碟計數器
    miner           提供以太坊的區塊建立和挖礦
    mobile          移動端使用的一些warpper
    node            以太坊的多種型別的節點
    p2p         以太坊p2p網路協議
    rlp         以太坊序列化處理
    rpc         遠端方法呼叫
    swarm           swarm網路處理
    tests           測試
    trie            以太坊重要的資料結構Package trie implements Merkle Patricia Tries.
    whisper         提供了whisper節點的協議。

可以看到以太坊的程式碼量還是挺大的,但是粗略看,程式碼結構還是挺好的。我希望先從一些比較獨立的模組來進行分析。然後在深入分析內部的程式碼。重點可能集中在黃皮書裡面沒有涉及到的p2p網路等模組。








網址:http://www.qukuailianxueyuan.io/



欲領取造幣技術與全套虛擬機器資料

區塊鏈技術交流QQ群:756146052  備註:CSDN

尹成學院微信:備註:CSDN





網址:http://www.qukuailianxueyuan.io/



欲領取造幣技術與全套虛擬機器資料

區塊鏈技術交流QQ群:756146052  備註:CSDN

尹成學院微信:備註:CSDN

相關文章