超級賬本Hyperledger Fabric的系統架構


1、系統的邏輯架構

  1. 應用程序角度

    1. 身份管理

    2. 賬本管理

    3. 交易管理

    4. 只能合約

  2. 底層角度

    1. 成員管理

      MSP

    2. 共識服務

      同一條鏈上不同結點的區塊的一致性,同時確保區塊里面的交易有效和有序

    3. 鏈碼服務

    4. 安全和密碼服務

2、網絡結點架構

  1. 結點分類

    客戶端、Peer結點、排序服務結點、CA結點

  2. 結點描述

    1. 客戶端結點

      由用戶操作,並且與背書結點和排序服務結點通信。向背書結點提交交易提案,讓背書結點背書,當收集到足夠的背書以后向排序服務結點廣播交易。

    2. Peer結點

      • 所有的Peer結點都是記賬結點,他們驗證區塊中的交易,並將區塊添加到賬本

      • 部分Peer結點同時是交易的背書結點,一個交易的背書結點由該交易對應的鏈碼指定

      • 當多個Peer結點成為一個組織,那么這個組織中會有一個Peer結點成為主結點,他與排序服務結點通信並且將新區塊分發給組織內部

    3. 排序服務結點

      接收包含足夠背書的交易,並按順序將他們打包成區塊,然后將區塊分發給各個組織的主結點

    4. CA結點

      CA結點是證書頒發機構,由客戶端和服務器組成。

