這裡將詳細地對示例性實施例進行說明,其示例表示在附圖中。下面的描述涉及附圖時,除非另有表示,不同附圖中的相同數字表示相同或相似的要素。以下示例性實施例中所描述的實施方式並不代表與本說明書一個或多個實施例相一致的所有實施方式。相反,它們僅是與如所附申請專利範圍中所詳述的、本說明書一個或多個實施例的一些方面相一致的裝置和方法的例子。
需要說明的是:在其他實施例中並不一定按照本說明書示出和描述的順序來執行相應方法的步驟。在一些其他實施例中,其方法所包括的步驟可以比本說明書所描述的更多或更少。此外,本說明書中所描述的單個步驟,在其他實施例中可能被分解為多個步驟進行描述;而本說明書中所描述的多個步驟,在其他實施例中也可能被合併為單個步驟進行描述。
區塊鏈一般被劃分為三種類型:公有鏈(Public Blockchain),私有鏈(Private Blockchain)和聯盟鏈(Consortium Blockchain)。此外,還有多種類型的結合,比如私有鏈+聯盟鏈、聯盟鏈+公有鏈等不同組合形式。其中去中心化程度最高的是公有鏈。公有鏈以比特幣、以太坊為代表,加入公有鏈的參與者可以讀取鏈上的資料記錄、參與交易以及競爭新區塊的記帳權等。
而且,各參與者(即節點)可自由加入以及退出網路,並進行相關操作。私有鏈則相反,該網路的寫入權限由某個組織或者機構控制,資料讀取權限受組織規定。簡單來說,私有鏈可以為一個弱中心化系統,參與節點具有嚴格限制且少。這種類型的區塊鏈更適合於特定機構內部使用。
基於區塊鏈的基本特性,區塊鏈通常是由若干個區塊構成。在這些區塊中分別記錄有與該區塊的創建時刻對應的時間戳記,所有的區塊嚴格按照區塊中記錄的時間戳記,構成一條在時間上有序的資料鏈條。
對於物理世界產生的真實資料,可以將其構建成區塊鏈所支持的標準的交易(transaction)格式,然後發佈至區塊鏈,由區塊鏈中的節點設備進行共識,並在達成共識後,由區塊鏈中作為記帳節點的節點設備,將這筆交易打包進區塊,在區塊鏈中進行持久化存證。
在區塊鏈領域,有一個重要的概念就是帳戶(Account);以以太坊為例,以太坊通常將帳戶劃分為外部帳戶和合約帳戶兩類;外部帳戶就是由用戶直接控制的帳戶;而合約帳戶則是由用戶透過外部帳戶創建的,包含合約代碼的帳戶(即智慧合約)。
當然,對於一些基於以太坊的架構而衍生出的區塊鏈項目(比如螞蟻區塊鏈),還可以對區塊鏈支持的帳戶類型,進行進一步的擴展,在本說明書中不進行特別限定。
對於區塊鏈中的帳戶而言,通常會透過一個結構體,來維護帳戶的帳戶狀態。當區塊中的交易被執行後,區塊鏈中與該交易相關的帳戶的狀態通常也會發生變化。
以以太坊為例,帳戶的結構體通常包括Balance,Nonce,Code和storage等欄位。其中:
Balance欄位,用於維護帳戶目前的帳戶餘額;
Nonce欄位,用於該帳戶的交易次數;它是用於保障每筆交易能且只能被處理一次的計數器,有效避免重放攻擊。
code欄位,用於維護該帳戶的合約代碼;在實際應用中,code欄位中通常僅維護合約代碼的hash值;因而,code欄位通常也稱之為codehash欄位。對於外部帳戶而言,該欄位為空值。
storage欄位,用於維護該帳戶的儲存(預設為空)。在實際應用中,storage欄位僅維護基於帳戶的儲存內容構建的MPT(Merkle Patricia Trie)樹的根節點;因此,storage欄位通常也稱之為storageRoot欄位。
其中,對於外部帳戶而言,以上示出的code欄位和storage欄位為空值。
而大多數區塊鏈專案,通常都會使用Merkle樹;或者,基於Merkle樹的資料結構,來儲存和維護資料。以以太坊為例,以太坊使用了MPT樹(一種Merkle樹變種),作為資料組織形式,用來組織和管理帳戶狀態、交易資訊等重要資料。
以太坊針對區塊鏈中需要儲存和維護的資料,設計了三顆MPT樹,分別是MPT狀態樹、MPT交易樹和MPT收據樹。
MPT狀態樹,是區塊鏈中所有帳戶的帳戶狀態資料(state),組織成的MPT樹;MPT交易樹是區塊中的交易資料(transaction),組織成的MPT樹;MPT收據樹,是區塊中的交易執行完畢後生成的與每筆交易對應的交易收據(receipt),組織成的MPT樹。以上示出的MPT狀態樹、MPT交易樹和MPT收據樹的根節點的hash值,都會被添加至區塊頭中。
其中,MPT交易樹和MPT收據樹,與區塊相對應,每一個區塊都有自己的MPT交易樹和MPT收據樹。而MPT狀態樹是一個全域的MPT樹,並不與某一個特定的區塊相對應,而是涵蓋了區塊鏈中所有帳戶的帳戶狀態資料。
對於組織成的MPT交易樹、MPT收據樹和MPT狀態樹,最終都會在採用多級資料儲存結構的Key-Value型資料庫(比如,LevelDB)中進行儲存。
而採用多級儲存結構的上述資料庫,通常可以被劃分為n級資料儲存;例如,各級資料儲存可以依次設為L0,L1,L2,L3....L(n-1);對於上述資料庫中的各級資料儲存而言,等級編號越小通常級別越高;例如,L0儲存的是最新的若干區塊的資料,L1儲存的是次新的若干區塊資料,依次類推。
其中,各級資料儲存對應的儲存媒體的讀寫性能,通常也可以存在性能差異;級別高(即等級編號較小的)的資料儲存對應的儲存媒體的讀寫性能,可以高於級別低的資料儲存對應的儲存媒體的讀寫性能。
例如,在實際應用中,級別高的資料儲存,可以使用讀寫性能較高的儲存媒體;而級別低的資料儲存,可以使用單位成本低,且容量較大的儲存媒體。
在實際應用中,隨著區塊高度的增長,在資料庫中儲存的資料,會包含很多歷史資料;而且,區塊號越小的區塊中的資料越久遠,越不重要。因此,為了降低整體的儲存成本,通常需要對不同區塊高度的資料進行“區別對待”;
例如,可以將區塊號較小的區塊中的資料,儲存至成本較低的儲存媒體上;而將區塊號較大的區塊中的資料,儲存在成本較高的儲存媒體上。
在針對資料庫中儲存的MPT交易樹、MPT收據樹和MPT狀態樹等資料進行分級儲存時,由於MPT交易樹和MPT收據樹,與各個區塊相對應, 實際上是“區塊間無關”的資料;因此,對於MPT交易樹和MPT收據樹,很容易進行分級儲存;例如,直接按照MPT交易樹和MPT收據樹上的node所屬的區塊號進行資料遷移即可完成分級儲存。
基於此,本說明書將不再具體闡述MPT交易樹和MPT收據樹的分級儲存,而重點闡述MPT狀態樹的分級儲存。
請參見圖1,圖1為本說明書示出的一種將區塊鏈的帳戶狀態資料組織成MPT狀態樹的示意圖。
MPT樹,是一種經過改良的,融合了Merkle樹和Trie字典樹(也稱之為前綴樹)兩種樹形結構的優點的Merkle樹變種。
在MPT樹中通常包括三種資料節點,分別為葉子節點(leaf node),擴展節點(extension node)和分支節點(branch node)。
葉子節點,表示為[key,value]的一個鍵值對,其中key是種特殊十六進位編碼。
擴展節點,也是[key,value]的一個鍵值對,但是這裡的value是其他節點的hash值(hash指標)。也就是說透過hash指標連結到其他節點。
分支節點,因為MPT樹中的key被編碼成一種特殊的16進位的表示,再加上最後的value,所以分支節點是一個長度為17的list,前16個元素對應著key中的16個可能的十六進位字元(一個字元對應一個半位元組nibble)。如果有一個[key,value]對在這個分支節點終止,最後一個元素代表一個value值,即分支節點既可以是搜索路徑的終止也可以是路徑的中間節點。
假設需要組織成MTP狀態樹的帳戶狀態資料如下表1所示:
帳戶地址(Key) | 帳戶狀態(Value) |
a | 7 | 1 | 1 | 3 | 5 | 5 | state1 |
a | 7 | 7 | d | 3 | 3 | 7 | state2 |
a | 7 | f | 9 | 3 | 6 | 5 | state3 |
a | 7 | 7 | d | 3 | 9 | 7 | state4 |
表1
在表1中,帳戶地址是由若干16進位的字元構成的字串。帳戶狀態state,是由上述Balance,Nonce,Code和storage等欄位構成的結構體。
最終按照表1中的帳戶狀態資料組織成的MPT狀態樹,參見圖1所示;如圖1所示,按照表1中的帳戶狀態資料組織成的MPT狀態樹,是由4個葉子節點,2個分支節點,和2個擴展節點構成。
在圖1中,prefix欄位為擴展節點和葉子節點共同具有的前綴欄位。該prefix欄位的取值,在實際應用中可以用於表示節點類型。
prefix欄位的取值為0,表示包含偶數個nibbles的擴展節點;如前所述,nibble表示半位元組,由4位元二進位組成,一個nibble可以對應一個組成帳戶地址的字元。
prefix欄位的取值為1,表示包含奇數個nibble(s)的擴展節點;
prefix欄位的取值為2,表示包含偶數個nibbles的葉子節點;
prefix欄位的取值為3,表示包含奇數個nibble(s)的葉子節點。
而分支節點,由於其是並列單nibble的前綴節點,因此分支節點不具有上述prefix欄位。
擴展節點中的Shared nibble欄位,對應該擴展節點所包含的鍵值對的key值,表示帳戶地址之間的共同字元前綴;比如,上表中的所有帳戶地址均具有共同的字元前綴a7。Next Node欄位中填充下一個節點的hash值(hash指標)。
分支節點中的16進位字元0~f欄位,對應該分支節點所包含的鍵值對的key值;如果該分支節點為帳戶地址在MPT樹上的搜索路徑上的中間節點,則該分支節點的Value欄位可以為空值。0~f欄位中用於填充下一個節點的hash值。
葉子節點中的Key-end,對應該葉子節點所包含的鍵值對的key值,表示帳戶地址的最後幾個字元。從根節點搜索到葉子節點的搜索路徑上的各個節點的key值,構成了一個完整的帳戶地址。該葉子節點的Value欄位填充帳戶地址對應的帳戶狀態資料;例如,可以對上述Balance,Nonce,Code和storage等欄位構成的結構體進行編號後,填充至葉子節點的Value欄位。
進一步的,如圖1所示的MPT狀態樹上的node,最終也是以Key-Value鍵值對的形式儲存在資料庫中;
其中,當MPT狀態樹上的node在資料庫中進行儲存時,MPT狀態樹上的node的鍵值對中的key,為node所包含的資料內容的hash值;MPT狀態樹上的node的鍵值對中的Value,為node所包含的資料內容。
也即,在將MPT狀態樹上的node儲存至資料庫時,可以計算該node所包含的資料內容的hash值(即對node整體進行hash計算),並將計算出的hash值作為key,將該node所包含的資料內容作為value,生成Key-Value鍵值對;然後,將生成的Key-Value鍵值對儲存至資料庫中。
由於MPT狀態樹上的node,是以node所包含的資料內容的hash值為Key,node所包含的資料內容為value進行儲存;因此,在需要查詢MPT狀態樹上的node時,通常可以基於node所包含的資料內容的hash值作為key來進行內容定址。而採用“內容定址”,對於一些“內容重複”的node,則通常可以進行“複用”,以節約資料儲存的儲存空間。
如圖2所示,圖2為本說明書示出的一種MPT狀態樹上的node複用的示意圖。
在實際應用中,區塊鏈每產生一個最新區塊,則在該最新區塊中的交易被執行之後,區塊鏈中與這些被執行的交易相關帳戶的帳戶狀態,通常也會隨之發生變化;
例如,當區塊中的一筆“轉帳交易”執行完畢後,與該“轉帳交易”相關的轉出方帳戶和轉入方帳戶的餘額(即這些帳戶的Balance欄位的取值),通常也會隨之發生變化。
而節點設備在區塊鏈產生的最新區塊中的交易執行完畢後,由於當前區塊鏈中的帳戶狀態發生了變化,因此節點設備需要根據區塊鏈中所有帳戶當前的帳戶狀態資料,來構建MPT樹,用於維護區塊鏈中所有帳戶的最新狀態。
也即,每當區塊鏈中產生一個最新區塊,並且該最新區塊中的交易執行完畢後,導致區塊鏈中的帳戶狀態發生變化,節點設備都需要基於區塊鏈中所有帳戶最新的帳戶狀態資料,重新構建一顆MPT樹。
換句話說,區塊鏈中每一個區塊,都有一個與之對應的MPT狀態樹;該MPT狀態樹,維護了在該區塊中的交易在執行完畢後,區塊鏈中所有帳戶最新的帳戶狀態。
而需要說明的是,一個最新區塊中的交易執行完畢後,可能僅僅會導致部分帳戶的帳戶狀態發生變化;因此,在更新MPT狀態樹時,並不需要基於區塊鏈中所有的帳戶當前的狀態資料,重新構建一顆完整的MPT狀態樹,而只需要在該最新區塊之前的區塊對應的MPT狀態樹的基礎上,對部分帳戶狀態發生變化的帳戶對應的node進行更新即可。而對於MPT狀態樹上與帳戶狀態未發生變化的帳戶對應的node而言,由於這些node為發生資料更新,可以直接複用該最新區塊之前的區塊對應的MPT狀態樹上相應的node即可。
如圖2所示,假設表1中的帳戶狀態資料,為Block N中的交易執行完畢後,區塊鏈上所有帳戶的最新帳戶狀態;基於表1中的帳戶狀態資料組織成的MPT狀態樹,仍如圖1所示。
假設當Block N+1中的交易執行完畢後,導致上述表1中的帳戶地址為“a7f9365”的帳戶狀態,由“state3”更新為“state5”;此時,在Block N+1更新MPT狀態樹時,並不需要基於Block N+1中的交易執行完畢後,區塊鏈中所有的帳戶當前的狀態資料,重新構建一顆MPT狀態樹。
請參見圖2,在這種情況下,可以僅將Block N 對應的MPT樹上(即圖1示出的MPT狀態樹),“key-end”為“9365”的葉子節點中的Value,由“state3”更新為“state5”,並繼續更新從root節點到該葉子節點的路徑上的所有節點的hash指標;也即,當MPT狀態樹上的葉子節點發生更新,由於該葉子節點整體的hash值發生更新,那麼從根節點到該葉子節點的路徑上的所有的節點的hash指標也會隨之發生更新。例如,請繼續參見圖2,除了需要更新“key-end”為“9365”的葉子節點中的Value值以外,還需要更新該葉子節點的上一個分支節點(Branch Node)的f欄位中填充的,指向該葉子節點的雜湊指標;進一步的,還可以繼續向根節點追溯,繼續更新該分支節點的上一個根節點(Root Extension Node)的“Next Node”欄位中填充的,指向該分支節點的hash指標。
而除了以上發生更新的節點以外,其它未發生更新的節點,都可以直接複用Block N的MPT狀態樹上對應的節點即可;
其中,由於Block N對應的MPT樹,最終需要作為歷史資料進行保留;因此,在Block N+1更新MPT狀態樹時,對於這些發生更新的node,並不是對Block N對應的MPT狀態樹上原來的node的基礎上,直接進行修改更新,而是在Block N+1對應的MPT樹上重新創建這些發生更新的node。
也即,對於與Block N+1對應的MPT狀態樹上,實際上只需要重新創建少量發生更新的node,對於其它未發生更新的node,可以透過直接複用Block N對應的MPT狀態樹上對應的節點。
例如,如圖2所示,對於Block N+1對應的MPT狀態樹上,實際上只需要重新創建少量發生更新的node;比如,圖2中僅需要重新創建一個作為根節點的擴展節點、一個分支節點和一個葉子節點;對於未發生更新的node,可以透過在該MPT狀態樹上這些重新創建的node中,添加指向Block N對應的MPT狀態樹上的相應node的hash指標來完成node的複用。而Block N對應的MPT狀態樹上那些更新前的node,將作為歷史帳戶狀態資料進行保存;比如,圖2示出的“key-end”為“9365”,且Value為“state3”的葉子節點,將作為歷史資料進行保留。在以上例子中,以Block N+1的MPT狀態樹上的少量node發生內容更新,可以“複用”上一個區塊Block N的大多數node為例進行了說明。而在實際應用中,Block N+1的MPT狀態樹上也可能會較上一個區塊Block N新增node。
在這種情況下,該新增的node雖然無法直接從上一個區塊Block N的MPT樹中進行複用,但有可能從更早之前的區塊的MPT狀態樹上進行“複用”;
例如,Block N+1的MPT狀態樹上新增的node,雖然在Block N的MPT狀態樹上出現過,但出現在更早的Block的MPT狀態樹上;比如,出現在Block N-1的MPT狀態樹上;因此,Block N+1的MPT狀態樹上新增的node,可以直接複用Block N-1的MPT狀態樹上對應的node即可。
可見,MPT狀態樹的節點複用,一共有兩種“複用”的情形:
一種情形是,一個區塊的MPT狀態樹上只有少量的節點發生內容更新,則可以“複用”上一個區塊的大多數節點;
另一種情形是,一個區塊的MPT狀態樹較上一個區塊的MPT狀態樹新增了節點,則可以“複用”更早之前的區塊的MPT狀態樹上對應的節點。
然而,透過節點複用,雖然可以節約資料庫的儲存空間,但由於各個區塊的MPT狀態樹上的節點之間,可能存在複雜的複用關係,每個區塊的MPT狀態樹上的node,都可能被下一個區塊,或者是下一個區塊之後的若干連續的區塊進行複用;因此,這種複雜的節點複用關係,勢必會對MPT狀態樹的分級儲存造成困難。
例如,在需要將一些節點作為歷史資料,從本級資料儲存向下一級資料儲存遷移時,由於這些節點可能會被下一個區塊;甚至是該下一個區塊之後的若干個區塊複用;而這些節點將會被哪些節點複用,又是無法準確預知的;因此,這就會導致無法對資料庫中儲存的MPT狀態樹上的節點進行精確剪枝;其中,所謂剪枝,是指清除各區塊的MPT狀態樹上的節點之間的複用關係,將記錄了歷史狀態資料的節點從MPT狀態樹上移除,並保留記錄了最新狀態資料的node。在這種情況下,顯然無法滿足分級儲存的需求。
基於此,本說明書提出一種針對由區塊鏈的帳戶狀態資料組成的Merkle狀態樹進行分級儲存的方法。
在實現時,仍然可以將區塊鏈的帳戶狀態資料組織成Merkle狀態樹,在採用多級資料儲存結構的資料庫中進行儲存;例如,仍然可以採用MPT樹的資料結構,將區塊鏈的帳戶狀態資料組織成MPT狀態樹;假設採用多級儲存結構的上述資料庫,被劃分為n級資料儲存;各級資料儲存可以依次設為L0,L1,L2,L3....L(n-1);其中,等級編號越小對應的級別越高;則可以將最新的若干區塊的MPT狀態樹儲存在L0中(即最高級資料儲存),將次新的若干區塊資料儲存在L1中,依次類推。
當資料庫中的任一級目標資料儲存滿足了資料遷移條件時;比如,當該目標資料儲存的儲存容量達到閾值;此時,本級資料儲存可以進入到雙工作資料表階段,可以在該目標資料儲存的工作資料表的基礎上,為該目標資料儲存創建一個與工作資料表對應的空資料表。
進一步的,當該目標資料儲存進入到雙工作資料表階段時,後續可以將寫入該目標資料儲存的新增區塊的Merkle狀態樹將儲存至該空資料表,而且還可以將該工作資料表中儲存的與目標區塊號對應的區塊的Merkle狀態樹遷移至該空資料表;其中,該目標區塊號為該目標資料儲存中儲存的若干Merkle狀態樹對應的區塊號中的最大區塊號;
例如,當上述目標資料儲存滿足了資料遷移條件時,可以立即記錄該目標資料儲存中儲存的若干Merkle狀態樹對應的區塊號中的最大區塊號,然後在該目標資料儲存進入了雙工作資料表階段後,可以遍歷上述工作資料表中儲存的與該最大區塊號對應的區塊的Merkle狀態樹上的node,並將遍歷到的node依次遷移至上述空資料表。
當上述工作資料表中儲存的與上述目標區塊號對應的區塊的Merkle狀態樹遷移至所述空資料表之後,可以將上述工作資料表中儲存的Merkle狀態樹(即遷移後的剩餘區塊對應的Merkle狀態樹)進一步遷移至所述目標資料儲存的下一級資料儲存。
在以上技術方案中,由於目標資料儲存的工作資料表中儲存的若干Merkle狀態樹對應的區塊號中的最大區塊號,通常指示該工作資料表中儲存的最新區塊的區塊號;因此,將寫入目標資料儲存的新增區塊的Merkle狀態樹儲存至為該目標資料儲存創建的與工作資料表對應的空資料表,並將工作資料表中儲存的與上述最大區塊號對應的Merkle狀態樹也遷移至上述空資料表,可以實現將目標資料儲存中儲存的最新區塊的Merkle狀態樹儲存至上述空資料表,而將歷史區塊的Merkle狀態樹繼續保留在上述工作資料表中;從而,在將工作資料表中儲存的與上述最大區塊號對應的Merkle狀態樹遷移至上述空資料表之後,透過將該工作資料表中儲存的Merkle狀態樹進一步遷移至目標資料儲存的下一級資料儲存,即可完成針對上述目標資料儲存的Merkle狀態樹的分級儲存,在本級儲存繼續保留最新區塊的Merkle狀態樹,而將歷史區塊的Merkle狀態樹遷移至下一級資料儲存。
請參見圖3,圖3是一示例性實施例提供的一種基於區塊鏈的分級儲存方法的流程圖。所述方法應用于區塊鏈節點設備;其中,所述區塊鏈的帳戶狀態資料被組織成Merkle狀態樹在資料庫中儲存;所述資料庫包括多級資料儲存;所述方法包括以下步驟:
步驟302,當所述資料庫中的任一級目標資料儲存滿足了資料遷移條件時,為所述目標資料儲存創建與工作資料表對應的空資料表;
步驟304,將寫入所述目標資料儲存的新增區塊的Merkle狀態樹儲存至所述空資料表,並將所述工作資料表中儲存的與目標區塊號對應的區塊的Merkle狀態樹遷移至所述空資料表;其中,所述目標區塊號為所述目標資料儲存中儲存的若干Merkle狀態樹對應的區塊號中的最大區塊號;
步驟306,在將所述工作資料表中儲存的與所述目標區塊號對應的區塊的Merkle狀態樹遷移至所述空資料表之後,將所述工作資料表中儲存的Merkle狀態樹進一步遷移至所述目標資料儲存的下一級資料儲存。
上述資料庫,具體可以是採用多級資料儲存結構的Key-Value型資料庫;例如,在示出的一種實施方式中,上述資料庫可以為LevelDB資料庫;或者,基於LevelDB架構的資料庫;比如,Rocksdb資料庫就是一種典型的基於LevelDB資料庫架構的資料庫。區塊鏈中的帳戶狀態資料,可以被組織成Merkle狀態樹的資料結構,在上述資料庫中進行儲存;例如,上述Merkle狀態樹具體可以是MPT樹,可以採用MPT樹的資料結構,將區塊鏈的帳戶狀態資料組織成MPT狀態樹。
以下以採用MPT樹的資料結構,將區塊鏈中的帳戶狀態資料組織成MPT狀態樹為例,對本說明書的技術方案進行詳細描述;
其中,需要強調的是,以採用MPT樹的資料結構來組織區塊鏈中的帳戶狀態資料,僅為示例性的。
在實際應用中,對於基於以太坊架構而衍生出的區塊鏈項目,除了可以採用諸如MPT樹等改良版的Merkle樹以外,也可以採用其他形式的類似於MPT樹的融合了Trie字典樹的樹形結構的Merkle樹變種,在本說明書中不再進行一一列舉。
在本說明書中,接入區塊鏈的用戶客戶端,可以將資料打包成區塊鏈所支持的標準的交易格式,然後發佈至區塊鏈;而區塊鏈中的節點設備,可以基於搭載的共識演算法與其它節點設備一起,對用戶客戶端發佈至區塊鏈的這些交易進行共識,以此來為區塊鏈產生最新區塊;
其中,區塊鏈中支持的共識演算法,通常分為節點設備需要爭奪每一輪的記帳週期的記帳權的共識演算法,和預先為每一輪記帳週期選舉記帳節點(不需要爭奪記帳權)的共識演算法。
例如,前者以工作量證明(Proof of Work, POW)、股權證明(Proof of Stake,POS)、委任權益證明(Delegated Proof of Stake,DPOS)等共識演算法為代表;後者以實用拜占庭容錯(Practical Byzantine Fault Tolerance,PBFT)等共識演算法為代表。
對於採用工作量證明(Proof of Work, POW)以及股權證明(Proof of Stake,POS)、委任權益證明(Delegated Proof of Stake,DPOS)等共識演算法的區塊鏈網路中,爭奪記帳權的節點設備,都可以在接收到交易後執行該筆交易。爭奪記帳權的節點設備中可能其中一個在本輪爭奪記帳權的過程中勝出,成為記帳節點。記帳節點可以將將收到的交易與其它交易一起打包並生成最新區塊,並將生成的最新區塊發送至其它節點設備進行共識。
對於採用實用拜占庭容錯(Practical Byzantine Fault Tolerance,PBFT)等共識演算法的區塊鏈網路中,具有記帳權的節點設備在本輪記帳前已經商定好。因此,節點設備在接收到交易後,如果自身不是本輪的記帳節點,則可以將該交易發送至記帳節點。對於本輪的記帳節點,在將該交易與其它交易一起打包並生成最新區塊的過程中或者之前,可以執行該交易。記帳節點在將該交易與其它交易一起打包生成新區塊後,可以將生成的最新區塊或者該最新區塊的區塊頭發送至其它節點設備進行共識。
如上所述,無論區塊鏈採用以上示出的哪種共識演算法,本輪的記帳節點都可以將接收到的交易打包並生成最新區塊,並將生成的最新區塊或者該最新區塊的區塊頭發送至其它節點設備進行共識驗證。如果其它節點設備接收到最新區塊或者該最新區塊的區塊頭後,經驗證沒有問題,可以將該最新區塊追加到原有的區塊鏈末尾,從而完成區塊鏈的記帳過程。
在本說明書中,區塊鏈中的節點設備在執行了經過共識產生的最新區塊中打包的交易之後,區塊鏈中與這些被執行的交易相關的帳戶狀態,通常也會隨之發生變化;因此,節點設備在最新區塊中打包的交易執行完畢後,可以根據區塊鏈中所有帳戶最新的帳戶狀態資料,組織成MPT狀態樹的資料結構。
其中,根據區塊鏈中所有帳戶最新的帳戶狀態資料,組織成MPT狀態樹時,仍然可以採用如圖2示出的複用該最新區塊之前的區塊對應的MPT樹上的節點的方式,在本說明書中不再贅述。
當節點設備根據區塊鏈中所有帳戶最新的帳戶狀態資料,組織成MPT狀態樹後,可以將該MPT狀態樹上的資料節點,以Key-Value鍵值對的形式在採用多級資料儲存結構的Key-Value型資料庫中進行儲存。
例如,在實際應用中,對於最新的若干區塊對應的MPT狀態樹上的資料節點,可以預設存放在上述資料庫中的級別最高的L0級資料儲存中。對於次新的若干區塊對應的MPT狀態樹上的資料節點,可以存放在上述資料庫中的級別次高的L1級資料儲存中;以此類推。
其中,每一級資料儲存所儲存的MPT狀態樹對應的區塊數,在本說明書中不進行特別限定;比如,可以規定級別最高的L0級資料儲存中儲存最新的N個區塊的MPT狀態樹,級別次高的L1級資料儲存次新的N個區塊的MPT狀態樹;以此類推。
在本說明書中,節點設備還可以在本地啟動一個“遷移執行緒”,用於將上述資料庫中各級資料儲存中儲存的MPT狀態樹上的node資料,向下級資料儲存進行遷移。
上述“遷移執行緒”,具體可以執行一個定時任務,可以週期性的確定上述資料庫中的各級資料儲存是否滿足預設的資料遷移條件;
其中,上述資料庫中的各級資料儲存的資料遷移條件,可以基於實際的資料遷移需求來設置,在本說明書中不進行特別限定;
例如,在實際應用中,上述資料庫的各級資料儲存的資料遷移條件,具體可以是各級資料儲存的儲存容量達到閾值;或者,也可以是各級資料儲存所儲存的資料所對應的區塊數達到閾值。
上述“遷移執行緒”,在確定上述資料庫中任一級目標資料儲存,滿足了資料遷移條件,則該“遷移執行緒”可以針對該目標資料儲存進行資料遷移處理,將該目標資料儲存中儲存的部分區塊的MPT狀態樹,作為歷史資料向下一級資料儲存進行遷移。
在實際應用中,上述資料庫中的各級資料儲存,均可以包括一工作資料表;對於上述資料庫中的任一級資料儲存來說,該級資料儲存中儲存的MPT狀態樹都會預設寫入該工作資料表;相應的,當需要查詢該級資料儲存中儲存的MPT狀態樹上的node,可以從該工作資料表中讀取資料即可。
當上述“遷移執行緒”在確定上述目標資料儲存滿足了資料遷移條件時,此時該目標資料儲存可以進入到雙工作資料表階段,上述“遷移執行緒”可以在該目標資料儲存的工作資料表的基礎上,為該目標資料儲存創建一個與工作資料表對應的空資料表(即空資料表也是一個工作資料表)。
其中,上述“遷移執行緒”在該目標資料儲存的工作資料表的基礎上,為該目標資料儲存創建一個空資料表的具體過程,在本說明不再進行詳述;
例如,在實現時,可以在該目標資料儲存的工作資料表對應的資料庫實例(一個資料庫可以有多個資料庫實例)的基礎上,創建一個新的資料庫實例,並將該新的資料庫實例與創建的空資料表關聯起來,使得接入該資料庫的程式,可以透過該資料庫實例來訪問寫入該空資料表的資料;
其中,資料庫實例通常是指,是位於用戶和作業系統之間的一層資料管理程式,用戶對資料庫中的資料做任何的操作,包括資料定義、資料查詢、資料維護、資料庫運行控制等等,都是在資料庫實例下進行的,應用程式只有透過資料庫實例才能訪問資料庫中儲存的資料。
需要說明的是,上述資料庫中的各級資料儲存的工作資料表,具體可以僅包含一張資料表,也可以包含多張資料表;相應的,上述“遷移執行緒”為上述目標資料儲存創建的與工作資料表對應的空資料表,具體也可以僅包含一張資料表或者也可以包含多張資料表。也即,本說明書中描述的上述工作資料表和上述空資料表,均可以理解成是由一張資料表或者是由多張資料表組成的一個獨立的資料庫。
而且,在實際應用中,由於上述資料庫中的各級資料儲存實際的儲存容量,可能並不相同;因此,上述資料庫中的各級資料儲存的工作資料表,實際所包含的資料表的數量,也可以存在差異。
例如,以上述資料庫為LevelDB資料庫為例,LevelDB資料庫包含多個level的資料儲存,每一個level的資料儲存都可以包含若干SStable(Sorted String Table,有序字串表)。SStable也稱之為SST檔,其充當資料表的角色,用於儲存寫入各個level的資料儲存的資料。
其中,對於LevelDB資料庫的各個level的資料儲存而言,實際的儲存容量,通常也會存在一定的差異。在實際應用中,級數越高的資料儲存通常採用的儲存媒體的讀寫性能也會越高;而與之相對應的是,級數低的資料儲存採用的儲存媒體的讀寫性能雖然低於級數高的資料儲存,但其採用的儲存媒體的儲存容量通常會高於級數高的資料儲存採用的儲存媒體。
因此,級數越高的資料儲存,其包含的SStable資料表的數量也會越少;反之,級數越低的資料儲存,由於其採用的儲存媒體的讀寫性能低於級數高的資料儲存,其通常會具有更大的儲存容量,因此其包含的SStable資料表的數量也會越多。
在說明書中,當上述目標資料儲存進入到雙工作資料表階段,由上述“遷移執行緒”為該目標資料儲存創建了與該級資料儲存的工作資料表對應的空資料表之後,後續寫入該目標資料儲存的新增區塊的MPT狀態樹上的資料節點,將不再寫入該目標資料儲存的工作資料表,而是寫入為該目標資料儲存創建的空資料表。
其中,需要寫入該目標資料儲存的新增區塊的MPT狀態樹,通常包含以下示出的兩種情況:
在一種情況下,如果該目標資料儲存為上述資料庫中級數最高的資料儲存,對於級數最高的資料儲存而言,通常用於寫入區塊鏈產生的最新區塊的MPT狀態樹;因此,在這種情況下,需要寫入該目標資料儲存的新增區塊的MPT狀態樹,則是指區塊鏈產生的最新區塊的MPT狀態樹。
在另一種情況下,如果該目標資料儲存並不是上述資料庫中級數最高的資料儲存,在這種情況下,需要寫入該目標資料儲存的新增區塊的MPT狀態樹,則是指該目標資料儲存的上一級資料儲存遷移至該目標資料儲存的歷史區塊的Merkle狀態樹。
在本說明書中,除了寫入該目標資料儲存的新增區塊的MPT狀態樹,不再需要寫入該目標資料儲存的工作資料表以外,上述“遷移執行緒”還可以將該目標資料儲存的工作資料表中儲存的與目標區塊號對應的區塊的MPT狀態樹作為最新的狀態資料遷移至所述空資料表;其中,在本說明書中,上述目標區塊號為上述目標資料儲存中當前儲存的若干MPT狀態樹對應的區塊號中的最大區塊號。
例如,在實現時,當上述目標資料儲存滿足了資料遷移條件時,上述遷移執行緒可以立即記錄該目標資料儲存中儲存的所有Merkle狀態樹對應的區塊號中的最大區塊號,然後在該目標資料儲存進入了雙工作資料表階段後,可以遍歷上述工作資料表中儲存的與該最大區塊號對應的區塊的Merkle狀態樹上的node,並將遍歷到的node依次遷移至上述空資料表;比如,在實現時,上述“遷移執行緒”可以遍歷並複製該最大區塊號對應的區塊的Merkle狀態樹上的node,並將複製的node寫入上述空資料表,然後在將複製的node成功寫入上述空資料表之後,再將該node從上述工作資料表中清除。
其中,需要說明的是,由於需要寫入上述目標資料儲存的新增區塊的MPT狀態樹,後續將會直接寫入上述空資料表;因此,在實際應用中,與上述最大區塊號對應的區塊的MPT狀態樹上的部分node,可能會直接寫入上述空資料表;
例如,當上述目標資料儲存滿足資料遷移條件時,如果上述最大區塊號對應的區塊的MPT狀態樹上所有的node,還沒有全部寫入上述工作資料表時,就可能導致該MPT狀態樹上尚未寫入上述工作資料表的部分node,後續會直接寫入上述空資料表。
在這種情況下,“遷移執行緒”將該目標資料儲存的工作資料表中儲存的與上述最大區塊號對應的區塊的MPT狀態樹上的node遷移至空資料表的過程,實際上是針對上述空資料表中儲存的該MPT狀態樹上的node的“增量補全”過程。
也即,當上述目標資料儲存進入雙工作資料表階段後,上述“遷移執行緒”會將上述工作資料表中儲存的與上述最大區塊號對應的區塊的MPT狀態樹上的部分node,對上述空資料表新寫入的該MPT狀態樹上的部分node進行補全。
進一步的,上述遷移執行緒在將上述工作資料表中儲存的與上述最大區塊號對應的區塊的MPT狀態樹,遷移至上述空資料表之後,上述工作資料表中儲存的“最新區塊”的MPT狀態樹,已經遷移至新創建的空資料表;此時,上述遷移執行緒可以將該工作資料表中儲存的MPT狀態樹,進一步遷移至上述目標資料儲存的下一級儲存,以完成針對上述目標資料儲存中儲存的MPT狀態樹的分級儲存;
在示出的一種實施方式中,上述遷移執行緒在將上述工作資料表中儲存的與上述最大區塊號對應的區塊的MPT狀態樹,遷移至上述空資料表之後,可以將上述工作資料表切換為歷史資料表,並將上述空資料表切換為工作資料表;此時,上述目標資料儲存將重新進入到單工作資料表階段。
相應的,上述遷移執行緒具體也可以在將上述工作資料表切換為歷史資料表之後,再開始執行將該歷史資料表中儲存的與上述最大區塊號對應的區塊的MPT狀態樹遷移至該目標資料儲存的下一級資料儲存的動作。
也即,當上述遷移執行緒,可以在上述目標資料儲存重新進入到單工作資料表階段之後,再開始將切換之前的工作資料表中儲存的與上述最大區塊號對應的區塊的MPT狀態樹遷移至該目標資料儲存的下一級資料儲存。
例如,在實現時,當上述工作資料表被切換為歷史資料表之後,上述“遷移執行緒”可以遍歷並複製該歷史資料表中儲存的各個區塊對應的MPT狀態樹上的node,並將複製的node寫入下一級資料儲存,然後在將複製的node成功寫入下一級資料儲存之後,再將該node從上述歷史資料表中清除。
其中,當上述遷移執行緒將上述歷史資料表中儲存的MPT狀態樹全部遷移至下一級資料儲存之後,可以將該歷史資料表從該目標資料儲存中刪除。
在本說明書中,上述目標資料儲存在處於單工作資料表階段和處於雙工作資料表階段時,針對該目標資料儲存中儲存的MPT狀態樹上的node的讀取流程,也會存在一定的差異。
如果上述目標資料儲存當前處於單工作資料表階段,即該目標資料儲存只存在唯一的工作資料表,通常只會從該唯一的工作資料表中讀寫資料。而如果上述目標資料儲存當前處於雙工作資料表階段,即該目標資料儲存同時存在預設的工作資料表和新建的空資料表時,此時可以同時從該預設的工作資料表和新建的空資料表中讀取資料,也可以僅從新建的空資料表中讀取資料。
在示出的一種實施方式中,在上述目標資料儲存存在雙工作資料表期間,上述遷移執行緒也可以選擇將寫入上述目標資料儲存的新增區塊的MPT狀態樹僅儲存至上述空資料表;在這種情況下,節點設備在上述目標資料儲存存在雙資料表期間接收到針對上述目標資料儲存的MPT狀態樹上的node的查詢請求時,可以回應該查詢請求,同時從上述空資料表和上述工作資料表中查詢node。
在示出的另一種實施方式中,在上述目標資料儲存存在雙工作資料表期間,上述遷移執行緒也可以選擇將寫入上述目標資料儲存的新增區塊的MPT狀態樹同時儲存至上述空資料表和上述工作資料表;在這種情況下,節點設備在上述目標資料儲存存在雙資料表期間接收到針對上述目標資料儲存的MPT狀態樹上的node的查詢請求時,可以回應該查詢請求,只從上述工作資料表中查詢node。
也即,在本說明書中,在目標資料儲存滿足了資料遷移條件,進入了雙工作資料表階段期間,寫入該目標資料儲存的新增區塊的MPT狀態樹上的node,可以僅寫入創建的空資料表中,也可以同時寫入該空資料表和上述工作資料表中,在本說明書中不進行特別限定。
在以上技術方案中,由於目標資料儲存的工作資料表中儲存的若干MPT狀態樹對應的區塊號中的最大區塊號,通常指示該工作資料表中儲存的最新區塊的區塊號;因此,將寫入目標資料儲存的新增區塊的MPT狀態樹儲存至為該目標資料儲存創建的與工作資料表對應的空資料表,並將工作資料表中儲存的與上述最大區塊號對應的MPT狀態樹也遷移至上述空資料表,可以實現將目標資料儲存中儲存的最新區塊的MPT狀態樹儲存至上述空資料表,而將歷史區塊的MPT狀態樹繼續保留在上述工作資料表中;從而,在將工作資料表中儲存的與上述最大區塊號對應的MPT狀態樹遷移至上述空資料表之後,透過將該工作資料表中儲存的MPT狀態樹進一步遷移至目標資料儲存的下一級資料儲存,即可完成針對上述目標資料儲存的MPT狀態樹的分級儲存,在本級儲存繼續保留最新區塊的MPT狀態樹,而將歷史區塊的MPT狀態樹遷移至下一級資料儲存。
與上述方法實施例相對應,本申請還提供了裝置的實施例。
與上述方法實施例相對應,本說明書還提供了一種基於區塊鏈的分級儲存裝置的實施例。
本說明書的基於區塊鏈的分級儲存裝置的實施例可以應用在電子設備上。裝置實施例可以透過軟體實現,也可以透過硬體或者軟硬體結合的方式實現。以軟體實現為例,作為一個邏輯意義上的裝置,是透過其所在電子設備的處理器將非易失性記憶體中對應的電腦程式指令讀取到記憶體中運行形成的。
從硬體層面而言,如圖4所示,為本說明書的基於區塊鏈的分級儲存裝置所在電子設備的一種硬體結構圖,除了圖4所示的處理器、記憶體、網路介面、以及非易失性記憶體之外,實施例中裝置所在的電子設備通常根據該電子設備的實際功能,還可以包括其他硬體,對此不再贅述。
圖5是本說明書一示例性實施例示出的一種基於區塊鏈的分級儲存裝置的方塊圖。
請參考圖5,所述基於區塊鏈的分級儲存裝置50可以應用在前述圖4所示的電子設備中,所述區塊鏈的帳戶狀態資料被組織成Merkle狀態樹在資料庫中儲存;所述資料庫包括多級資料儲存;所述裝置50包括:
創建模組501,當所述資料庫中的任一級目標資料儲存滿足了資料遷移條件時,為所述目標資料儲存創建與工作資料表對應的空資料表;
第一遷移模組502,將寫入所述目標資料儲存的新增區塊的Merkle狀態樹儲存至所述空資料表,並將所述工作資料表中儲存的與目標區塊號對應的區塊的Merkle狀態樹遷移至所述空資料表;其中,所述目標區塊號為所述目標資料儲存中儲存的若干Merkle狀態樹對應的區塊號中的最大區塊號;
第二遷移模組503,在將所述工作資料表中儲存的與所述目標區塊號對應的區塊的Merkle狀態樹遷移至所述空資料表之後,將所述工作資料表中儲存的Merkle狀態樹進一步遷移至所述目標資料儲存的下一級資料儲存。
在本實施例中,所述第一遷移模組502:
在將所述工作資料表中儲存的與所述目標區塊號對應的區塊的Merkle狀態樹遷移至所述空資料表之後,將所述工作資料表切換為歷史資料表,並將所述空資料表切換為工作資料表。
在本實施例中,所述第二遷移模組503進一步:
在所述工作資料表切換為歷史資料表之後,將所述歷史資料表中儲存的Merkle狀態樹進一步遷移至所述目標資料儲存的下一級資料儲存;以及,
在所述歷史資料表中的儲存的Merkle狀態樹成功遷移至所述目標資料儲存的下一級資料儲存之後,刪除所述歷史資料表。
在本實施例中,所述第一遷移模組502:
將寫入所述目標資料儲存的新增區塊的Merkle狀態樹僅儲存至所述空資料表;或者,
將寫入所述目標資料儲存的新增區塊的Merkle狀態樹同時儲存至所述空資料表和所述工作資料表。
在本實施例中,還包括:
查詢模組504(圖5中未示出),在所述目標資料儲存存在雙資料表期間接收到針對所述目標資料儲存的Merkle狀態樹上的資料節點的查詢請求時,如果寫入所述目標資料儲存的新增區塊的Merkle狀態樹僅儲存至所述空資料表,則回應於所述查詢請求,同時從所述空資料表和所述工作資料表中查詢資料節點;如果寫入所述目標資料儲存的新增區塊的Merkle狀態樹同時儲存至所述空資料表和所述工作資料表,則回應於所述資料查詢請求,僅從所述工作資料表中查詢資料節點。
在本實施例中,所述新增區塊的Merkle狀態樹,包括:
所述區塊鏈產生的最新區塊的Merkle狀態樹;或者,
所述目標資料儲存的上一級資料儲存遷移至所述目標資料儲存的歷史區塊的Merkle狀態樹。
在本實施例中,所述資料庫為Key-Value資料庫;
所述Merkle狀態樹上的資料節點以Key-Value鍵值對的形式儲存在所述資料庫中;其中,所述Key-Value鍵值對的key為所述資料節點包含的資料內容的hash值;所述Key-Value鍵值對的value為所述資料節點包含的資料內容。
在本實施例中,所述Merkle樹為融合了Trie字典樹的樹形結構的Merkle樹變種。
在本實施例中,所述 Merkle狀態樹為Merkle Patricia Tree狀態樹。
在本實施例中,所述資料庫為LevelDB資料庫;或者基於LevelDB架構的資料庫。
在本實施例中,所述資料庫為基於LevelDB架構的Rocksdb資料庫。
在本實施例中,所述多級資料儲存對應的儲存媒體的讀寫性能,存在性能差異;其中,級數高的資料儲存對應的儲存媒體的讀寫性能,高於級數低的資料儲存對應的儲存媒體的讀寫性能。
上述實施例闡明的系統、裝置、模組或單元,具體可以由電腦晶片或實體實現,或者由具有某種功能的產品來實現。一種典型的實現設備為電腦,電腦的具體形式可以是個人電腦、膝上型電腦、行動電話、相機電話、智慧型電話、個人數位助理、媒體播放機、導航設備、電子郵件收發設備、遊戲控制台、平板電腦、可穿戴設備或者這些設備中的任意幾種設備的組合。
在一個典型的配置中,電腦包括一個或多個處理器 (CPU)、輸入/輸出介面、網路介面和記憶體。
記憶體可能包括電腦可讀媒體中的非永久性記憶體,隨機存取記憶體 (RAM) 和/或非易失性記憶體等形式,如唯讀記憶體 (ROM) 或快閃記憶體(flash RAM)。記憶體是電腦可讀媒體的示例。
電腦可讀媒體包括永久性和非永久性、可移動和非可移動媒體可以由任何方法或技術來實現資訊儲存。資訊可以是電腦可讀指令、資料結構、程式的模組或其他資料。電腦的儲存媒體的例子包括,但不限於相變記憶體 (PRAM)、靜態隨機存取記憶體 (SRAM)、動態隨機存取記憶體 (DRAM)、其他類型的隨機存取記憶體 (RAM)、唯讀記憶體 (ROM)、電可擦除可編程唯讀記憶體 (EEPROM)、快閃記憶體或其他記憶體技術、唯讀光碟唯讀記憶體 (CD-ROM)、數位多功能光碟 (DVD) 或其他光學儲存、磁盒式磁帶、磁片儲存、量子記憶體、基於石墨烯的儲存媒體或其他磁性存放裝置或任何其他非傳輸媒體,可用於儲存可以被計算設備存取的資訊。按照本文中的界定,電腦可讀媒體不包括暫存電腦可讀媒體 (transitory media),如調變的資料信號和載波。
還需要說明的是,術語“包括”、“包含”或者其任何其他變體意在涵蓋非排他性的包含,從而使得包括一系列要素的過程、方法、商品或者設備不僅包括那些要素,而且還包括沒有明確列出的其他要素,或者是還包括為這種過程、方法、商品或者設備所固有的要素。在沒有更多限制的情況下,由語句“包括一個……”限定的要素,並不排除在包括所述要素的過程、方法、商品或者設備中還存在另外的相同要素。
上述對本說明書特定實施例進行了描述。其它實施例在所附申請專利範圍的範圍內。在一些情況下,在申請專利範圍中記載的動作或步驟可以按照不同於實施例中的順序來執行並且仍然可以實現期望的結果。另外,在附圖中描繪的過程不一定要求示出的特定順序或者連續順序才能實現期望的結果。在某些實施方式中,多工處理和並行處理也是可以的或者可能是有利的。
在本說明書一個或多個實施例使用的術語是僅僅出於描述特定實施例的目的,而非旨在限制本說明書一個或多個實施例。在本說明書一個或多個實施例和所附申請專利範圍中所使用的單數形式的“一種”、“所述”和“該”也旨在包括多數形式,除非上下文清楚地表示其他含義。還應當理解,本文中使用的術語“和/或”是指並包含一個或多個相關聯的列出專案的任何或所有可能組合。
應當理解,儘管在本說明書一個或多個實施例可能採用術語第一、第二、第三等來描述各種資訊,但這些資訊不應限於這些術語。這些術語僅用來將同一類型的資訊彼此區分開。例如,在不脫離本說明書一個或多個實施例範圍的情況下,第一資訊也可以被稱為第二資訊,類似地,第二資訊也可以被稱為第一資訊。取決於語境,如在此所使用的詞語“如果”可以被解釋成為“在……時”或“當……時”或“回應於確定”。
以上所述僅為本說明書一個或多個實施例的較佳實施例而已,並不用以限制本說明書一個或多個實施例,凡在本說明書一個或多個實施例的精神和原則之內,所做的任何修改、等同替換、改進等,均應包含在本說明書一個或多個實施例保護的範圍之內。