國內最專業
盈幣寶資訊中心

使用Java開發一個自己的區塊鏈產品、聯盟鏈

使用Java開發一個自己的區塊鏈產品、聯盟鏈

起因
公司要開發區塊鏈,原本是想著使用以太坊開發個合約或者是使用個第三方平台來做,後來發現都不符合業務需求。原因很簡單,以太坊、超級賬本等平台都是做共享賬本的,有代幣和挖礦等模塊。而我們需要的就是數家公司組個聯盟,來共同見證、記錄一些不可篡改的交互信息,如A公司給B公司發了一個xxx請求,B公司響應了什麼什麼。其實要的就是一個分佈式數據庫,而且性能要好,不能像比特幣那種10分鐘才生成一個區塊。我們要的更多的是數據庫的性能,和區塊鏈的一些特性。

經過
項目於18年3月初開始研發,歷時一月發布了第一版。主要做了存儲模塊、加密模塊、網絡通信、PBFT共識算法、公鑰私鑰、區塊內容解析落地入庫等。已經初步具備了區塊鏈的基本特徵,但在merkle tree、智能合約以及其他的一些細節上,尚不到位。

希望高手不吝賜教,集思廣益,提出見解或方案,來做一個區塊鏈平台項目,適合更多的區塊鏈場景,而不僅僅是賬本和各種忽悠人的代幣。

理想中的區塊鏈平台:

項目說明
主要有存儲模塊、網絡模塊、PBFT共識算法、加密模塊、區塊解析入庫等。

該項目屬於”鏈”,非”幣”。不涉及虛擬幣和挖礦。

存儲模塊
Block內存儲的是類Sql語句。聯盟間預先設定好符合業務場景需要的數據庫表結構,然後設定好各個節點對錶的操作權限(ADD,UPDATE,DELETE),將來各個節點就可以按照自己被允許的權限,進行Sql語句的編寫,並打包至Block中,再全網廣播,等待全網校驗簽名、權限等信息的合法性。如果Block合法,則進入PBFT共識算法機制,各節點開始按照PrePrepare、Prepare、Commit等狀態依次執行,直到2f+1個commit後,開始進行本地生成新區塊。新區塊生成後,各節點進行區塊內容解析,並落地入庫的操作。

場景就比較廣泛了,可以設定不同的表結構,或者多個表,進而能完成各自類型信息的存儲。譬如商品溯源,從生產商、運輸、經銷商、消費者等,每個環節都可以對某個商品進行ADD信息的操作。

存儲采用的是key-value數據庫rocksDB,了解比特幣的知道,比特幣用的是levelDB,都是類似的東西。可以通過修改yml中db.levelDB為true,db.RocksDB為false來動態切換使用哪個數據庫。

結構類似於sql的語句,如ADD(增刪改) tableName(表名)ID(主鍵) JSON(該記錄的json)。這裡設置了回滾的邏輯,也就是當你做了一個ADD操作時,會同時存儲一條Delete語句,以用於將來可能的回滾操作。

網絡模塊
網絡層,採用的是各節點互相長連接、斷線重連,然後維持心跳包。網絡框架使用的是t-io,也是oschina的知名開源項目。t-io採用了AIO的方式,在大量長連接情況下性能優異,資源佔用也很少,並且具備group功能,特別適合於做多個聯盟鏈的SaaS平台。並且包含了心跳包、斷線重連、retry等優秀功能。

在項目中,每個節點即是server,又是client,作為server則被其他的N-1個節點連接,作為client則去連接其他N-1個節點的server。同一個聯盟,設定一個Group,每次發消息,直接調用sendGroup方法即可。

但仍需要注意的是,由於項目採用了pbft共識算法,在達到共識的過程中,會產生N的3次方數量的網絡通信,當節點數量較多,如已達到100時,每次共識將會給網絡帶來沉重的負擔。這是算法本身的限制。

