Hyperledger Fabric channel配置交易


一個超級賬本區塊鏈網絡里每個channel的共享配置都是存儲在一個配置交易里。每個配置交易通常被簡稱為configtx

Channel 配置有以下重要屬性:

1、有版本標識:配置里的所有元素都有一個關聯版本。每次更新配置,版本號都維持最新。另外,每個提交的配置會獲得一個序列號。

2、有權限:配置里的每個元素都有一個關聯策略,用來管理是否允許對這個元素進行修改。每一個保存有當前配置副本的實例,都會按照關聯策略的內容對新收到的配置改動進行驗證權限。

3、層次性:一個配置根組包含多個子組,並且層次中的每個組都有關聯的值和策略。較低層次可以獲取上層的策略。


配置分析

配置作為一個HeaderType_CONFIG類型的交易存儲在一個不包含其他交易的區塊中。這些區塊被稱為Configuration Blocks,所有區塊中的第一個區塊稱為genesis block

配置的樣例存儲在fabric/protos/common/configtx.protoHeaderType_CONFIG類型的Envelope編碼ConfigEnvelop信息作為Payload data的值。ConfigEnvelop定義如下:

message ConfigEnvelope {
    Config config = 1;
    Envelope last_update = 2;
}

last_update字段在下面的更新配置中有定義,該字段僅用於驗證配置。當前提交的配置存在config字段,包含一個Config消息。

message Config {
    uint64 sequence = 1;
    ConfigGroup channel_group = 2;
}

sequence的值在每次提交配置后加1,channel_group字段是包含該配置的根組。ConfigGroup是一個遞歸定義的結構,生成一個gruops樹,每個組都包含值和策略。ConfigGroup的定義如下:

message ConfigGroup {
    uint64 version = 1;
    map<string,ConfigGroup> groups = 2;
    map<string,ConfigValue> values = 3;
    map<string,ConfigPolicy> policies = 4;
    string mod_policy = 5;
}

因為ConfigGroup是一個遞歸結構,有層次概念。接下來我們用go語言例子來表示。


// Assume the following groups are defined
var root, child1, child2, grandChild1, grandChild2, grandChild3 *ConfigGroup

// Set the following values
root.Groups["child1"] = child1
root.Groups["child2"] = child2
child1.Groups["grandChild1"] = grandChild1
child2.Groups["grandChild2"] = grandChild2
child2.Groups["grandChild3"] = grandChild3

// The resulting config structure of groups looks like:
// root:
// child1:
// grandChild1
// child2:
// grandChild2
// grandChild3

config層次結構中,每個組定義了一個層次,每個組有一系列關聯的值和策略。值的定義如下:

message ConfigValue {
    uint64 version = 1;
    bytes value = 2;
    string mod_policy = 3;
}

策略的定義如下:

message ConfigPolicy {
    uint64 version = 1;
    Policy policy = 2;
    string mod_policy = 3;
}

注意值、策略和組都有一個versionmod_policy字段。一個元素的version在每次更改后遞增。mod_policy用來管理修改元素的簽名。對於組,更改就是添加或者移除ValuesPolicies、或者組地圖(或者修改mod_policy)。對於ValuesPolicies,修改就是改變修改Value或者Policy字段(或者修改mod_policy)。每個元素的mod_policy在當前當前元素中有效

下面是一個定義在Channel.Groups["Application"]中的策略的示例(這里用的是golang語法,因此Channel.Groups["Application"].Policies["policy1"]表示根組Channel的子組ApplicationPolicies里的policy1對應的策略)

  • policy1對應Channel.Groups["Application"].Policies["policy1"]

  • Org1/policy2對應Channel.Groups["Application"].Groups["Org1"].Policies["policy2"]

  • /Channel/policy3對應Channel.Policies["policy3"]

注意,如果mod_policy引用了一個不存在的策略,那么該元素不可修改。

Configuration updates / 更新配置

更新配置是提交一個HeaderType_CONFIG_UPDATE類型的Envelope消息,交易的Payload.data字段是序列化的ConfigUpdateEnvelope,其定義如下:

message ConfigUpdateEnvelope {
    bytes config_update = 1; // A marshaled ConfigUpdate structure
    repeated ConfigSignature signatures = 2; // Signatures over the config_update
}

其中signatures字段包含了授權更新配置的簽名集,定義如下:

message ConfigSignature {
    bytes signature_header = 1; // A marshaled SignatureHeader
    bytes signature = 2; // Signature over the concatenation signatureHeader bytes and config bytes
}

signature_header如標准交易所定義,而簽名則是signature_header字節和ConfigUpdateEnvelope中的config_update字節的拼接。

ConfigUpdateEnvelope中的config_update字段是序列化的ConfigUpdate,其定義為:

message ConfigUpdate {
    string channel_id = 1; // Which channel this config update is for
    ConfigGroup read_set = 2; // ReadSet explicitly lists the portion of the config which was read, this should be sparse with only Version set
    ConfigGroup write_set = 3; // WriteSet lists the portion of the config which was written, this should included updated Versions
}

其中channel_id是配置更新所對應的channel ID,該字段是必要,因為它界定了支持本次配置更新的所需的簽名范圍。

read_set是現有配置的一個子集,其中僅含version字段,ConfigValue.valueConfigPolicy.policy等其他字段不包含在read_set中。ConfigGroupmap字段組成的子集,以便引用配置樹的深層元素。例如,為使Applicationgroup包含到read_set,它的上層(Channelgroup)也必須包含到read_set中,但不必將Channelgroup中所有的key都包括進去,比如Orderer``group或者任何valuespolicies

write_set指定了要被修改的那部分配置。由於配置的分層特性,修改深層元素就必須在write_set中包含其上層元素。write_set中的任意元素都會在read_set中指定相同版本的該元素。

例如,給出如下配置:

Channel: (version 0)
    Orderer (version 0)
    Appplication (version 3)
     
 Org1 (version 2)

修改Org1提交的read_set應為:

Channel: (version 0)
   
Application: (version 3)

對應的write_set應是:

Channel: (version 0)
    Application: (version 3)
     
  Org1 (version 3)

When the CONFIG_UPDATE is received, the orderer computes the resulting CONFIG by doing the following:

接收到CONFIG_UPDATE后,orderer會通過以下步驟計算CONFIG結果:

  1. 校驗channel_idread_setread_set中所有元素必須存在對應的版本。

  2. 收集read_setwrite_set中版本不一致的元素,計算更新集。

  3. 校驗更新集中的元素的版本號是否遞增1

  4. 校驗更新集中每個元素,ConfigUpdateEnvelope的簽名滿足mod_policy

  5. 通過將更新集應用於當前配置,計算該配置的完整新版本

  6. 將新配置寫成ConfigEnvelope作為CONFIG_UPDATE賦給last_update字段,新的配置賦給config字段,sequence字段自增。

  7. ConfigEnvelope寫成CONFIG類型的Envelope,最終將此作為唯一交易寫入配置區塊。

peer(或者任意其他接收Deliver者)接收到這個配置區塊后,就會通過將last_update信息應用到當前配置並校驗orderer計算的config字段是否包含正確的新配置,來驗證該配置是否被正確校驗。

Permitted configuration groups and values / 組和值得配置許可

有效的配置都是下面配置的子集。在此,用peer.<MSG>表示一個ConfigValue,其value字段是稱為<MSG>的序列化后的信息,定義在fabric/protos/peer/configuration.protocommon.<MSG>msp.<MSG>orderer.<MSG>分別定義在fabric/protos/common/configuration.protofabric/protos/msp/mspconfig.protofabric/protos/orderer/configuration.proto

Note, that the keys {{org_name}} and {{consortium_name}} represent arbitrary names, and indicate an element which may be repeated with different names.

注意,下面的{{org_name}} {{consortium_name}}是任意的名字,表示可以重復使用不同名稱的元素。

&ConfigGroup{
    Groups: map<string, *ConfigGroup> {
       
"Application":&ConfigGroup{
            Groups:map<String, *ConfigGroup> {
               
{{org_name}}:&ConfigGroup{
                   
Values:map<string, *ConfigValue>{
                       
"MSP":msp.MSPConfig,
                       
"AnchorPeers":peer.AnchorPeers,
                    },
                },
            },
        },
        "Orderer":&ConfigGroup{
            Groups:map<String, *ConfigGroup> {
               
{{org_name}}:&ConfigGroup{
                   
Values:map<string, *ConfigValue>{
                       
"MSP":msp.MSPConfig,
                    },
                },
            },

            Values:map<string, *ConfigValue> {
               
"ConsensusType":orderer.ConsensusType,
               
"BatchSize":orderer.BatchSize,
               
"BatchTimeout":orderer.BatchTimeout,
               
"KafkaBrokers":orderer.KafkaBrokers,
            },
        },
       
"Consortiums":&ConfigGroup{
            Groups:map<String, *ConfigGroup> {
               
{{consortium_name}}:&ConfigGroup{
                   
Groups:map<string, *ConfigGroup> {
                       
{{org_name}}:&ConfigGroup{
                           
Values:map<string, *ConfigValue>{
                               
"MSP":msp.MSPConfig,
                            },
                        },
                    },
                   
Values:map<string, *ConfigValue> {
                       
"ChannelCreationPolicy":common.Policy,
                    }
                },
            },
        },
    },

    Values: map<string, *ConfigValue> {
       
"HashingAlgorithm":common.HashingAlgorithm,
       
"BlockHashingDataStructure":common.BlockDataHashingStructure,
       
"Consortium":common.Consortium,
       
"OrdererAddresses":common.OrdererAddresses,
    },
}

