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流程如下:

    1. ProposalsSDK/CLI向Peer节点发起提案,设置背书策略
    2. Execute:Peer执行合约
    3. ProposalRespond【Endorsed】:Peer对执行结果进行签名,向SDK/CLI返回背书结果
    4. BroadcastSDK/CLI整理背书结果,向Orderer广播背书结果
    5. Orderer:Orderer节点对交易排序,然后打包出块
    6. Deliver:Orderer节点将区块发送给Peer节点
    7. Validate & Commit:Peer节点验证和确认
    8. 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
posted @ 2020-10-30 10:24  水中墨色  阅读(894)  评论(1编辑  收藏  举报