1. 程式人生 > >[blockchain-012] tendermint 安裝和文件讀書筆記

[blockchain-012] tendermint 安裝和文件讀書筆記

1. 安裝go 1.9
  1.1 下載 
    https://golang.org/doc/install?download=go1.9.4.linux-amd64.tar.gz
  1.2 解壓縮到目錄 /home/bri/usr/go-1.9
    tar -C /home/bri/usr/go-1.9  -xzf go1.9.4.linux-amd64.tar.gz
  1.3 修改/etc/profile增加環境變數
---------------------
#for go
#gopath is woring directory
export GOPATH=/home/bri/workspace/go
#goroot is go install directory
export GOROOT=/home/bri/usr/go-1.9/go
export PATH=$PATH:$GOROOT/bin:$GOPATH/bin
---------------------




  1.4 在liteide編譯一個helloworld.go以驗證安裝無誤
  1.5 go version 檢查版本為1.9




2.tendermint原始碼分析
  2.1 獲取原始碼
    git clone -b v0.15.0 https://github.com/tendermint/tendermint.git
  2.2 tendermint官網
    https://www.tendermint.com/
  2.3 tendermint文件
    https://tendermint.readthedocs.io/en/master/




3. tendermint文件要點
  3.1 tendermint分量部分:共識引擎; 應用介面。共識引擎,又叫tendermint core。應用介面,又叫 ABCI,Application BlockChain Interface。tendermint的共識引擎可以單獨部署,非go語言開發的應用也可以使用。
  3.2 bft最多執行1/3的節點壞掉,這個壞掉是指任意的攻擊詐騙行為。
  3.3 早期,tendermint是內建的共識引擎,是pos的。現在,tendermint已經變成了通用的區塊鏈共識引擎,支援各種應用,可拔插式的。
  3.4 cosmos是一個基於tendermint的加密數字貨幣。https://cosmos.network/ 
  3.5 ABCI,讓多種語言可以寫BFT共識應用。它的實現是TSP(tendermint socket protocal)
  3.6 tendermint把共識引擎和p2p網路這兩個東東解耦出來了,比特幣是整體設計。解耦更好。
  3.7 如果開發一個類似比特幣的東東,ABCI和app分別解決不同的問題。ABCI需要解決的是:在節點間共享區塊和交易事務; 用區塊鏈建立不可變的事務次序。app需要解決的問題是:維護UTXO資料庫; 驗證交易事務的加密簽名; 防範雙花; 讓客戶端可以查詢UTXO資料庫。
  3.8 ABCI有三種訊息型別:DeliverTx; CheckTx; Commit。
    3.8.1 DeliverTx 區塊鏈上的每一個交易事務都是有DeliverTx訊息傳送的,app需要驗證從DeliverTx收到的每個事務的當前狀態,協議,加密驗證等等。交易事務被驗證後,app更新狀態,把交易事務存入資料庫,比如UTXO。
    3.8.2 CheckTx 跟DeliverTx相似,但僅用於驗證交易事務。
    3.8.3 Commit 計算一個加密的提交給當前app的狀態,這個提交將放在下一個區塊的頭部。
  3.9 一個app可以建立多個ABCI socket連線,每個連線處理一類訊息。這個一個流程https://tendermint.readthedocs.io/en/master/_images/abci.png 




3. tendermint 二進位制 安裝
  3.1 下載Linux 64的版本 https://github.com/tendermint/tendermint/releases 解壓縮到~/usr/tendermint
  3.2 執行
    初始化  tendermint init
    執行  tendermint node --proxy_app=dummy
  3.3 tendermint配置分析
    在~/.tendermint目錄下,有三個json檔案,有一個config.toml檔案。
    addrbook.json是記錄各節點的地址。
    priv_validator.json是私鑰檔案。 
    genesis.json是公鑰檔案。
    config.toml是配置資訊,包括proxy, 資料庫,rpc, p2p等各引數。