Orderer system channel configuration / Order channel 配置

ordering系統channel定義了創建channelordering參數和consortiumsordering service必須有一個ordering系統channel,這是被創建的第一個channel。建議不要在ordering系統channel初始配置中定義application部分,但是測試是可以這么做。注意,任何對ordering系統channel有讀權限的成員都可以查看所有channel創建,因此channel的訪問應受限制。

The ordering parameters are defined as the following subset of config:

ordering參數定義如下:

&ConfigGroup{
    Groups: map<string, *ConfigGroup> {
        "Orderer":&ConfigGroup{
            Groups:map<String, *ConfigGroup> {
               
{{org_name}}:&ConfigGroup{
                   
Values:map<string, *ConfigValue>{
                       
"MSP":msp.MSPConfig,
                    },
                },
            },

            Values:map<string, *ConfigValue> {
               
"ConsensusType":orderer.ConsensusType,
               
"BatchSize":orderer.BatchSize,
               
"BatchTimeout":orderer.BatchTimeout,
               
"KafkaBrokers":orderer.KafkaBrokers,
            },
        },
   
},

ordering中的每個組織都在Orderer組下有一個組元素,這個組定義了一個MSP參數,這個參數包含該組織的加密身份信息。Orderer組中的Values決定了ordering節點的功能。他們存在於每個channel中,所以像orderer.BatchTimeout就可在不同channel中指定不同值。

啟動時,orderer面對含有很多channel信息的文件系統,orderer通過識別帶有consortiums組定義的channel來標識系統channelconsortiums組結構如下。

&ConfigGroup{
    Groups: map<string, *ConfigGroup> {
       
"Consortiums":&ConfigGroup{
            Groups:map<String, *ConfigGroup> {
               
{{consortium_name}}:&ConfigGroup{
                   
Groups:map<string, *ConfigGroup> {
                       
{{org_name}}:&ConfigGroup{
                           
Values:map<string, *ConfigValue>{
                               
"MSP":msp.MSPConfig,
                            },
                        },
                    },
                   
Values:map<string, *ConfigValue> {
                       
"ChannelCreationPolicy":common.Policy,
                    }
                },
            },
        },
    },
},

注意,每個consortium定義一組成員,就行ordering組織的組織成員一樣。每個consortium也都定義了一個ChannelCreationPolicy,它是一種應用於授權channel創建請求的策略,通常這個值設為ImplicitMetaPolicy,要求channel的新成員簽名授權channel創建。有關channel創建更信息的內容,請參閱文檔后面的內容。

Application channel configuration / APP channel 配置

應用程序配置用於為應用類型交易設計的channel。其定義如下:

&ConfigGroup{
    Groups: map<string, *ConfigGroup> {
       
"Application":&ConfigGroup{
            Groups:map<String, *ConfigGroup> {
               
{{org_name}}:&ConfigGroup{
                   
Values:map<string, *ConfigValue>{
                       
"MSP":msp.MSPConfig,
                       
"AnchorPeers":peer.AnchorPeers,
                    },
                },
            },
        },
    },
}

就像Orderer部分,每個組織被編碼為一個組。然而,app channel不僅有MSP身份信息,每個組織都附加了一個AnchorPeers列表。這個列表允許不同組織的節點彼此聯系。

應用程序channel通過對orderer組織和共識選項的編碼,以允許對這些參數進行確定性更新,因此包含了orderer系統channel配置的相同Orderer部分。但從應用角度看,這會在很大程度上被忽略。

Channel creation / 創建channel

Orderer 接收到對一個不存在的channelCONFIG_UPDATE信息時,orderer就會假設這是個創建channel的請求並執行以下操作:

  1. 通過查看高層組中的Consortium值,orderer標識所要執行創建channel請求的consortium(譯注:這個詞暫時不知翻譯成什么好)

  2. orderer驗證Application組中的組織是對應的consortium中組織的一部分,並驗證ApplicationGroup的版本是1

  3. orderer驗證consortium是否有成員,新的channel也會有application成員(創建沒有成員的consortiumschannel只用於測試)。

  4. ordererordering系統channel取得Orderer組,並創建一個包含新指定成員的Application組,並將其mod_policy指定為在consortium config中指定的ChannelCreationPolicy,從而創建一個模板配置。注意,這個策略(mod_policy)是基於新配置的上下文的,因此需要所有成員的策略就是要需要新channel中所有成員的簽名,而不是consortium中的所有成員。

  5. ordererCONFIG_UPDATE更新這個模板配置。因為CONFIG_UPDATE用於Application組(其版本是1)的修改,所以配置碼根據ChannelCreationPolicy驗證這些更新。如果channel創建包含任何其它修改,例如修改單個組織的錨節點,則調用該元素的相應mod策略。

  6. 帶有新channel配置的CONFIG交易被包裝並通過order系統channel發送到orderingordering之后channel就創建完成。



免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM