一文帶大家瞭解Fabric 2.0的新特性(詳細版)

前言

鏈碼不需要"實例化",可以同時運行java和go鏈碼,同一個鏈碼多次實例化。

<strong>之前發的這篇 被頭條彈窗了,但是寫的不夠詳細,今天特別把這篇文章補充完整。 此外歡迎大家關注我的github:https://github.com/haojunsheng

想要了解上面的特性,請看下面的分解。

Fabric 2.0 在2020年1月29號終於release了,我們來看下有哪些新的變化。

主要體現在:對新應用和隱私的支持,增強了智能合約的管理,增加了對節點的操作。

需要注意的是,只能由fabric-1.4.x升級到2.0。

ps:在網上有個翻譯,那一字一句的翻譯,真的讓我很難受。

下面我嘗試使用自己的理解來解讀。

1. 智能合約的去中心化管理

fabric 2.0引入了智能合約的去中心化管理,在此之前,鏈碼的安裝和實例化都是一個由組織在操作,現在則發生了變化。新的鏈碼的生命週期中,只有多個組織達成了共識,才可以和賬本才可以進行交互。

· 多個組織必須同意鏈碼的參數

。在2.0之前,一個組織可以為channel中的所有成員設置鏈碼的參數(例如實例化鏈碼時指定的背書策略),拒絕安裝鏈碼的組織將不能參與鏈碼的調用。在2.0中,同時提供中心化的模型和去中心化的模型。

· 鏈碼的升級更加安全。在之前的鏈碼生命週期中,一個組織即可升級鏈碼。在新的版本中,需要別的組織進行同意。

· 簡化了背書策略和private data的更新。我們不必重新打包/安裝鏈碼即可更新背書策略和private data集合的配置。同時我們設置了默認的背書策略,默認的背書策略在我們增加或者刪除組織的時候會自動生效。

· 打包鏈碼:會打包為tar文件,方便進行閱讀。

· 一次打包多次複用:之前鏈碼是通過名字+版本號來決定的,現在一次打包生成多個名字,可以多次安裝(在相同或者不同的通道上)

· 不需要所有人的同意即可打包chaincode:組織可以擴展鏈碼,不需要所有人的同意,只要符合背書要求,這些交易即可被更新到賬本中。這樣做的好處是,不需要所有人的同意,即可小規模的修改鏈碼的bug。

1.1 鏈碼新的生命週期

1.1.1 鏈碼的安裝和定義

新的鏈碼週期要求組織對鏈碼的名字,版本,背書策略達成一致,需要執行以下四步,但不需要每個組織都執行:

· 打包鏈碼:一個或者每一個組織完成。

· 自己的節點安裝鏈碼。每個組織要執行,因為需要交易或者查詢賬本。

· 同意鏈碼的定義:需要滿足channel LifecycleEndorsment(默認是大多數)策略的足夠數量的組織來執行。

· 提交chaincode的定義:第一個收集到足夠數量的節點來執行。

下面來詳細的看上面4步:

1.1.1.1 打包鏈碼

鏈碼在安裝前需要打包為tar文件。我們可以使用peer命令,node sdk,或者第三方工具。

第三方的打包工具需要滿足以下要求:

· 鏈碼以tar.gz結尾;

· tar文件需要包含2個文件(不是目錄),元文件Chaincode-Package-Metadata.json和chaincode文件。

· Chaincode-Package-Metadata.json文件長成下面這樣。

· {"Path":"fabric-samples/chaincode/fabcar/go","Type":"golang","Label":"fabcarv1"}

一個demo如下。2個組織不需要使用相同的名字。

一文帶大家瞭解Fabric 2.0的新特性(詳細版)


1.1.1.2 安裝鏈碼

每個節點上都需要安裝。強烈建議每個組織只打包一次鏈碼,然後把該鏈碼安裝在該組織的所有節點上。如果一個channel想要保證所有的組織運行相同的鏈碼,那麼打包命令應該由一個組織來進行。

安裝成功後會返回MYCC_1:hash.這樣的格式,我們需要進行保存,方便後面的使用,如果忘記了,可以進行查詢。

一文帶大家瞭解Fabric 2.0的新特性(詳細版)


1.1.1.3 同意鏈碼的定義

我的理解是,在上面,每個組織都給chaincode起了一個名字,這樣,在實際中是無法使用的,所以現在大家來投票來確定一個統一的名字,包含下面的參數:

· 名字

· 版本:chaincode打包的時候生成的。

· Sequence:用來追蹤鏈碼的升級過程。是自增的。

· 背書策略:哪些組織可以執行可以驗證交易。

