天天看點

一文讀懂Fabric 2.0新特性前言1. 智能合約的去中心化管理2. private data增強3. 外部鍊碼啟動器4. CouchDB中使用了狀态資料庫緩存來提高性能5. 基于Alpine來打包docker鏡像6. Release notes廢除

文章目錄

  • 前言
  • 1. 智能合約的去中心化管理
    • 1.1 鍊碼新的生命周期
      • 1.1.1 鍊碼的安裝和定義
        • 1.1.1.1 打包鍊碼
        • 1.1.1.2 安裝鍊碼
        • 1.1.1.3 同意鍊碼的定義
        • 1.1.1.4 送出鍊碼的定義
      • 1.1.2 鍊碼的更新
      • 1.1.3 完整的demo
      • 1.1.4 比較
  • 2. private data增強
    • 2.1 什麼是private data 集合?
    • 2.2 一個demo
    • 2.3 private交易流程
    • 2.4 私有資料的共享
      • 2.4.1 私有資料共享模型
      • 2.4.2 私有資料執行個體
    • 2.5 删除私有資料
    • 2.6 私有資料集合的定義
  • 3. 外部鍊碼啟動器
    • 3.1 外部構模組化型
        • `detect`:
        • `build`
        • `release`
        • `run`
    • 3.2 配置外部的建構器和運作器
  • 4. CouchDB中使用了狀态資料庫緩存來提高性能
  • 5. 基于Alpine來打包docker鏡像
  • 6. Release notes
    • 新特性
    • 重要變化
  • 廢除

前言

鍊碼不需要“執行個體化”,可以同時運作java和go鍊碼,同一個鍊碼多次執行個體化。

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

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

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

需要注意的是,隻能由fabric-1.4.x更新到2.0。

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

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

(ps:我是在本地寫的,導緻導入的時候,有些圖檔未能上傳,有需要看的,請移步到我的blog:https://haojunsheng.github.io/2020/02/fabric-relase-2/)

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個組織不需要使用相同的名字。

[外鍊圖檔轉存失敗,源站可能有防盜鍊機制,建議将圖檔儲存下來直接上傳(img-tgtM5BdB-1582029897382)(…/images/posts/fabric/Lifecycle-package.png)]

1.1.1.2 安裝鍊碼

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

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

[外鍊圖檔轉存失敗,源站可能有防盜鍊機制,建議将圖檔儲存下來直接上傳(img-d2cqLO8D-1582029897383)(…/images/posts/fabric/Lifecycle-install.png)]

1.1.1.3 同意鍊碼的定義

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

  • 名字
  • 版本:chaincode打包的時候生成的。
  • Sequence:用來追蹤鍊碼的更新過程。是自增的。
  • 背書政策:哪些組織可以執行可以驗證交易。
  • **Collection Configuration:**私有資料相關。
  • Initialization:原來chaincode的預設的init函數不執行,現在可以了。
  • ESCC/VSCC Plugins

[外鍊圖檔轉存失敗,源站可能有防盜鍊機制,建議将圖檔儲存下來直接上傳(img-QjcOOW7T-1582029897383)(…/images/posts/fabric/Lifecycle-approve.png)]

1.1.1.4 送出鍊碼的定義

一旦得到了絕大多數成員的同意,就可以送出鍊碼的定義了。

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

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

[外鍊圖檔轉存失敗,源站可能有防盜鍊機制,建議将圖檔儲存下來直接上傳(img-u1wIoDGz-1582029897384)(…/images/posts/fabric/Lifecycle-commit.png)]

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

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

[外鍊圖檔轉存失敗,源站可能有防盜鍊機制,建議将圖檔儲存下來直接上傳(img-KSkVwjYw-1582029897384)(…/images/posts/fabric/Lifecycle-start.png)]

1.1.2 鍊碼的更新

更新和安裝類似,我們既可以更新鍊碼的内容,還可以更新鍊碼的背書政策。

  1. 打包鍊碼。隻有在更新鍊碼内容的時候需要。

    [外鍊圖檔轉存失敗,源站可能有防盜鍊機制,建議将圖檔儲存下來直接上傳(img-pN4ACywl-1582029897386)(…/images/posts/fabric/Lifecycle-upgrade-package-20200217233850395.png)]

  2. 安裝新鍊碼。同上。

    [外鍊圖檔轉存失敗,源站可能有防盜鍊機制,建議将圖檔儲存下來直接上傳(img-UN0fCSd6-1582029897387)(…/images/posts/fabric/Lifecycle-upgrade-install.png)]

  3. 鍊碼定義投票。sequence将會自增1。

    [外鍊圖檔轉存失敗,源站可能有防盜鍊機制,建議将圖檔儲存下來直接上傳(img-wntCVO9Q-1582029897388)(…/images/posts/fabric/Lifecycle-upgrade-approve-20200218163958279.png)]

  4. 送出定義。

    [外鍊圖檔轉存失敗,源站可能有防盜鍊機制,建議将圖檔儲存下來直接上傳(img-wZPOieSz-1582029897388)(…/images/posts/fabric/Lifecycle-upgrade-commit.png)]

将會啟動新的鍊碼容器。

[外鍊圖檔轉存失敗,源站可能有防盜鍊機制,建議将圖檔儲存下來直接上傳(img-IU1hSe4v-1582029897389)(…/images/posts/fabric/Lifecycle-upgrade-start.png)]

1.1.3 完整的demo

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

## at first we package the chaincode
packageChaincode 1

## Install chaincode on peer0.org1 and peer0.org2
echo "Installing chaincode on peer0.org1..."
installChaincode 1
echo "Install chaincode on peer0.org2..."
installChaincode 2

## query whether the chaincode is installed
queryInstalled 1

## approve the definition for org1
approveForMyOrg 1

## check whether the chaincode definition is ready to be committed
## expect org1 to have approved and org2 not to
checkCommitReadiness 1 "\"Org1MSP\": true" "\"Org2MSP\": false"
checkCommitReadiness 2 "\"Org1MSP\": true" "\"Org2MSP\": false"

## now approve also for org2
approveForMyOrg 2

## check whether the chaincode definition is ready to be committed
## expect them both to have approved
checkCommitReadiness 1 "\"Org1MSP\": true" "\"Org2MSP\": true"
checkCommitReadiness 2 "\"Org1MSP\": true" "\"Org2MSP\": true"

## now that we know for sure both orgs have approved, commit the definition
commitChaincodeDefinition 1 2

## query on both orgs to see that the definition committed successfully
queryCommitted 1
queryCommitted 2

## Invoke the chaincode
chaincodeInvokeInit 1 2

sleep 10

## Invoke the chaincode
chaincodeInvoke 1 2

# Query chaincode on peer0.org1
echo "Querying chaincode on peer0.org1..."
chaincodeQuery 1
           

下面來看圖:

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

[外鍊圖檔轉存失敗,源站可能有防盜鍊機制,建議将圖檔儲存下來直接上傳(img-CMSQvQ3G-1582029897390)(…/images/posts/fabric/Lifecycle-join-approve.png)]

如果背書政策是預設的大多數,那麼背書政策會自動更新,把新的組織計算在内。

[外鍊圖檔轉存失敗,源站可能有防盜鍊機制,建議将圖檔儲存下來直接上傳(img-2qG6GXQC-1582029897391)(…/images/posts/fabric/Lifecycle-join-start.png)]

更新背書政策

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

[外鍊圖檔轉存失敗,源站可能有防盜鍊機制,建議将圖檔儲存下來直接上傳(img-2Z7D7LYF-1582029897391)(…/images/posts/fabric/Lifecycle-endorsement-approve.png)]

新的背書政策在新的鍊碼定義通過後,即可生效,我們不必重新開機容器即可更新背書政策。

[外鍊圖檔轉存失敗,源站可能有防盜鍊機制,建議将圖檔儲存下來直接上傳(img-CKnURxDs-1582029897392)(…/images/posts/fabric/Lifecycle-endorsement-commit.png)]

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

[外鍊圖檔轉存失敗,源站可能有防盜鍊機制,建議将圖檔儲存下來直接上傳(img-5vaWVnNX-1582029897392)(…/images/posts/fabric/Lifecycle-no-package.png)]

不同意鍊碼定義的組織将不能使用鍊碼:

[外鍊圖檔轉存失敗,源站可能有防盜鍊機制,建議将圖檔儲存下來直接上傳(img-ueV6I1vz-1582029897393)(…/images/posts/fabric/Lifecycle-no-package-20200217235444051.png)]

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

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

[外鍊圖檔轉存失敗,源站可能有防盜鍊機制,建議将圖檔儲存下來直接上傳(img-qQxHw9xK-1582029897393)(…/images/posts/fabric/Lifecycle-majority-disagree.png)]

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

[外鍊圖檔轉存失敗,源站可能有防盜鍊機制,建議将圖檔儲存下來直接上傳(img-woH2XOU7-1582029897394)(…/images/posts/fabric/Lifecycle-languages.png)]

一次打包,多次使用:

我們可以打包一次,給鍊碼建立不同的定義,進而運作多個智能合約執行個體(但是背書政策要有差別)。

[外鍊圖檔轉存失敗,源站可能有防盜鍊機制,建議将圖檔儲存下來直接上傳(img-BsrJfrpy-1582029897394)(…/images/posts/fabric/Lifecycle-multiple.png)]

1.1.4 比較

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

1.x 2.0
package
install
approve
commit
instantiate
upgrade

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。注意,必須配置錨節點資訊,設定CORE_PEER_GOSSIP_EXTERNALENDPOINT變量。
  • 私有資料的hash,會寫入到區塊鍊網絡中,其他人可以進行審計。
一文讀懂Fabric 2.0新特性前言1. 智能合約的去中心化管理2. private data增強3. 外部鍊碼啟動器4. CouchDB中使用了狀态資料庫緩存來提高性能5. 基于Alpine來打包docker鏡像6. Release notes廢除

當集合中的成員需要把該私有資料向第三方共享時,第三方可以通過比較該資料的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

[外鍊圖檔轉存失敗,源站可能有防盜鍊機制,建議将圖檔儲存下來直接上傳(img-lRHH8fyY-1582029897394)(…/images/posts/fabric/PrivateDataConcept-1.png)]

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

[外鍊圖檔轉存失敗,源站可能有防盜鍊機制,建議将圖檔儲存下來直接上傳(img-Vkfx0HxF-1582029897395)(…/images/posts/fabric/PrivateDataConcept-3.png)]

2.3 private交易流程

  1. 用戶端發送提案給授權的背書節點,提案中加入transient 字段;
  2. 私有資料存儲在transient data store(臨時的存儲在peer節點);
  3. 背書節點發送提案響應到用戶端,響應的内容是private data的hash值;
  4. 用戶端節點把hash值發送給order節點;
  5. 在送出階段,授權的節點将會檢查政策,自己是否有權限通路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. 資産所有者和買家線上下達成交易價格;
  2. 賣家需要證明資産的所有權。既可以線下提供私有資料的細節,也可以提供線上的憑證;
  3. 賣家線上驗證hash;
  4. 買家調用鍊碼記錄出價的細節到自己的private data中。監管者可能也需要記錄。
  5. 賣家調用鍊碼轉移資産,需要資産和出價細節的隐私資料,需要賣家,買家,監管者參與,除此之外,還需要滿足背書政策;
  6. 鍊碼會對上述資訊進行驗證;
  7. 賣家把公開的資料和私有資料的hash送出給order節點,打包成區塊;
  8. 其他節點将會驗證是否滿足背書政策,私有資料的狀态是否被其他的交易更改;
  9. 所有節點會進行記賬;
  10. 至此交易完成,其他的節點可以查詢這筆資産的公開的資訊,但無法擷取私有資訊。

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的配置來自定義自己的服務。

# List of directories to treat as external builders and launchers for
    # chaincode. The external builder detection processing will iterate over the
    # builders in the order specified below.
    externalBuilders: []
        # - path: /path/to/directory
        #   name: descriptive-builder-name
        #   environmentWhitelist:
        #      - ENVVAR_NAME_TO_PROPAGATE_FROM_PEER
        #      - GOPROXY
           

3.1 外部構模組化型

fabric的建構器使用了Heroku Buildpacks。

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

  • bin/detect

    : 判斷是否由我們自定義的模型來運作。
  • bin/build

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

    (optional): 提供chaincode的中繼資料。
  • bin/run

    (optional): 運作鍊碼。

下面分别是四個腳本的内容:

detect

#!/bin/bash

CHAINCODE_METADATA_DIR="$2"

# use jq to extract the chaincode type from metadata.json and exit with
# success if the chaincode type is golang
if [ "$(jq -r .type "$CHAINCODE_METADATA_DIR/metadata.json" | tr '[:upper:]' '[:lower:]')" = "golang" ]; then
    exit 0
fi

exit 1
           

build

#!/bin/bash

CHAINCODE_SOURCE_DIR="$1"
CHAINCODE_METADATA_DIR="$2"
BUILD_OUTPUT_DIR="$3"

# extract package path from metadata.json
GO_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 release
if [ -d "$CHAINCODE_SOURCE_DIR/META-INF" ]; then
    cp -a "$CHAINCODE_SOURCE_DIR/META-INF" "$BUILD_OUTPUT_DIR/"
fi
           

release

#!/bin/bash

BUILD_OUTPUT_DIR="$1"
RELEASE_OUTPUT_DIR="$2"

# copy indexes from META-INF/* to the output directory
if [ -d "$BUILD_OUTPUT_DIR/META-INF" ] ; then
   cp -a "$BUILD_OUTPUT_DIR/META-INF/"* "$RELEASE_OUTPUT_DIR/"
fi
           

run

BUILD_OUTPUT_DIR="$1"
RUN_METADATA_DIR="$2"

# setup the environment expected by the go chaincode shim
export CORE_CHAINCODE_ID_NAME="$(jq -r .chaincode_id "$RUN_METADATA_DIR/chaincode.json")"
export CORE_PEER_TLS_ENABLED="true"
export CORE_TLS_CLIENT_CERT_FILE="$RUN_METADATA_DIR/client.crt"
export CORE_TLS_CLIENT_KEY_FILE="$RUN_METADATA_DIR/client.key"
export CORE_PEER_TLS_ROOTCERT_FILE="$RUN_METADATA_DIR/root.crt"
export CORE_PEER_LOCALMSPID="$(jq -r .mspid "$RUN_METADATA_DIR/chaincode.json")"

# populate the key and certificate material used by the go chaincode shim
jq -r .client_cert "$RUN_METADATA_DIR/chaincode.json" > "$CORE_TLS_CLIENT_CERT_FILE"
jq -r .client_key  "$RUN_METADATA_DIR/chaincode.json" > "$CORE_TLS_CLIENT_KEY_FILE"
jq -r .root_cert   "$RUN_METADATA_DIR/chaincode.json" > "$CORE_PEER_TLS_ROOTCERT_FILE"
if [ -z "$(jq -r .client_cert "$RUN_METADATA_DIR/chaincode.json")" ]; then
    export CORE_PEER_TLS_ENABLED="false"
fi

# exec the chaincode to replace the script with the chaincode process
exec "$BUILD_OUTPUT_DIR/chaincode" -peer.address="$(jq -r .peer_address "$ARTIFACTS/chaincode.json")"
           

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.

繼續閱讀