1. 程式人生 > >超級賬本學習之二:瞭解Peer

超級賬本學習之二:瞭解Peer

在進一步瞭解超級賬本以前,我覺得有必要了解一些基本概念,這些概念可以在官方文件中找到。其中,特別重要的是關於Peer的一些理解。在這裡我嘗試去翻譯這篇文章,同時加入我自己的一些理解。

關於Peers

區塊鏈網路主要由一系列的Peers節點組成。Peers是整個網路的基礎,因為它是賬本和智慧合約的載體。通過智慧合約,賬本以不可篡改的方式記錄了交易的全過程。在區塊鏈中,智慧合約和賬本被用來封裝整個網路中的共享處理工程和共享資訊。從這個角度來說,Peer是瞭解超級賬本的一個很好的入口。當然,超級賬本還有很多其他的重要概念,比如,賬本、智慧合約、排序服務、通道、成員管理等。本文重點關注peers以及它與超級賬本網路中其他模組的關係與互動。


一個區塊鏈網路由peer節點組成,每一個peer節點持有一個或多個賬本,以及一個或多個智慧合約。上圖中網路N由三個peer組成P1、P2和P3。每一個Peer都持有了一個賬本例項L1;每個peer都通過鏈碼(智慧合約)S1去訪問各自的賬本副本L1。(注意:從這裡我們知道,鏈碼是一段可以訪問賬本的程式碼,賬本是通過鏈碼來訪問的!)

通過暴露的一系列介面,可以允許管理員和運用程式來建立、開啟、停止、重新配置甚至刪除peer。

賬本與鏈碼

進一步瞭解peer,我們可以說peer持有了賬本和鏈碼。但是,更準確的說應該是peer持有了賬本和鏈碼的例項。實際上,一個peer可以持有多個賬本例項和多個碼例項。


正是由於peer持有了賬本和鏈碼,管理員和運用程式必須通過peer才能訪問這些資源。正因如此,peer被稱作超級賬本區塊鏈網路中最基礎的模組。當peer被建立的時候,裡面既沒有賬本也沒有鏈碼。後面將描述賬本是如何建立的以及鏈碼是如何安裝的。

多賬本和多鏈碼

一個peer可以持有多個賬本,這對於增加系統設計的靈活性至關重要。當然,超級賬本也允許一個賬本沒有鏈碼,但這種情況很少,因為這就意味著這個賬本不能被訪問和更改。通常情況,我們每個賬本至少有一個鏈碼用於查詢或者更改賬本例項。實際上,不管使用者是否已經安裝了自己的鏈碼,每一個peer都有一些系統鏈碼(據我所知,channel的建立以及lead節點的確定就是通過系統鏈碼來完成的)。這些不在本章節的討論之列。

此外,鏈碼數量與賬本數量也沒有必然關係。如下圖,賬本L1可以通過鏈碼S1和S2訪問;賬本L2可以通過S1和S3訪問。因此,S1可以同時訪問L1和L2(個人認為,這個特性在實際運用中非常重要,這使得跨系統的聯盟鏈成為可能。)

實際上,由於一個Peer可能持有多個賬本和多個鏈碼,超級賬本中通道(channel)就顯得尤為重要了。

Application與Peer

接下來我們將介紹應用程式如何通過Peer去訪問賬本。簡單的說,Application與Peer的互動主要包括賬本查詢與賬本更新。賬本查詢只需要簡單的三次會話;而賬本更新需要額外的兩次會話。Application總是通過Peer去訪問賬本和鏈碼的。超級賬本提供的SDK可以允許application連線peer、呼叫鏈碼產生交易、提交交易到整個網路並接收處理過程中產生的事件。

通過連線到一個peer,application開執行鏈碼來查詢或者更新賬本。查詢結果可以很快返回;但是更新賬本需要更復雜的互動,這些互動涉及到application、peer還有orderer:


Orderer用來確保所有的Peer持有的賬本同步更新。在上圖中,查詢賬本的步驟可以做如下的簡單描述:

  1. application連線到peer。
  2. application生成提案,並將提案提交給peer。
  3. peer根據提案呼叫相應的鏈碼執行。
  4. 鏈碼根據提案查詢對應的超級賬本。
  5. 向application返回提案應答。