· Collection Configuration:私有數據相關。

· Initialization:原來chaincode的默認的init函數不執行,現在可以了。

· ESCC/VSCC Plugins


一文帶大家瞭解Fabric 2.0的新特性(詳細版)


1.1.1.4 提交鏈碼的定義

一旦得到了絕大多數成員的同意,就可以提交鏈碼的定義了。

我們可以使用checkcommitreadiness命令來檢查是否已經有鏈碼的定義了,首先會發送給所有的peer節點,在發送給order節點。提交必須是組織的管理員來完成的。

Channel/Application/LifecycleEndorsement來管理認可的組織的數量,默認是大多數。LifecycleEndorsement和chaincode的背書策略是分離的,沒有任何關係的。

一文帶大家瞭解Fabric 2.0的新特性(詳細版)


即使一個組織沒有安裝鏈碼,仍然可以響應鏈碼的定義。

當鏈碼的定義被確認後,將會在所有安裝鏈碼的節點上啟動鏈碼容器。如果我們在定義鏈碼的時候要求使用init函數,那麼init函數將會被調用。

一文帶大家瞭解Fabric 2.0的新特性(詳細版)


1.1.2 鏈碼的升級

升級和安裝類似,我們既可以升級鏈碼的內容,還可以升級鏈碼的背書策略。

1. 打包鏈碼。只有在升級鏈碼內容的時候需要。

·

一文帶大家瞭解Fabric 2.0的新特性(詳細版)

·

1. 安裝新鏈碼。同上。

·

一文帶大家瞭解Fabric 2.0的新特性(詳細版)

·

1. 鏈碼定義投票。sequence將會自增1。

·

一文帶大家瞭解Fabric 2.0的新特性(詳細版)

·

1. 提交定義。

·

一文帶大家瞭解Fabric 2.0的新特性(詳細版)

·

將會啟動新的鏈碼容器。

一文帶大家瞭解Fabric 2.0的新特性(詳細版)


1.1.3 完整的demo

下面是chaincode的比較完整的操作。來自。

<code>## at first we package the chaincodepackageChaincode 1## Install chaincode on peer0.org1 and peer0.org2echo "Installing chaincode on peer0.org1..."installChaincode 1echo "Install chaincode on peer0.org2..."installChaincode 2## query whether the chaincode is installedqueryInstalled 1## approve the definition for org1approveForMyOrg 1## check whether the chaincode definition is ready to be committed## expect org1 to have approved and org2 not tocheckCommitReadiness 1 "\"Org1MSP\": true" "\"Org2MSP\": false"checkCommitReadiness 2 "\"Org1MSP\": true" "\"Org2MSP\": false"## now approve also for org2approveForMyOrg 2## check whether the chaincode definition is ready to be committed## expect them both to have approvedcheckCommitReadiness 1 "\"Org1MSP\": true" "\"Org2MSP\": true"checkCommitReadiness 2 "\"Org1MSP\": true" "\"Org2MSP\": true"## now that we know for sure both orgs have approved, commit the definitioncommitChaincodeDefinition 1 2## query on both orgs to see that the definition committed successfullyqueryCommitted 1queryCommitted 2## Invoke the chaincodechaincodeInvokeInit 1 2sleep 10## Invoke the chaincodechaincodeInvoke 1 2# Query chaincode on peer0.org1echo "Querying chaincode on peer0.org1..."chaincodeQuery 1/<code>

下面來看圖:

加入通道:如果一個channel已經有了定義好的chaincode,那麼新加入的組織在安裝鏈碼後可以直接使用原來的名字。

一文帶大家瞭解Fabric 2.0的新特性(詳細版)


如果背書策略是默認的大多數,那麼背書策略會自動更新,把新的組織計算在內。

一文帶大家瞭解Fabric 2.0的新特性(詳細版)


升級背書策略

我們不必重新打包或者安裝鏈碼即可升級背書策略。channel中的成員會重新生成一個chaincode定義。

一文帶大家瞭解Fabric 2.0的新特性(詳細版)


新的背書策略在新的鏈碼定義通過後,即可生效,我們不必重啟容器即可更新背書策略。

一文帶大家瞭解Fabric 2.0的新特性(詳細版)


無法安裝鏈碼即可同意鏈碼的定義:

一文帶大家瞭解Fabric 2.0的新特性(詳細版)


不同意鏈碼定義的組織將不能使用鏈碼:

一文帶大家瞭解Fabric 2.0的新特性(詳細版)


上圖中的組織三不可以使用鏈碼。

channel不認可鏈碼的定義:這裡比較繞,說的是channel中的組織沒有對鏈碼的定義達成共識。

一文帶大家瞭解Fabric 2.0的新特性(詳細版)


組織安裝了不同類型的鏈碼:這裡的意思是說只要鏈碼產生相同的讀寫集,那麼可以安裝不同語言寫的鏈碼,比如java和go。

一文帶大家瞭解Fabric 2.0的新特性(詳細版)


一次打包,多次使用:

我們可以打包一次,給鏈碼創建不同的定義,從而運行多個智能合約實例(但是背書策略要有區別)。

一文帶大家瞭解Fabric 2.0的新特性(詳細版)


1.1.4 比較

做了個表格,把舊的聲明週期和新的進行了比較。


2. private data增強

Fabric 2.0增強了private data,我們不需要創建私有數據集合即可使用私有數據。做了以下增強:

· 私有數據的共享和驗證。當私有數據向非原來的集合中的成員共享時,該成員可以通過GetPrivateDataHash() 函數來驗證hash是不是和鏈上保存的hash一致。

· 集合級別的背書策略。我們可以使用背書策略來定義私有數據集合。

· 每個組織都有暗含的私有數據集合。

2.1 什麼是private data 集合?

在同一個channel中,A組織的數據不想給其他的組織看的數據。從v1.2開始,創造了private data collections,我們可以背書,提交和查詢私有數據,在不創建一個獨立channel的情況下。

private data collections由兩部分組成:

· 實際的私有數據。在不同的節點間通過gossip協議來發送。私有數據存儲在授權的peer節點上的sidedb數據庫中,可以通過Chaincode來訪問。order節點無法看到private data。注意,必須配置錨節點信息,設置COREPEERGOSSIP_EXTERNALENDPOINT變量。

· 私有數據的hash,會寫入到區塊鏈網絡中,其他人可以進行審計。

一文帶大家瞭解Fabric 2.0的新特性(詳細版)

private-data.private-data

當集合中的成員需要把該私有數據向第三方共享時,第三方可以通過比較該數據的hash和鏈上保存的hash,看是否一致。

還有一些特殊情況,每個組織都可以創建一個私有數據集合,之後可以共享給其他成員。

我們把private data和channel進行一個比較。

· channel:所有的交易和賬本都是私密的。

· 私有數據集合:通道中組織的子集共享數據時。直接通過p2p來傳播每條具體的交易,而不是區塊,order節點無法看到真實的交易。

2.2 一個demo

有下面5個角色:

Farmer出售商品,Distributor分銷商負責把商品運到海外,Shipper負責在兩個角色之間運貨,Wholesaler批發商從distributors批發商品,Retailer零售商從shippers和wholesaler購買商品。

場景是:

· Distributor想和Farmer,Shipper共享數據,但是不想讓Retailer和wholesaler看到數據;

· Distributor賣給Retailer和wholesaler的價格不同;

· wholesaler和Retailer,Shipper之間也需要共享數據;

為了滿足上面的場景,我們不需要建立這麼多的channel,可以使用PDC。

· PDC1: Distributor, Farmer and Shipper

· PDC2: Distributor and Wholesaler

· PDC3: Wholesaler, Retailer and Shipper

一文帶大家瞭解Fabric 2.0的新特性(詳細版)


上面場景下,peer節點的賬本如下,也稱為SideDB。

一文帶大家瞭解Fabric 2.0的新特性(詳細版)


2.3 private交易流程

1. 客戶端發送提案給授權的背書節點,提案中加入transient 字段;

1. 私有數據存儲在transient data store(臨時的存儲在peer節點);

1. 背書節點發送提案響應到客戶端,響應的內容是private data的hash值;

1. 客戶端節點把hash值發送給order節點;

1. 在提交階段,授權的節點將會檢查策略,自己是否有權限訪問private data,如果有的話,將會檢查transient data store 字段,看看是否在背書階段拿到了private data。沒有的話,會從其他節點去拉取。在驗證和提交階段,private data將會被存儲到數據庫中,同時把transient data store 刪除。

2.4 私有數據的共享

我們可能會有把私有數據向其他組織或者其他集合共享的需求,接受方需要驗證hash:

· 只要滿足背書策略(fabric 2.0中,我們可以定義鏈碼級別,鍵和集合級別的背書策略),不需要是集合中的成員,即可訪問私有數據的鍵

· 我們可以使用GetPrivateDataHash()來驗證hash

在實際中,我們可能會創建大量的私有數據集合,這個不利於我們的維護。更好的情況是每個組織都是一個集合,然後共享就可以了。更好的是我們不必為此進行定義,因為在2.0中默認設置了。

