這裡將詳細地對示例性實施例進行說明,其示例表示在附圖中。下面的描述涉及附圖時,除非另有表示,不同附圖中的相同數字表示相同或相似的要素。以下示例性實施例中所描述的實施方式並不代表與本說明書一個或多個實施例相一致的所有實施方式。相反,它們僅是與如所附申請專利範圍中所詳述的、本說明書一個或多個實施例的一些方面相一致的裝置和方法的例子。
需要說明的是:在其他實施例中並不一定按照本說明書示出和描述的順序來執行相應方法的步驟。在一些其他實施例中,其方法所包括的步驟可以比本說明書所描述的更多或更少。此外,本說明書中所描述的單個步驟,在其他實施例中可能被分解為多個步驟進行描述;而本說明書中所描述的多個步驟,在其他實施例中也可能被合併為單個步驟進行描述。
區塊鏈一般被劃分為三種類型:公有鏈(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狀態樹;
而對於在資料庫中儲存的Merkle狀態樹,可以針對該Merkle狀態樹上的node,分別標記一個區塊號,該區塊號具體用於指示該node發生資料更新時所在區塊的區塊號;
例如,在一種實施方式中,區塊鏈產生的最新區塊中的交易執行完畢後,可以基於該最新區塊中的交易的執行結果,來確定該最新區塊的Merkle狀態樹上發生資料更新的node;其中,發生資料更新的node,通常包含value值發生更新的node和新增的node。當確定該最新區塊的Merkle狀態樹上發生資料更新的node之後,可以為這些發生資料更新的node標記該最新區塊的區塊號,表示該node在該區塊號對應的區塊發生了資料更新。
進一步的,當資料庫中的任一級目標資料儲存滿足了資料遷移條件時;比如,當該目標資料儲存的儲存容量達到閾值;首先,可以確定該目標資料儲存中需要遷移至下一級資料儲存的node對應的區塊號區間,並基於該區塊號區間確定遷移臨界值;其中,該遷移臨界值為大於該區塊號區間的區塊號臨界值;
例如,在一種實施方式中,如果該區塊號區間的右區間為開區間,則將該區塊號區間的右端點值,確定為上述遷移臨界值;比如,假設該區塊號區間為[a,b)時,則將b確定為上述遷移臨界值;如果該區塊號區間的右區間為閉區間,將該區塊號區間的右端點值與區塊鏈的區塊號遞增步長的和,確定為上述遷移臨界值;比如,假設該區塊號區間為[a,b],區塊鏈的區塊號遞增步長為1(即區塊鏈中的區塊號以1為遞增步長致密遞增)時,則將b+1確定為上述遷移臨界值。
當確定了上述遷移臨界值後,可以遍歷與該遷移臨界值對應的目標區塊的Merkle狀態樹,查找被標記的區塊號小於該遷移臨界值的目標node,並將查找到的目標node的區塊號修改為該遷移臨界值;
進一步的,在將查找到的目標node的區塊號強制修改為該遷移臨界值之後,可以繼續遍歷與上述區塊號區間中的各個區塊號對應的區塊的Merkle狀態樹,查找被標記的區塊號小於該遷移臨界值的node,然後將查找到的node從上述目標資料儲存中,遷移至該目標資料儲存的下一級資料儲存;例如,先將查找到的node寫入到該目標資料儲存的下一級資料儲存,在寫入成功後,再將該node從目標資料儲存中清除。
透過以上技術方案,可以實現對資料庫中儲存的Merkle狀態樹上的node進行精確剪枝,將記錄了歷史狀態資料的node從Merkle狀態樹上移除,遷移至下一級資料儲存,並在本級資料儲存中繼續儲存和保留記錄了最新狀態資料的node,進而完成針對資料庫中儲存的Merkle狀態樹的分級儲存。
請參見圖3,圖3是一示例性實施例提供的一種基於區塊鏈的分級儲存方法的流程圖。所述方法應用於區塊鏈節點設備;其中,區塊鏈的帳戶狀態資料被組織成Merkle狀態樹在資料庫中儲存;該資料庫包括多級資料儲存;上述Merkle狀態樹上的資料節點被標記了區塊號;該區塊號指示該資料節點發生資料更新時所在的區塊;所述方法包括以下步驟:
步驟302,當所述資料庫中的任一級目標資料儲存滿足了資料遷移條件時,確定所述目標資料儲存中待遷移至下一級資料儲存的資料節點對應的區塊號區間;
步驟304,基於所述區塊號區間確認遷移臨界值;其中,所述遷移臨界值為大於所述區塊號區間的區塊號臨界值;
步驟306,遍歷與所述遷移臨界值對應的目標區塊的Merkle狀態樹,查找被標記的區塊號小於所述遷移臨界值的目標資料節點,並將查找到的所述目標資料節點的區塊號修改為所述遷移臨界值;
步驟308,遍歷與所述區塊號區間中的各個區塊號對應的區塊的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狀態樹上的資料節點,可以被標記區塊號;其中,為MPT狀態樹上的資料節點所標記的區塊號,具體用於指示該資料節點發生資料更新時所在的區塊;
例如,如圖2所示,以Block N+1對應的MPT狀態樹上發生資料更新的node為例,為這些node標記的區塊號,即為N+1,以表示這些node在Block N+1中的交易執行完畢後,發生了資料更新。
在實現時,節點設備可以在本地啟動一個“區塊狀態更新執行緒”,來維護和更新MPT狀態樹上的node的狀態。當區塊鏈產生的最新區塊中的交易執行完畢後,該“區塊狀態更新執行緒”可以確定該最新區塊對應的MPT狀態樹上發生資料更新的node;其中,發生資料更新的node,通常包含value值發生更新的node和新增的node。
例如,在實現時,可以直接根據該最新區塊中的交易的執行結果,來確定該最新區塊對應的MPT狀態樹上發生資料更新的node;或者,也可以透過判斷MPT狀態樹上的node是否為複用的node,來確定該最新區塊對應的MPT狀態樹上發生資料更新的node;比如,如果是複用的node,則表明該node是未發生資料更新的node;
當確定該最新區塊對應的MPT狀態樹上發生資料更新的node之後,該“區塊狀態更新執行緒”,可以為這些發生資料更新的node標記該最新區塊的區塊號,表示該node在該區塊號對應的區塊發生了資料更新。
透過這種方式,每當區塊鏈產生一個最新區塊,“區塊狀態更新執行緒”都可以及時的對該最新區塊對應的MPT狀態樹上發生資料更新的node,標記該最新區塊的區塊號,使得透過遍歷上述資料庫中儲存的MPT狀態樹上的各個node,就能夠透過為各個node標記的區塊號,獲知到該node發生資料更新時所在的區塊;由於MPT狀態樹上的各個node(尤其是MPT樹上的葉子節點)最近一次發生資料更新後的value值,通常可以指示該node的最新狀態;因此,透過查看為各個node標記的區塊號,則可以獲知各個node的最新狀態,是在哪個區塊產生的;從而這種為node標記區塊號的機制,可以對上述資料庫的各級資料儲存的資料遷移提供依據。
其中,需要說明的是,“區塊狀態更新執行緒”為MPT狀態樹上的node標記區塊號的動作,可以發生在構建MPT狀態樹的過程中,也可以發生在將構建完成的MPT狀態樹儲存至上述資料庫的過程中,在本說明書中不進行特別限定。
也即,“區塊狀態更新執行緒”可以在節點設備構建MPT狀態樹的過程中,為MPT狀態樹上發生資料更新的node標記區塊號,也可以在將構建完成的MPT狀態樹儲存至上述資料庫的過程中,為MPT狀態樹上發生資料更新的node標記區塊號。
其中,需要說明的是,在本說明書中,為MPT狀態樹上的node標記的區塊號,具體可以標記在與node的Value對應的區塊號欄位中。在實際應用中,上述區塊號欄位具體可以與node的Value儲存在一起,也可以不與node的Value儲存在一起,而是儲存在另外物理位置。
在示出的一種實施方式中,可以在上述資料庫中儲存的MPT狀態樹上的node的Value之中,設置一區塊號欄位;為該MPT狀態樹上的node標記的區塊號,可以添加在該node的value中設置的該區塊號欄位之中。其中,該區塊號欄位在node的Value之中的位置,在本說明書中不進行特別限定;
例如,在一個例子中,可以在MPT狀態樹上每個發生資料更新的node的Value之後(也可以放置在Value之前),增加一個區塊號欄位,然後在該區塊號欄位中為該node標記區塊號。
在示出的另一種實施方式中,上述區塊號欄位具體也可以不與MPT狀態樹上的node的Value儲存在一起,而是設置在單獨的物理位置上;在這種情況下,可以在上述資料庫中,設置一個指向MPT狀態樹上的node的Value的儲存位置的區塊號欄位;為該MPT狀態樹上的node標記的區塊號,可以添加在設置在單獨的物理位置上的該區塊號欄位之中。
例如,以上述資料庫為基於LevelDB架構的Rocksdb資料庫為例,可以將上述區塊號欄位設置在單獨的column family(列族)之中。
透過將區塊號欄位不與node的Value儲存在一起,而是儲存在單獨的物理位置上,使得在需要遍歷為MPT狀態樹上的node標記的區塊號時,可以只從單獨的物理位置上讀取區塊號即可,而並不需要讀取該node整個的value值,可以提升遍歷為MPT狀態樹上的node標記的區塊號時的查找效率。
在本說明書中,節點設備還可以在本地啟動一個“遷移執行緒”,用於將上述資料庫中各級資料儲存中儲存的MPT狀態樹上的node資料,向下級資料儲存進行遷移。
上述“遷移執行緒”,具體可以執行一個定時任務,可以週期性的確定上述資料庫中的各級資料儲存是否滿足預設的資料遷移條件;
其中,上述資料庫中的各級資料儲存的資料遷移條件,可以基於實際的資料遷移需求來設置,在本說明書中不進行特別限定;
例如,在實際應用中,上述資料庫的各級資料儲存的資料遷移條件,具體可以是各級資料儲存的儲存容量達到閾值;或者,也可以是各級資料儲存所儲存的資料所對應的區塊數達到閾值。
上述“遷移執行緒”,在確定上述資料庫中任一級目標資料儲存,滿足了資料遷移條件,則該“遷移執行緒”可以針對該目標資料儲存進行資料遷移處理,將該目標資料儲存中儲存的部分區塊的MPT狀態樹,作為歷史資料向下一級資料儲存進行遷移。
在實現時,當目標資料儲存滿足了資料遷移條件時,上述“遷移執行緒”可以確定該目標資料儲存中,需要遷移至下一級資料儲存的node對應的區塊號區間;
其中,該目標資料儲存中需要遷移至下一級資料儲存的node對應的區塊號區間,可以基於上一次資料遷移發生後的下一區塊的區塊號,和該目標資料儲存一次能夠遷移走的最大區塊數來確定;比如,假設上一次資料遷移後的下一個區塊是Block N,該目標資料儲存一次能夠遷移走的區塊數為30,那麼上述區塊號區間具體可以是[N,N+29];或者,也可以是[N,N+30)。
當上述“遷移執行緒”確定出該目標資料儲存中,需要遷移至下一級資料儲存的node對應的區塊號區間之後,可以基於該區塊號區間,來確定本次資料遷移的遷移臨界值;其中,該遷移臨界值具體可以是一個大於該區塊號區間的區塊號臨界值;
需要說明的是,在實際應用中,上述區塊號區間的右區間具體可以是開區間,也可以是閉區間;而在基於上述區塊號區間來確定上述遷移臨界值時,上述區塊號區間的右區間為開區間或者閉區間時,確定出的遷移臨界值也可以存在一定的差異。
在示出的一種實施方式中,如果上述區塊號區間的右區間為開區間,在基於上述區塊號區間來確定上述遷移臨界值時,可以將上述區塊號區間的右端點值,確定為上述遷移臨界值;
例如,假設上述區塊號區間為[a,b),那麼基於該區塊號區間確定出的遷移臨界值為該區塊號區間的右端點值b。
在示出的另一種實施方式中,如果上述區塊號區間的右區間為閉區間,在基於上述區塊號區間來確定上述遷移臨界值時,可以將上述區塊號區間的右端點值與區塊鏈的區塊號遞增步長的和,確定為上述遷移臨界值;
例如,假設上述區塊號區間為[a,b],區塊鏈的區塊號遞增步長為1,那麼基於該區塊號區間確定出的遷移臨界值為該區塊號區間的右端點值b+1。
其中,上述區塊鏈的區塊號遞增步長,通常可以是1;也即,區塊鏈的區塊號按照1為步長進行致密遞增;比如,區塊號按照1、2、3、4…的順序進行遞增。
當然,在實際應用中,區塊鏈的區塊號遞增步長具體也可以是大於1的整數;比如,區塊號也可以按照1、3、5、7…的順序進行遞增,在本說明書中不進行特別限定。
進一步的,當上述“遷移執行緒”,基於上述區塊號區間,確定出本次資料遷移的遷移臨界值之後,可以根據該遷移臨界值,將該目標資料儲存中儲存的與上述區塊號區間對應的區塊的MPT狀態樹,作為歷史資料向下一級資料儲存進行遷移。
具體地,上述“遷移執行緒”,首先可以遍歷與上述遷移臨界值對應的目標區塊的MPT狀態樹,查找該MPT狀態樹中,被標記的區塊號小於上述遷移臨界值的目標資料節點,然後將為查找到的上述目標資料節點標記的區塊號修改為上述遷移臨界值;
例如,假設上述區塊號區間為[a,b),上述遷移臨界值為該區塊號區間的右端點值b,那麼上述“遷移執行緒”可以遍歷第b號區塊的MPT狀態樹,查找該MPT狀態樹上,被標記的區塊號小於上述遷移臨界值的資料節點,然後將為查找到的這些資料節點標記的區塊號修改b。
進一步的,當上述“遷移執行緒”,透過遍歷與上述遷移臨界值對應的目標區塊的MPT狀態樹,將該MPT狀態樹中,被標記的區塊號小於上述遷移臨界值的目標資料節點,全部修改為上述遷移臨界值後,此時上述“遷移執行緒”可以依次遍歷與上述區塊號區間中的各個區塊號對應的區塊的MPT狀態樹,查找這些區塊的MPT狀態樹上,被標記的區塊號小於上述遷移臨界值的資料節點;此時,在這些區塊的MPT狀態樹上查找到的,被標記的區塊號小於上述遷移臨界值的資料節點,即為可以作為遷移至該目標資料儲存的下一級資料儲存的歷史資料,上述“遷移執行緒”可以將查找到的這些資料節點,遷移至該目標資料儲存的下一級資料儲存;
例如,在實現時,上述“遷移執行緒”可以複製查找到的這些資料節點,並將複製的這些資料儲存至下一級資料儲存,然後在將複製的這些資料節點成功儲存至下一級資料儲存之後,再將這些資料節點從上述目標資料儲存中清除。
透過這種方式,由於與上述區塊號區間中的各個區塊號對應的區塊的MPT狀態樹上,被標記的區塊號小於上述遷移臨界值的node的區塊號,已經被修改為上述遷移臨界值;因此,按照上述方式完成資料遷移後,對於這些被標記的區塊號修改為上述遷移臨界值的node而言,將會繼續在本級資料儲存中儲存和保留;這相當於對資料庫中儲存的MPT狀態樹上的node進行了一次剪枝,將記錄了歷史狀態資料的node從MPT狀態樹上移除,遷移至下一級資料儲存,並在本級資料儲存中繼續儲存和保留記錄了最新狀態資料的node,進而完成針對資料庫中儲存的MPT狀態樹的分級儲存。
其中,需要說明的是,上述“區塊狀態更新執行緒”和上述“遷移執行緒”對應的處理動作,可以併發執行;也即,上述“區塊狀態更新執行緒”和上述“遷移執行緒”可以對MPT狀態樹上的同一個node進行併發競爭處理。因此,在實際應用中,為了避免上述“區塊狀態更新執行緒”和上述“遷移執行緒”對同一個node進行併發競爭處理,可能造成的處理錯誤,可以透過技術手段,來保證在任一時刻,只能有一個執行緒來存取MPT狀態樹上的同一個node。
其中,在保證在任一時刻,只能有一個執行緒來存取MPT狀態樹上的同一個node所採用的具體技術手段,在本說明書中不進行特別限定;例如,在實現時,可以採用互斥鎖技術、單執行緒技術來實現,在本說明書中不再進行詳述。
與上述方法實施例相對應,本申請還提供了裝置的實施例。
與上述方法實施例相對應,本說明書還提供了一種基於區塊鏈的分級儲存裝置的實施例。
本說明書的基於區塊鏈的分級儲存裝置的實施例可以應用在電子設備上。裝置實施例可以透過軟體實現,也可以透過硬體或者軟硬體結合的方式實現。以軟體實現為例,作為一個邏輯意義上的裝置,是透過其所在電子設備的處理器將非易失性記憶體中對應的電腦程式指令讀取到主記憶體中運行形成的。
從硬體層面而言,如圖4所示,為本說明書的基於區塊鏈的分級儲存裝置所在電子設備的一種硬體結構圖,除了圖4所示的處理器、主記憶體、網路介面、以及非易失性記憶體之外,實施例中裝置所在的電子設備通常根據該電子設備的實際功能,還可以包括其他硬體,對此不再贅述。
圖5是本說明書一示例性實施例示出的一種基於區塊鏈的分級儲存裝置的方塊圖。
請參考圖5,所述基於區塊鏈的分級儲存裝置50可以應用在前述圖4所示的電子設備中,其中所述區塊鏈的帳戶狀態資料被組織成Merkle狀態樹在資料庫中儲存;所述資料庫包括多級資料儲存;所述Merkle狀態樹上的資料節點被標記了區塊號;所述區塊號指示所述資料節點發生資料更新時所在的區塊;所述裝置50包括:
確定模組501,當所述資料庫中的任一級目標資料儲存滿足了資料遷移條件時,確定所述目標資料儲存中待遷移至下一級資料儲存的資料節點對應的區塊號區間;基於所述區塊號區間確認遷移臨界值;其中,所述遷移臨界值為大於所述區塊號區間的區塊號臨界值;
修改模組502,遍歷與所述遷移臨界值對應的目標區塊的Merkle狀態樹,查找被標記的區塊號小於所述遷移臨界值的目標資料節點,並將查找到的所述目標資料節點的區塊號修改為所述遷移臨界值;
遷移模組503,遍歷與所述區塊號區間中的各個區塊號對應的區塊的Merkle狀態樹,查找被標記的區塊號小於所述遷移臨界值的資料節點,並將查找到的資料節點從所述目標資料儲存中,遷移至所述目標資料儲存的下一級資料儲存。
在本實施例中,所述確定模組501:
如果所述區塊號區間的右區間為開區間,將所述區塊號區間的右端點值,確定為所述遷移臨界值;
如果所述區塊號區間的右區間為閉區間,將所述區塊號區間的右端點值與所述區塊鏈的區塊號遞增步長的和確定為所述遷移臨界值。
在本實施例中,所述資料庫為Key-Value資料庫;
所述Merkle狀態樹上的資料節點以Key-Value鍵值對的形式儲存在所述資料庫中;其中,所述Key-Value鍵值對的key為所述資料節點包含的資料內容的hash值;所述Key-Value鍵值對的value為所述資料節點包含的資料內容。
在本實施例中,所述裝置50還包括:
標記模組504(圖5中未示出),確定最新區塊的Merkle狀態樹上發生資料更新的資料節點;為所述最新區塊的Merkle狀態樹上發生資料更新的資料節點標記所述最新區塊的區塊號。
在本實施例中,所述資料庫中儲存的所述Merkle狀態樹上的資料節點的Value中,包含預設的區塊號欄位;為所述Merkle狀態樹上的資料節點標記的區塊號,添加在所述區塊號欄位中。
在本實施例中,所述資料庫中預設了指向所述Merkle狀態樹上的資料節點的Value的儲存位置的區塊號欄位;為所述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),如調變的資料信號和載波。
還需要說明的是,術語“包括”、“包含”或者其任何其他變體意在涵蓋非排他性的包含,從而使得包括一系列要素的過程、方法、商品或者設備不僅包括那些要素,而且還包括沒有明確列出的其他要素,或者是還包括為這種過程、方法、商品或者設備所固有的要素。在沒有更多限制的情況下,由語句“包括一個……”限定的要素,並不排除在包括所述要素的過程、方法、商品或者設備中還存在另外的相同要素。
上述對本說明書特定實施例進行了描述。其它實施例在所附申請專利範圍的範圍內。在一些情況下,在申請專利範圍中記載的動作或步驟可以按照不同於實施例中的順序來執行並且仍然可以實現期望的結果。另外,在附圖中描繪的過程不一定要求示出的特定順序或者連續順序才能實現期望的結果。在某些實施方式中,多工處理和並行處理也是可以的或者可能是有利的。
在本說明書一個或多個實施例使用的術語是僅僅出於描述特定實施例的目的,而非旨在限制本說明書一個或多個實施例。在本說明書一個或多個實施例和所附申請專利範圍中所使用的單數形式的“一種”、“所述”和“該”也旨在包括多數形式,除非上下文清楚地表示其他含義。還應當理解,本文中使用的術語“和/或”是指並包含一個或多個相關聯的列出項目的任何或所有可能組合。
應當理解,儘管在本說明書一個或多個實施例可能採用術語第一、第二、第三等來描述各種資訊,但這些資訊不應限於這些術語。這些術語僅用來將同一類型的資訊彼此區分開。例如,在不脫離本說明書一個或多個實施例範圍的情況下,第一資訊也可以被稱為第二資訊,類似地,第二資訊也可以被稱為第一資訊。取決於語境,如在此所使用的詞語“如果”可以被解釋成為“在……時”或“當……時”或“回應於確定”。
以上所述僅為本說明書一個或多個實施例的較佳實施例而已,並不用以限制本說明書一個或多個實施例,凡在本說明書一個或多個實施例的精神和原則之內,所做的任何修改、等同替換、改進等,均應包含在本說明書一個或多個實施例保護的範圍之內。