共識模塊PBFT
分佈式共識算法是分佈式系統的核心,常見的有Paxos、pbft、bft、raft、pow等。區塊鏈中常見的是POW、POS、DPOS、pbft等。

比特幣採用了POW工作量證明,需要耗費大量的資源進行hash運算(挖礦),由礦工來完成生成Block的權利。其他多是採用選舉投票的方式來決定誰來生成Block。共同的特點就是只能特定的節點來生成區塊,然後廣播給其他人。

區塊鏈分如下三類:

私有鏈:這是指在企業內部部署的區塊鏈應用,所有節點都是可以信任的,不存在惡意節點;

聯盟鏈:半封閉生態的交易網絡,存在不對等信任的節點,可能存在惡意節點;

公有鏈:開放生態的交易網絡,為聯盟鍊和私有鍊等提供全球交易網絡。

由於私有鍊是封閉生態的存儲系統,因此採用Paxos類共識算法(過半同意)可以達到最優的性能;聯盟鏈有半公開半開放特性,因此拜占庭容錯是適合選擇之一,例如IBM超級賬本項目;對於公有鏈來說,這種共識算法的要求已經超出了普通分佈式系統構建的範疇,再加上交易的特性,因此需要引入更多的安全考慮。所以比特幣的POW是個非常好的選擇。

我們這裡可選的是raft和pbft,分別做私鍊和聯盟鏈,項目中我使用了修改過的pbft共識算法。

先來簡單了解pbft:

(1)從全網節點選舉出一個主節點(Leader),新區塊由主節點負責生成。

(2)每個節點把客戶端發來的交易向全網廣播,主節點將從網絡收集到需放在新區塊內的多個交易排序後存入列表,並將該列表向全網廣播。

(3)每個節點接收到交易列表後,根據排序模擬執行這些交易。所有交易執行完後,基於交易結果計算新區塊的哈希摘要,並向全網廣播。

(4)如果一個節點收到的2f(f為可容忍的拜占庭節點數)個其它節點發來的摘要都和自己相等,就向全網廣播一條commit消息。

(5)如果一個節點收到2f+1條(包括自己)commit消息,即可提交新區塊到本地的區塊鍊和狀態數據庫。

(6)客戶端收到f + 1個成功(即便有f個失敗、再f個惡意返回的錯誤信息,f + 1個正確的也是多數派)的返回,即可認為該次寫入請求是成功的。

可以看到,傳統的pbft是需要先選舉出leader的,然後由leader來蒐集交易,並打包,然後廣播出去。然後各個節點開始對新Block進行校驗、投票、累積commit數量,最後落地。

而我這裡對pbft做了修改,這是一個聯盟,各個節點是平等的,而且性能要高。所以我不想讓每個節點都生成一個指令後,發給其他節點,再大家選舉出一個節點來蒐集網絡上的指令組合再生成Block,太複雜了,而且又存在了leader節點的故障隱患。

我對pbft的修改是,不需要選擇leader,任何節點都可以構建Block,然後全網廣播。其他節點收到該Block請求時即進入Pre-Prepare狀態,校驗格式、hash、簽名、和table的權限,校驗通過後,進入Prepare狀態,並全網廣播狀態。待自己累積的各節點Prepare的數量大於2f+1時,進入commit狀態,並全網廣播該狀態。待自己累積的各節點Commit的數量大於2f+1時,認為已達成共識,將Block加入區塊鏈中,然後執行Block中sql語句。

很明顯,和有leader時相比,缺少了順序的概念。有leader時能保證Block的順序,當有並發生成Block的需求時,leader能按照順序進行廣播。譬如大家都已經到number=5的區塊了,然後需要再生成2個,有leader時,則會按照6、7的順序來生成。而沒有leader時,則可能發生多節點同時生成6的情況。為了避免分叉,我做了一些處理,具體的可以在代碼裡看實現邏輯。