2.4.1 私有數據共享模型

下面這個是每個組織一個集合的模型:

· 使用相應的公鑰來追蹤公共狀態的變化:

· 鏈碼訪問控制:我們可以在鏈碼實現訪問控制,指定哪些客戶端可以查看私有數據。

· 共享私有數據:通過hash來確認;

· 和其他集合共享私有數據:

· 可以把私有數據轉移到其他的集合。這個時候會刪除原來的集合。

· 在交易達成之前,可以使用私有數據進行預請求;

· 保護交易者的隱私

2.4.2 私有數據實例

把私有數據模型和鏈碼結合可以發揮出很大的作用,具體如下所示:

· 可以通過處於公共鏈碼狀態的UUID密鑰來跟蹤資產。僅記錄資產的所有權,關於資產的其他信息一無所知。

· 鏈碼將要求任何轉移請求都必須來自擁有權限的客戶,並且密鑰受基於狀態的認可約束,要求所有者組織和監管機構的同級必須認可任何轉移請求。

· 資產的所有者可以看到該資產的所有交易詳情,其他的組織只可以看到hash。

· 監管者可以保留私有數據。

具體的交易流如下所示:

1. 資產所有者和買家在線下達成交易價格;

1. 賣家需要證明資產的所有權。既可以線下提供私有數據的細節,也可以提供線上的憑證;

1. 賣家線上驗證hash;

1. 買家調用鏈碼記錄出價的細節到自己的private data中。監管者可能也需要記錄。

1. 賣家調用鏈碼轉移資產,需要資產和出價細節的隱私數據,需要賣家,買家,監管者參與,除此之外,還需要滿足背書策略;

1. 鏈碼會對上述信息進行驗證;

1. 賣家把公開的數據和私有數據的hash提交給order節點,打包成區塊;

1. 其他節點將會驗證是否滿足背書策略,私有數據的狀態是否被其他的交易更改;

1. 所有節點會進行記賬;

1. 至此交易完成,其他的節點可以查詢這筆資產的公開的信息,但無法獲取私有信息。

2.5 刪除私有數據

對於非常敏感的數據,比如政府要求的。我們可以從peer節點上徹底的刪除,只留下hash來證明該數據確實存在過。數據刪除後,無法從鏈碼進行查詢,其他的peer節點也不可查詢。

2.6 私有數據集合的定義

從fabric 2.0開始,在chaincode定義階段來進行定義:

· name:集合的名字;

· policy:private data的policy必須比鏈碼的背書策略更加廣泛,因為背書節點必須有private data才可以進行背書。比如一個channel裡面包含了10個組織,5個組織需要有private data的權限,背書策略可以指定為5箇中的三個;

· requiredPeerCount:在背書節點把提案響應返回到客戶端之前,最少把private data傳遞到其他節點的數量。不建議寫0,因為這樣的話,將會導致private data的丟失。

· maxPeerCount:如果設置為0,在背書階段,private data將不會傳播,在commit階段,數據才會傳播;

· blockToLive:私有數據的存活時間,到期自動刪除。設為0表示,永不刪除;

· memberOnlyRead:表示只有授權的人可以讀。

· memberOnlyWrite:

· endorsementPolicy:

3. 外部鏈碼啟動器

我們可以使用自己喜歡的方式來構建和啟動鏈碼,不必使用docker。

· 解除了對docker daemon的依賴。之前的fabric要求peer節點可以訪問到docker daemon,而這在生產環境不一定是現實的。

· 容器的替代品:我們不一定在使用容器了。

· 鏈碼作為外部的服務。之前鏈碼是被peer啟動的,現在鏈碼可以作為單獨的外部服務。

在Hyperledger Fabric 2.0之前,用於構建和啟動鏈碼的過程是peer節點實現的一部分,無法輕鬆自定義。必須使用特定的語言。這種方法限制了鏈碼的語言,必須依賴容器,chaincode無法作為單獨運行的服務。

從2.0開始,我們在peer的core.yaml中,加入了一個externalBuilder的配置來自定義自己的服務。

3.1 外部構建模型

fabric的構建器使用了。

外部構建和運行期由下面四個部分組成:

· bin/detect: 判斷是否由我們自定義的模型來運行。

· bin/build: 把打包後的鏈碼變為可執行版本。用來構建,編譯鏈碼。

· bin/release (optional): 提供chaincode的元數據。

· bin/run (optional): 運行鏈碼。

下面分別是四個腳本的內容:

detect:

<code>

build

