1. 程式人生 > >談談自己對鉑鏈(Bottos)的看法和分析

談談自己對鉑鏈(Bottos)的看法和分析

首次接觸和第一印象

第一次接觸鉑鏈是在初鏈群中被鉑鏈群管拉進技術群時開始的。鉑鏈對我來說印象最深的還是他那長達70多頁的白皮書。作為一條主攻AI領域的專用公鏈,我在還沒開始看鉑鏈專案程式碼時就設想鉑鏈對於AI部分的處理應該是在區塊鏈內部構建一個執行AI運算的基礎設施模組,再由區塊鏈完成AI模組產出資料的確權,AI的運算可能將一部分交由智慧合約處理,做到運算和資料雙雙上鍊。AI計算天生是構建在大資料之上的,可以將大資料比作糧食,AI比作野獸,野獸只有在充分進食後才能進化,所以如果AI運算的基礎設施和區塊鏈整合在一起那區塊鏈一定會大資料緊密結合,區塊鏈如果和大資料緊密結合那對於資料儲存這一塊兒的要求就非常高了,資料分片技術可能會成為一個瓶頸。AI+大資料+區塊鏈?再加上那70多頁的白皮書?基於以上猜想,我對鉑鏈充滿好奇。在進入鉑鏈技術群之後,我就從GitHub上下載了鉑鏈的程式碼,花了一個星期左右的時間看完了絕大部分程式碼,也發現了一些小BUG和不足,目前的感受是鉑鏈的程式碼其實寫得挺好的,看得出來是在一個經驗豐富的架構師的帶領下發起的專案,但在架構設計上和我之前對鉑鏈的設想有明顯的出入,我並未看到任何和AI相關的程式碼,也未發現對於資料儲存這一塊兒有明顯亮眼的處理。

重新整理對“AI+區塊鏈”的認知

