Fabric 2.2底层结构设计分析
Fabric的底层定义项目:hyperledger/fabric-protos-go
一、Block类型分析
Block定义
- Block
type Block struct {
Header *BlockHeader `protobuf:"bytes,1,opt,name=header,proto3" json:"header,omitempty"`
Data *BlockData `protobuf:"bytes,2,opt,name=data,proto3" json:"data,omitempty"`
Metadata *BlockMetadata `protobuf:"bytes,3,opt,name=metadata,proto3" json:"metadata,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
- BlockHeader
type BlockHeader struct {
Number uint64 `protobuf:"varint,1,opt,name=number,proto3" json:"number,omitempty"`
PreviousHash []byte `protobuf:"bytes,2,opt,name=previous_hash,json=previousHash,proto3" json:"previous_hash,omitempty"`
DataHash []byte `protobuf:"bytes,3,opt,name=data_hash,json=dataHash,proto3" json:"data_hash,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
- BlockData
type BlockData struct {
Data [][]byte `protobuf:"bytes,1,rep,name=data,proto3" json:"data,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
- BlockMetaData
type BlockMetadata struct {
Metadata [][]byte `protobuf:"bytes,1,rep,name=metadata,proto3" json:"metadata,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
具体关系参考如下Channel的Genesis Block生成过程
// Block constructs and returns a genesis block for a given channel ID.
func (f *factory) Block(channelID string) *cb.Block {
payloadChannelHeader := protoutil.MakeChannelHeader(cb.HeaderType_CONFIG, msgVersion, channelID, epoch)
payloadSignatureHeader := protoutil.MakeSignatureHeader(nil, protoutil.CreateNonceOrPanic())
protoutil.SetTxID(payloadChannelHeader, payloadSignatureHeader)
payloadHeader := protoutil.MakePayloadHeader(payloadChannelHeader, payloadSignatureHeader)
payload := &cb.Payload{Header: payloadHeader, Data: protoutil.MarshalOrPanic(&cb.ConfigEnvelope{Config: &cb.Config{ChannelGroup: f.channelGroup}})}
envelope := &cb.Envelope{Payload: protoutil.MarshalOrPanic(payload), Signature: nil}
block := protoutil.NewBlock(0, nil)
block.Data = &cb.BlockData{Data: [][]byte{protoutil.MarshalOrPanic(envelope)}}
block.Header.DataHash = protoutil.BlockDataHash(block.Data)
block.Metadata.Metadata[cb.BlockMetadataIndex_LAST_CONFIG] = protoutil.MarshalOrPanic(&cb.Metadata{
Value: protoutil.MarshalOrPanic(&cb.LastConfig{Index: 0}),
})
block.Metadata.Metadata[cb.BlockMetadataIndex_SIGNATURES] = protoutil.MarshalOrPanic(&cb.Metadata{
Value: protoutil.MarshalOrPanic(&cb.OrdererBlockMetadata{
LastConfig: &cb.LastConfig{Index: 0},
}),
})
return block
}
Block类型关系图
二、交易结构定义分析
交易类型分类
HeaderType_MESSAGE HeaderType = 0
// channel配置交易
HeaderType_CONFIG HeaderType = 1
//
HeaderType_CONFIG_UPDATE HeaderType = 2
// 链码交易
HeaderType_ENDORSER_TRANSACTION HeaderType = 3
//
HeaderType_ORDERER_TRANSACTION HeaderType = 4
HeaderType_DELIVER_SEEK_INFO HeaderType = 5
HeaderType_CHAINCODE_PACKAGE HeaderType = 6
交易类型说明
1. HeaderType_MESSAGE
对应的交易类型
hyperledger/fabric-protos-go/common/configtx.pb.go
type ConfigValue struct {
Version uint64 `protobuf:"varint,1,opt,name=version,proto3" json:"version,omitempty"`
Value []byte `protobuf:"bytes,2,opt,name=value,proto3" json:"value,omitempty"`
ModPolicy string `protobuf:"bytes,3,opt,name=mod_policy,json=modPolicy,proto3" json:"mod_policy,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
2. HeaderType_CONFIG
对应的交易类型
hyperledger/fabric-protos-go/common/configtx.pb.go
type ConfigEnvelope struct {
Config *Config `protobuf:"bytes,1,opt,name=config,proto3" json:"config,omitempty"`
LastUpdate *Envelope `protobuf:"bytes,2,opt,name=last_update,json=lastUpdate,proto3" json:"last_update,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
3. HeaderType_CONFIG_UPDATE
对应的交易类型
hyperledger/fabric-protos-go/common/configtx.pb.go
type ConfigUpdateEnvelope struct {
ConfigUpdate []byte `protobuf:"bytes,1,opt,name=config_update,json=configUpdate,proto3" json:"config_update,omitempty"`
Signatures []*ConfigSignature `protobuf:"bytes,2,rep,name=signatures,proto3" json:"signatures,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
4. HeaderType_ENDORSER_TRANSACTION
对应的交易类型
hyperledger/fabric-protos-go/peer/transaction.pb.go
type Transaction struct {
// The payload is an array of TransactionAction. An array is necessary to
// accommodate multiple actions per transaction
Actions []*TransactionAction `protobuf:"bytes,1,rep,name=actions,proto3" json:"actions,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
5. HeaderType_ORDERER_TRANSACTION
对应的交易类型
hyperledger/fabric-protos-go/common/common.pb.go
type Envelope struct {
// A marshaled Payload
Payload []byte `protobuf:"bytes,1,opt,name=payload,proto3" json:"payload,omitempty"`
// A signature by the creator specified in the Payload header
Signature []byte `protobuf:"bytes,2,opt,name=signature,proto3" json:"signature,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
6. HeaderType_DELIVER_SEEK_INFO
对应的交易类型
hyperledger/fabric-protos-go/orderer/ab.pb.go
type SeekInfo struct {
Start *SeekPosition `protobuf:"bytes,1,opt,name=start,proto3" json:"start,omitempty"`
Stop *SeekPosition `protobuf:"bytes,2,opt,name=stop,proto3" json:"stop,omitempty"`
Behavior SeekInfo_SeekBehavior `protobuf:"varint,3,opt,name=behavior,proto3,enum=orderer.SeekInfo_SeekBehavior" json:"behavior,omitempty"`
ErrorResponse SeekInfo_SeekErrorResponse `protobuf:"varint,4,opt,name=error_response,json=errorResponse,proto3,enum=orderer.SeekInfo_SeekErrorResponse" json:"error_response,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
7. HeaderType_CHAINCODE_PACKAGE
对应的交易类型
在源码中未看到使用情况
交易类型关系图
三、链码相关
1. 支持的链码开发语言类型
hyperledger/fabric-protos-go/peer/chaincode.pb.go
ChaincodeSpec_UNDEFINED ChaincodeSpec_Type = 0
ChaincodeSpec_GOLANG ChaincodeSpec_Type = 1
ChaincodeSpec_NODE ChaincodeSpec_Type = 2
ChaincodeSpec_CAR ChaincodeSpec_Type = 3
ChaincodeSpec_JAVA ChaincodeSpec_Type = 4
2. 链码交易定义
type ChaincodeSpec struct {
Type ChaincodeSpec_Type `protobuf:"varint,1,opt,name=type,proto3,enum=protos.ChaincodeSpec_Type" json:"type,omitempty"`
ChaincodeId *ChaincodeID `protobuf:"bytes,2,opt,name=chaincode_id,json=chaincodeId,proto3" json:"chaincode_id,omitempty"`
Input *ChaincodeInput `protobuf:"bytes,3,opt,name=input,proto3" json:"input,omitempty"`
Timeout int32 `protobuf:"varint,4,opt,name=timeout,proto3" json:"timeout,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
type ChaincodeID struct {
//deploy transaction will use the path
Path string `protobuf:"bytes,1,opt,name=path,proto3" json:"path,omitempty"`
//all other requests will use the name (really a hashcode) generated by
//the deploy transaction
Name string `protobuf:"bytes,2,opt,name=name,proto3" json:"name,omitempty"`
//user friendly version name for the chaincode
Version string `protobuf:"bytes,3,opt,name=version,proto3" json:"version,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
type ChaincodeInput struct {
Args [][]byte `protobuf:"bytes,1,rep,name=args,proto3" json:"args,omitempty"`
Decorations map[string][]byte `protobuf:"bytes,2,rep,name=decorations,proto3" json:"decorations,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"`
// is_init is used for the application to signal that an invocation is to be routed
// to the legacy 'Init' function for compatibility with chaincodes which handled
// Init in the old way. New applications should manage their initialized state
// themselves.
IsInit bool `protobuf:"varint,3,opt,name=is_init,json=isInit,proto3" json:"is_init,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
3. 链码的安装过程
-
Fabric经典的
lifecycle
流程如下:- Proposals:SDK/CLI向Peer节点发起提案,设置背书策略
- Execute:Peer执行合约
- ProposalRespond【Endorsed】:Peer对执行结果进行签名,向SDK/CLI返回背书结果
- Broadcast:SDK/CLI整理背书结果,向Orderer广播背书结果
- Orderer:Orderer节点对交易排序,然后打包出块
- Deliver:Orderer节点将区块发送给Peer节点
- Validate & Commit:Peer节点验证和确认
- Notify:Peer节点将验证结果返回给SDK/CLI
-
CLI对应lifecycle安装流程如下:
package
->install package
->queryinstalled
->approveformyorg
->checkcommitreadiness
(检查智能合约是否就绪,需要背书策略中的大部分组织同意) ->commit
->querycommitted
->done
approveformyorg
(组织认可智能合约定义)创建的是CommitChaincodeDefinition proposal
交易commit
(提交智能合约定义)创建的是ApproveChaincodeDefinitionForMyOrg proposal
交易
参考:Fabric test-network搭建[solo-1orderer-2peer]
- 链码过程的request的实现代码位置(SDK)
hyperledger/fabric-sdk-go/pkg/resource/lifecycle.go