區塊鏈時代的拜占庭容錯:Tendermint(二)

萬雲WANCLOUD發表於2018-08-16

原文題目:《Tendermint: Byzantine Fault Tolerance in the Age of Blockchains》

原文作者:Ethan Buchman

翻譯:饒雲坤

校對:傅曉波

本文為節選

正文

本章闡述Tendermint共識演算法和用於原子廣播( atomic broadcast)的相關區塊鏈。拜占庭容錯共識問題將被詳細討論,並且Tendermint共識的一個正式說明將以π-calculus的形式給出。Tendermint區塊鏈已經被非正式地證明為滿足原子廣播。將來我們將以程式演進的方式來描述完整的區塊鏈協議,並證明相關特性。

Tendermint綜述

Tendermint是區塊鏈正規化中的一個安全的狀態機複製演算法。其演算法形態為BFT-ABC,並且附加責任制,便於驗證拜占庭節點的不誠實行為。

Tendermint演算法給每個區塊賦予一個增量索引或者高度(height),在某一高度中只存在一個有效的區塊,區塊鏈從高度為0的創世紀塊開始,由一個驗證者集合投票產生下一個區塊,其中每一個驗證者由各自的公鑰標識。每一個驗證者需要維護一份完整的複製狀態的拷貝。在投票產生某一高度的區塊的過程中,在正式提交(commit)某一高度的區塊之前,至少需要經過一輪(round)投票(vote)來達成共識。每一輪都會通過round robin的方法產生一個提議者(proposer),該提議者在當輪以廣播的形式提出一個提議(proposal),提議經過驗證者的集體投票,來決定是否最終提交該區塊或者進入下一輪。在提議的區塊真正被提交(commit)之前,驗證者們需要進行兩輪投票(pre-vote & pre-commit), 通過一個簡單的鎖機制用來阻止少於總數1/3的拜占庭節點攻擊。由於Tendermint網路的不同時性(asynchrony),當拜占庭節點超過總數的1/3,網路存在癱瘓的可能性。

注意到,tendermint的多輪投票機制的核心是共識演算法。每一個區塊包含一些後設資料(metadata),稱作區塊頭(header)。區塊頭裡包含本區塊的高度,提議時間,本區塊所有交易的梅克爾根雜湊值。

共識

共識演算法可以大致分為以下幾部分:

提議(Proposals):在每一輪(round)中,新區塊的提議者必須是有效的,並且告訴(gossiped)其他驗證者。如果在一定時間內沒有收到當輪提議(proposal),當前提議者將被後面的提議者接替。

投票(Votes):兩階段的投票基於優化的拜占庭容錯。它們分別被稱作預投票(pre-vote)和預提交(pre-commit)。對於同一個區塊同一輪如果存在超過2/3的預提交(pre-commit)則對應產生一個提交(commit)。
鎖(Locks):在拜占庭節點數少於節點總數的1/3的情況下,Tendermint中的鎖機制可以確保沒有兩個驗證者在同一高度提交(commit)了兩個不同的區塊。鎖機制確保了在當前高度驗證者的下一輪預投票或者預提交依賴於這一輪的預投票或者預提交。

為了應對單個拜占庭故障節點,Tendermint網路至少需要包括4個驗證者。每個驗證者擁有一對非對稱金鑰,其中私鑰用來進行數字簽名,公鑰用來標識自己的身份ID。驗證者們從公共的初始狀態開始,初始狀態包含了一份驗證者列表。所有的提議和投票都需要各自的私鑰簽名,便於其他驗證者進行公鑰驗證。

區塊鏈時代的拜占庭容錯:Tendermint(二)

(驗證人在發起提議(proposal)步驟之後,當且僅當收到其它驗證人超過三分之二(+2/3)的投票後才會進一步推進流程。虛線箭頭表示進入下一個區塊高度共識流程的原子廣播。)

共識開始於第0輪,第一個提議者(proposer)是區塊鏈頭裡驗證者列表裡的第一個驗證者。每一輪最終要麼完成了一個提交(commit),要麼直接進入當前高度的下一輪,每一輪都會產生一個新的提議者。

與其他選舉(leader election )演算法不同,Tendermint每一輪都會產生一個新的提議者(proposer),驗證者投票決定是否進入下一輪,這與接受提議的流程類似。