區塊信息查詢
各節點通過執行相同的sql來實現一個同步的sqlite數據庫(或mysql等其他關係型數據庫),將來對數據的查詢都是直接查詢sqlite,性能高於傳統的區塊鏈項目。

由於各個節點都能生成Block,在高並發下會出現區塊不一致的情況。如果因為某些原因導致鏈分叉了,也提供了回滾機制,sql可以回滾。原理也很簡單,你ADD一個數據時,我會在區塊裡同時記錄兩個指令,一個是ADD,一個是回滾用的DELETE。同理,UPDATE時也會保存原來的舊數據。區塊裡的sql落地,譬如順序執行1-10個指令,回滾時就是從10-1執行回滾指令。

每個節點都會記錄自己已經同步了的區塊的值,以便隨時進行sql落地入庫。

對區塊鏈信息的查詢,那就簡單了,直接做數據庫查詢即可。相比於比特幣需要檢索整個區塊鏈的索引樹,速度和方便性就大不同了。

簡單使用說明
使用方法:先下載md_blockchain_manager項目,然後導入工程裡的sql數據庫文件,修改application.yml數據庫配置,最後啟動manager項目。

然後修改md_blockchain中application.yml裡的name、appid和manager項目數據庫裡的某個值對應,作為一個節點。如果有多個節點,則某個節點都和數據庫裡對應,填寫各節點的ip。managerUrl就是manager項目的url,讓該項目能訪問到manager項目。

在md_blockchian項目啟動時,在ClientStarter類中可見,啟動時會從manager項目拉取所有節點的數據,並進行連接。如果自己的ip和appId等不在manager數據庫中,則無法啟動。

可以通過訪問localhost:8080/block?content=1來生成一個區塊。正常使用時至少要啟動4個節點才行,否則無法達成共識,PBFT要求2f+1個節點同意才能生成Block。為了方便測試,可以直接修改pbftSize的返回值為0,這樣就能自己一個節點玩起來了。如果有多個節點,在生成Block後就會發現別的節點也會自動同步自己新生成的Block。目前代碼裡默認設置了一張表message,裡面也只有一個字段content,相當於一個簡單的區塊鏈記事本。當有4個節點時,可以通過並發訪問其中的幾個來同時生成Block進行測試,看是否會分叉。還可以關停其中的一個,看其他的三個是否能達成共識(拜占庭最多容許f個節點故障,4個節點允許1個故障),恢復故障的那個,看是否能夠同步其他正常節點的Block。可以進行各種測試,歡迎提bug。

可以通過localhost:8080/block/sqlite來查看sqlite裡存的數據,就是根據Block裡的sql語句執行後的結果。

我把項目部署到docker裡了,共啟動4個節點,如圖:

區塊鏈產品

區塊鏈產品

區塊鏈產品區塊鏈產品區塊鏈產品

此外還有高並發情況下,各節點同時生成Block,系統處理共識、保證區塊鏈不分叉的一些測試。

這個生成區塊的接口是寫好用來測試的,正常走的流程是調用instuction接口,先生產符合自己需求的指令,然後組合多個指令,調用BlockController裡的生成區塊接口。

————————————————
版權聲明:本文為CSDN博主「天涯淚小武」的原創文章,遵循 CC 4.0 BY-SA 版權協議,轉載請附上原文出處鏈接及本聲明。
原文鏈接:https://blog.csdn.net/tianyaleixiaowu/article/details/79899529

讚(0)

【盈幣寶Bingbon】
專業數字資產管理平臺來為您解決數字資產理財、交易等金融服務,致力於幫助使用者達到數字資產增值!
那麼好的盈幣寶APP當然要趕快下載來用,越快下載越快獲利喔!佛系理財就靠bingbon盈幣寶!

已經有許多許多人搭上這班財富列車
你還在等什麼!趕緊加入Bingbon盈幣寶!
財富的頂尖世界在等著你!

註冊連結:http://bit.ly/2qHh3hJ