3、典型交易流程

  1. 創建交易提案並發送給背書結點

    SignedProposal:{
            ProposalBytes(Proposal):{
                #提案消息頭部
                Header:{
                    #通道頭部
                    ChannelHeader:{
                        Type:"HeaderType_ENDORSER_TRANSACTION",
                        #客戶端本地生成的交易號,跟客戶端的身份證書相關,並且背書結點和記賬結點利用這個校驗是否存在重復交易
                        TxId:TxId,
                        TimeStamp:TimeStamp,
                        ChannelId:ChannelId,
                        Extension(ChaincodeHeaderExtension):{
                            PayloadVisibility:PayloadVisibility,
                            ChaincodeId:{
                                Path:Path,
                                Name:Name,
                                Version:Version
                            }
                        },
                        Epoch:Epoch
                    },
                    #簽名頭部,用於消息有效性校驗
                    SignatureHeader:{
                        #客戶端的身份證書
                        Creator:Creator,
                        #隨機數
                        Nonce:Nonce
                    }
                },
                Payload:{
                    ChaincodeProposalPayload:{
                        Input(ChaincodeInvocationSpec):{
                            ChaincodeSpec:{
                                Type:Type,
                                ChaincodeId:{
                                    Name:Name
                                },
                                Input(ChaincodeInput):{
                                    Args:[]
                                }
                            }
                        },
                        TransientMap:TransientMap
                    }
                }
            },
            # 調用者的簽名信息,客戶端將這個提案發送給背書結點,這個就是客戶端的簽名信息
            Signature:Signature
    }
    

      

    正常情況下,客戶端將這個交易提案發給不同的背書結點背書,不同的背書結點模擬執行交易的結果應該是相同的,只有背書結點對結果的簽名信息不一樣

  2. 背書結點模擬執行交易並生成背書簽名

    背書結點收到來自客戶端的交易提案以后進行下列驗證:

    • 交易提案的格式是否正確

    • 交易是否曾經被提交過

    • 交易簽名是否有效

    • 交易提案的客戶端在當前channel上是否有write權限

    上面驗證通過以后,背書結點根據當前賬本上的數據模擬執行提案中的交易,並生成一個讀寫集,但是此時賬本數據不會發生更新,然后背書結點將生成的讀寫集簽名,就是提案響應,並將響應返回給客戶端

    ProposalResponse:{
        Version:Version,
        TimeStamp:Timestamp,
        Response:{
            Status:Status,
            Message:Message,
            Payload:Payload
        },
        Payload(ProposalResponPayload):{
            ProposalHash:ProposalHash,
            Extension(ChaincodeAction):{
                #返回的結果包含了交易模擬執行的讀寫集
                Results(TxRwSet):{
                    NsRwSets(NsRwSet):[
                        NameSpace:NameSpace,
                        KvRwSet:{
                            Reads(KVRead):[
                                Key:Key,
                                Version:{
                                    BlockNum:BlockNum,
                                    TxNum:TxNum
                                }
                            ],
                            RangeQueriesInfo(RangeQueryInfo):[
                                StartKey:StartKey,
                                EndKey:EndKey,
                                ItrExhausted:ItrExhausted,
                                ReadsInfo:ReadsInfo
                            ],
                            Writes(KVWrite):[
                                Key:Key,
                                IsDelete:IsDelete,
                                Value:Value
                            ]
                        }
                    ]
                },
                Events(ChaincodeEvent):{
                    ChaincodeId:ChaincodeId,
                    TxId:TxId,
                    EventName:EventName,
                    Payload:Payload
                }
                Response:{
                    Status:Status,
                    Message:Message,
                    Payload:Payload
                },
                ChaincodeId:ChaincodeId
            }
        },
        #背書結點簽名
        Endorsement:{
            Endorser:Endorser,
            Signature:Signature
        }
    }
    

      

  3. 客戶端收集交易的背書

    客戶端首先對提案相應的背書結點簽名進行驗證

    如果交易只是進行查詢操作,那么這個提案響應不會發送給排序服務結點

  4. 客戶端構造交易請求並發送給排序服務結點

    客戶端收到足夠多的提案響應后就生成交易,將他發送給排序服務結點。

    此時的交易中包含了交易提案,提案響應,背書簽名

    Envelope:{
    	Payload:{
    		#Envelope.Payload.Header==SignedProposal.Proposal.Header,都是交易提案的頭部
    		Header:{
    			ChannelHeader:{
    				Type:"HeaderType_ENDORSER_TRANSACTION",
    				TxId:TxId,
    				Timestamp:Timestamp,
    				Extension(ChaincodeHeaderExtension):{
    					PayloadVisibility:PayloadVisibility,
    					ChaincodeId:{
    						Path:Path,
    						Name:Name,
    						Version:Version
    					}
    				},
    				Epoch:Epoch
    			},
    			SignatureHeader:{
    				Creator:Creator,
    				Nonce:Nonce
    			}
    		},
    		Data(Transaction):{
    			TransactionAction:[
    				# Envelope.Payload.Data.Transaction.Header是交易提交者的身份信息
    				# 與SignedProposal.Proposal.Header.SignatureHeader
    				# 和Envelope.Payload.Header.SignatureHeader是冗余的
    				Header(SignatureHeader):{
    					Creator:Creator,
    					Nonce:Nonce
    				},
    				Payload(ChaincodeActionPayload):{
    					# Envelope.Payload.Data.TransactionAction.Payload.ChaincodeProposalPayload
    					# 與交易提案的SignedProposal.Proposal.Payload.ChaincodeProposalPayload相同,不同的地方是
    					# TransientMap字段被強行設置為nil--保證了隱私性
    					ChaincodeProposalPayload:{
    						Input(ChaincodeInvocationSpec):{
    							ChaincodeSpec:{
    								Type:Type,
    								ChaincodeId:{
    									Name:Name
    								},
    								Input(ChaincodeInput):{
    									Args:[]
    								}
    							}
    						},
    						TransientMap:nil
    					},
    					Action(ChaincodeEndorseAction):{
    						# Envelope.Payload.Data.TransactionAction.Payload.Action.Payload
    						# 與ProposalResponse.Payload結構完全一樣
    						Payload(ProposalResponsePayload):{
    							ProposalHash:ProposalHash,
    							Extension(ChaincodeAction):{
    								Results(TxRwSet):{
    									NsRwSets(NsRwSet):[
    										NameSpace:NameSpace,
    										KvRwSet:{
    											Reads(KVRead):[
    												Key:Key,
    												Version:{
    													BlockNum:BlockNum,
    													TxNum:TxNum
    												}
    											],
    											RangeQueriesInfo(RangeQueryInfo):[
    												StartKey:StartKey,
    												EndKey:EndKey,
    												ItrExhausted:ItrExhausted,
    												ReadsInfo:ReadsInfo
    											],
    											Writes(KVWrite):[
    												Key:Key,
    												IsDelete:IsDelete,
    												Value:Value
    											]
    										}
    									]
    								},
    								Events(ChaincodeEvent):{
    									ChaincodeId:ChaincodeId,
    									TxId:TxId,
    									EventName:EventName,
    									Payload:Payload
    								}
    								Response:{
    									Status:Status,
    									Message:Message,
    									Payload:Payload
    								},
    								ChaincodeId:ChaincodeId
    							}
    						},
    						# Envelope.Payload.Data.TransactionAction.Payload.Action.Endorsement變成了數組,
    						# 表示多個背書結點的簽名
    						Endorsement:[
    							Endorser:Endorser,
    							Signature:Signature
    						]
    					}
    				}
    			]
    		}
    	},
    	# 這是整個信封的簽名,是交易提交者(客戶端)對整個Envelope.Payload的簽名
    	Signature:Signature
    }
    

      

    客戶端可以將上面的簽名信封(生成的交易)發送給任意幾個排序服務結點

  5. 排序服務結點對交易進行排序並生成區塊

    排序服務結點不會讀取交易的內容,只是通過Envelope.Payload.Header.ChannelHeader.ChannelId獲取通道名稱,並把的交易生成的區塊發送往這個通道

  6. 排序服務結點分發區塊

    排序服務結點向通道中的各個組織的主結點分發區塊

  7. 記賬結點驗證區塊內容並寫入區塊

    • 所有的Peer結點都是記賬結點,它首先驗證接收的區塊中交易的有效性,然后將區塊提交到本地賬本,並且產生一個生成區塊的事件,監聽區塊事件的客戶端就可以根據這個事件做后續的處理。

    • 如果記賬結點接收到的是配置區塊,就會根據區塊的內容跟新本地的配置信息。

    1. 交易數據的驗證

      區塊數據的驗證是以交易為單位

      • 是否為合法的交易:交易格式是否正確,簽名是否合法,內容是否被篡改

      • 記賬結點是否加入了這個通道

    2. 記賬結點與VSCC

      鏈碼的交易是隔離的,每個交易的模擬執行結果讀寫集TxRwSet都包含了交易所屬的鏈碼,所以在將交易提交給系統鏈碼VSCC驗證之前,還會對應用鏈碼進行校驗,以下交易是非法的:

      • 鏈碼名稱或版本為空

      • 交易消息頭部的鏈碼名稱Envelope.Payload.Header.ChannelHeader.Extension.ChaincodeId.Name和交易數據里的鏈碼名稱Envelope.Payload.Data.TransactionAction.Payload.ChaincodeProposalPayload.Input.ChaincodeSpec.ChaincodeSpec.Chaincode.Name不一樣

      • 鏈碼更新當前鏈碼數據時,產生的讀寫集的鏈碼版本不是LSCC記錄的最新版本

      • 應用程序鏈碼更新了LSCC鏈碼的數據

      • 應用程序鏈碼更新了不可被外部調用的系統鏈碼的數據

      • 應用程序鏈碼更新了不可被其他鏈碼調用的的系統鏈碼的數據

      • 應用程序鏈碼調用了不可被外部調用的系統鏈碼

    3. 基於狀態數據的驗證和MVCC檢查

      交易通過了VSCC校驗以后就進入了記賬流程,kvledger會對讀寫集TxRwSet進行MVCC(Multi-Version Concuruency Control,版本並發控制)檢查

      • kvledger是基於鍵值對的狀態數據模型

        • 讀,寫,刪除狀態數據

        • 基於單一的鍵讀取

        • 基於鍵范圍查詢

      • MVCC對讀數據(包括讀集合和范圍查詢集合)進行校驗,邏輯是對模擬執行時狀態數據的版本和提交時的狀態數據版本進行比較,如果版本不匹配,說明了在這段時間別的交易改變了狀態數據,所以當前基於之前狀態數據的交易是存在問題的

      • 交易提交時並行的,所以在生成區塊之前並不能確定交易執行的順序,如果多個交易之間存在着執行依賴(幾個交易必須串行化),MVCC還是檢查這種依賴關系,如果依賴發生改變,也認定為交易是不合法的,(依賴關系發生變化實際上是狀態數據發生了改變)

      • 寫集合包含了寫入和刪除數據兩種操作

      • 整個區塊的交易的狀態是同時提交的,保證了整個區塊的狀態數據要么都成功提交,要么都失敗,所以只可能是賬本數據和狀態數據不一致,不會出現狀態數據與區塊數據不一致

    4. 無效交易的處理

      偽造的交易是無效的交易,正常的交易也可能是無效的交易,MVCC檢查的時候是檢查的背書結點在模擬執行交易時的環境是否與記賬結點提交交易時的環境(key,value,version)一樣。

      無效交易也會保存在區塊中。但是無效交易的的讀寫集不會提交到狀態數據庫中,不會導致狀態數據庫發生改變

  8. 在組織內部同步最新的區塊

