1. 程式人生 > >Fabric 1.0 讀寫集

Fabric 1.0 讀寫集

Fabric 1.0 讀寫集

轉:https://blog.csdn.net/lengconglin/article/details/76863195

本文譯自Fabric 1.0 文件,這篇文件詳述了當前讀寫集語義實現的細節。文件地址為: 
https://hyperledger-fabric.readthedocs.io/en/latest/readwrite.html

交易模擬和讀寫集 
在一個背書人上進行交易模擬期間,會為交易準備一個讀寫資料集。讀集包含一份唯一鍵的列表和該鍵的提交版本,用於交易模擬期間讀取。寫集包含一份唯一鍵的列表(鍵值可能與讀集有重疊)和交易寫入的對應的新鍵值。如果交易更新是刪除該鍵,那麼會對該鍵做一個刪除標記。 
進一步的,如果交易對一個鍵對應的值進行多次寫操作,該鍵只會保留最後一次寫入的值。同樣,如果交易讀取一個鍵對應的值,會返回處於已提交狀態的值。即使在進行讀取操作之前該交易已經更新了該鍵的值。換句話說就是,不支援在交易中讀取該交易寫入的資料。 
正如前面提到的,鍵的版本只被記錄在讀集中。寫集僅包含唯一鍵的列表和交易設定的鍵的最新值。 
有很多方案可以實現版本控制,最簡單的方案是給每一個鍵生成一個

獨一無二的識別符號。例如:用單調遞增數字代表版本號就是這樣一種方案。在Fabric 1.0 中,我們基於版本控制,使用了正在提交的交易所在的區塊鏈高度作為所有被交易改變的鍵的最新版本。在此方案中,一筆交易的高度使用一個元組表示(txNumber 是該交易所在區塊的高度)。這種方式相比於單調遞增數字的方案有很多優勢,首要的就是它讓狀態資料庫、交易模擬和驗證等元件進行有效的設計選擇成為可能。

下面是對讀寫集例子的說明,為了簡便,這裡使用單調遞增數字代表版本: 
這裡寫圖片描述 
另外,如果交易在模擬中進行了range查詢操作,查詢操作和其結果都將被新增到讀寫集作為query-info。

交易驗證和使用讀寫集更新世界狀態

 
提交者使用讀寫集的讀集部分校驗一筆交易的有效性,使用寫集更新相關鍵的版本和鍵值。 
在驗證階段,如果一筆交易中每個讀集中的鍵與世界狀態中對應鍵的版本號一致,那麼該筆交易被認為是有效的–假設先前的有效交易都已經被提交了,包括同一區塊中的先前交易。但是如果讀寫集中包含了一個或者多個query-info,就需要執行額外的驗證。 
額外的驗證要確保在先前的query-info中的結果沒有鍵被插入、刪除或者更新。換句話說,如果我們在驗證時基於已提交狀態重複執行range查詢操作,應該得到和我們在交易模擬時觀察到的一樣的結果。這種驗證確保如果一筆交易在提交時觀察到幽靈條目,該筆交易應該被標記為無效。注意虛假保護僅限於range查詢(比如鏈碼中的GetStateByRange函式),還沒有在其他查詢操作中實現。其他查詢操作對幽靈有風險,所以應該被用於只讀的並不提交到ordering的交易,除非應用可以保證模擬和驗證/提交時的結果集的穩定性。 
如果一筆交易通過了有效性驗證,提交者會使用寫集更新世界狀態。在更新階段,寫集中每個鍵所對應的世界狀態中的該鍵的值都會被設定為寫集中確定的值。並且,世界狀態中的鍵的版本也更新到最新版本。

模擬和驗證例子 
這節通過小例子來幫助理解讀寫集語義。為此,鍵k在世界狀態中被表示為(k,ver,val),其中ver是最新版本,val是它的值。 
現在假設有T1,T2,T3,T4和T5共5筆交易,所有的模擬都基於同一個世界狀態的快照。下面的片段展示了世界狀態的快照以及交易模擬和每個交易模擬的一系列讀寫操作: 
這裡寫圖片描述

現在假定這些交易被排序為T1到T5依次執行: 
1、T1通過驗證,因為它並沒有任何讀操作。並且世界狀態中k1和k2鍵的值別更新為(k1,2,v1’), (k2,2,v2’)。 
2、T2不能通過驗證,因為它讀取了k1鍵的值,該值在T1中被修改了。 
3、T3通過驗證,因為它並沒有任何讀操作。並且世界狀態中k2的值被更新為(k2,3,v2”)。 
4、T4不能通過驗證,因為它讀取了k2鍵的值,該值在T1中被修改了。 
5、T5通過驗證,雖然讀取了k5的值,但是k5的值之前交易並未修改過。

注意:目前不支援帶有多重讀寫集的交易。