至此,賬本查詢的完成。更新賬本還需要接下來完成下面的步驟:

  1. application根據查詢的返回結果生成一個交易併發送給排序服務模組(Orderer)。
  2. orderer將交易發給網路內的所有節點(peers)。
  3. peer根據交易呼叫相關的鏈碼完成賬本更新(此處圖中可能產生誤導,P1不可以直接呼叫L1,應該先呼叫S1,再通過S1呼叫L1)。
  4. 賬本更新完成後產生事件通知application更新完成。

對於賬本查詢操作,peer本地儲存了賬本的副本,它不需要向網路內的其它peer查詢,因此可以很快的返回操作結果。當然,application可以連線到多個peer上,以儘量確保查詢的結果來自最新的賬本。

對於賬本更新操作,雖然本質上來說application仍然是通過連線的peer呼叫鏈碼來完成操作,但是與賬本查詢不同,賬本更新以前需要與其他peer達成一致,即共識。因此,需要Orderer將交易提案發送給整個網路的所有peer。每個peer收到交易提案後會從自己的角度判斷是接受還是拒絕交易提案。由於整個過程比較耗時,application會在整個過程完成後得到一個非同步的通知。關於orderer的工作流程交易流程

Peer與通道(Channel)

通道為網路中的所有模組提供了私有的溝通與交易渠道。這些模組包括peer節點、oderder節點、application。加入通道後,這些模組可以共享或管理通道內的所有賬本。一個節點可以加入到多個通道中(即,擁有多個賬本),但是每個通道的賬本是隔離的。因此,通道是一個邏輯結構,它由物理存在的各種節點組成。需要注意的是,peers提供了訪問通道或者管理通道的介面(個人覺得,通道就是一個區塊鏈,一個區塊鏈由一個賬本,一個賬本可能有一個或者多個鏈碼)。


Peers與組織(Organizations)

在明白了Peer與賬本、鏈碼和通道的關係後,需要進一步瞭解多個組織怎麼樣組成一個區塊鏈網路。通常情況,一個區塊鏈網路由多個組織組成,而非一個單一的組織(譯註:通俗的說,我們的區塊鏈很有可能是跨域(domain)的,很多時候我們需要多個域一起才能構成一個完整的區塊鏈網路。因此,這裡的組織可以看成域的概念)。如下圖所示:

  • 在圖中,我們可以看見4個組織提供了8個peers,進而組成了整個區塊鏈網路。而通道C連線了其中的5個peers,其塔的節點並沒有連線到當前通道。但是其他peers(P2、P4和P6)加入了至少一個其他的通道(圖中未給出)。每個組織的application只會連線到自己所在組織的peers上。另外,圖中沒有給出Orderer節點。
  • 因此,整個區塊鏈網路應該是由它所包含的組織構成的。因為組織才是區塊鏈網路所需資源的擁有者和提供者。雖然我們這裡討論的是peer,但是實際上組織才是真正的區塊鏈的價值基礎。因此,如果沒有有價值的組織,那麼區塊鏈網路也就失去了存在的意義。區塊鏈網路的規模與其擁有的有價值的組織有直接的正相關關係(個人覺得,這才是超級賬本的真正實際意義所在)。
  • 從上圖可以看出,沒有一箇中心化的資源存在。因此,整個區塊鏈網路並不依賴於某個單獨的組織。只要還存在有資源價值的組織,整個區塊鏈網路並不會依賴於某一個組織的出現或者消失。這正是去中心化的核心所在。
  • 每個組織都有自己的application。雖然使用的是同樣的賬本,但是由於每個組織關注的重點不一樣,因此他們的application也會有很大的差異。一個application可以連線到自己所在組織的peer,也可以連線到其他組織的賬本。這依賴於application與賬本的互動方式。比如:對於查詢操作,application只需要連線到自己組織的peer即可;但是對於更新操作,需要連線到所有組織的指定peer,因為更新操作需要背書操作。
  • 為了與當前的區塊鏈網路互動,每一個組織都需要一個錨定節點(Anchor Peer)。如圖中的P1、P3、P5、P7和P8就是錨定節點。

Peer與身份

通過特定的認證授權,每個Peer都被賦予了一個指定的數字簽名。數字簽名像一個身份證,包含了當前peer的各種資訊。每個Peer都擁有所在組織管理員簽發的數字簽名。


  • 當一個Peer加入通道的時候,它的數字簽名表明了它所在的組織。如圖所示,P1和P2的數字簽名有CA1簽發;而P3和P4的數字簽名由CA2簽發。通過配置,通道C知道CA1來自組織ORG1;而CA2來自ORG2。ORG1.MSP和ORG2.MSP由通道的MSP統一管理。
  • 通過配置(Channel Configuration),通道知道接入的每個Peer的許可權。MSP(Membership Service Provider)模組完成了這個功能。MSP決定了一個Peer的角色,訪問區塊鏈資源的許可權。由於一個Peer只能屬於一個組織,因此它只能被關聯到一個MSP上面。
  • 實際上,所有的節點在訪問區塊鏈網路的時候都需要進行身份認證。包括Peer節點、application、Orderer節點以及管理員等。
  • 需要注意的是,節點的物理位置並不重要。它可以是位於雲端,也可以是組織的中心伺服器或者本地的計算機。節點的身份認證決定了它是否可以加入指定的區塊鏈網路,以及加入網路後的角色和許可權。

Peer與排序服務(Orderer)

排序服務保證了application和Peers在互動的時候賬本的一致性。正如上面看到的,在賬本更新的時候,我們需要需要與網路中其它節點達成共識。通常情況,application需要3個步驟來完成賬本更新並保障資料的一致性:

  1. application將更新提案發給指定的背書節點,背書節點對提案背書,但不更新本地賬本,然後將背書結果返回給application。在這裡,背書節點是所有節點的一個子集,即不要求所有節點參與背書。
  2. application將收集所有的背書,然後打包到塊中。
  3. TODO

由上可知,排序節點(Orderer Node)是整個處理的核心。下面來詳細介紹application和peer是怎樣在分散式的環境下確保更新的一致性的。

步驟一:提案

第一步提案階段排序服務(Orderer),主要由application和一些相關的Peer節點完成。提案階段是application向不同組織的背書節點提交更新請求。如下圖所示:


  • application產生一個交易提案,並將提案發送給所有相關的背書Peer節點。每個背書節點根據交易提案獨立的執行鏈碼,並返回提案回執。需要注意的是,這個階段背書節點並不更新本地賬本,只是對提案簽名並返回給application。當application收集到了足夠的提案回執,提案階段就完成了。
  • 如圖,A1根據交易T1產生提案P,並分發給通道內的所有背書節點P1和P2。P1和P2分別進行背書,P1呼叫自己的鏈碼S1產生回執R1和背書E1。P2同理。P1和P2背書完成後將回執發回給application。
  • 背書節點的確認依賴於背書策略,背書策略由鏈碼確定,它定義了一個交易在被整個網路接受以前需要哪些組織背書。從業務上來說,當產生一個交易的時候需要哪些組織確認才能讓交易生效,那麼這些組織就需要為交易背書。
  • 背書節點(Endorser Peer)在回執中新增數字簽名,並且使用私鑰對整個payload域加密。因此,背書回執可以看作是該組織對該交易的一個有效證明。
  • 需要注意的是,對於相同的提案,不同的背書節點返回的回執結果可能不一樣。導致結果不一樣的情況可能原因有兩種:一是每個背書節點持有的賬本狀態不一致,導致背書回執是基於不同的賬本狀態產生的。對於這種情況,我們只需要簡單的請求一個最新回執即可;另外一個原因是由於背書節點鏈碼的不確定性導致的。這種情況就會比較嚴重,因為不確定性是鏈碼和賬本的天敵。不確定性出現說明交易提案本身就有問題,而且很明顯這種不一致的結果是不能寫入到賬本的。而且,每個單獨的背書節點並不知道他們的回執具有不確定性,因此需要收集所有的回執並加以比較才能知道是否存在不確定性。關於更多的不確定性的討論參加交易相關的文章。對於application來說,它在發現不一致的時候可以終止交易,實際上回執不一致的交易會在接下來的步驟中被拒絕掉。

步驟二:打包

打包操作由排序節點(Orderer)完成。所有application的交易在提案完成背書後,包含背書結果的回執會被髮送到排序節點。因此,排序節點會收到來自所有application的各種背書提案,它會對所有交易進行排序然後打包發給所有的Peers(包括先前參與背書的Peer)。如下圖所示:


  • 圖中,A1傳送的交易T1包含了回執R1和背書E1 E2;A2傳送的交易T2包含了回執R2和背書E1。這些交易咋排序節點中進行排序打包處理,形成一個塊B2。
  • 排序服務節點會同步收到不同application傳送的很多交易,排序節點會對這些交易排序,然後打包成塊。實際上,這些塊接下來會發給所有Peer,併成為賬本中的新塊。在第三步中我們會看見這些塊是怎麼處理的。
  • 需要注意的是,排序後的交易順序並不和他們到達的順序一致。排序後的交易順序就是它們在鏈碼上的執行順序,交易之間應該是有嚴格的順序的。
  • 在其它的區塊鏈中,同樣的交易可能被打包到不同的塊中。但是在超級賬本的區塊鏈中這是不允許的,因為一旦一個交易被寫入到塊中,它的位置也就不可篡改,交易歷史也不能在未來被修改,以防止賬本分叉(即,要保證一個交易的所有記錄被寫入到同一個塊中。如果交易未完全結束,則等待它完全結束後再寫入。防止不可預知的交易結果導致賬本分叉)。
  • 由此可見,Orderer只是對交易進行排序並打包。它本身不對交易進行驗證,因此它和Peer節點不一樣,它不包含賬本和鏈碼。

步驟三:驗證

最後,打包後的交易會被分發到所有節點(Peer)。每個Peer節點會對打包的每一個交易進行驗證,以確保每個交易都被相關節點背書,且背書回執是一致的。如果發現不一致,交易將會被審查並保留,不會被寫入到賬本中。如下圖所示:


  • Peer節點連線到排序服務,以確保有新的區塊產生的時候能獲得這個區塊的拷貝。每個Peer會單獨的處理新的區塊。實際上它們的處理方式是一樣的,這樣確保了賬本的一致性。需要注意的是,不是所有的Peer都會連線到Orderer節點。Peer節點可以通過GOSSIP將新的區塊散佈到網路的其它節點。
  • 每個Peer都需要驗證接收到的每個交易已經被正確的背書。不同的交易有不同的背書策略,需要不同的組織參與背書。Peer需要確保所有需要參與背書的Peer都參與了背書,併產生了同樣的背書結果。
  • 在驗證成功後,Peer還需要確保當前賬本的狀態與交易產生是的賬本狀態是一致的。這就確保了更新後的賬本與網路內的其它賬本是一致的。因為它們都遵循相同的更新規則。
  • 需要注意的是,驗證階段並不需要鏈碼的參與,鏈碼僅在第一步背書的時候用到。這使得參與背書的組織可以對它的背書鏈碼保密。與之對應的是查詢鏈碼,它可以對通道內的所有Peer開放。
  • 最後,每次Peer的賬本更新後都會產生一個塊事件。塊事件包含了整個塊的內容,包括塊內的所有交易是否有效或者無效等;而塊交易事件僅僅包含了一些摘要資訊;除此之外,鏈碼也可以在這個時候產生鏈碼事件。application可以通過註冊這些事件知道交易流程。

排序服務與共識

整個交易流程可以被稱之為共識,因為所有的Peer在排序和交易內容上達成了一致。共識是通過多個步驟達成的,而application只是在共識完成後得到通知而已。排序服務本身也是一個很複雜的處理,但是這裡我們簡單的認為排序只是蒐集、分發來自application的交易提案,而Peer負責驗證並將交易更新到賬本中。