在鉑鏈技術群裡發表了自己對鉑鏈架構設計的看法,也得到了鉑鏈開發者的迴應,這才認識到自己對“AI+區塊鏈”的認知存在偏差。“AI+區塊鏈”其實並不是將AI和區塊鏈整合在一起,AI構建在大資料之上,而區塊鏈則是作為AI在資料確權和分享上的一種延申。根據 《Blockchain —構建新一代的人工智慧生態系統(http://www.blockchainbrother.com/article/1024)》 這篇文章的描述,AI的發展歸咎於算力、演算法和資料這三個核心因素。AI演算法在上世紀就已被研究透徹,但當時AI並未發展起來的原因正是算力和資料的缺失。在21世紀的今天,CPU/GPU的算力依據摩爾定律(甚至超過摩爾定律)在增長,網際網路的發展加快了社會進步的節奏,以往線上下堆積的資料也逐漸搬到了線上,大資料和雲端計算的出現更是讓AI在算力和資料上的不足得以彌補,所以近幾年AI領域出現了爆發式地增長:演算法一直都有,現在算力和資料也跟上了,AI發展的三要素也都集齊了。雖然算力和資料跟上了,但也只是在“量”上粗暴地增加了而已,在算力共享、資料交換和資料確權等“質”的轉變上,由於區塊鏈的出現也迎來了轉機。區塊鏈構建在密碼學基礎上的數字身份讓資料天然的具有“身份”屬性,其去中心化的特性也讓資料的流轉脫離了中心化的束縛而變得更加高效。資料具有身份驗證而且流通更快,這讓AI產生的資料更具價值,再配合上區塊鏈網路龐大的協同計算能力,AI的運轉速度無疑將更上一個臺階。所以我想,像鉑鏈這樣主打AI的區塊鏈,更多的還是為現有的AI體系提供資料上鍊和分享服務,而並不是構建一個獨立的AI生態系統,如果是這樣,那以後跨鏈通訊應該會是這些主攻AI市場的區塊鏈所應該具備的功能。

鉑鏈程式碼的簡單分析

> 高併發框架

鉑鏈程式碼由Go語言編寫,程式碼結構比較清晰,程式碼質量和原創程度都比較高,沒有看到明顯抄襲的痕跡。鉑鏈主體採用高併發的Actor模型構建,由ProtoActor.Go實現。鉑鏈將API服務(Api)、鏈處理(Chain)、P2P網路處理(Net)、區塊生產(Producer)、交易處理(Transaction)和可選的MongoDB服務(OptionDB)抽象為對應的Actor模型:

  • API服務:以RPC(遠端過程呼叫)的形式對外提供API服務,與鉑鏈的訊息互動採用Protobuf編碼,天然支援由多種語言編寫的外部應用程式
  • 鏈處理:實現鉑鏈的區塊鏈資料庫功能,包括區塊查詢、交易查詢、區塊接收與廣播和鏈資訊查詢功能
  • P2P網路處理:實現交易和區塊在P2P網路中的傳播功能
  • 區塊生產:每500毫秒檢測一次自己是否是當前區塊的生產者,是的話就構建一個區塊併發送給“鏈處理”處理
  • 交易處理:從終端或P2P網路接收交易放入交易池,並將交易傳送給“P2P網路處理”處理,支援獲取所有可加入區塊的交易和交易的移除操作
  • MongoDB服務:MongoDB服務作為一個可選服務,可在配置檔案中配置是否啟用,啟用MongoDB服務後可以將區塊寫入MongoDB中

每一個Actor對應一個執行緒,完全獨立地執行,與外部隔離。Actor之間的互動手段採用訊息通訊地方式,只有通過傳送訊息才能改變一個Actor的內部狀態。鉑鏈使用Actor模型讓幾個可以獨立執行的模組在高併發的環境下併發執行,在資料量大的環境中執行效率應該會有比較明顯的提升。

> RESTFUL化服務

幾乎每一個區塊鏈專案都提供了基於Http的Restful介面,提供Restful化的介面可以提供統一的介面呼叫規則,適合讓區塊鏈伺服器同時服務多種型別的終端,其中一些終端就包括區塊鏈瀏覽器和線上錢包。鉑鏈的Restful服務提供查詢區塊、交易和賬戶的服務,也提供傳送交易、獲取合約ABI(應用程式二進位制介面)和合約程式碼的服務,鉑鏈的命令列客戶端就使用Restful介面與區塊鏈通訊。

> 資料庫持久化服務

除開像MongoDB這樣的分散式資料庫外,鉑鏈還使用了另外兩個嵌入式資料庫,分別是LevelDB和BuntDB。以太坊中也使用LevelDB為資料持久化提供服務,由於以太坊採用特殊的MPT字典樹結構儲存狀態,所以每個樹節點的值都可以鍵值對的形式儲存在LevelDB中。鉑鏈採用的區塊儲存結構非常簡單,就是普通的二進位制序列,所以對於區塊和區塊頭的增刪查改就交由像LevelDB這樣的以鍵值對形式組織的非結構化資料庫來做,非常方便。BuntDB是用Go語言編寫的記憶體資料庫,類似於Redis和Memcache,提供資料持久化和查詢功能,支援結構化查詢,鉑鏈使用它完成賬戶的儲存和結構化查詢操作。由於鉑鏈採用DPOS作為其共識演算法,經常需要對投票賬戶進行排序,所以使用BuntDB這類的提供結構化查詢服務的資料庫是一個不錯的選擇,而且BuntDB是個記憶體資料庫,所以也不需要再額外使用快取儲存頻繁查詢的資料,直接用就行:

  • MongoDB資料庫: 以可選外掛形式存在的Actor模組,主要用於持久化儲存鏈上的區塊,還提供轉賬和建立賬戶兩個內建的合約功能,和LevelDB功能重疊,但作為一個本身就提供資料分片儲存功能的主從分散式資料庫,可能在以後區塊資料激增的情況下接替部分LevelDB的功能,為鉑鏈提供一個數據分片的解決方案。
  • LevelDB資料庫:以鍵值對的形式為區塊鏈提供區塊儲存和查詢功能,以雜湊作為鍵,以BPL(Bottos-Pack-Library,鉑鏈自研二進位制編解碼庫)編碼作為值,但需要配合LruCache為其提供輔助的資料快取服務
  • BuntDB資料庫:記憶體資料庫高效存取,不需要提供資料快取服務,並且還支援結構化查詢和回滾操作,特別適合需要頻繁存取和排序查詢的賬戶資料的儲存

> P2P網路節點發現機制

不同於基於POW共識設計的區塊鏈,基於DPOS共識設計的區塊鏈由於可能存在固定的代理人節點,所以在區塊鏈的對等網路中,對節點發現機制的複雜度要求就沒那麼高。很多基於POW共識演算法設計的區塊鏈在節點發現機制上採用DHT(分散式雜湊表)系列演算法,比如初鏈就採用Kadelima作為其節點發現機制的演算法,按照距離讓節點在對等網路中均勻排布,以最大化優化訊息在網路中的傳播效率,為了實現內網穿透,一般採用UDP協議建立連線,而鉑鏈則自研了一套基本能用的節點發現演算法,節點之間採用TCP協議連線。在鉑鏈的節點發現演算法中,存在三個層次的角色,分別是Neighbors、Candidates和Runners,在配置檔案中預配置的種子節點列表則首先放入Neighbors層次中。節點在三個層次之間通過Discover模組驅動流轉,其中Runners層次中的節點通過KeepAlive模組完成心跳檢測。具體的發現機制如下:

  • 角色介紹:
    a) Neighbors層次:處在該層次的節點都是鄰居,所有在Neighbors層次中的節點都沒有與其建立連線,都以IP和埠等節點資訊的形式儲存,處在該層次的節點通過Discover模組與本節點建立連線後被提升至Candidates層次成為候選者節點
    b) Candidates層次:處在該層次的節點都是候選者,本節點與所有候選者節點都已經建立了TCP連線,在連線建立後會立即開啟三次握手流程,在雙方都已達到最後一次握手流程時會互相將對方提升至Runners層次成為連線者
    c) Runners層次:處在改層次的節點都是正式的連線者,所有的P2P通訊都會通過他們進行轉發,也會通過他們完成接收,可廣播也可單播。
  • 流程介紹:
    A) 從配置檔案中讀取所有種子節點的IP和埠等資訊,全部放入Neighbors層次中
    B) Discover模組每5秒從Neighbors層次中取出10個節點資訊並嘗試建立TCP連線,連線成功後將節點從Neighbors層次中移除並放入Candidates層次中
    C) 每5秒中向所有處於Candidates層次中的節點開啟三次握手流程並將對應節點的握手計數器加1,如果超過10次握手都沒有成功那直接關閉和該節點的連線,然後將節點從Candidates層次中移除
    D) 在三次握手流程結束後將節點從Candidates層次中移除並放入Runners層次中並初始化該節點的心跳計數
    E) KeepAlive模組每10秒向所有處於Runners層次中的節點發送一次Ping、Pong心跳檢測,在收到Pong訊息後將對應節點的心跳計數加1
    F) 在終端啟動之後的前三個8秒中向所有處於Runners層次中的節點索要他們的Runners層次中的所有節點資訊,將這些節點資訊全部傳回本節點,然後放入本節點的Neighbors層次中
    G) 在終端啟動之後的第三個8秒之後的每8秒向最新加入Runners層次中的節點所要他的Runners層次中的所有節點資訊,將這些節點資訊全部傳回本節點,然後放入本節點的Neighbors層次中
    H) KeepAlive模組每40秒檢測一次在Runners層次中的節點的心跳狀態,將所有心跳計數為0的節點從Runners層次中移除,關閉和他們的連線,然後放入Neighbors層次中