4. tendermint原始碼結構
  4.1 README.md 介紹性資料
  4.2 Makefile  go語言使用Makefile
    4.2.1 編譯tendermint需要安裝gox(https://github.com/mitchellh/gox): go get github.com/mitchellh/gox   
    4.2.2 需要ghr https://github.com/tcnksm/ghr#install,安裝 go get -u github.com/tcnksm/ghr
    4.2.3 需要gometalinter.v2,安裝 go get -u gopkg.in/alecthomas/gometalinter.v2
    4.2.4 類似,大部分需要的庫都以go get的形式安裝即可,如果有些包找不到,就到github上搜,搜到後用go get安裝
  4.3 cobra庫是一個命令列操作庫,在https://github.com/spf13/cobra這裡把demo執行一次就可以理解了,很簡單。
 
5 tendermint執行dummy分析
 5.1 執行tendermint node --proxy_app=dummy,出現如下提示
    I[02-13|04:57:32.545] Executed block                               module=state height=95 validTxs=0 invalidTxs=0
    I[02-13|04:57:32.548] Committed state                              module=state height=95 txs=0 appHash=
    I[02-13|04:57:33.603] Executed block                               module=state height=96 validTxs=0 invalidTxs=0
    由此,找到提示所在的程式碼,是
    state/execution.go:229:logger.Info("Executed block", "height", block.Height, "validTxs", validTxs, "invalidTxs", invalidTxs)
    這裡對應的函式是execBlockOnProxyApp,這個函式,是先向abci提交block,然後再執行block,再跟投票節點更新validator。
  5.2 execBlockOnProxyApp在state/execution.go:409被執行,此處函式名ExecCommitBlock,它做5.1的執行動作,然後向 鏈 提交block。
  5.3 ExecCommitBlock在consensus/replay.go:344被執行,此處函式名replayBlocks。
  5.4 replayBlocks又被同名首字母大寫ReplayBlocks函式呼叫
  5.5 ReplayBlocks被Handshake函式呼叫,
  5.6 Handshake被proxy/multi_app_conn.go:108被呼叫,在接口裡實現了multiAppConn的OnStart函式。NewMultiAppConn建立一組連結。
  5.7 NewMultiAppConn被NewAppConns呼叫
  5.8 NewAppConns被node/node.go:164 呼叫,也就是NewNode函式
  5.9 NewNode函式被node/node.go:78呼叫,也就是DefaultNewNode
  5.10 DefaultNewNode在cmd/tendermint/main.go:35呼叫
  5.11 在main函式,cobra有一個NewRunNodeCmd操作DefaultNewNode,主要是為了建立新節點。
  5.12 如果是本地執行,node init已經執行,然後執行 tendermint node --proxy_app=dummy,則進入AddNodeFlags函式設定引數,proxy_app對應config.ProxyApp,ProxyApp的預設值是"tcp://127.0.0.1:46658",
  5.13 


6. 除錯 dummy app的執行過程
  node --proxy_app=dummy
  執行到run_node.go的n, err := nodeProvider(config, logger)就開始輸出commit state資訊了。nodeProvider就是 nm.NodeProvider
  再到 node.go的NewNode
  再到 blockStoreDB, err := dbProvider(&DBContext{"blockstore", config})
  再到 DefaultDBProvider
  再到 proxyApp.Start(),開始啟動服務,出現committed state
  再到NewNode完成各種行為,
  NewNode函式最重要。


7. tendermint node --proxy_app=dummy執行機制
  7.1 這個過程,首先會啟動一個程序內的dummy app,這個dummy app是一個client,每一秒向tendermint的共識引擎傳送一次請求。client的程式碼在tendermint/abci/client.go和proxy/client.go裡。
  7.2 proxy/client.go:67,NewLocalClientCreator,呼叫NewDummyApplication
  7.3 NewDummyApplication 在abci/example/dummy/dummy.go,這裡根據abci介面定義了四個函式。
  7.4 這個dummy講發起各種任務給共識引擎。




8. tendermint文件
  8.1 abci-cli.rst abci客戶端教程,可以啟動counter和dummy兩個應用。
    8.1.1 check_tx驗證一個事務是不是正確。
    8.1.2 commit 提交一個應用的狀態,並返回默克爾樹的hash
    8.1.3 deliver_tx 嚮應用提交新的事務
    8.1.4 info 讓應用顯示基礎資訊
    8.1.5 query 查詢應用狀態
    8.1.6 dummy使用過程
      8.1.6.1 首先編譯安裝abci-cli
      8.1.6.2 在一個視窗執行abci-cli dummy開啟服務端。寫一個server的範例在tendermint/abci/tree/master/server,這是go語言的。注意,這個服務端是不儲存資料的,只要dummy關掉了,資料就消失了。
      8.1.6.3 在另一個視窗執行abci-cli echo hello,這是dummy客戶端命令。
  8.1.7 counter使用過程
    8.1.7.1 在一個視窗開啟abci-cli counter
    8.1.7.2 在另一個視窗開啟abci-cli console
    8.1.7.3 在cousole執行各種命令
      set_option serial on
    8.1.7.4 一個js版本的counter https://github.com/tendermint/js-abci/tree/master/example
  8.1.8 tendermint生態系統諸多開源專案 https://tendermint.com/ecosystem


  8.2 app-architecture.rst
    8.2.1 一個區塊鏈應用涉及諸多方面,比abci示例演示的共識引擎和事務邏輯多得多,同時,也可能有移動、桌面、web能多種客戶端。
    8.2.2 安全:abci應用和tendermint core之間的連線,要高度保護,validator。app和core要在同一個機器裡執行,如果app也是go語言寫的,最好將app和core打包成一個二進位制可執行程式碼,如果不是,那麼要讓core繫結只使用127.0.0.1的連線進來。如果這個做不到,使用ssh,注意保護validator機的許可權,關閉一切非ssh服務,也不要讓別人輕易接觸這個機器。
    8.2.3 tendermint core rpc: abci app跟外界做了充分隔離,只用一些有限的充分測試的介面給tendmint core進行通訊。
    8.2.4 自定義abci server: 示例專案https://github.com/wolfposd/TMChat。自定義伺服器,支援rest或者websocket或者json-rpc等介面,由移動app使用,同時具有abci app和data store功能,可以處理複雜的時間。
    8.2.5 擴充套件性:使用非驗證節點,以便提升讀和查詢速度,除非validator節點資料太多了,以至於非驗證節點無法及時更新。


  8.3 app-development.rst
    8.3.1 abci提供一個簡潔的介面:單節點上的狀態轉換機,多節點上的狀態轉化機的複製。前者叫應用邏輯,後者叫共識機制。前者驗證事務並執行事務,事務可能會修改狀態機。共識引擎確保所有的事務在每個節點上都按照同樣的順序執行。共識引擎的每一個節點,叫做 validator。


    8.3.2 abci提供的元件
    8.3.3 abci server
    8.3.4 abci client https://github.com/tendermint/abci/tree/master/client這裡是一個範例。持久化dummy在https://github.com/tendermint/abci/blob/master/example/dummy/persistent_dummy.go,提供了區塊鏈的開始,區塊鏈結束,區塊鏈初始化等動作。
    8.3.5 區塊鏈協議  在abci,一個事務就是一個簡單的任意長度的位元組陣列,如何解釋這個位元組陣列是應用app的事情。事務有兩種執行階段。第一階段,validator從client接收到一個事務,它把事務放到記憶體池或者事務池,這裡意味著checkTx。第二階段,事務已經成功提交給三分之二的validator,稱之為deliverTx。前一個階段只做檢查,不實際執行事務,後一個階段會執行事務且由此改變狀態機。
    8.3.6 mempool連線  mempool連線只用於checktx請求。validator按照接收次序checktx執行事務。如果checktx返回ok,那麼這些事務就會儲存在記憶體裡,然後以同樣的次序轉發給其他validtor。如果checktx返回錯誤,相關事務就會被拋棄。checktx同時也會併發執行區塊處理,主區塊鏈會實時更新維護最長區塊,每個validator都有一份主區塊的複製,checktx在這個複製鏈上執行事務。當一個區塊被提交後,應用會主動更新複製鏈,然後tendermint core會根據最新的複製鏈,對mempoll裡的事務進行過濾,去掉那些已經被最新區塊打包的事務,以免出現重複,並且,會在post-commit階段重新執行過濾後的事務。
    8.3.7 共識連線 只在一個新塊被提交時使用,這個塊有一系列請求 beginblock delivertx,..., endblock, commit。tendermint以非同步有序的方式轉發delivertx請求確保app以同樣的次序接收,block header可以儲存一些資訊,目前還沒有做。
      commit,當一個塊的所有處理都完成了,tendermint會發送commit請求和這個塊,然後等到response,此時,mempool會上鎖直到commit動作完成,所以應用不要在這個時候對mempool做任何阻塞通訊,做了就死鎖。commit完成後,應用會返回一個位元組陣列,這個位元組陣列是一個類似hash的用於驗證區塊有效性的東西,放在下一個區塊。
      beginblock, 它可以執行每個區塊的頭部的程式碼,也可以讓tendermint在傳送事務之前傳送當前區塊的hash和頭部給應用。建議應用儲存最新的height和header,以便加快某些處理。
      endblock, 它執行每個區塊的尾部的程式碼。此外,endblock的response也包含一系列的validator,以便更新validator set,所以如果要增加或者減少validator,只要把它們加在endblock的validator就行了,注意,修改的validator必須要少於三分之一,否則會導致無法形成共識。
      query連線,查詢應用,不設計共識引擎。它在tendermint core rpc暴露,因此比較安全。tenddermint cor可以根據ip和公鑰過濾節點。
      handshake,當app和tendermint重啟,它們需要同步到同一個height,先建立abci連線,然後tendermint在query連線上呼叫infobinging,response包含lastblockheight和lastblockapphash,跟著這兩個資訊,tendermint判斷如何做轉發,以及如何做同步。
      genesis,創世,initchain在創世階段執行一次,引數包括初始validator集,以及共識引數。
  
  8.4 getting-started.rst 這個是使用兩種demo的文件,演示用法。
    8.4.1 Basecoin是一個更嚴謹的數字貨幣的例子。
      https://github.com/cosmos/cosmos-sdk
      http://cosmos-sdk.readthedocs.io/en/latest/basecoin-basics.html




  8.5 using-tendermint.rst  這是一篇詳細文件
    根目錄 ~/.tendermint
    init   tendermint init
    run    tendermint noe
    事務    可以用curl傳送事務
    reset   重置區塊鏈
    配置    config.toml用作配置,
    不允許空區塊 是可配置的
    廣播api  早期,用broadcast_tx_commit廣播事務,一個事務傳送給tendermint節點,節點先做checktx,事務如果能通過checktx,則被加入到這個節點的mempoll,然後被轉發給其他節點,然後最終打包到區塊鏈。因為有多個階段,因此有多個廣播命令。
    Tendermint網路  創世檔案包含多個公鑰,這些公鑰是參與共識投票的,也有權重。
    peers    p2p網路,在啟動的時候可以配置種子節點。可以增加非validator節點,也可以增加validator節點。
    本地網路  測試用
    升級     這是一個很複雜的問題,要很小心,各版本差異比較大。










  












 




  
    








9.https://github.com/hyperledger/burrow
這是一個使用tendermint的類似以太坊的專案






10.py-tendermint專案 https://github.com/davebryson/py-tendermint


11. py-abci專案 https://github.com/davebryson/py-abci