<code>#!/bin/bashCHAINCODE_SOURCE_DIR="$1"CHAINCODE_METADATA_DIR="$2"BUILD_OUTPUT_DIR="$3"# extract package path from metadata.jsonGO_PACKAGE_PATH="$(jq -r .path "$CHAINCODE_METADATA_DIR/metadata.json")"if [ -f "$CHAINCODE_SOURCE_DIR/src/go.mod" ]; then    cd "$CHAINCODE_SOURCE_DIR/src"    go build -v -mod=readonly -o "$BUILD_OUTPUT_DIR/chaincode" "$GO_PACKAGE_PATH"else    GO111MODULE=off go build -v  -o "$BUILD_OUTPUT_DIR/chaincode" "$GO_PACKAGE_PATH"fi# save statedb index metadata to provide at releaseif [ -d "$CHAINCODE_SOURCE_DIR/META-INF" ]; then    cp -a "$CHAINCODE_SOURCE_DIR/META-INF" "$BUILD_OUTPUT_DIR/"fi/<code>

release

<code>#!/bin/bashBUILD_OUTPUT_DIR="$1"RELEASE_OUTPUT_DIR="$2"# copy indexes from META-INF/* to the output directoryif [ -d "$BUILD_OUTPUT_DIR/META-INF" ] ; then   cp -a "$BUILD_OUTPUT_DIR/META-INF/"* "$RELEASE_OUTPUT_DIR/"fi/<code>

run

<code>

3.2 配置外部的構建器和運行器

上面說了,這個是在core.yaml中配置的,一個demo如下所示:

chaincode: externalBuilders: - name: my-golang-builder path: /builders/golang environmentWhitelist: - GOPROXY - GONOPROXY - GOSUMDB - GONOSUMDB - name: noop-builder path: /builders/binary


4. CouchDB中使用了狀態數據庫緩存來提高性能

· 使用外部CouchDB狀態數據庫時,背書和驗證階段的讀取延遲歷來是性能瓶頸。

· fabric 2.0中,每個peer都進行了緩存,在core.yaml中的cacheSize來進行配置。

5. 基於Alpine來打包docker鏡像

從 v2.0 開始,Hyperledger Fabric Docker 鏡像將使用 Alpine Linux 作為基礎鏡像,這是一個面向安全的輕量級 Linux 發行版。這意味著 Docker 鏡像現在要小得多,提供更快的下載和啟動時間,以及佔用主機系統上更少的磁盤空間。Alpine Linux 的設計從一開始就考慮到了安全性,Alpine 發行版的最小化特性大大降低了安全漏洞的風險。

6. Release notes

新特性

FAB-11237:去中心化的智能合約管理

新的應用程序模式:

· FAB-10889: Implicit org-specific collections

·

FAB-15066: Endorsement policies for collections

· FAB-13581: memberOnlyWrite collection configuration option

· FAB-13527: GetPrivateDataHash chaincode API

· FAB-12043: Option to include private data in block events

FAB-103: State database cache for CouchDB

重要變化

· FAB-5177: The ccenv build image no longer includes the shim

· FAB-15366: Logger removed from chaincode shim

· FAB-16213: The go chaincode entities extension has been removed

· FAB-12075: Client Identity (CID) library has moved

· FAB-14720: Support for CAR chaincode package format removed

· FAB-15285: Support for invoking system chaincodes from user chaincodes has been removed.

· FAB-15390: Support for peer's Admin service has been removed.

·

FAB-16303: GetHistoryForKey returns results from newest to oldest

· FAB-16722: The 'provisional' genesis method of generating the system channel for orderers has been removed.

· FAB-16477 and FAB-17116: New configuration for orderer genesismethod and genesisfile

· FAB-15343: System Chaincode Plugins have been removed.

· FAB-11096: Docker images with Alpine Linux

· FAB-11096: Bash not available in Docker images with Alpine Linux

· 使用sh或者ash

· FAB-15499: Ledger data format upgrade

· FAB-16866: Chaincode built upon installation on peer

· FAB-15837: Orderer FileLedger location moved if specified with relative path

· FAB-14271: Policies must be specified in configtx.yaml

· FAB-17000: Warn when certificates are about to expire

· FAB-16987: Go version has been updated to 1.13.4.

廢除

· FAB-15754: The 'Solo' consensus type is deprecated.

· FAB-16408: The 'Kafka' consensus type is deprecated.

· FAB-7559: Support for specifying orderer endpoints at the global level in channel configuration is deprecated.

· FAB-17428: Support for configtxgen flag --outputAnchorPeersUpdate is deprecated.


分享到:


相關文章: