深度探索Hyperledger技術與應用之超級帳本的策略管理

image

上一篇分享了超級帳本的系統邏輯架構和網絡節點架構典型交易流程,本篇主要分享超級帳本的消息協議結構和策略管理。git

1

消息協議結構

一、信封消息結構github

信封消息是認證內容中最基本的單元。它由一個消息負載(Payload)和一個簽名(Signature)組成。算法

// 信封包含一個帶有簽名的負載,以便認證該消息

message Envelope {

    // 編組的負載

    bytes payload = 1;

    // 負載頭中指定建立者簽名

    bytes signature = 2;

}

    // 負載是消息內容(容許簽名)

message Payload {

    // 負載頭部,提供身份驗證並防止重放

    Header header = 1;

    // 數據,其編碼由頭的類型定義

    bytes data = 2;

}
複製代碼

負載包含:編程

**1)消息頭部。**頭部帶有類型,描述負載的性質以及如何解組數據字段。此外,頭部還包含建立者的信息和隨機數,以及用來標識時間邏輯窗口的時期信息。只有在兩個條件都成立的狀況下,Peer節點才能接受一個信封。數組

  • 消息中指定的時期信息是當前窗口期;安全

  • 該負載在該週期內只看到一次(即沒有重放)。bash

**2)數據字段的類型由頭部指定。**頭部消息的組織方式以下所示:網絡

message Header {

    bytes channel_header = 1;

    bytes signature_header = 2;

}

    // 通道頭是一個通用的預防重放和身份標識的消息,它包含在一個被簽名的負載之中

message ChannelHeader {

    int32 type = 1; // 頭類型0-10000由HeaderType保留和定義

    // 版本指示消息協議版本

    int32 version = 2;

    // 時間戳是發件人建立消息的本地時間

    google.protobuf.Timestamp timestamp = 3;

    // 該消息綁定通道的標識符

    string channel_id = 4;

    // 端到端使用惟一的標識符

    //  -  由較高層設置,如最終用戶或SDK

    //  -  傳遞給背書節點(將檢查惟一性)

    //  -  當消息正確傳遞時,它將被記帳節點檢索(也會檢查惟一性)

    //  -  存儲於帳本中

    string tx_id = 5;

    // 時期信息基於區塊高度而定義,此字段標識時間的邏輯窗口

    // 只有在兩個條件都成立的狀況下,對方纔接受提案響應

    // 1\. 消息中指定的時期信息是當前時期

    // 2\. 該消息在該時期內只看到一次(即沒有重放)

    uint64 epoch = 6;

    // 根據消息頭類型附加的擴展

    bytes extension = 7;

}

enum HeaderType {

    MESSAGE = 0;                   // 非透明消息

    CONFIG = 1;                    // 通道配置

    CONFIG_UPDATE = 2;             // 通道配置更新

    ENDORSER_TRANSACTION = 3;      // SDK提交背書

    ORDERER_TRANSACTION = 4;       // 排序管理內部使用

    DELIVER_SEEK_INFO = 5;         // 指示Deliver API查找信息

    CHAINCODE_PACKAGE = 6;         // 鏈碼打包安裝

}

message SignatureHeader {

    // 消息的建立者,鏈的證書

    bytes creator = 1;

    // 只能使用一次的任意數字,可用於檢測重放攻擊

    bytes nonce = 2;

}
複製代碼

信封消息結構對於驗證負載的簽名是必要的。不然,對於大載荷消息,就必須鏈接全部的載荷再進行簽名驗證,這每每成本很高。架構

通過排序後,批量的信封消息交付給記帳節點進行驗證,經過驗證後的數據被記錄到帳本之中。併發

二、配置管理結構

區塊鏈有與之相關的配置,配置設置在創世區塊之中,但可能在後續被修改。該配置信息在類型爲CONFIGURATION_TRANSACTION的信封消息中編碼。配置信息自己就是區塊的一個單獨交易。配置信息交易沒有任何依賴,因此每一個配置信息交易必須包含對於鏈的全量數據,而不是增量數據。使用全量數據更容易引導新的peer或排序節點,也便於將來進行裁剪工做。

CONFIGURATION_TRANSACTION類型的信封消息具備ConfigurationEnvelope類型的負載數據。它定義爲:

message ConfigurationEnvelope {

    repeated SignedConfigurationItem Items = 3;

}
複製代碼

配置信息的信封消息有與之關聯的序列號和鏈ID。每次修改配置序列號必須遞增,這能夠做爲防止重放攻擊的一個簡單機制。配置信息的信封中會嵌入一系列的SignedConfigurationItems,定義以下:

message SignedConfigurationItem {

    bytes ConfigurationItem = 1;

    repeated Envelope Signatures = 2;

}
複製代碼

由於SignedConfigurationItem必須支持多個簽名,因此它包含一組重複的信封消息。這些消息中每一個都有一個類型爲CONFIGURATION_ITEM的頭部。負載的數據部分在ConfigurationItem中保存,定義爲:

message ConfigurationItem {

    enum ConfigurationType {

        Policy = 0;

        Chain = 1;

        Orderer = 2;

        Fabric = 3;

            }

    bytes ChainID = 1;

    uint64 LastModified = 2;

    ConfigurationType Type = 3;

    string ModificationPolicy = 4;

    string Key = 5;

    bytes Value = 6;

}
複製代碼

Type提供了配置項的範圍和編碼信息。LastModified字段設置爲上一次配置項被修改時配置信息信封中的序列號。ModificationPolicy指向一個已經命名的策略,用來對未來的簽名進行評估,以肯定修改是否被受權。Key和Value字段分別用做引用配置項及其內容。

修改配置包含如下內容:

  • 檢索現有配置;

  • 遞增配置信息信封消息中的序列號;

  • 修改所需的配置項,將每一個配置項的LastModified字段設置爲遞增後的序列號;

  • 更新SignedConfigurationItem中的簽名信息;

  • 將簽名後的信封信息提交給排序節點。

配置管理員將驗證:

  • 全部配置項和信封都指向正確的鏈;

  • 添加或修改了哪些配置項;

  • 有沒有現有的配置項被忽略(即提交的數據是全集);

  • 全部配置更改的LastModification都等於信封消息中的序列號;

  • 全部配置更改均符合相應的修改策略。

任何有權更改配置項的角色均可以構建新的配置信息交易。修改配置項將更新序列號併產生新的創始區塊,這將引導新加入網絡的各類節點。

三、背書流程結構

當Envelope.data中攜帶與鏈碼相關的消息時,使用ENDORSER_TRANSACTION類型。

得到批准的ENDORSER_TRANSACTION負載流程以下。

首先,客戶端向全部相關的背書節點發送提案消息(提案基本上是要進行一些影響帳本的動做)。

而後,每一個背書節點向客戶端發送一個提案響應消息。提案響應包含背書結果的成功/錯誤碼、應答負載和簽名。應答負載之中包含提案的哈希值信息,用此信息能夠將提案和針對該提案的應答安全地鏈接起來。

最後,客戶端將背書結果寫入交易中,簽名併發送到排序服務。

在接下來的章節中,咱們將詳細介紹消息及其流程。

1. 交易提案結構

一個提案消息包含頭部(包含描述它的一些元數據,例如類型、調用者的身份、時間、鏈的ID、加密的隨機數)和不透明的負載:

message SignedProposal {

    // 提案

    bytes proposal_bytes = 1;

    // 對提案進行簽名,該簽名將和頭部的建立者標識進行驗證

    bytes signature = 2;

}

message Proposal {

    // 提案頭部

    bytes header = 1;

    // 提案負載,具體結構由頭部的類型決定

    bytes payload = 2;

    // 提案的可選擴展。對於CHAINCODE類型的消息,其內容多是ChaincodeAction消息

    bytes extension = 3;

}
複製代碼

一個提案發送給背書節點進行背書。該提案包含:

  • 頭部,能夠解組爲頭部信息;

  • 負載,由頭部的類型決定;

  • 擴展,由頭部的類型決定。

和信封消息結構相似,這種SignedProposal消息結構也是重要的。不然,對於大載荷消息,咱們必須鏈接全部的載荷再進行簽名驗證,這每每成本很高。

當背書節點收到簽名後的提案消息後,它將驗證消息中的簽名。驗證簽名須要如下步驟。

  • 預驗證用戶生成簽名證書的有效性。一旦SignedProposal.proposal_bytes和Proposal.header都解組成功,就能夠認爲證書基本是可用的。雖然這種在證書驗證前的解組操做可能並不太理想,可是在這個階段能夠過濾掉證書過時的狀況。

  • 驗證證書是否可信(證書是否由受信任的CA簽名),並容許交易(可否經過ACL檢查)。

  • 驗證SignedProposal.proposal_bytes上的簽名是否有效。

  • 檢測重放攻擊。

如下是當ChainHeader的類型爲ENDORSER_TRANSACTION時的消息:

message ChaincodeHeaderExtension {

    // 控制提案的負載在最終交易和帳本中的可見程度

    bytes payload_visibility = 1;

    // 要定位的鏈代碼ID

    ChaincodeID chaincode_id = 2;

}
複製代碼

ChaincodeHeaderExtension消息用於指定要調用的鏈碼以及應在帳本中呈現的內容。理想狀況下,**payload_visibility是可配置的,**支持至少3種主要可見性模式:

  • 負載全部字節均可見;

  • 只有負載的哈希值可見;

  • 任何東西都不可見。

注意,可見性功能可能也會由ESCC設置,此時本字段將會被覆蓋。另外本字段也將影響ProposalResponsePayload.proposalHash的內容。

message ChaincodeProposalPayload {

    // 包含調用鏈碼的參數,

    bytes input  = 1;

    // 用於實現某些應用程序級的加密數據

    map<string, bytes> TransientMap = 2;

}
複製代碼

ChaincodeProposalPayload消息包含調用鏈碼的參數。TransientMap字段的內容應始終從信封消息中省略掉,並不記錄到帳本之中。

message ChaincodeAction {

    // 調用鏈碼產生的讀/寫集

    bytes results = 1;

    // 調用鏈碼產生的事件

    bytes events = 2;

    // 調用鏈碼的結果

    Response response = 3;

    // 含鏈ID、背書節點在模擬執行提案時設置

    // 帳本節點將驗證版本號是否與鏈碼最新版本匹配,含有鏈ID信息將支持單個交易打開多個鏈碼

    ChaincodeID chaincode_id = 4;

}
複製代碼

ChaincodeAction消息包含執行鏈碼所產生的動做和事件。results字段包含讀取集合,events字段包含由鏈碼執行生成的事件。

2. 提案響應結構

提案響應消息從背書節點返回給提案客戶端。背書節點使用該消息表達對於交易提案的處理結果。應答結果多是成功也多是失敗,另外還會包含動做描述和背書節點的簽名。若是足夠數量的背書節點贊成相同的動做並進行簽名,則能夠生成負載消息,併發送給排序節點。

message ProposalResponse {

    // 消息協議版本

    int32 version = 1;

    // 消息建立時間,由消息發送者定義

    google.protobuf.Timestamp timestamp = 2;

    // 某個動做的背書是否成功

    Response response = 4;

    // 負載,ProposalResponsePayload字節序列

    bytes payload = 5;

    // 提案的具體背書內容,基本上就是背書節點的簽名

    Endorsement endorsement = 6;

}

message ProposalResponsePayload {

    // 觸發此應答交易提案的哈希值

    bytes proposal_hash = 1;

    // 擴展內容,應該解組爲特定類型的消息

    bytes extension = 2;

}

message Endorsement {

    // 背書節點身份(例如,證書信息)

    bytes endorser = 1;

    // 簽名,對提案應答負載和背書節點證書這兩個內容進行簽名

    bytes signature = 2;

}
複製代碼

ProposalResponsePayload消息是提案響應的負載部分。這個消息是客戶端請求和背書節點動做之間的「橋樑」。對於鏈碼來講,它包含一個表示提議的哈希值proposal_hash,以及表示鏈碼狀態變化和事件extension字段。

proposal_hash字段將交易提案和提案響應二者對應起來,即爲了實現異步系統的記帳功能也爲了追責和抗抵賴的安全訴求。哈希值一般會覆蓋整個提案消息的全部字節中。可是,這樣實現就意味着只有得到完整的提案消息才能驗證哈希值的正確性。

出於保密緣由,使用鏈碼不太可能將提案的負載直接存儲在帳本中。例如,類型爲ENDORSER_TRANSACTION的消息,須要將提案的頭部和負載分開進行處理:頭部老是進行完整散列的,而負載則可能進行完整散列或對哈希值再進行散列,或者根本不進行散列。

3. 背書交易結構

客戶端得到足夠的背書後,能夠將這些背書組合成一個交易信息。這個交易信息能夠設置爲負載信息的數據字段。如下是在這種狀況下要使用的具體消息:

message Transaction {

    // 負載是一個TransactionAction數組,每一個交易須要一個數組來適應多個動做

    repeated TransactionAction actions = 1;

}

message TransactionAction {

    // 提案頭部

    bytes header = 1;

    // 負載由頭部類型決定,它是ChaincodeActionPayload字節序列

    bytes payload = 2;

}

TransactionAction消息將提案綁定到其動做。它的頭部是SignatureHeader消息,它的負載是ChaincodeActionPayload消息。

message ChaincodeActionPayload {

    // ChaincodeProposalPayload消息的字節序列,內容來自鏈碼原始調用的參數

    bytes chaincode_proposal_payload = 1;

    // 應用於帳本的動做列表

    ChaincodeEndorsedAction action = 2;

}
複製代碼

ChaincodeActionPayload消息攜帶chaincodeProposalPayload和已經經過背書的動做以應用於帳本。主要的可見性模式是「full」(整個ChaincodeProposalPayload消息包含在這裏)、「hash」(僅包含ChaincodeProposalPayload消息的哈希值)或「nothing」。該字段將用於檢查ProposalResponsePayload.proposalHash的一致性。此外,action字段包含應用於帳本的動做列表。

message ChaincodeEndorsedAction {

    // 由背書節點簽名的ProposalResponsePayload消息字節序列

    bytes proposal_response_payload = 1;

    // 提案背書,基本上是背書節點的簽名

    repeated Endorsement endorsements = 2;

}
複製代碼

ChaincodeEndorsedAction消息承載有關具體提案的背書信息。proposalResponsePayload是由背書節點簽名的,對於ENDORSER_TRANSACTION類型,ProposalResponsePayload的extenstion字段會帶有一個ChaincodeAction。此外,endorsements字段包含提案已經收到的背書信息。

2

策略管理和訪問控制

在Hyperledger Fabric 1.0中,較多的地方都使用策略進行管理,它是一種權限管理的方法,包括交易背書策略、鏈碼的實例化策略、通道管理策略等。

一、策略定義及其類型

策略定義了一些規則,驗證簽名數據是否符合定義的條件,結果爲TRUE或者FALSE。策略的定義以下:

type Policy struct {

    Type  int32  // 策略的類型

    Value []byte // 策略的內容

}
複製代碼

策略的類型有兩種。

1)SignaturePolicy:在基於驗證簽名策略的基礎上,支持條件AND、OR、NOutOf的任意組合,其中的NOutOf指的是知足m個條件中的n個就表示知足策略(m≥n)。好比OR(Org1.Admin, NOutOf(2, Org2.Member))表示Org1的管理員或者兩個Org2的成員簽名都知足策略。

2)ImplicitMetaPolicy:隱含的元策略,是在SignaturePolicy之上的策略,支持大多數的組織管理員這種策略,只適用於通道管理策略。

SignaturePolicy實際只有兩種類型,SignedBy和NOutOf,其餘的,好比AND和OR都會轉換成NOutOf類型。其定義以下:

type SignaturePolicy struct {

    // 支持的類型有:

    // *SignaturePolicy_SignedBy,驗證單個簽名是否正確

    // *SignaturePolicy_NOutOf_,驗證是否有n個簽名都正確

    Type isSignaturePolicy_Type `protobuf_oneof:"Type"`

}
複製代碼

ImplicitMetaPolicy是遞歸策略的定義方法,名稱中的Implicit說明規則是由子策略生成的,Meta說明策略依賴其餘策略的驗證結果。

type ImplicitMetaPolicy struct {

    SubPolicy string                   // 子策略的名稱

    Rule      ImplicitMetaPolicy_Rule  // 策略的規則

}
複製代碼

策略的規則支持3種形式:

  • ImplicitMetaPolicy_ANY:任意一個子規則成立就知足策略;

  • ImplicitMetaPolicy_ALL:所有子規則都成立才知足策略;

  • ImplicitMetaPolicy_MAJORITY:大多數的子規則成立就知足策略。

特別說明ImplicitMetaPolicy_MAJORITY須要知足子規則數的計算方法:

threshold = len(subPolicies)/2 + 1

好比一共有3個子策略,須要至少2個子策略成立才能知足策略。若是總共有4個子策略,須要至少3個子策略成立才能知足策略。若是沒有子策略,默認是知足的。

策略的內容能夠有多種,下面分別來看幾種策略:交易背書策略、鏈碼實例化策略和通道管理策略。

二、交易背書策略

交易背書策略是對交易進行背書的規則,是跟通道和鏈碼相關的,在鏈碼實例化的時候指定。在鏈碼調用的時候,須要從背書節點收集足夠的簽名背書,只有經過背書策略的交易纔是有效的。這是經過應用程序和背書節點之間的交互來完成的,這在前面的交易流程裏已經介紹過了。

交易背書策略的驗證

背書是由一組簽名組成的,每一個Peer節點接收到區塊時,都能根據交易的內容本地驗證背書是否符合背書策略,不須要和其餘節點交互。驗證交易背書的基本原則是:

  • 全部的背書都是有效的,驗證消息用有效的證書進行正確的簽名;

  • 知足背書策略的有效背書數量,轉化爲NOutOf格式進行比較;

  • 背書是指望的背書節點簽名的,在背書策略中指定了哪些組織和角色是有效的背書節點。

如何來實現這幾個原則的呢?咱們先從背書籤名的命令行語法開始,背書籤名的語法AND和OR均可以轉爲NOutOf:

  • AND(A, B)能夠轉換爲NOutOf(1, A, B);

  • OR(A, B)能夠轉換爲NOutOf(2, A, B)。

咱們主要來看下NOutOf如何實現,背書策略的定義以下:

type SignaturePolicyEnvelope struct {

    Version    int32                    // 背書策略版本,默認都是0

    Rule       *SignaturePolicy         // 背書策略規則:簽名策略

    Identities []*common1.MSPPrincipal  // 背書策略主體:MSP主體簽名

}
複製代碼

其中,MSP主體(Principal)是基於MSP的身份標識的,有以下幾種類型。

  • **MSPPrincipal_ROLE:**基於MSP角色的驗證方法,目前只有admin和member兩種。

  • MSPPrincipal_ORGANIZATION_UNIT:基於部門的驗證方法,同一個MSP中的不一樣部門。

  • MSPPrincipal_IDENTITY:基於某個具體身份證書的驗證方法,驗證簽名是否有效。

MSPPrincipal的定義以下:

type MSPPrincipal struct {

    PrincipalClassification MSPPrincipal_Classification // MSP的類型

    Principal []byte                // 根據MSP的類型不一樣,實體有不一樣的內容

}
複製代碼

根據不一樣的MSP類型,主體是不一樣的。

(1)基於MSP角色的驗證

當PrincipalClassification是MSPPrincipal_ROLE時,主體存儲的內容以下:

type MSPRole struct {

    // MSP標識符

    MspIdentifier string

    // MSP角色:可選值是MSPRole_MEMBER和MSPRole_ADMIN

    Role MSPRole_MSPRoleType

}
複製代碼

不一樣角色的驗證方法以下:

  • **MSPRole_MEMBER:**驗證是否爲同一個MSP的有效簽名;

  • **MSPRole_ADMIN:**驗證簽名者是不是MSP設置好的admin成員。

(2)基於部門的驗證

當PrincipalClassification是MSPPrincipal_ORGANIZATION_UNIT時,主體存儲的內容以下:

type OrganizationUnit struct {

    // MSP標識符

    MspIdentifier string

    // 組織部門標識符

    OrganizationalUnitIdentifier string

    // 證書標識符:信任證書鏈和組織部門信息的哈希

    CertifiersIdentifier []byte

}
複製代碼

驗證過程的步驟是:

  • 驗證是否爲相同的MSP;

  • 驗證是不是有效的證書;

  • 驗證組織部門信息是否匹配。

(3)基於身份證書的驗證

當PrincipalClassification是MSPPrincipal_IDENTITY時,主體存儲的內容以下:

type identity struct {

    // 身份標識符,包含MSP標識符和身份編號

    id *IdentityIdentifier

    // 身份的數字證書,包含了對公鑰的簽名

    cert *x509.Certificate

    // 身份的公鑰

    pk bccsp.Key

    // 身份的MSP信息

    msp *bccspmsp

}
複製代碼

這樣驗證MSP是不是有效證書就能夠了。

命令行的背書策略語法

在命令行裏,能夠用一種簡單的語言,根據主體的布爾表達式來表示策略。主體是用MSP來表示的,用來驗證簽名者的標識和簽名者在MSP裏的角色。目前支持兩種角色:member和admin。主體的表示方法是MSP.ROLE,其中MSP是MSP的標識,ROLE能夠是memeber也能夠是admin。這都是有效的主體:Org0.admin表示由MSP標識Org0的任何一個管理員,Org1.memeber表示由MSP標識Org1的任何一個成員。

其語法是:EXPR(E[, E...]),其中EXPR能夠是AND也能夠是OR,E能夠爲一個主體,也能夠爲嵌套的EXPR。好比:

  • AND('Org1.member', 'Org2.member', 'Org3.member')要求3個MSP標識Org一、Org2和Org3,其中每一個MSP都有1個成員有1個簽名;

  • OR('Org1.member', 'Org2.member')要求2個MSP標識Org一、Org2,其中任何1個成員有1個簽名;

  • OR('Org1.member', AND('Org2.member', 'Org3.member'))要求MSP標識Org1的成員有1個簽名,或者MSP標識Org2和Org3的成員都有1個簽名。

目前在命令行的語法中,背書策略只支持AND和OR兩種,並不支持更爲複雜的NOutOf。這部分的設計在後續內容中也會有調整。SDK對背書策略都會轉換成NOutOf語法,不過不是全部的SDK都支持。好比目前fabric-sdk-go提供的默認接口不支持NOutOf語法,但其內部是支持的,稍加改動很容易就能支持。詳細能夠參考cauthdsl_builder.go文件。

給鏈碼指定背書策略

背書策略能夠在部署的時候用-P參數指定,後面是具體的背書策略。好比:

peer chaincode deploy -C testchainid -n mycc -p github.com/hyperledger/fabric/

examples/chaincode/go/chaincode_example02 -c '{"Args":["init","a","100","b","200"]}’

-P "AND('Org1.member', 'Org2.member')"

這個命令在鏈testchainid上部署鏈碼 mycc,背書策略是AND('Org1.member', 'Org2.member')。若是命令行裏沒有指定策略,那麼默認的背書策略要求MSP標識DEFAULT成員的一個簽名。

三、鏈碼實例化策略

鏈碼實例化策略是用來驗證是否有權限進行鏈碼實例化和鏈碼升級的。鏈碼實例化策略是在對鏈碼打包和簽名的時候指定的,若是沒有指定實例化策略,默認是通道的管理員才能實例化。

type SignedChaincodeDeploymentSpec struct {

    // 鏈碼部署規範

    ChaincodeDeploymentSpec []byte

    // 鏈碼的實例化策略,結構同背書策略,在實例化的時候驗證

    InstantiationPolicy []byte

    // 鏈碼全部者的簽名背書列表

    OwnerEndorsements []*Endorsement

}
複製代碼

鏈碼實例化策略的定義和背書策略徹底同樣,驗證方法也相同,只是用途和用法不同。鏈碼實例化策略是直接從鏈碼打包中獲取的,實例化完成後會將策略存放在鏈上。在鏈碼實例化和升級的時候會先驗證是否符合當前的實例化策略,驗證經過才能夠更新鏈碼實例化策略。存儲在鏈上的鏈碼信息結構以下所示:

type ChaincodeData struct {

    // 鏈碼名稱

    Name string

    // 鏈碼版本

    Version string

    // 鏈碼的ESCC

    Escc string

    // 鏈碼的VSCC

    Vscc string

    // 鏈碼的背書策略

    Policy []byte

    // 鏈碼的內容:包含鏈碼的名稱、版本、鏈碼源碼哈希、鏈碼名稱和版本的元數據哈希等內容

    // 不包含鏈碼源碼

    Data []byte

    // 鏈碼指紋標識,目前沒有使用

    Id []byte

    // 鏈碼實例化策略

    InstantiationPolicy []byte

}
複製代碼

鏈碼信息結構ChaincodeData在鏈上是按鏈碼的名稱索引的。

四、通道管理策略

通道配置是遞歸定義的:

type ConfigGroup struct {

    Version   uint64                   // 配置版本

    Groups    map[string]*ConfigGroup   // 子配置

    Values    map[string]*ConfigValue   // 配置值

    Policies  map[string]*ConfigPolicy  // 配置策略定義

    ModPolicy string                   // 配置修改策略的名稱

}
複製代碼

其中,配置值ConfigValue定義的是一些配置數據,定義以下:

type ConfigValue struct {

    Version   uint64 // 配置版本

    Value     []byte // 配置數據,能夠是JSON結構的

    ModPolicy string // 配置修改策略名稱

}
複製代碼

好比在通道配置中區塊生成間隔BatchTimeout設置的值是「2s」,局部的格式以下:

"BatchTimeout": {

    "mod_policy": "Admins",

    "value": {

        "timeout": "2s"

    }

}
複製代碼

咱們再來看最重要的配置策略的定義:

type ConfigPolicy struct {

    Version   uint64  // 配置策略版本

    Policy    *Policy // 配置策略的內容,這在前面已經介紹過

    ModPolicy string  // 配置策略中修改策略的名稱

}
複製代碼

從上面的定義中咱們能夠看到,配置策略是基於SignaturePolicy和ImplicitMetaPolicy的,ModPolicy表明的是修改同級策略用到的策略名稱。通道定義了3種配置策略,如表3-1所示。

image

通道配置的遞歸定義

咱們來看一個簡化的通道配置是如何遞歸定義的。

Channel:

    Policies:

        Readers

        Writers

        Admins

    Groups:

        Orderer:

            Policies:

                Readers

                Writers

                Admins

            Groups:

                OrdereringOrganization1:

                    Policies:

                        Readers

                        Writers

                        Admins

        Application:

            Policies:

                Readers

----------->    Writers

                Admins

            Groups:

                ApplicationOrganization1:

                    Policies:

                        Readers

                        Writers

                        Admins

                ApplicationOrganization2:

                    Policies:

                        Readers

                        Writers

                        Admins
複製代碼

在上面的配置中,最外層是Channel,它定義了通道的子配置和策略定義。Channel的子配置裏面定義了Orderer和Application配置,它們分別是相同的遞歸定義結構。其中"------->"顯示的一行按照層級展開,表明的是/Channel/Application/Writers。

怎麼來使用這些配置策略呢?好比在排序服務節點調用Deliver接口的時候會檢查這個節點是否知足/Channel/Readers策略。Peer節點同步區塊的時候也會檢查是否知足/Channel/Application/Readers策略。

通道配置的默認策略

在使用configtxgen工具生成創世區塊或者通道配置時,使用的默認策略如表3-2所示。

image

image
深度探索區塊鏈 A.jpg

深度探索區塊鏈

Hyperledger技術與應用

區塊鏈

張增駿,董寧,朱軒彤,陳劍雄  著

本書由超級帳本執行董事Brian Behlendorf領銜推薦,區塊鏈一線落地實踐團隊、Hyperleger會員智鏈骨幹團對撰寫。深刻講解Hyperledger Fabric 1.0的架構、執行邏輯、核心功能實現、從零部署,並以票據案例爲例,講解具體開發實踐,穿插開發所需的最佳實踐和遇到的問題解決。

機械工業

出版社

image

華章科技是機械出版社的旗下品牌,出版了「計算機科學叢書」等近30個經典套系,在各個細分領域均處於領導地位,其中《Java編程思想》、《算法導論》、《編譯原理》、《數據挖掘:概念與技術》、《深刻理解計算機系統》、《深刻理解Java虛擬機》等著做猶如計算機圖書領域的璀璨明珠,長銷不衰!

image

HiBlock秉承開放、協做、透明、連接、分享的價值觀,致力打造區塊鏈開發者社區。專一於在開發者中推廣區塊鏈,幫助開發者真正掌握區塊鏈技術和應用。

本文內容節選自《深度探索區塊鏈:Hyperledger技術與應用》一書的第3章《超級帳本的系統架構》。

本書做者:張增駿,董寧,朱軒彤,陳劍雄

感謝機械工業出版社華章分社的支持和分享。

活動推薦

**主題:**5月25-27日,Blockathon2018北京站,招募100名開發者一塊兒挑戰區塊鏈開發。

開發者免費,報名需審覈。識別下圖二維碼或點擊「閱讀原文」便可報名參加。

image

點擊「閱讀原文」便可報名。

相關文章
相關標籤/搜索