> DPOS共識演算法

作為摻雜了“人治”因素的共識演算法,DPOS共識演算法也像POW共識演算法那樣飽受爭議,POW共識演算法在挖礦演算法設計不當的情況下,容易催生ASIC專用礦機從而在人性“逐利”的驅使下導致算力逐步集中為礦池,導致去中心化程度明顯降低。針對目前POW共識演算法的不足,DPOS共識演算法並沒有給出一個優化方案,比如基於抗ASIC專用礦機挖礦演算法的POW共識演算法優化(比如初鏈就設計了一套抗ASIC專用礦機的挖礦演算法),而是基於目前無法做到完全去中心化的事實,設計出一套從一開始就摒棄追求完全去中心化的初衷,以犧牲去中心化程度為代價來換取區塊鏈效能提升的基於“人治”的共識演算法。DPOS共識演算法涉及代理人節點的競選、投票和換屆,獲得投票數量排前幾位的競選者將在當前的代理人換屆週期內被提升為正式的區塊生產代理人節點,即記賬節點。每一個代理人節點都會在換屆週期內被分配一個出塊時間槽,輪到你出塊時就必須在當前時間槽內完成區塊的生成和廣播,不然就會被記錄為錯過一次出塊任務,這個記錄會廣播給全網,其他節點在收到這些記錄資訊後自然也能權衡在下次代理人換屆時是否還繼續給你投票。每一個節點都可以參與代理人競選,不過有沒有節點給你投票那就不是你能決定的了,人都有惰性和從眾心理,獲票數量始終在前的代理人節點會在頭部效應的影響下,地位越來越穩固,留給其他“小白節點”的機會就會越來越少,除非他們“資金”雄厚。DPOS共識演算法會是在區塊鏈去中心化程度和執行效率的折中權衡下的一箇中長期共識方案,但一定不會是公鏈的最終共識形態。DPOS共識演算法適合那種需要由人或社群去維護執行在區塊鏈之上的產品的專用公鏈,這些產品質量維護的好壞程度很難用演算法去衡量其背後的工作量,但使用這些產品的使用者卻能深切感受到,在這種環境下設計的區塊鏈適合選用DPOS作為其共識演算法,因為既然只能由人去確認區塊鏈的執行狀況,那“人治”就是不可避免的也是十分必要的一個環節,比如觸控科技的BCX區塊鏈遊戲引擎專案就是一個很好的例子。BCX區塊鏈採用DPOS共識演算法,專為區塊鏈遊戲生態打造,如果人人都能參與區塊鏈遊戲的維護,都有權力為遊戲新增更多好玩的元素,那遊戲是否好玩就需要由玩家去鑑定,玩家會一直把票投給能讓遊戲真正變得好玩的維護者讓他們變成代理人,這些代理人一旦作惡讓遊戲變得不好玩或者不平衡,玩家自然不會再把票投給他們。扯了那麼多都沒有講鉑鏈DPOS共識演算法的執行過程,鉑鏈團隊設計的DPOS共識演算法和傳統的DPOS共識演算法基本相同,沒有太大的出入,最多就調整了下代理人的選取規則。不過目前鉑鏈還處在測試階段,共識流程為測試網路中的流程,在正式網路釋出後應該會有完善和變更。測試網路中的共識流程如下:

a) 節點在區塊鏈初始化時建立Bottos內建合約賬戶並注入大量資金,如果Bottos合約賬戶已存在則跳過此步驟
b) 通過向區塊鏈傳送合約交易呼叫內建合約程式碼,與共識相關的內建合約功能包括建立賬戶、交易轉賬、劃撥權益、註冊代理人競選和代理人投票
c) 節點先發送“建立賬戶”的交易建立金鑰賬戶、餘額賬戶和權益賬戶,然後傳送“交易轉賬”交易從Bottos內建賬戶中索取需要的轉賬金額填充餘額賬戶,再發送“劃撥權益”交易將資金從餘額賬戶劃撥至權益賬戶,最後傳送“註冊代理人競選”交易建立代理人投票賬戶
d) 以上所有交易都會進行全網廣播並執行對應的合約功能,這樣全網所有節點都能看到任意一個節點建立的代理人投票賬戶,他們可以選擇給指定的代理人投票賬戶投票,通過傳送“代理人投票”交易將權益賬戶中的餘額用來更新指定註冊競選代理人的投票狀態
e) 每29個區塊完成一次代理人換屆,所有節點在收到區塊編號是29的倍數的區塊時開啟代理人換屆流程,從所有代理人投票賬戶中選取28個票數最高的賬戶和1個剩餘完成時間最小的賬戶,將這29個賬戶隨機打亂後就成為本屆的出塊代理人賬戶名單
f) 根據節點的系統時間獲得當前的出塊槽位(Slot),再根據出塊槽位從29個代理人賬戶中選取對應槽位下的代理人賬戶,如果該賬戶在節點的本地賬戶名單中,那麼在代理人蔘與率和出塊排程時間都達標的情況下,本節點會被指定為當前時間段內的出塊人,在立即將交易打包進區塊並全網廣播後完成本輪出塊任務
g) 在目前的測試網路中,節點在出塊後並沒有分配相應的記賬獎勵,鏈上所有的資金都來自於初始化的Bottos內建合約賬戶中,該賬戶具有非常龐大的資金儲備,足夠在測試網路中使用,在正式網路中將完善整個獎勵過程

> 智慧合約和WASM虛擬機器

同以太坊類似,鉑鏈也具有普通賬戶和合約賬戶兩種賬戶型別。在鉑鏈中,普通賬戶和合約賬戶都使用同樣一個數據結構,在普通賬戶的基礎上為其部署智慧合約程式碼和ABI資料(可選),那普通賬戶就算是一個合約賬戶了。鉑鏈的智慧合約模組主要為內建的合約賬戶服務,該內建合約賬戶名為“Bottos”,包含多種基礎的合約方法,像建立賬戶、交易轉賬、部署智慧合約程式碼和部署ABI資料等方法都實現在該合約裡,“Bottos”內建合約也是唯一一個在鉑鏈中使用ABI來為合約方法的呼叫引數進行解碼的智慧合約,因為在WASM虛擬機器中並未看到有對合約引數進行解碼的操作,這可能是因為目前鉑鏈還處在測試階段的原因,也可能是WASM虛擬機器在執行合約方法時不需要從外部提供呼叫引數。在鉑鏈裡所有的交易都是在呼叫智慧合約裡的方法,像最基本的交易轉賬等功能也都是由內建合約方法實現。節點在執行一個交易時會先判斷交易觸發的合約方法是否為內建合約方法,如果是則解碼交易中附帶的呼叫引數,然後呼叫該內建合約方法,比如交易轉賬,如果不是那麼就交給WASM虛擬機器處理,WASM虛擬機器會從交易指定的合約賬戶中查詢部署的智慧合約程式碼,在解析完合約程式碼後就會開始執行交易中指定的合約方法,如果方法執行完畢後還發現有子交易未處理,那麼就繼續遞迴地執行下去,但遞迴深度不能超過10。鉑鏈會使用WASM位元組碼作為合約程式碼應該是參考了EOS的設計,WASM全名為WebAssemly,是一個能被瀏覽器解析執行的位元組碼資料,目的是為了解決JavaScript在瀏覽器中執行過慢的問題。WASM最亮眼的特點就是支援將多種語言編寫的程式程式碼編譯為WASM位元組碼,這其中就包括C/C++、C#、Java、JS等語言。相比於以太坊單一的Solidity智慧合約語言,WASM能讓區塊鏈支援多種語言編寫智慧合約程式碼,這無疑會極大地豐富區塊鏈的應用生態,也是下一代區塊鏈的基本要求。扯了那麼多還是羅列下鉑鏈處理智慧合約的基本流程:

a) 從交易中取出合約賬戶、合約方法和合約引數三個資料,判斷合約賬號和合約方法是否屬於內建合約
b) 如果是,則依據合約方法內建的ABI結構解析合約引數,將解析出來的引數傳遞給對應的內建函式並呼叫執行,交易執行完畢
c) 如果不是,則依據合約賬戶從資料庫中取出部署在該賬戶下的合約程式碼,建立WASM虛擬機器並解析合約程式碼,找到合約程式碼中的入口函式“Start”和合約方法地址,將方法的地址傳入入口函式執行,如果在執行後存在子交易要處理,則回到第一步繼續遞迴處理直到再無子交易或遞迴深度超過10為止,否則交易執行完畢

> 總結

鉑鏈的標籤就是“DPOS+WASM”,這不禁讓人聯想到EOS,可能鉑鏈就是在對標EOS,只不過更加關注AI領域,但再造一個EOS真的有意義嗎?目前鉑鏈公開的程式碼還在測試網路中執行,期待後續跟進的Beta版主網程式碼,可能會有相當大程度的改進,到時候我們再一一解析吧。希望這篇文章能讓你更進一步地理解鉑鏈(Bottos)的設計和追求的目標,目前鉑鏈的程式碼已可在GitHub上下載,上去搜“Bottos”就能找到,如果你對鉑鏈感興趣,不妨閱讀下他們的程式碼,相信你一定會有所收穫的。相比於以太坊和EOS,鉑鏈的程式碼應該更基礎也更容易閱讀,對於急切需要了解區塊鏈設計全貌的朋友來說是個不錯的切入點。再者,加入鉑鏈社群也是一個瞭解區塊鏈社群生態的不錯的選擇,社群裡會時不時地釋出一些有償的任務或無償的培訓計劃,讓社員在社群的激勵下逐步瞭解一款區塊鏈產品。