4、消息協議結構

  1. 信封消息結構

    信封消息是認證內容中的基本單元,包括一個消息負載(Payload)和一個簽名(Signature)

    // 信封包含一個帶有簽名的負載,以便認證該消息
    // Peer接收這個信封的條件是:
    // 1.消息中指定的時期信息是當前窗口期
    // 2.該負載在該周期內只看到一次(沒有重放)
    message Envelope{
    	// 負載
    	payload bytes
    	// 簽名
    	signature bytes
    }
     
    // 負載
    payload Payload{
        // 負載頭部,包含類型,負載的性質,如何解組負載的數據字段,創建者的信息和隨機數,標識時間邏輯窗口的時期信息
        header Header
        // 負載數據
        data bytes
    }
    

      

    // 負載的頭部
    header Header{
        // 負載頭部中的通道頭部信息
        channel_header bytes
        // 負載頭部中的簽名頭部信息
        signature_header bytes
    }
    

      

    // 通道頭部信息,用於預防重放和身份標識
    channel_header ChannelHeader{
        // 消息類型,由HeaderType定義
        type int32
        // 消息協議的版本
        version int32
        // 這個時間戳是發件人創建消息的本地時間
        timestamp google.protobuf.Timestamp
        // 該消息綁定的通道的標識符
        channel_id string
        // 端到端使用的唯一的標識符,由較高層(客戶端)設置,傳遞給背書結點(用於檢查消息的唯一性),當消息正確傳遞是,它被記賬結點檢索,存儲與賬本中
        tx_id string
        // 這個時期信息基於區塊高度定義,這個字段用於標識時間的邏輯窗口
        // 只有在如下兩個條件都成立的情況下,對方才接受提案響應
        // 1.消息中指定的時期信息是當前時期
        // 2.該消息在該時期內只看到一次
        epoch uint64
        // 根據消息頭類型附加的擴展
        extension bytes
    }
    

      

    // 消息類型
    enum HeaderTyoe{
        // 非透明消息
        MESSAGE
        // 通道配置消息
        CONFIG
        // 通道配置更新消息
        CONFIG_UPDATE
        // 客戶端提交的背書提案消息
        ENDORSER_TRANSACTION
        // 排序管理服務內部使用
        ORDERER_TRANSACTION
        // 指示deliver API查找信息
        DELIVER_SEEK_INFO
        // 鏈碼打包安裝消息
        CHAINCODE_PACKAGE
    }
    

      

    // 簽名頭部信息
    signature_header SignatureHeader{
        // 消息的創建者,鏈的證書
        creator bytes
        // 一個隨機數,用於檢測重放攻擊
        nonce bytes
    }
    

      

  2. 配置管理結構

    • 配置設置在創世區塊中,在后續也可以更改配置

    • 配置信息在CONFIGURATION_TRANSACTION的信封消息中,這個信封消息就是基於前文描述的信封消息

    • 配置信息是一個單數的交易,配置信息沒有任何的依賴,包含了全量數據而不是增量數據

    CONFIGURATION_TRANSACTION類型的信封消息的負載部分除了編組的負載,簽名還有ConfigurationEnvelope類型的負載數據

    // 配置信息的消息信封
    message ConfigurationEnvelope{
        // 負載
        payload bytes
        // 簽名
        signature bytes
        // 主要是配置信息的序列號和ID,repeated的意思是這個數據成員可以包含多個
        repeated Item SignedConfigurationItem
    }
    

      

    // 這個結構主要用來關聯與配置信息相關的序列號和ID,序列號遞增,可以防止重放攻擊
    Item SignedConfigurationItem{
        // 這個結構就是用來保存序列號和ID之類的信息
        ConfigurationItem bytes
        // 多個簽名消息
        repeated Signatures Envelope
    }
    

      

    // 配置條目的數據信息保存在這個結構中
    configurationItem ConfigurationItem{
        enum ConfigurationType{
            Policy
            Chain
            Order
            Fabric
        }
        // 鏈的id
        ChainID bytes
        // 上一次配置信息被修改時配置消息信封中的序列號,如果需要修改配置,那么就將這個字段修改為遞增后的序列號
        LastModified uint64
        // 配置消息的類型
        Type ConfigurationType
        // 指向一個已經命名的策略,用來對將來的簽名進行評估,以確定修改是否被授權
        ModificationPolicy string
        // Key和Value分別是配置項及其內容
        Key string
        Value bytes
    }
    

      

    修改配置包含以下內容

    • 檢索現有配置

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

    • 修改所需要的配置項,將每個配置項的LastModified字段設置為遞增后的序列號

    • 更新SignedConfigurationItem中的簽名信息

    • 將簽名后的信封信息提交給排序服務結點

    配置管理員將驗證

    • 所有的配置項和信封都指向了正確的鏈(通過ChainID這個字段)

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

    • 是否有現有的配置項被忽略

    • 所有配置更改的LastModification都等於信封消息中的序列號

    • 所有的更改配置都符合修改策略

    注意:修改配置項將會產生新的創世區塊。

  3. 背書流程結構

    • 客戶端向所有相關的背書結點發送提案消息

    • 每個背書結點向客戶端發送提案響應消息

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

    1. 交易提案結構

      頭部(一些元數據,如類型,調用者的身份,時間,鏈的ID,加密的隨機數)

      不透明負載

      // 包含簽名的提案消息
      signedProposal SignedProposal{
          // 真正的提案,bytes序列化
          proposal_bytes bytes(Proposal)
          // 消息創建者的簽名
          signature bytes
      }
      

        

      // 真正的提案,包含了頭部,負載和可選的擴展三個部分
      proposal Proposal{
          // 提案頭部
          header bytes
          // 提案負載,具體類型由頭部的類型決定
          payload bytes
          // 可選的擴展,對於CHAINCODE類型的消息,其內容可能是ChaincodeAction消息
          extension bytes
      }
      

        

      背書結點驗證從客戶端發送過來的提案消息的簽名

      • 預驗證用戶生成簽名證書的有效性

      • 驗證證書是否可信(證書是否由受信任的CA簽名),並允許交易(能否通過ACL檢查,訪問控制)

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

      • 檢測重放攻擊

      當ChainHeader的類型為ENDORSER_TRANSACTION時。Proposal中的擴展消息如下:

      // 可選的擴展
      extension ChaincodeHeaderExtension{
          // 控制提案的負載在交易和賬本中的可見程度
          // 負載所有字節可見
          // 只有負載的hash值可見
          // 任何東西都不可見
          // 可見性也可以由系統鏈碼ESCC設置,此時本字段的值會被覆蓋掉
          payload_visibility bytes
          // 要定位的鏈碼ID
          chaincode_id ChaincodeID
      }
      

        

      chaincodeProposalPayload ChaincodeProposalPayload{
          // 包含調用的應用鏈碼傳入的參數
          input bytes
          // 實現應用程序級的加密數據,這個字段的值不會記錄到賬本中
          TransientMap map[string]bytes
      }
      

        

      // 本字段包含鏈碼執行所產生的動作和事件
      chaincodeAction ChaincodeAction{
          // 調用鏈碼產生的讀寫集
          results bytes
          // 調用鏈碼產生的事件
          events bytes
          // 調用鏈碼的結果
          response bytes
          // 鏈ID
          chaincode_id ChaincodeID
      }
      

        

    2. 提案響應結構

      提案響應從背書結點返回給客戶端,響應結果可能是提案成功,也可能是失敗,如果足夠多的背書結點都同意這個提案,那么這個提案就可以生成負載消息並且發送給排序服務結點

      // 包含背書結點背書的相關信息的提案響應消息
      proposalResponse ProposalResponse{
          // 消息協議的版本
          version int32
          // 消息創建的時間,由消息發送者(背書結點)定義
          timestamp google.protobuf.Timestamp
          // 某個提案的背書是否成功
          response Response
          // 負載,ProposalResponsePayload的字節序列
          payload bytes
          // 提案的背書內容,基本就是背書結點的簽名
          endorsement Endorsement 
      }
      

        

      // 提案響應的真正負載
      payload ProposalResponsePayload{
          // 觸發此應答交易提案的哈希值
          proposal_hash bytes
          // 擴展內容,被解組為特定類型的消息
          extension bytes
      }
      

        

      proposal_hash字段將交易提案和提案響應對應起來,為異步系統的記賬功能實現了追責和防抵賴

      // 背書結點的背書內容
      endorsement Endorsement{
          // 背書結點的身份(如證書信息)
          endorser bytes
          // 簽名(對提案響應和背書結點證書這兩個內容簽名)
          signature bytes
      }
      

        

    3. 背書交易結構

      客戶端收到足夠多的背書后,將這些背書組合成一個交易信息

      // 一個交易信息
      transaction Transaction{
          // 負載是一個TransactionAction數組,每個交易需要一個數組來適應多個動作
          repeated actions TransactionAction
      }
      

        

      transactionAction TransactionAction{
          // 交易信息頭部
          header bytes
          // 負載,是ChaincodeActionPayload字節序列
          payload bytes
      }
      

        

      chaincodeActionPayload ChaincodeActionPayload{
          // ChaincodeProposalPayload的字節序列,內容來自鏈碼原始調用的參數
          // full--整個ChaincodeProposalPayload消息包含在這里
          // hash--僅包含ChaincodeProposalPayload的hash值
          // nothing
          chaincode_proposal_payload bytes
          // 應用於賬本的動作列表
          action ChaincodeEndorsedAction
      }
      

        

      // 本結構承載有關具體提案的背書信息
      chaincodeProposalPayload ChaincodeProposalPayload{
          // 背書結點簽名的ProposalResponsePayload的字節序列
          proposal_response_payload bytes
          // 提案背書,基本是背書結點自己的簽名,這個字段包含提案已經收到的所有的背書信息
          repeated endorsements Endorsement
      }
      

        

    5、策略管理和訪問控制

    策略管理主要包括交易背書策略,鏈碼的實例化策略,通道管理策略等。

    1. 策略定義及其類型

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

      type Policy struct{
          // 策略的類型,有如下兩種
          // SignaturePolicy:在驗證簽名策略的基礎上,支持AND,OR,NOutOf(NOutOf(n,m)指的是m個條件中滿足n個就返回true)
          // ImplicitMetaPolicy:只適用於通道管理策略,在SignaturePolicy之上的策略
          Type int32
          // 策略的內容
          Value []byte
      }
      

        

      SignaturePolicy實際只有兩種,SignedBy和NOutOf,其他的比如AND和OR都會轉化成NOutOf

      type SignaturePolicy struct{
          // 支持的類型有:
          // *SignaturePolicy_SignedBy    驗證單個簽名是否正確
          // *SignaturePolicy_NOutOf_     驗證是否有n個簽名正確
          Type isSignaturePolicy_Type `protobuf_oneof:"Type"`
      }
      

        

      ImplicitMetaPolicy是遞歸定義的方法,Implict(隱含的)說明規則是由子策略生成的,Meta說明策略依賴其他策略的驗證結果

      type ImplicitMetaPolicy struct{
          // 子策略的名稱
          SubPolicy string
          // 策略的規則,有如下三種形式
          // ImplicitMetaPolicy_ANY:任意一個子規則成立就滿足策略
          // ImplicitMetaPolicy_ALL:所有子規則成立才滿足策略
          // ImplicitMetaPolicy_MAJORITY:大多數子規則成立就滿足策略,計數方法len(subPolicies)/2+1
          Rule ImplicitMetaPolicy_Rule
      }
      

        

    2. 交易背書策略

      交易背書策略是對交易進行背書的規則,在鏈碼實例化的時候指定

      • 交易背書策略的驗證

        背書是由一組簽名組成,每個Peer結點接收到區塊時,都能根據交易的內容本地校驗證書本書是否滿足背書策略,不需要和其他結點交互

        驗證交易背書的基本原則:

        • 所有背書有效

        • 滿足背書策略的有效背書數量(轉化為NOutOf)

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

        NOutOf的實現:

        // 背書策略定義
        type SignaturePolicyEnvelope struct{
            // 背書策略的版本,默認是0
            Version int32
            // 背書策略規則,簽名策略
            Rule *SignaturePolicy
            // 背書策略主體,MSP主體簽名,MSP主體是基於MSP身份標識的,有如下幾種類型
            // MSPPrincipal_ROLE:基於MSP角色驗證,目前只有admin和member兩種
            // MSPPrincipal_ORGANIZATION_UNIT:基於部門的驗證方法,同一個MSP中不同的部門
            // MSPPrincipal_IDENTITY:基於某個具體的身份證書的驗證方法,驗證簽名是否有效
            Identities []*common1.MSPPrincipal
        }
        

          

        MSPPrincipal的定義:

        type MSPPrincipal struct{
            // MSP的類型
            PrincipalClassifiication MSPPrincipal_Classification
            // 根據MSP的類型不同,實體有不同的內容
            Principal []byte
        }
        

          

        • 基於MSP角色的驗證

        // 當PrincipalClassificition是MSPPrincipal_ROLE時,主體存儲的內容如下
        type MSPRole struct{
            // MSP標識符
            MspIdentifier string
            // MSP角色:可選值是MSPRole_MEMBER和MSPRole_ADMIN
            // MSPRole_MEMBER驗證是否為同一個MSP的有效簽名
            // MSPRole_ADMIN驗證簽名者是否是MSP設置好的admin成員
            Role MSPRole_MSPRoleType
        }
        

          

      • 基於部門的驗證

        // 當PrincipalClassificition是MSPPrincipal_ORGANIZATION_UNIT時,主體存儲的內容如下
        // 驗證過程為:
        // 驗證是否為相同的MSP
        // 驗證是否是有效的證書
        // 驗證組織部門信息是否匹配
        type OrganizationUnit struct{
            // MSP標識符
            MspIdentifier string
            // 組織部門標識符
            OrganizationalUnitIdentifier string
            // 證書標識符:信任證書鏈和組織部門信息的哈希
            CertifiersIdentifier []byte
        }
        

          

      • 基於身份證書的驗證

        // 當PrincipalClassificition是MSPPrincipal_IDENTITY時,主體存儲的內容如下
        type identity struct{
            // 身份標識符,包含MSP標識符和身份編號
            id *IdentityIdentifier
            // 身份的數字證書,包含了對公鑰的簽名
            cert *x59.Certtificate
            // 身份的公鑰
            pk bccsp.Key
            // 身份的msp信息
            msp *bccspmsp
        }
        

          

    3. 鏈碼的實例化策略

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

      // 鏈碼的實例化策略是直接從鏈碼打包中獲取的,實例化完成后會將策略存放在鏈上
      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(指紋)標識,未使用
          Id []byte
          // 鏈碼實例化策略
          InstantiationPolicy []byte
      }
      

        

    4. 通道管理策略

      通道配置是遞歸定義的

      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
          // 配置數據,可以是json結構
          Value []byte
          // 配置修改策略的名稱
          ModPolicy string
      }
      

        

      配置策略的定義:

      // 基於SignaturePolicy和ImplicitMetaPolicy,ModPolicy代表的是修改統計策略用到的策略名稱
      type ConfigPolicy struct{
          // 配置策略的版本
          Version uint64
          // 配置策略的內容,前面有
          Policy *Policy
          // 配置策略中修改策略的定義
          ModPolicy string
      }
      

        

      通道設置了三種配置策略

      策略名稱 策略含義 策略說明
      Readers 通道讀權限 任何讀取通道交易的權限控制策略
      Writers 通道寫權限 任何向通道提交交易的權限控制策略
      Admins 通道管理權限 任何修改通道配置的權限管理策略

       


免責聲明!

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



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