每輪的開始對同步有弱的依賴性。每一輪開始期間,存在一個用來計時的本地同步時鐘,如果驗證者在TimeoutPropose時間內沒有收到提議,驗證者將參與投票來決定是否跳過當前提交者。TimeoutPropose會隨著輪數的增加而增加。

每輪收到提議以後,進入完全非同步模式。之後驗證者的每一個網路決定需要得到2/3驗證者以上的同意。這樣降低了對同步時鐘的依賴或者網路的延遲。但是這也意味著如果得不到1/3以上驗證者的響應,整個網路將癱瘓。

簡言之,每輪,開始提議弱同步,之後投票完全非同步。

為了增強Tendermint共識網路的安全性,引入了少量的鎖定規則(locking rules)來迫使驗證者自證其投票的合法性。儘管我們不需要實時廣播他們的合法證明,但是我們確實期望驗證者們儲存相關資料。這樣當網路被拜占庭故障節點癱瘓時,其可以存留為相關證據。這個問責機制確保在網路故障(例如PBFT)的時候Tendermint具有一個更健壯的擔保(guarantees)。

驗證者使用一組不同的訊息(messages)來管理區塊鏈,應用程式狀態,p2p網路和共識。其中,核心的共識演算法包含兩類訊息:

ProposalMsg: 對應某一高度及某一輪數的區塊的提議(proposal),該提議已經由提議者簽名

VoteMsg: 對某一提議的簽名投票

一、提議

每輪開始於一個提議(proposal),提議者從記憶體池(Mempool)選取一批交易進而構成了一個區塊,該區塊隨後被巢狀在ProposalMsg中,最後提議者廣播(broadcast)ProposalMsg。如果這個提議者是拜占庭節點,他可能向不同的驗證者廣播不同的ProposalMsg。

提議者通過一個簡單並且相對固定的的roubd robin輪流坐莊,所以每一輪只有一個有效且被所有驗證者公認的提議者。如果驗證者收到了之前更低輪次的提議或者提議來自於非法的提議者,該提議將被拒絕。

提議者的輪流坐莊對於拜占庭容錯是必要的。比如,對於raft演算法,如果選舉出來的leader是拜占庭,並且leader與其他節點網路連線狀態良好,該leader可以完全控制整個網路,網路節點的安全和正常運轉將無從得到保障。Tendermint通過投票和鎖的機制(voting and locking mechanisms )確保了系統的安全性。如果一個提議者在限定時間內沒有處理任何交易,排在其後的提議者將會接替他。更有趣的是驗證者能通過治理模組投票來移出或者替換拜占庭驗證者。

二、投票

一旦驗證者從網路中收到了一份完整的提議(proposal ),他對該提議進行預投票(pre-vote)簽名,並且廣播到網路中。如果驗證者在ProposalTimeout時間內沒有接收到一個有效的提議,其對該提議的預投票為空(nil)。

在存在拜占庭節點的非同步環境中,單階投票,即每個驗證者對每個提議只投一次,不能足以確保整個系統的安全。本質上,因為驗證者可能做出一些不誠實的行為,並且訊息的到達時間沒有任何保障,一個不誠實的驗證者可以與其他驗證者進行協作來提交(commit)一個區塊,然而其他沒有看到這個提交區塊的驗證者進入了新的一輪,並提交(commit)了一個不同的區塊。

一個單階的投票允許驗證者互相溝通他們知道的關於該提議的資訊。但是為了容忍拜占庭故障,他們也需要互相告訴對方他們自己瞭解到的其他驗證者聲稱瞭解到的關於該提交的資訊。換句話說,二階段提交確保了足夠的驗證者見證了第一階段的結果。

對於某個區塊的非空預投票是為網路提交(commit)區塊已做好準備的投票。空預投票是為網路直接進入下一輪的投票。在理想的一輪中,超過2/3的驗證者為該提議進行了預投票。在任意一輪中,區塊具有的超過2/3的預投票被稱作一個波爾卡(polka)。超過2/3的空預投票成為空波爾卡(nil-polka)。

當一個驗證者收到了一個波爾卡(polka),他接受到了一個訊號,即網路準備提交該區塊,作為一個驗證者簽名並且廣播預提交(pre-commit)的背書。有時,由於網路的不同時性,驗證者可能沒有收到對應的波爾卡或者波爾卡根本就不存在。在這種情況下,驗證者沒有對應的波爾卡為這個預提交背書,此時預提交為空。也就是說,在沒有收到波爾卡背書的情況下,簽名一個預提交被看作是一個惡意行為。

預提交(pre-commit)是關於提交(commit)一個塊的投票。空預提交則投票進入到下一輪。如果驗證者收到2/3以上驗證者的預提交,則其在本地提交該塊,計算結果狀態,並移動到下一高度的第0輪。如果驗證者接收到超過2/3的空預提交,則投票進入下一輪。

三、鎖

多輪投票的安全問題是棘手的,必須避免同一高度不同輪數分別提交兩個不同區塊的情形。在Tendermint中,這個問題可以通過鎖機制(locking mechanism)得到解決。鎖機制的大致定位在波爾卡附近。本質上,預提交必須有一個波爾卡為其背書,驗證者被鎖定在其最近預提交(pre-commit)的區塊上。

鎖定規則:

· 預投票鎖(Prevote-the-Lock):驗證者只能預投票(pre-vote)他們被鎖定的區塊。這樣就阻止驗證者在上一輪中預提交(pre-commit)一個區塊,之後又預投票了下一輪的另一個區塊。

· 波爾卡解鎖(Unlock-on-Polka ):驗證者只有在看到更高一輪(相對於其當前被鎖定區塊的輪數)的波爾卡之後才能釋放該鎖。這樣就允許驗證者解鎖,如果他們預提交了某個區塊,但是這個區塊網路的剩餘節點不想提交,這樣就保護了整個網路的運轉,並且這樣做並沒有損害網路安全性。

簡單來說,驗證者可以被看作鎖在任意高度-1輪的nil-block上,所以波爾卡解鎖意味著驗證者不能預提交一個新高度的區塊直到他們看見一個波爾卡。

這些規則可以以例子的形式被更直觀的理解。考慮4個驗證者,A,B,C,D,假設有一個第R輪關於blockX的提議。現在假設blockX已經有一個波爾卡,但是A看不見它,預提交(pre-commit)為空,然而其他人對blockX進行了預提交。進一步假設只有D看見了所有的預提交,然而其他人並沒有看見D的預提交(他們只看見他們的預提交和A的空預提交)。D現在將要提交(commit)這個區塊,然而其他人進入到R+1輪。由於任何驗證者都可能是新的提議者,如果他們提議並投票了一個新的區塊blockY,他們可能提交這個區塊。可是D已經提交了bockX,因此損害了系統的安全性。注意,這裡並沒有任何拜占庭行為,僅僅是不同時性。

區塊鏈時代的拜占庭容錯:Tendermint(二)

(為了便於讀者理解,譯者補充此表格,下同)

鎖定解決了這個問題通過強迫驗證者粘附在他們預提交(pre-commit)的區塊上,因為其他的驗證者可能居於這個預提交進行了提交(如上例中的D)。本質上,在任何一個節點一旦存在超過2/3預提交(pre-commit),整個網路被鎖定在這個區塊上,也就是說在下一輪中無法產生一個不同塊的波爾卡。這是預投票鎖的直接動機。

當然這裡必須有相應的解鎖方式。假設在某一輪中,A和B預提交(pre-commit)了blockX,與此同時C和D的預提交為空。因此所有的驗證者進入到下一輪,預提議(pre-vote)blockY。假設A是拜占庭,為blockY也進行了預投票(不考慮其被鎖在blockX上),導致了一個波爾卡。假設B並沒有看見這個波爾卡,預提交為空,此時A下線,C,D預提交bolckY。他們進入到下一輪,但是B仍然被鎖定在blockX上,C和D被鎖定在blockY上。這時因為A下線了,他們將永遠得不到一個波爾卡。因此即使在拜占庭節點少於1/3的情況下,這裡網路的正常運轉仍然受到了影響。

區塊鏈時代的拜占庭容錯:Tendermint(二)


區塊鏈時代的拜占庭容錯:Tendermint(二)

區塊鏈時代的拜占庭容錯:Tendermint(二)

解鎖的條件是1個波爾卡。一旦B看見了blockY的波爾卡(用來為C和D的關於blockY的預提交背書),他應當能夠解鎖並預提交(pre-commit)blockY。這是波爾卡解鎖的動機,其允許驗證者在看見更高輪數波爾卡的時候解鎖並且提交對應的新區塊。

區塊鏈

Tendermint對交易按批或塊進行處理。區塊之間通過加密哈雜湊演算法鏈成一個完整的區塊鏈。區塊鏈包括經過排序的交易日誌和驗證者提交的相關證據。

一、為什麼是區塊?

共識演算法一次提交若干個交易(transactions)。正如在第二章提到的那樣。從分批原子廣播(batched atomic broadcast)的角度來看待這個問題,對應兩個主要的優化,其給了我們更多的吞吐量和容錯能力:

· 頻寬優化:因為每一次提交(commit)需要驗證者之間的兩輪通訊,以塊為單位交易的批處理,平攤了提交的成本在該區塊中的所有交易上。

· 完整性優化:區塊的雜湊鍊形成了一個不可篡改的資料結構,跟git倉庫很像,具備歷史任意點的子狀態認證檢查的能力。

區塊也引起了另外一個效應,看上去更微妙,但是可能更重要。他們增加了單個交易的最小延遲到區塊的最小延遲,對於Tendermint來說在數百毫秒到數秒量級。傳統的序列化資料庫系統提供了提交延遲在毫秒到數百毫秒量級。他們的低延遲是因為這些資料庫不是拜占庭容錯的,只需要一輪通訊而不是兩輪和來自於1/2而不是2/3節點的響應。然而,與其他具有快速提交時間(commit times)的選舉演算法不同,Tendermint提供了一個更常規的脈衝(pulse ),在節點故障和網路不同時方面對整個網路的狀態具有更好的響應度。

脈衝在通訊自治系統一致性方面的角色現在並不明朗,但是由此引發的延遲在金融市場中是具有前景的。

二、區塊的結構

區塊的目的是打包一批交易,並且連結到前面一個塊。連結包含兩種形式:前面一個區塊的雜湊和前面區塊的預提交的集合,其也被稱作LastCommit。因此一個區塊由三部分構成:區塊頭,交易列表和Lastcommit。

安全性

這裡我們簡要的證明一下Tendermint滿足原子廣播。原子廣播被定義為滿足以下條件:

· 有效性(validity) - 如果一個正確的程式廣播m,它最終成功傳達了m

· 一致性(agreement) - 如果一個正確的程式成功傳達了m,所有最終所有的程式成功傳達m

· 完整性(integrity) - m只傳遞一次,並且是以廣播的形式被髮送者傳送出去

· 總的順序(total order) - 如果正確的程式p和q分別傳遞出m和m',p傳達m在m'之前,那麼q傳達m在m'之前

注意到, 如果把m看作一個區塊,Tendermint並不滿足有效性,因為並不能保證提議的區塊最會會被提交,因為驗證者可能進入到新的一輪,並提交一個不同的區塊。

如果我們把m看作某一區塊裡的一批交易,那麼我們能夠滿足有效性通過驗證者重新提議同一批交易直至交易最終被提交。

為了滿足完整性的第一部分,我們必須引入額外的規則來禁止一個合法的驗證者提議或者預提交一個區塊,其中這個區塊包含的這批交易已經被提交過。幸運的是,交易可以被梅克爾根索引,在提議和預提交以前可以進行相關的查詢來濾除已經提交的交易。

或者我們可以把m當成一個交易(transaction),通過引入記憶體池的持久屬性,可以滿足有效性,即,交易可以駐留在記憶體池中直到它被提交。然而為了滿足完整性的第一部分,我們必須依賴應用程式狀態(application state)來制定一些針對交易的規則,這樣一個給定的交易只能進行一次。例如,可以通過基於賬戶的序列號,正如在以太坊中的那樣。或者儲存一份未使用資源的列表,每一個資源只能被使用一次,正如在比特幣中使用的那樣。因為有多種方法,Tendermint本身並不保證訊息只傳達一次,但是允許應用開發者來指定相關特性。完整性的第二部分顯而易見,因為只有正確的提議者提議的區塊中的交易才能被提交。

為了證明Tendermint滿足“總的順序”,我們引入了一個新的特性,狀態機安全性(state machine safety),並且可以證明滿足狀態機安全性的協議必定滿足“一致性”和“總的順序”。所謂的狀態機安全是指如果一個正確的驗證者在高度H提交了一個區塊,沒有其他的驗證者在同一高度提交一個不同的區塊。考慮到所有的訊息最終被接收,這個立刻暗示了一致性,因為如果一個正確的驗證者在高度H提交了一個區塊B,包含了交易m,所有其他的正確的驗證者不能提交其他的區塊,因此最終提交了區塊B,傳達了訊息m。

現在,我們需要證明狀態機安全滿足“總的順序”,並且Tendermint滿足狀態機安全。為了證明前者,考慮兩個訊息m和m'分別由驗證者p和q發出。狀態機安全確保p發出訊息m在高度Hm當且僅當q發出訊息m在高度Hm,並且p發出訊息m'在高度Hm'當且僅當q發出訊息m'在高度Hm'。不失一般性,因為高度是嚴格遞增的,假設Hm<Hm'。那麼我們有p發出訊息m在m'之前當且僅當q發出訊息m在m'之前,這恰恰就是“總的順序"的定義。

最後,為了證明當拜占庭節點少於1/3的時候,Tendermint滿足狀態機安全,我們採用反證法。假設Tendermint並不滿足狀態機安全,允許在某一高度提交多個區塊。那麼我們可以證明至少需要1/3的拜占庭節點,與假設矛盾。

考慮一個有效的驗證者在高度H和輪數R提交了一個區塊B。提交一個區塊意味著驗證者在第R輪收到了關於區塊B的超過2/3的預提交。假設另一個區塊C在高度H提交。我們有兩個選項:要麼在第R輪提交要麼在S輪提交(S>R)。

如果區塊C在第R輪提交,那麼超過2/3的驗證者必須為該區塊預提交,那麼意味著至少1/3的驗證者在第R輪同時對區塊B和C進行了預提交,那麼顯然這些同時節點是拜占庭節點。假設區塊C在S輪提交。因為超過2/3對B區塊進行了預提交,他們在S輪也將被鎖定在區塊B上,因此他們必須對B進行預投票。為了對區塊C進行預提交,他們必須接收到關於區塊C的波爾卡,因此需要關於區塊C的超過2/3的預投票。然而,超過2/3的驗證者已經被鎖定在區塊B上。節點為了收到區塊C的波爾卡至少需要網路中1/3的驗證者違背鎖機制,這部分節點顯然是拜占庭節點。因此,為了違背狀態機安全,至少需要1/3的拜占庭驗證者。即若網路中的拜占庭節點少於總數的1/3,Tendermint滿足狀態機安全性。

綜上,Tendermint滿足原子廣播。

在未來的工作中,我們會提供關於Tendermint的安全性的更正式的證明。

責任制

一個具有問責制的拜占庭容錯演算法能夠在存在安全隱患時標識所有的拜占庭驗證者。傳統的拜占庭容錯演算法並沒與這個特性,對應地也沒有任何相應的保證。當然,問責制僅能適用在拜占庭節點在1/3到2/3的情況。如果超過2/3的節點是拜占庭,他們能夠完全佔據協議,此時無法保證一個合法的驗證者可以收到任何拜占庭節點違法的證據。

進一步,問責制是在非同步網路環境下最終性的盡力而為,在這樣的網路環境中著安全問題,關鍵訊息(critical messages)的延遲使得在探測到安全問題以後才可能發現拜占庭驗證者。事實上,如果正確的程式(correct processes)可以接受拜占庭行為的相關證據(evidence),但是在他們能夠通訊之前不可逆地失敗了(fail irreversibly),可能使得問責制永久失效( Permanently compromised),儘管實際上這種情形可以通過高階備份策略來克服。

通過列舉安全問題的各種隱患,拜占庭驗證者是可以識別的,這樣協議是具有問責制的。與其它競選相關的協議相比,Tendermint的簡潔給予了其更簡單的分析方法。

在Tendermint存在兩類安全隱患,每一種都是可問責的。第一種,拜占庭提議者在單輪中產生兩個衝突的提議,並且拜占庭驗證者同時對這兩個提議進行投票(vote)。第二種,一些驗證者在單輪已經提交(commit)之後,拜占庭驗證者違反鎖機制(locking rules),致使其他驗證者在隨後的輪數提交一個不同的區塊。注意到,若拜占庭驗證者少於2/3,只通過違反解鎖機制的方法是無法引發安全性問題的,同時超過1/3的節點必須違背波爾卡鎖機制,因為每一個提交(commot)需要有一個波爾卡為其背書。

在存在提議或者投票衝突的情況下,同時接受衝突的提議或者投票,可以根據這些提議或投票的簽名來辨別這些拜占庭節點。

在違反鎖定機制(locking rules)的情況下,伴隨著相應的安全性問題,有效的驗證者必須廣播在當前高度看到的所有投票,這樣證據可以被收集起來。少於2/3的正確驗證者在所有導致兩個區塊被同時提交的投票中集體隱匿。此時在這些投票中,如果沒有1/3或者更多的驗證者簽名衝突的投票,那麼存在1/3或者更多的驗證者違反了鎖定機制。

如果預投票( pre-vote )或者預提交( pre-commit)影響了一個提交,它一定會被一個合法的驗證者看見。因此,通過蒐集所有的投票,通過匹配每一個預投票和最近的預提交,可以探測到違反鎖機制的行為(violations of Prevotethe-Lock )。

類似的,通過匹配預提交(pre-commit )和為其背書的波卡爾卡(polka),可以探測到違反解鎖機制的行為(violations of Unlock-on-Polka )。注意到這就意味著如果拜占庭驗證者可以在看見波爾卡之前預提交(pre-commit),並且如果相應的波爾卡最終發生的話,拜占庭驗證者將逃脫責任制。然而,如果每一個預提交有波爾卡背書的話,這些安全隱患就不存在。

目前的設計提供了問責制,伴隨著後危機廣播協議(post-crisis broadcast protocol),但是其能夠用來提高實時的問責制。也就是說,一旦提交被改變,相應的預提交,為預提交背書的預投都會發生改變,這樣一直回退到創世紀塊。通過上面的方式,如果發生安全問題,沒有背書的投票可以立即被探測到。

故障和可用性

作為一個拜占庭共識容錯演算法,Tendermint可以容忍拜占庭故障節點到(但不包括)節點總數的1/3。這就意味著節點可能會崩潰,傳送不同和衝突的訊息到不同的節點,拒絕中繼訊息或者表現異常,安全或者運轉存在問題。

協議中有兩個地方我們可以通過使用本地時鐘的超時特性,為不同時性做一些優化:在接收到2/3或者更多預投票(pre-votes)之後(不針對單個區塊或者nil)和在收到2/3或更多預提交(pre-commit)以後(不針對單個區塊或者nil)。在每一中情形中,我們可以睡眠一段時間用來給延遲的投票一個被接受的機會,因此減少在新的一輪沒有提交區塊的可能性。時鐘不需要在驗證者之間同步,因為驗證者在觀測到2/3或更多的投票時會重置各自的時間。

如果1/3或者更多的驗證者崩潰,網路癱瘓,因為任何共識進展需要2/3以上驗證者的投票。網路仍然可以讀取資料,但是沒有新的區塊的提交。只要驗證者重新上線,他們能夠從之前的投票狀態開始。共識狀態機應該配置一個預寫式日誌(write-ahead log),這樣重新上線的的驗證者可以快速回退到之前機器崩潰時的位置,確保沒有違反規則。

如果1/3或者更多的驗證者是拜占庭,他們能夠以多種方式損害系統的安全性。例如,在同一輪提交兩個塊,並且投票提交這兩個區塊或者通過通過違反鎖定機制在同一高度不同輪提交兩個不同的區塊。在每一種情形中,有清晰的證據顯示哪些驗證者是拜占庭節點。在第一個例子中,他們在同一輪簽名兩個不同的提議,違反規則。在第二個例子中,他們鎖定在r-1輪在第r輪提交了一個不同的區塊,違反了鎖定機制。

當使用經濟和治理元件來激勵和管理共識,這些額外的責任制保證是具有決定性的。

結論

Tendermint本身是弱同步,拜占庭容錯,狀態機複製協議,擁有優化的拜占庭容錯和額外的責任制來保證當超過拜占庭容錯假設上限時的情形。協議採用round robin的提議者產生方法,用同樣的機制跳過一個提議者。多輪投票之間的安全性通過鎖機制得到了保障。


本章是關於協議的表述,存在許多有待進一步討論的重要細節,例如塊之間有效的通訊(efficient gossiping of blocks),快取交易,驗證者集合的改變和應用邏輯的介面。這些重要的話題將在隨後的章節得到進一步的解釋。




相關文章