兄弟连区块链技术培训Fabric 1.0源代码分析(25) Orderer

合集下载

兄弟连区块链技术培训Fabric 1.0源代码分析(6)configtx(配置交易) ChannelConfig(通道配置)

兄弟连区块链技术培训Fabric 1.0源代码分析(6)configtx(配置交易) ChannelConfig(通道配置)

兄弟连区块链技术培训Fabric 1.0源代码分析(6)configtx (配置交易)ChannelConfig(通道配置)# Fabric 1.0源代码笔记之 configtx(配置交易) #ChannelConfig(通道配置)## 1、ChannelConfig概述ChannelConfig代码分布在common/config目录下。

目录结构如下:* channel_util.go,channel相关工具函数。

* orderer_util.go,orderer(系统通道)相关工具函数。

* application_util.go,应用通道相关工具函数。

* consortiums_util.go,联盟相关工具函数。

* api.go,核心接口定义,如Org、ApplicationOrg、Channel、Orderer、Applicati on、Consortium、Consortiums、ValueProposer接口定义。

* root.go,Root结构体及方法。

* channel.go,ChannelGroup结构体及方法。

* orderer.go,OrdererGroup结构体及方法。

* application.go,ApplicationGroup结构体及方法。

## 2、工具函数### 2.1、channel相关工具函数```go//用key和value构建cb.ConfigGroupfunc configGroup(key string, value []byte) *cb.ConfigGroup {result := cb.NewConfigGroup()result.Values[key] = &cb.ConfigValue{Value: value,}}//设置联盟//ConsortiumKey = "Consortium"//configGroup(ConsortiumKey, utils.MarshalOrPanic(&cb.Consortium{Name: name}))func TemplateConsortium(name string) *cb.ConfigGroup//设置哈希函数//HashingAlgorithmKey = "HashingAlgorithm"//configGroup(HashingAlgorithmKey, utils.MarshalOrPanic(&cb.HashingAlgo rithm{Name: name}))func TemplateHashingAlgorithm(name string) *cb.ConfigGroup//默认哈希函数//const defaultHashingAlgorithm = bccsp.SHA256//TemplateHashingAlgorithm(defaultHashingAlgorithm)func DefaultHashingAlgorithm() *cb.ConfigGroup//设置块数据哈希结构//BlockDataHashingStructureKey = "BlockDataHashingStructure"//configGroup(BlockDataHashingStructureKey, utils.MarshalOrPanic(&cb.Bl ockDataHashingStructure{Width: width}))func TemplateBlockDataHashingStructure(width uint32) *cb.ConfigGroup//默认块数据哈希结构//const defaultBlockDataHashingStructureWidth = math.MaxUint32//TemplateBlockDataHashingStructure(defaultBlockDataHashingStructureWid th)func DefaultBlockDataHashingStructure() *cb.ConfigGroup//设置Orderer地址//OrdererAddressesKey = "OrdererAddresses"//configGroup(OrdererAddressesKey, utils.MarshalOrPanic(&cb.OrdererAddr esses{Addresses: addresses}))func TemplateOrdererAddresses(addresses []string) *cb.ConfigGroup//默认Orderer地址//var defaultOrdererAddresses = []string{"127.0.0.1:7050"}//TemplateOrdererAddresses(defaultOrdererAddresses)func DefaultOrdererAddresses() *cb.ConfigGroup//代码在common/config/channel_util.go```补充cb.ConfigGroup定义:```gotype ConfigGroup struct {Version uint64Groups map[string]*ConfigGroupValues map[string]*ConfigValuePolicies map[string]*ConfigPolicyModPolicy string}//代码在protos/common/configtx.pb.go```### 2.2、orderer相关工具函数```gofunc ordererConfigGroup(key string, value []byte) *cb.ConfigGroupfunc TemplateConsensusType(typeValue string) *cb.ConfigGroupfunc TemplateBatchSize(batchSize *ab.BatchSize) *cb.ConfigGroupfunc TemplateBatchTimeout(batchTimeout string) *cb.ConfigGroupfunc TemplateChannelRestrictions(maxChannels uint64) *cb.ConfigGroup func TemplateKafkaBrokers(brokers []string) *cb.ConfigGroup//代码在common/config/orderer_util.go```### 2.3、应用通道相关工具函数```gofunc applicationConfigGroup(orgID string, key string, value []byte) *cb. ConfigGroupfunc TemplateAnchorPeers(orgID string, anchorPeers []*pb.AnchorPeer) *c b.ConfigGroup//代码在common/config/application_util.go```### 2.4、联盟相关工具函数```gofunc TemplateConsortiumsGroup() *cb.ConfigGroupfunc TemplateConsortiumChannelCreationPolicy(name string, policy *cb.Po licy) *cb.ConfigGroup//代码在common/config/consortiums_util.go```## 3、核心接口定义```gotype Org interface { //组织接口Name() string //组织名称MSPID() string //组织MSPID}type ApplicationOrg interface { //应用组织接口Org //嵌入OrgAnchorPeers() []*pb.AnchorPeer //锚节点}type Channel interface { //通道配置接口HashingAlgorithm() func(input []byte) []byte //哈希算法BlockDataHashingStructureWidth() uint32 //指定计算 BlockDataHash 时使用的 Merkle 树的宽度OrdererAddresses() []string //Orderer地址}type Application interface { //应用配置接口Organizations() map[string]ApplicationOrg //应用组织map}type Consortiums interface { //联盟配置map接口Consortiums() map[string]Consortium //Consortium map}type Consortium interface { //联盟配置接口ChannelCreationPolicy() *cb.Policy //通道创建策略}type Orderer interface { //Orderer配置接口ConsensusType() string //共识类型BatchSize() *ab.BatchSize //块中的最大消息数BatchTimeout() time.Duration //创建批处理之前等待的时间量MaxChannelsCount() uint64 //最大通道数KafkaBrokers() []string //Kafka地址Organizations() map[string]Org //Orderer组织}type ValueProposer interface {BeginValueProposals(tx interface{}, groups []string) (ValueDeserial izer, []ValueProposer, error) //配置Proposal前RollbackProposals(tx interface{}) //回滚配置ProposalPreCommit(tx interface{}) error //提交前CommitProposals(tx interface{}) //提交}//代码在common/config/api.go```## 4、Root结构体及方法```gotype Root struct {channel *ChannelGroupmspConfigHandler *msp.MSPConfigHandler}func NewRoot(mspConfigHandler *msp.MSPConfigHandler) *Root //构造Root //启动新的配置Proposal,r.mspConfigHandler.BeginConfig(tx)func (r *Root) BeginValueProposals(tx interface{}, groups []string) (Va lueDeserializer, []ValueProposer, error)//回滚配置Proposal,r.mspConfigHandler.RollbackProposals(tx)func (r *Root) RollbackProposals(tx interface{})//提交前校验配置,r.mspConfigHandler.PreCommit(tx)func (r *Root) PreCommit(tx interface{}) error//提交配置Proposal,mitProposals(tx)func (r *Root) CommitProposals(tx interface{})//获取r.channelfunc (r *Root) Channel() *ChannelGroup//获取r.channel.OrdererConfig()func (r *Root) Orderer() *OrdererGroup//获取r.channel.ApplicationConfig()func (r *Root) Application() *ApplicationGroup//获取r.channel.ConsortiumsConfig()func (r *Root) Consortiums() *ConsortiumsGroup {//代码在common/config/root.go```## 5、ChannelGroup结构体及方法### 5.1、ChannelGroup结构体及方法```gotype ChannelGroup struct {*ChannelConfig //嵌入ChannelConfig*Proposer //嵌入ProposermspConfigHandler *msp.MSPConfigHandler}type ChannelConfig struct {*standardValuesprotos *ChannelProtoshashingAlgorithm func(input []byte) []byteappConfig *ApplicationGroupordererConfig *OrdererGroupconsortiumsConfig *ConsortiumsGroup}type ChannelProtos struct {HashingAlgorithm *cb.HashingAlgorithmBlockDataHashingStructure *cb.BlockDataHashingStructureOrdererAddresses *cb.OrdererAddressesConsortium *cb.Consortium}构造ChannelGroup,以及构造ChannelConfig和Proposerfunc NewChannelGroup(mspConfigHandler *msp.MSPConfigHandler) *ChannelGr oupfunc (cg *ChannelGroup) Allocate() Values //构造channelConfigSetter//获取cg.ChannelConfig.ordererConfigfunc (cg *ChannelGroup) OrdererConfig() *OrdererGroup//获取cg.ChannelConfig.appConfigfunc (cg *ChannelGroup) ApplicationConfig() *ApplicationGroup//获取cg.ChannelConfig.consortiumsConfigfunc (cg *ChannelGroup) ConsortiumsConfig() *ConsortiumsGroupfunc (cg *ChannelGroup) NewGroup(group string) (ValueProposer, error)//构造ChannelConfig,NewStandardValues(cc.protos)func NewChannelConfig() *ChannelConfig//获取cc.hashingAlgorithmfunc (cc *ChannelConfig) HashingAlgorithm() func(input []byte) []byte //获取cc.protos.BlockDataHashingStructure.Widthfunc (cc *ChannelConfig) BlockDataHashingStructureWidth() uint32//获取cc.protos.OrdererAddresses.Addressesfunc (cc *ChannelConfig) OrdererAddresses() []string//获取func (cc *ChannelConfig) ConsortiumName() stringfunc (cc *ChannelConfig) Validate(tx interface{}, groups map[string]Val ueProposer) errorfunc (cc *ChannelConfig) validateHashingAlgorithm() errorfunc (cc *ChannelConfig) validateBlockDataHashingStructure() error func (cc *ChannelConfig) validateOrdererAddresses() error//代码在common/config/channel.go```补充cb.HashingAlgorithm、cb.BlockDataHashingStructure、cb.OrdererAddress es、cb.Consortium定义:```go//哈希算法type HashingAlgorithm struct {Name string}//块数据哈希结构type BlockDataHashingStructure struct {Width uint32 //指定计算 BlockDataHash 时使用的 Merkle 树的宽度}//Orderer地址type OrdererAddresses struct {Addresses []string}type Consortium struct {Name string}//代码在protos/common/configuration.pb.go```### 5.2、Proposer结构体及方法```gotype Proposer struct {vh Handlerpending map[interface{}]*configcurrent *configpendingLock sync.RWMutex}func NewProposer(vh Handler) *Proposerfunc (p *Proposer) BeginValueProposals(tx interface{}, groups []string) (ValueDeserializer, []ValueProposer, error)func (p *Proposer) PreCommit(tx interface{}) errorfunc (p *Proposer) RollbackProposals(tx interface{})func (p *Proposer) CommitProposals(tx interface{})//代码在common/config/proposer.go```### 5.3、OrdererGroup结构体及方法```gotype OrdererGroup struct {*Proposer*OrdererConfigmspConfig *msp.MSPConfigHandler}type OrdererConfig struct {*standardValuesprotos *OrdererProtosordererGroup *OrdererGrouporgs map[string]OrgbatchTimeout time.Duration}type OrdererProtos struct {ConsensusType *ab.ConsensusTypeBatchSize *ab.BatchSizeBatchTimeout *ab.BatchTimeoutKafkaBrokers *ab.KafkaBrokersChannelRestrictions *ab.ChannelRestrictions}//构造OrdererGroup,以及Proposerfunc NewOrdererGroup(mspConfig *msp.MSPConfigHandler) *OrdererGroup func (og *OrdererGroup) NewGroup(name string) (ValueProposer, error) func (og *OrdererGroup) Allocate() Values//构造OrdererConfigfunc NewOrdererConfig(og *OrdererGroup) *OrdererConfig//oc.ordererGroup.OrdererConfig = ocfunc (oc *OrdererConfig) Commit()//获取oc.protos.ConsensusType.Typefunc (oc *OrdererConfig) ConsensusType() string//获取oc.protos.BatchSizefunc (oc *OrdererConfig) BatchSize() *ab.BatchSize//获取oc.batchTimeoutfunc (oc *OrdererConfig) BatchTimeout() time.Duration//获取oc.protos.KafkaBrokers.Brokersfunc (oc *OrdererConfig) KafkaBrokers() []string//获取oc.protos.ChannelRestrictions.MaxCountfunc (oc *OrdererConfig) MaxChannelsCount() uint64//获取sfunc (oc *OrdererConfig) Organizations() map[string]Orgfunc (oc *OrdererConfig) Validate(tx interface{}, groups map[string]Val ueProposer) errorfunc (oc *OrdererConfig) validateConsensusType() errorfunc (oc *OrdererConfig) validateBatchSize() errorfunc (oc *OrdererConfig) validateBatchTimeout() errorfunc (oc *OrdererConfig) validateKafkaBrokers() errorfunc brokerEntrySeemsValid(broker string) bool//代码在common/config/orderer.go```### 5.4、ApplicationGroup结构体及方法```go//代码在common/config/application.go```。

兄弟连区块链教程Fabric1.0源代码分析Peer EndorserClient(Endorser客户端)

兄弟连区块链教程Fabric1.0源代码分析Peer EndorserClient(Endorser客户端)

兄弟连区块链教程Fabric1.0源代码分析Peer EndorserClient(Endorser客户端)兄弟连区块链教程Fabric1.0源代码分析Peer EndorserClient(Endorser客户端),2018年下半年,区块链行业正逐渐褪去发展之初的浮躁、回归理性,表面上看相关人才需求与身价似乎正在回落。

但事实上,正是初期泡沫的渐退,让人们更多的关注点放在了区块链真正的技术之上。

# Fabric 1.0源代码笔记之 Peer #EndorserClient(Endorser客户端)## 1、EndorserClient概述EndorserClient相关代码分布如下:* protos/peer/peer.pb.go,EndorserClient接口及实现。

* peer/common/common.go,EndorserClient相关工具函数。

## 2、EndorserClient接口定义```gotype EndorserClient interface {//处理ProposalProcessProposal(ctx context.Context, in *SignedProposal,opts ...grpc.CallOption) (*ProposalResponse, error)}//代码在protos/peer/peer.pb.go```## 3、EndorserClient接口实现EndorserClient接口实现,即endorserClient结构体及方法。

```gotype endorserClient struct {cc *grpc.ClientConn}func NewEndorserClient(cc *grpc.ClientConn) EndorserClient {return &endorserClient{cc}}func (c *endorserClient) ProcessProposal(ctx context.Context, in*SignedProposal, opts ...grpc.CallOption) (*ProposalResponse, error) { out := new(ProposalResponse)err := grpc.Invoke(ctx, "/protos.Endorser/ProcessProposal", in, out, , opts...)return out, nil}//代码在protos/peer/peer.pb.go```## 4、EndorserClient工具函数```go//获取Endorser客户端func GetEndorserClient() (pb.EndorserClient, error) { clientConn, err := peer.NewPeerClientConnection() endorserClient := pb.NewEndorserClient(clientConn) return endorserClient, nil}//代码在peer/common/common.go```感谢关注兄弟连区块链教程分享!。

兄弟连区块链技术培训Fabric 1.0源代码分析(2) blockfile(区块文件存储)

兄弟连区块链技术培训Fabric 1.0源代码分析(2) blockfile(区块文件存储)

兄弟连区块链技术培训Fabric 1.0源代码分析(2) blockfile (区块文件存储)# Fabric 1.0源代码笔记之 blockfile(区块文件存储)## 1、blockfile概述blockfile,即Fabric区块链区块文件存储,默认目录/var/hyperledger/production /ledgersData/chains,含index和chains两个子目录。

其中index为索引目录,采用leveldb实现。

而chains为各ledger的区块链文件,子目录以ledgerid为名,使用文件系统实现。

区块文件以blockfile_为前缀,最大大小默认64M。

blockfile,相关代码集中在common/ledger/blkstorage/fsblkstorage目录,目录结构如下:* blockfile_mgr.go,blockfileMgr和checkpointInfo结构体及方法。

* block_stream.go,blockfileStream、blockStream、blockPlacementInfo结构体及方法。

* blockfile_rw.go,blockfileWriter和blockfileReader结构体及方法(blockfi leReader未使用)。

* blockindex.go,index接口定义,index接口实现即blockIndex结构体及方法定义,以及blockIdxInfo、locPointer、fileLocPointer结构体及方法。

* blockfile_helper.go,定义了4个工具函数,constructCheckpointInfoFromBloc kFiles、retrieveLastFileSuffix、isBlockFileName、getFileInfoOrPanic。

作用分别为:扫描最新的blockfile并重新构造检查点信息、获取最新的文件后缀、根据文件前缀判断是否为区块文件、获取文件状态信息。

Fabric1.0源代码分析PeerBroadcastClient(Broadcast客户端)

Fabric1.0源代码分析PeerBroadcastClient(Broadcast客户端)

兄弟连区块链教程Fabric1.0源代码分析PeerBroadcastClient(Broadcast客户端)兄弟连区块链教程Fabric1.0源代码分析PeerBroadcastClient(Broadcast客户端),2018年下半年,区块链行业正逐渐褪去发展之初的浮躁、回归理性,表面上看相关人才需求与身价似乎正在回落。

但事实上,正是初期泡沫的渐退,让人们更多的关注点放在了区块链真正的技术之上。

# Fabric1.0源代码笔记之Peer DeliverClient(Deliver客户端)## 1、DeliverClient概述DeliverClient代码分布如下:* peer/channel/deliverclient.go,deliverClientIntf接口定义及实现,以及DeliverClient工具函数。

* protos/orderer/ab.pb.go,AtomicBroadcast_DeliverClient接口定义和实现。

## 2、deliverClientIntf接口定义及实现### 2.1、DeliverClient工具函数```go//构造deliverClientfunc newDeliverClient(conn *grpc.ClientConn, clientab.AtomicBroadcast_DeliverClient, chainID string) *deliverClient//代码在peer/channel/deliverclient.go```### 2.2、deliverClientIntf接口定义及实现```gotype deliverClientIntf interface {getSpecifiedBlock(num uint64) (*common.Block, error)getOldestBlock() (*common.Block, error)getNewestBlock() (*common.Block, error)Close() error}type deliverClient struct {conn *grpc.ClientConnclient ab.AtomicBroadcast_DeliverClientchainID string}//构造查询Envelopefunc seekHelper(chainID string, position *ab.SeekPosition)*common.Envelope//r.client.Send(seekHelper(r.chainID, &ab.SeekPosition{Type:&ab.SeekPosition_Specified{Specified: &ab.SeekSpecified{Number: blockNumber}}}))func (r *deliverClient) seekSpecified(blockNumber uint64) error//r.client.Send(seekHelper(r.chainID, &ab.SeekPosition{Type:&ab.SeekPosition_Oldest{Oldest: &ab.SeekOldest{}}}))func (r *deliverClient) seekOldest() error//return r.client.Send(seekHelper(r.chainID, &ab.SeekPosition{Type: &ab.SeekPosition_Newest{Newest: &ab.SeekNewest{}}}))func (r *deliverClient) seekNewest() error//r.client.Recv()读取块func (r *deliverClient) readBlock() (*common.Block, error)//r.seekSpecified(num)和r.readBlock()func (r *deliverClient) getSpecifiedBlock(num uint64) (*common.Block, error)//r.seekOldest()和r.readBlock()func (r *deliverClient) getOldestBlock() (*common.Block, error)//r.seekNewest()和r.readBlock()func (r *deliverClient) getNewestBlock() (*common.Block, error)//r.conn.Close()func (r *deliverClient) Close() error//cf.DeliverClient.getSpecifiedBlock(0)获取创世区块func getGenesisBlock(cf *ChannelCmdFactory) (*common.Block, error)//代码在peer/channel/deliverclient.go```func seekHelper(chainID string, position *ab.SeekPosition)*common.Envelope代码如下:```gofunc seekHelper(chainID string, position *ab.SeekPosition)*common.Envelope {seekInfo := &ab.SeekInfo{Start: position,Stop: position,Behavior: ab.SeekInfo_BLOCK_UNTIL_READY,}msgVersion := int32(0)epoch := uint64(0)env, err :=utils.CreateSignedEnvelope(common.HeaderType_CONFIG_UPDATE, chainID, localmsp.NewSigner(), seekInfo, msgVersion, epoch)return env}//代码在peer/channel/deliverclient.go```感谢关注兄弟连区块链教程分享!。

兄弟连区块链教程Fabric1.0源代码分析Peer peer node start命令实现

兄弟连区块链教程Fabric1.0源代码分析Peer peer node start命令实现

兄弟连区块链教程Fabric1.0源代码分析Peer peer node start命令实现兄弟连区块链教程Fabric1.0源代码分析Peer peer node start命令实现,2018年下半年,区块链行业正逐渐褪去发展之初的浮躁、回归理性,表面上看相关人才需求与身价似乎正在回落。

但事实上,正是初期泡沫的渐退,让人们更多的关注点放在了区块链真正的技术之上。

# Fabric 1.0源代码笔记之 Peer #peer node start命令实现有个图2## 1、peer node加载子命令start和statuspeer node加载子命令start和status,代码如下:```gofunc Cmd() *mand {nodeCmd.AddCommand(startCmd()) //加载子命令startnodeCmd.AddCommand(statusCmd()) //加载子命令statusreturn nodeCmd}var nodeCmd = &mand{Use: nodeFuncName,Short: fmt.Sprint(shortDes),Long: fmt.Sprint(longDes),}//代码在peer/node/node.go```startCmd()代码如下:其中serve(args)为peer node start的实现代码,比较复杂,本文将重点讲解。

另statusCmd()代码与startCmd()相近,暂略。

```gofunc startCmd() *mand {flags := nodeStartCmd.Flags()flags.BoolVarP(&chaincodeDevMode, "peer-chaincodedev", "", false, "Whether peer in chaincode development mode")flags.BoolVarP(&peerDefaultChain, "peer-defaultchain", "", false, "Whether to start peer with chain testchainid")flags.StringVarP(&orderingEndpoint, "orderer", "o", "orderer:7050", "Ordering service endpoint") //ordererreturn nodeStartCmd}var nodeStartCmd = &mand{Use: "start",Short: "Starts the node.",Long: `Starts a node that interacts with the network.`,RunE: func(cmd *mand, args []string) error {return serve(args) //serve(args)为peer node start的实现代码},}//代码在peer/node/start.go```**注:如下内容均为serve(args)的代码,即peer node start命令执行流程。

兄弟连区块链教程Fabric1.0源代码分析Peer peer根命令入口及加载子命令

兄弟连区块链教程Fabric1.0源代码分析Peer peer根命令入口及加载子命令

兄弟连区块链教程Fabric1.0源代码分析Peer peer根命令入口及加载子命令一兄弟连区块链教程Fabric1.0源代码分析Peer peer根命令入口及加载子命令,2018年下半年,区块链行业正逐渐褪去发展之初的浮躁、回归理性,表面上看相关人才需求与身价似乎正在回落。

但事实上,正是初期泡沫的渐退,让人们更多的关注点放在了区块链真正的技术之上。

# Fabric 1.0源代码笔记之 Peer #peer根命令入口及加载子命令## 1、加载环境变量配置和配置文件Fabric支持通过环境变量对部分配置进行更新,如:CORE_LOGGING_LEVEL为输出的日志级别、CORE_PEER_ID为Peer的ID等。

此部分功能由第三方包viper来实现,viper除支持环境变量的配置方式外,还支持配置文件方式。

viper使用方法参考:https:///spf13/viper。

如下代码为加载环境变量配置,其中cmdRoot为"core",即CORE_开头的环境变量。

```goviper.SetEnvPrefix(cmdRoot)viper.AutomaticEnv()replacer := strings.NewReplacer(".", "_")viper.SetEnvKeyReplacer(replacer)//代码在peer/main.go```加载配置文件,同样由第三方包viper来实现,具体代码如下:其中cmdRoot为"core",即/etc/hyperledger/fabric/core.yaml。

```goerr := common.InitConfig(cmdRoot)//代码在peer/main.go```如下代码为common.InitConfig(cmdRoot)的具体实现:```goconfig.InitViper(nil, cmdRoot)err := viper.ReadInConfig()//代码在peer/common/common.go```另附config.InitViper(nil, cmdRoot)的代码实现:优先从环境变量FABRIC_CFG_PATH中获取配置文件路径,其次为当前目录、开发环境目录(即:src//hyperledger/fabric/sampleconfig)、和OfficialPath(即:/etc/hyperledger/fabric)。

兄弟连区块链教程Fabric1.0源代码分析consenter#filter

兄弟连区块链教程Fabric1.0源代码分析consenter#filter

兄弟连区块链教程Fabric1.0源代码分析consenter#filter兄弟连区块链教程Fabric1.0源代码分析consenter(共识插件)#filter(过滤器),2018年下半年,区块链行业正逐渐褪去发展之初的浮躁、回归理性,表面上看相关人才需求与身价似乎正在回落。

但事实上,正是初期泡沫的渐退,让人们更多的关注点放在了区块链真正的技术之上。

# Fabric 1.0源代码笔记之 consenter(共识插件) #filter(过滤器)## 1、filter概述filter代码分布在orderer/common/filter、orderer/common/configtxfilter、orderer/common/sizefilter、orderer/common/sigfilter、orderer/multichain目录下。

orderer/common/filter/filter.go,Rule接口定义及emptyRejectRule和acceptRule实现,Committer接口定义及noopCommitter实现,RuleSet结构体及方法。

orderer/common/configtxfilter目录,configFilter结构体(实现Rule接口)及configCommitter结构体(实现Committer接口)。

orderer/common/sizefilter目录,maxBytesRule结构体(实现Rule接口)。

orderer/multichain/chainsupport.go,filter工具函数。

orderer/multichain/systemchain.go,systemChainFilter结构体(实现Rule接口)及systemChainCommitter结构体(实现Committer接口)。

## 2、Rule接口定义及实现### 2.1、Rule接口定义```gotype Action intconst (Accept = iotaRejectForward)type Rule interface { //定义一个过滤器函数, 它接受、拒绝或转发 (到下一条规则) 一个信封Apply(message *ab.Envelope) (Action, Committer)}//代码在orderer/common/filter/filter.go```### 2.2、emptyRejectRule(校验是否为空过滤器)```gotype emptyRejectRule struct{}var EmptyRejectRule = Rule(emptyRejectRule{})func (a emptyRejectRule) Apply(message *ab.Envelope) (Action, Committer) {if message.Payload == nil {return Reject, nil}return Forward, nil}//代码在orderer/common/filter/filter.go```### 2.3、acceptRule(接受过滤器)```gotype acceptRule struct{}var AcceptRule = Rule(acceptRule{})func (a acceptRule) Apply(message *ab.Envelope) (Action, Committer) {return Accept, NoopCommitter}//代码在orderer/common/filter/filter.go```### 2.4、configFilter(配置交易合法性过滤器)```gotype configFilter struct {configManager api.Manager}func NewFilter(manager api.Manager) filter.Rule //构造configFilter//配置交易过滤器func (cf *configFilter) Apply(message *cb.Envelope) (filter.Action, mitter) {msgData, err := utils.UnmarshalPayload(message.Payload) //获取Payload chdr, err :=utils.UnmarshalChannelHeader(msgData.Header.ChannelHeader) //获取ChannelHeaderif chdr.Type != int32(cb.HeaderType_CONFIG) { //配置交易return filter.Forward, nil}configEnvelope, err := configtx.UnmarshalConfigEnvelope(msgData.Data) //获取configEnvelopeerr = cf.configManager.Validate(configEnvelope) //校验configEnvelope return filter.Accept, &configCommitter{manager: cf.configManager,configEnvelope: configEnvelope,}}//代码在orderer/common/configtxfilter/filter.go```### 2.5、sizefilter(交易大小过滤器)```gotype maxBytesRule struct {support Support}func MaxBytesRule(support Support) filter.Rule //构造maxBytesRulefunc (r *maxBytesRule) Apply(message *cb.Envelope) (filter.Action, mitter) {maxBytes := r.support.BatchSize().AbsoluteMaxBytesif size := messageByteSize(message); size > maxBytes {return filter.Reject, nil}return filter.Forward, nil}//代码在orderer/common/sizefilter/sizefilter.go```### 2.6、sigFilter(签名数据校验过滤器)```gotype sigFilter struct {policySource stringpolicyManager policies.Manager}func New(policySource string, policyManager policies.Manager) filter.Rule //构造sigFilterfunc (sf *sigFilter) Apply(message *cb.Envelope) (filter.Action,mitter) {signedData, err := message.AsSignedData() //构造SignedDatapolicy, ok := sf.policyManager.GetPolicy(sf.policySource) //获取策略 err = policy.Evaluate(signedData) //校验策略if err == nil {return filter.Forward, nil}return filter.Reject, nil}//代码在orderer/common/sigfilter/sigfilter.go```### 2.7、systemChainFilter(系统链过滤器)```gotype systemChainFilter struct {cc chainCreatorsupport limitedSupport}func newSystemChainFilter(ls limitedSupport, cc chainCreator) filter.Rule //构造systemChainFilterfunc (scf *systemChainFilter) Apply(env *cb.Envelope) (filter.Action, mitter) {msgData := &cb.Payload{}err := proto.Unmarshal(env.Payload, msgData) //获取Payloadchdr, err :=utils.UnmarshalChannelHeader(msgData.Header.ChannelHeader)if chdr.Type != int32(cb.HeaderType_ORDERER_TRANSACTION){ //ORDERER_TRANSACTIONreturn filter.Forward, nil}maxChannels := scf.support.SharedConfig().MaxChannelsCount()if maxChannels > 0 {if uint64(.channelsCount()) > maxChannels {return filter.Reject, nil}}configTx := &cb.Envelope{}err = proto.Unmarshal(msgData.Data, configTx)err = scf.authorizeAndInspect(configTx)return filter.Accept, &systemChainCommitter{filter: scf,configTx: configTx,}}//代码在orderer/multichain/systemchain.go```## 3、Committer接口定义及实现### 3.1、Committer接口定义```gotype Committer interface {Commit() //提交Isolated() bool //判断交易是孤立的块,或与其他交易混合的块}//代码在orderer/common/filter/filter.go```### 3.2、noopCommitter```gotype noopCommitter struct{}var NoopCommitter = Committer(noopCommitter{})func (nc noopCommitter) Commit() {}func (nc noopCommitter) Isolated() bool { return false } //代码在orderer/common/filter/filter.go```### 3.3、configCommitter```gotype configCommitter struct {manager api.ManagerconfigEnvelope *cb.ConfigEnvelope}func (cc *configCommitter) Commit() {err := cc.manager.Apply(cc.configEnvelope)}func (cc *configCommitter) Isolated() bool {return true}//代码在orderer/common/configtxfilter/filter.go```### 3.4、systemChainCommitter```gotype systemChainCommitter struct {filter *systemChainFilterconfigTx *cb.Envelope}func (scc *systemChainCommitter) Isolated() bool {return true}func (scc *systemChainCommitter) Commit() {.newChain(scc.configTx)}//代码在orderer/multichain/systemchain.go```### 4、RuleSet结构体及方法```gotype RuleSet struct {rules []Rule}func NewRuleSet(rules []Rule) *RuleSet //构造RuleSetfunc (rs *RuleSet) Apply(message *ab.Envelope) (Committer, error) { for _, rule := range rs.rules {action, committer := rule.Apply(message)switch action {case Accept: //接受return committer, nilcase Reject: //拒绝return nil, fmt.Errorf("Rejected by rule: %T", rule)default:}}return nil, fmt.Errorf("No matching filter found")}//代码在orderer/common/filter/filter.go```### 5、filter工具函数```go//为普通 (非系统) 链创建过滤器集func createStandardFilters(ledgerResources *ledgerResources)*filter.RuleSet {return filter.NewRuleSet([]filter.Rule{filter.EmptyRejectRule, //EmptyRejectRulesizefilter.MaxBytesRule(ledgerResources.SharedConfig()),//sizefiltersigfilter.New(policies.ChannelWriters,ledgerResources.PolicyManager()), //sigfilterconfigtxfilter.NewFilter(ledgerResources), //configtxfilter filter.AcceptRule, //AcceptRule})}//为系统链创建过滤器集func createSystemChainFilters(ml *multiLedger, ledgerResources*ledgerResources) *filter.RuleSet {return filter.NewRuleSet([]filter.Rule{filter.EmptyRejectRule, //EmptyRejectRulesizefilter.MaxBytesRule(ledgerResources.SharedConfig()),//sizefiltersigfilter.New(policies.ChannelWriters,ledgerResources.PolicyManager()), //sigfilternewSystemChainFilter(ledgerResources, ml),configtxfilter.NewFilter(ledgerResources), //configtxfilter filter.AcceptRule, //AcceptRule})}//代码在orderer/multichain/chainsupport.go```。

兄弟连区块链技术培训Fabric 1.0源代码分析(10)consenter(共识插件)

兄弟连区块链技术培训Fabric 1.0源代码分析(10)consenter(共识插件)

兄弟连区块链技术培训Fabric 1.0源代码分析(10)consente r(共识插件)# Fabric 1.0源代码笔记之 consenter(共识插件)## 1、consenter概述consenter,即共识插件,负责接受交易信息进行排序,以及对交易进行切割并打包,打包后返回批量交易。

Orderer包含三种共识插件:* solo,单节点的排序功能,用于试验。

* kafka,基于kafka集群实现的排序,可用于生产环境。

* SBFT,支持拜占庭容错的排序实现,尚未完成开发。

consenter代码分布在orderer/multichain、orderer/solo、orderer/kafka、orde rer/common/blockcutter、orderer/common/filter目录下。

目录结构如下:* orderer/multichain目录:* chainsupport.go,Consenter和Chain接口定义。

* orderer/solo目录,solo版本共识插件。

* orderer/kafka目录,kafka版本共识插件。

* orderer/common/blockcutter目录,block cutter相关实现,即Receiver接口定义及实现。

* orderer/common/filter目录,过滤器相关实现。

## 2、Consenter和Chain接口定义```gotype Consenter interface { //共识插件接口//获取共识插件对应的Chain实例HandleChain(support ConsenterSupport, metadata *cb.Metadata) (Chai n, error)}type Chain interface {//接受消息Enqueue(env *cb.Envelope) boolErrored() <-chan struct{}Start() //开始Halt() //挂起}//代码在orderer/multichain/chainsupport.go```## 3、solo版本共识插件### 3.1、Consenter接口实现```gotype consenter struct{}//构造consenterfunc New() multichain.Consenter {return &consenter{}}//获取solo共识插件对应的Chain实例func (solo *consenter) HandleChain(support multichain.ConsenterSupport, metadata *cb.Metadata) (multichain.Chain, error) {return newChain(support), nil}//代码在orderer/solo/consensus.go```### 3.2、Chain接口实现```gotype chain struct {support multichain.ConsenterSupportsendChan chan *cb.Envelope //交易数据通道exitChan chan struct{} //退出信号}//构造chainfunc newChain(support multichain.ConsenterSupport) *chain//go ch.main()func (ch *chain) Start()//关闭通道,close(ch.exitChan)func (ch *chain) Halt()//Envelope写入通道ch.sendChanfunc (ch *chain) Enqueue(env *cb.Envelope) bool//获取ch.exitChanfunc (ch *chain) Errored() <-chan struct{}//goroutinefunc (ch *chain) main()//代码在orderer/solo/consensus.go```### 3.3、main()实现```gofunc (ch *chain) main() {var timer <-chan time.Time //超时通道for {select {case msg := <-ch.sendChan: //接受交易消息batches, committers, ok, _ := ch.support.BlockCutter().Orde red(msg)if ok && len(batches) == 0 && timer == nil {timer = time.After(ch.support.SharedConfig().BatchTimeo ut())continue}for i, batch := range batches {block := ch.support.CreateNextBlock(batch) //每个批处理创建一个块ch.support.WriteBlock(block, committers[i], nil) //写入块}if len(batches) > 0 {timer = nil}case <-timer://clear the timertimer = nilbatch, committers := ch.support.BlockCutter().Cut()if len(batch) == 0 {logger.Warningf("Batch timer expired with no pending re quests, this might indicate a bug")continue}logger.Debugf("Batch timer expired, creating block")block := ch.support.CreateNextBlock(batch)ch.support.WriteBlock(block, committers, nil)case <-ch.exitChan: //退出信号logger.Debugf("Exiting")return}}}//代码在orderer/solo/consensus.go```## 4、kafka版本共识插件### 4.1、Consenter接口实现```gotype consenterImpl struct {brokerConfigVal *sarama.ConfigtlsConfigVal localconfig.TLSretryOptionsVal localconfig.RetrykafkaVersionVal sarama.KafkaVersion}//构造consenterImplfunc New(tlsConfig localconfig.TLS, retryOptions localconfig.Retry, kaf kaVersion sarama.KafkaVersion) multichain.Consenter//构造chainImplfunc (consenter *consenterImpl) HandleChain(support multichain.Consente rSupport, metadata *cb.Metadata) (multichain.Chain, error)func (consenter *consenterImpl) brokerConfig() *sarama.Configfunc (consenter *consenterImpl) retryOptions() localconfig.Retry//代码在orderer/kafka/consenter.go```### 4.2、Chain接口实现```gotype chainImpl struct {consenter commonConsentersupport multichain.ConsenterSupportchannel channellastOffsetPersisted int64lastCutBlockNumber uint64producer sarama.SyncProducerparentConsumer sarama.ConsumerchannelConsumer sarama.PartitionConsumererrorChan chan struct{}haltChan chan struct{}startChan chan struct{}}//构造chainImplfunc newChain(consenter commonConsenter, support multichain.ConsenterSu pport, lastOffsetPersisted int64) (*chainImpl, error)//获取chain.errorChanfunc (chain *chainImpl) Errored() <-chan struct{}//go startThread(chain)func (chain *chainImpl) Start()//结束func (chain *chainImpl) Halt()//接收Envelope消息,序列化后发给kafkafunc (chain *chainImpl) Enqueue(env *cb.Envelope) bool//goroutine,调取chain.processMessagesToBlocks()func startThread(chain *chainImpl)//goroutine实际功能实现func (chain *chainImpl) processMessagesToBlocks() ([]uint64, error)func (chain *chainImpl) closeKafkaObjects() []errorfunc getLastCutBlockNumber(blockchainHeight uint64) uint64func getLastOffsetPersisted(metadataValue []byte, chainID string) int64 func newConnectMessage() *ab.KafkaMessagefunc newRegularMessage(payload []byte) *ab.KafkaMessagefunc newTimeToCutMessage(blockNumber uint64) *ab.KafkaMessage//构造sarama.ProducerMessagefunc newProducerMessage(channel channel, pld []byte) *sarama.ProducerMe ssagefunc processConnect(channelName string) errorfunc processRegular(regularMessage *ab.KafkaMessageRegular, support mul tichain.ConsenterSupport, timer *<-chan time.Time, receivedOffset int64, lastCutBlockNumber *uint64) errorfunc processTimeToCut(ttcMessage *ab.KafkaMessageTimeToCut, support mul tichain.ConsenterSupport, lastCutBlockNumber *uint64, timer *<-chan tim e.Time, receivedOffset int64) errorfunc sendConnectMessage(retryOptions localconfig.Retry, exitChan chan s truct{}, producer sarama.SyncProducer, channel channel) errorfunc sendTimeToCut(producer sarama.SyncProducer, channel channel, timeT oCutBlockNumber uint64, timer *<-chan time.Time) errorfunc setupChannelConsumerForChannel(retryOptions localconfig.Retry, hal tChan chan struct{}, parentConsumer sarama.Consumer, channel channel, s tartFrom int64) (sarama.PartitionConsumer, error)func setupParentConsumerForChannel(retryOptions localconfig.Retry, halt Chan chan struct{}, brokers []string, brokerConfig *sarama.Config, chan nel channel) (sarama.Consumer, error)func setupProducerForChannel(retryOptions localconfig.Retry, haltChan c han struct{}, brokers []string, brokerConfig *sarama.Config, channel ch annel) (sarama.SyncProducer, error)//代码在orderer/kafka/chain.go```func (chain *chainImpl) Enqueue(env *cb.Envelope) bool代码如下:```gofunc (chain *chainImpl) Enqueue(env *cb.Envelope) bool {select {case <-chain.startChan: //开始阶段已完成select {case <-chain.haltChan:return falsedefault:marshaledEnv, err := utils.Marshal(env) //env序列化payload := utils.MarshalOrPanic(newRegularMessage(marshaled Env))message := newProducerMessage(chain.channel, payload) //构造sarama.ProducerMessage_, _, err := chain.producer.SendMessage(message) //向kafka 发送messagereturn true}default:return false}}//代码在orderer/kafka/chain.go```func newProducerMessage(channel channel, pld []byte) *sarama.ProducerMe ssage代码如下:```gofunc newProducerMessage(channel channel, pld []byte) *sarama.ProducerMe ssage {return &sarama.ProducerMessage{Topic: channel.topic(),Key: sarama.StringEncoder(strconv.Itoa(int(channel.partition ()))),Value: sarama.ByteEncoder(pld),}}//代码在orderer/kafka/chain.go```func (chain *chainImpl) processMessagesToBlocks() ([]uint64, error)代码如下:```gofunc (chain *chainImpl) processMessagesToBlocks() ([]uint64, error) {counts := make([]uint64, 11) // For metrics and testsmsg := new(ab.KafkaMessage)var timer <-chan time.Timedefer func() { //Halt()时执行select {case <-chain.errorChan:default:close(chain.errorChan)}}()for {select {case <-chain.haltChan: //退出counts[indexExitChanPass]++return counts, nilcase kafkaErr := <-chain.channelConsumer.Errors(): //错误counts[indexRecvError]++select {case <-chain.errorChan:default:close(chain.errorChan)}go sendConnectMessage(chain.consenter.retryOptions(), chain. haltChan, chain.producer, chain.channel)case in, ok := <-chain.channelConsumer.Messages(): //接收消息select {case <-chain.errorChan: //错误chain.errorChan = make(chan struct{})default:}err := proto.Unmarshal(in.Value, msg)counts[indexRecvPass]++switch msg.Type.(type) { //消息类型case *ab.KafkaMessage_Connect: //连接_ = processConnect(chain.support.ChainID())counts[indexProcessConnectPass]++case *ab.KafkaMessage_TimeToCut: //超时err := processTimeToCut(msg.GetTimeToCut(), chain.suppo rt, &stCutBlockNumber, &timer, in.Offset)counts[indexProcessTimeToCutPass]++case *ab.KafkaMessage_Regular: //正常消息err := processRegular(msg.GetRegular(), chain.support, &timer, in.Offset, &stCutBlockNumber)counts[indexProcessRegularPass]++}case <-timer:err := sendTimeToCut(chain.producer, chain.channel, chain.l astCutBlockNumber+1, &timer)counts[indexSendTimeToCutPass]++}}}//代码在orderer/kafka/chain.go```func processRegular(regularMessage *ab.KafkaMessageRegular, support mul tichain.ConsenterSupport, timer *<-chan time.Time, receivedOffset int64, lastCutBlockNumber *uint64) error 代码如下:```gofunc processRegular(regularMessage *ab.KafkaMessageRegular, support mul tichain.ConsenterSupport, timer *<-chan time.Time, receivedOffset int64, lastCutBlockNumber *uint64) error {env := new(cb.Envelope)proto.Unmarshal(regularMessage.Payload, env) //发序列化为envbatches, committers, ok, pending := support.BlockCutter().Ordered(e nv)for i, batch := range batches {block := support.CreateNextBlock(batch)encodedLastOffsetPersisted := utils.MarshalOrPanic(&ab.KafkaMet adata{LastOffsetPersisted: offset})support.WriteBlock(block, committers[i], encodedLastOffsetPersi sted) //写入块*lastCutBlockNumber++offset++}if len(batches) > 0 {*timer = nil}return nil}//代码在orderer/kafka/chain.go```## 5、blockcutter### 5.1、Receiver接口定义```gotype Receiver interface {//交易信息排序Ordered(msg *cb.Envelope) (messageBatches [][]*cb.Envelope, committ ers [][]mitter, validTx bool, pending bool)//返回当前批处理,并启动一个新批次Cut() ([]*cb.Envelope, []mitter)}//代码在orderer/common/blockcutter/blockcutter.go```### 5.2、Receiver接口实现```gotype receiver struct {sharedConfigManager config.Ordererfilters *filter.RuleSetpendingBatch []*cb.EnvelopependingBatchSizeBytes uint32pendingCommitters []mitter}//构造receiverfunc NewReceiverImpl(sharedConfigManager config.Orderer, filters *filte r.RuleSet) Receiver//交易信息排序func (r *receiver) Ordered(msg *cb.Envelope) (messageBatches [][]*cb.En velope, committerBatches [][]mitter, validTx bool, pending bo ol)//返回当前批处理,并启动一个新批次func (r *receiver) Cut() ([]*cb.Envelope, []mitter)//获取消息长度func messageSizeBytes(message *cb.Envelope) uint32//代码在orderer/common/blockcutter/blockcutter.go```func (r *receiver) Ordered(msg *cb.Envelope) (messageBatches [][]*cb.En velope, committerBatches [][]mitter, validTx bool, pending bo ol)代码如下:```gofunc (r *receiver) Ordered(msg *cb.Envelope) (messageBatches [][]*cb.En velope, committerBatches [][]mitter, validTx bool, pending bo ol) {committer, err := r.filters.Apply(msg) //执行过滤器if err != nil {logger.Debugf("Rejecting message: %s", err)return}validTx = truemessageSizeBytes := messageSizeBytes(msg)//孤立的块,或者交易大小超限,将被隔离if committer.Isolated() || messageSizeBytes > r.sharedConfigManager. BatchSize().PreferredMaxBytes {if committer.Isolated() {//发现消息要求被隔离, 切割成自己的批logger.Debugf("Found message which requested to be isolated, cutting into its own batch")} else {//当前消息大于默认批处理大小, 将被隔离logger.Debugf("The current message, with %v bytes, is large r than the preferred batch size of %v bytes and will be isolated.", mes sageSizeBytes, r.sharedConfigManager.BatchSize().PreferredMaxBytes)}//剪切批处理if len(r.pendingBatch) > 0 {messageBatch, committerBatch := r.Cut()messageBatches = append(messageBatches, messageBatch)committerBatches = append(committerBatches, committerBatch) }//创建新批次messageBatches = append(messageBatches, []*cb.Envelope{msg})committerBatches = append(committerBatches, []mitter {committer})return}//混合块且大小未超限messageWillOverflowBatchSizeBytes := r.pendingBatchSizeBytes+messag eSizeBytes > r.sharedConfigManager.BatchSize().PreferredMaxBytesif messageWillOverflowBatchSizeBytes { //添加当前消息后,批处理将溢出messageBatch, committerBatch := r.Cut()messageBatches = append(messageBatches, messageBatch)committerBatches = append(committerBatches, committerBatch)}//消息添加到批处理r.pendingBatch = append(r.pendingBatch, msg)r.pendingBatchSizeBytes += messageSizeBytesr.pendingCommitters = append(r.pendingCommitters, committer)pending = trueif uint32(len(r.pendingBatch)) >= r.sharedConfigManager.BatchSize(). MaxMessageCount {//批次大小满足, 切割批次messageBatch, committerBatch := r.Cut()messageBatches = append(messageBatches, messageBatch)committerBatches = append(committerBatches, committerBatch)pending = false}11 / 12return}//代码在orderer/common/blockcutter/blockcutter.go```## 6、filter相关实现(过滤器)filter更详细内容,参考:[Fabric 1.0源代码笔记之 consenter(共识插件) #fil ter(过滤器)](filter.md)12 / 12。

兄弟连区块链教程Fabric1.0源代码分析配置交易-生成通道配置

兄弟连区块链教程Fabric1.0源代码分析配置交易-生成通道配置

兄弟连区块链教程Fabric1.0源代码分析配置jiaoyi-生成通道配置兄弟连区块链教程Fabric1.0源代码分析配置jiaoyi-生成通道配置,2018年下半年,区块链行业正逐渐褪去发展之初的浮躁、回归理性,表面上看相关人才需求与身价似乎正在回落。

但事实上,正是初期泡沫的渐退,让人们更多的关注点放在了区块链真正的技术之上。

# Fabric 1.0源代码笔记之 configtx(配置jiaoyi) #configtxgen(生成通道配置)## 1、configtxgen概述configtxgen,用于生成通道配置,具体有如下三种用法:* 生成Orderer服务启动的初始区块(即系统通道的创世区块文件)* configtxgen -profile TwoOrgsOrdererGenesis-outputBlock ./channel-artifacts/genesis.block* 生成新建应用通道的配置jiaoyi(即用于创建应用通道的配置jiaoyi文件)* configtxgen -profile TwoOrgsChannel-outputCreateChannelTx ./channel-artifacts/channel.tx -channelID mychannel* 生成锚节点配置更新文件* configtxgen -profile TwoOrgsChannel-outputAnchorPeersUpdate ./channel-artifacts/Org1MSPanchors.tx-channelID mychannel -asOrg Org1MSPconfigtxgen代码分布在common/configtx/tool目录,目录结构如下:* localconfig/config.go,configtx.yaml配置文件相关的结构体及方法。

## 2、configtx.yaml配置文件示例```bashProfiles:TwoOrgsOrdererGenesis: #Orderer系统通道配置Orderer:<<: *OrdererDefaults #引用OrdererDefaults并合并到当前Organizations: #属于Orderer通道的组织- *OrdererOrgConsortiums: #Orderer所服务的联盟列表SampleConsortium:Organizations:- *Org1- *Org2TwoOrgsChannel: #应用通道配置Consortium: SampleConsortium #应用通道关联的联盟Application:<<: *ApplicationDefaults #引用ApplicationDefaults并合并到当前 Organizations: #初始加入应用通道的组织- *Org1- *Org2Organizations:- &OrdererOrgName: OrdererOrgID: OrdererMSP # MSP IDMSPDir: crypto-config/ordererOrganizations//msp #MSP 相关文件本地路径- &Org1Name: Org1MSPID: Org1MSPMSPDir: crypto-config/peerOrganizations//mspAnchorPeers: #锚节点地址,用于跨组织的Gossip通信- Host: Port: 7051- &Org2Name: Org2MSPID: Org2MSPMSPDir: crypto-config/peerOrganizations//mspAnchorPeers: #锚节点地址,用于跨组织的Gossip通信- Host: Port: 7051Orderer: &OrdererDefaultsOrdererType: solo # Orderer共识插件类型,分solo或kafkaAddresses:- :7050 #服务地址BatchTimeout: 2s #创建批量jiaoyi的zui大超时,一批jiaoyi构成一个块BatchSize: #写入区块内的jiaoyi个数MaxMessageCount: 10 #一批消息的zui大个数AbsoluteMaxBytes: 98 MB #一批jiaoyi的zui大字节数,任何时候均不能超过PreferredMaxBytes: 512 KB #批量jiaoyi的建议字节数Kafka:Brokers: #Kafka端口- 127.0.0.1:9092Organizations: #参与维护Orderer的组织,默认空Application: &ApplicationDefaultsOrganizations: #加入到通道的组织信息,此处为不包括任何组织```配置文件解读:* 每个Profile表示某种场景下的通道配置模板,包括Orderer系统通道模板和应用通道模板,其中TwoOrgsOrdererGenesis为系统通道模板,TwoOrgsChannel为应用通道模板。

兄弟连区块链教程Fabric1.0源代码分析putils(protos utils工具包)

兄弟连区块链教程Fabric1.0源代码分析putils(protos utils工具包)

兄弟连区块链教程Fabric1.0源代码分析putils(protos/utils工具包)兄弟连区块链教程Fabric1.0源代码分析putils(protos/utils工具包),2018年下半年,区块链行业正逐渐褪去发展之初的浮躁、回归理性,表面上看相关人才需求与身价似乎正在回落。

但事实上,正是初期泡沫的渐退,让人们更多的关注点放在了区块链真正的技术之上。

# Fabric1.0源代码笔记之putils(protos/utils工具包)## 1、putils概述putils,即protos/utils工具包,代码分布在:protos/utils目录下。

包括:txutils.go、proputils.go、commonutils.go、blockutils.go。

## 2、txutils```go//TransactionAction.Payload => ChaincodeActionPayload//ChaincodeActionPayload.Action.ProposalResponsePayload => ProposalResponsePayload//ProposalResponsePayload.Extension => ChaincodeAction//从TransactionAction中获取ChaincodeActionPayload和ChaincodeAction func GetPayloads(txActions *peer.TransactionAction)(*peer.ChaincodeActionPayload, *peer.ChaincodeAction, error)//[]byte反序列化为Envelopefunc GetEnvelopeFromBlock(data []byte) (*common.Envelope, error)func CreateSignedEnvelope(txType common.HeaderType, channelID string, signer crypto.LocalSigner, dataMsg proto.Message, msgVersion int32, epoch uint64) (*common.Envelope, error)//由Proposal创建签名交易Envelopefunc CreateSignedTx(proposal *peer.Proposal, signer msp.SigningIdentity, resps ...*peer.ProposalResponse) (*common.Envelope, error) {func CreateProposalResponse(hdrbytes []byte, payl []byte, response*peer.Response, results []byte, events []byte, ccid *peer.ChaincodeID, visibility []byte, signingEndorser msp.SigningIdentity)(*peer.ProposalResponse, error)func CreateProposalResponseFailure(hdrbytes []byte, payl []byte, response *peer.Response, results []byte, events []byte, ccid *peer.ChaincodeID, visibility []byte) (*peer.ProposalResponse, error)//签名Proposalfunc GetSignedProposal(prop *peer.Proposal, signer msp.SigningIdentity) (*peer.SignedProposal, error)func GetSignedEvent(evt *peer.Event, signer msp.SigningIdentity)(*peer.SignedEvent, error)func MockSignedEndorserProposalOrPanic(chainID string, cs*peer.ChaincodeSpec, creator, signature []byte) (*peer.SignedProposal,*peer.Proposal)func MockSignedEndorserProposal2OrPanic(chainID string, cs*peer.ChaincodeSpec, signer msp.SigningIdentity) (*peer.SignedProposal, *peer.Proposal)func GetBytesProposalPayloadForTx(payload *peer.ChaincodeProposalPayload, visibility []byte) ([]byte, error)func GetProposalHash2(header *common.Header, ccPropPayl []byte) ([]byte, error)func GetProposalHash1(header *common.Header, ccPropPayl []byte, visibility []byte) ([]byte, error)//代码在protos/utils/txutils.go```## 3、proputils```gofunc GetChaincodeInvocationSpec(prop *peer.Proposal)(*peer.ChaincodeInvocationSpec, error)func GetChaincodeProposalContext(prop *peer.Proposal) ([]byte,map[string][]byte, error)//反序列化为common.Headerfunc GetHeader(bytes []byte) (*common.Header, error)func GetNonce(prop *peer.Proposal) ([]byte, error)//Header.ChannelHeader反序列化为peer.ChaincodeHeaderExtensionfunc GetChaincodeHeaderExtension(hdr *common.Header)(*peer.ChaincodeHeaderExtension, error)func GetProposalResponse(prBytes []byte) (*peer.ProposalResponse, error) func GetChaincodeDeploymentSpec(code []byte)(*peer.ChaincodeDeploymentSpec, error)func GetChaincodeAction(caBytes []byte) (*peer.ChaincodeAction, error) func GetResponse(resBytes []byte) (*peer.Response, error)func GetChaincodeEvents(eBytes []byte) (*peer.ChaincodeEvent, error)func GetProposalResponsePayload(prpBytes []byte)(*peer.ProposalResponsePayload, error)func GetProposal(propBytes []byte) (*peer.Proposal, error)//e.Payload反序列化为Payloadfunc GetPayload(e *common.Envelope) (*common.Payload, error)//[]byte反序列化为Transactionfunc GetTransaction(txBytes []byte) (*peer.Transaction, error)func GetChaincodeActionPayload(capBytes []byte)(*peer.ChaincodeActionPayload, error)//反序列化为peer.ChaincodeProposalPayloadfunc GetChaincodeProposalPayload(bytes []byte)(*peer.ChaincodeProposalPayload, error)//反序列化为common.SignatureHeaderfunc GetSignatureHeader(bytes []byte) (*common.SignatureHeader, error) func CreateChaincodeProposal(typ common.HeaderType, chainID string, cis *peer.ChaincodeInvocationSpec, creator []byte) (*peer.Proposal, string, error)func CreateChaincodeProposalWithTransient(typ common.HeaderType, chainID string, cis *peer.ChaincodeInvocationSpec, creator []byte, transientMap map[string][]byte) (*peer.Proposal, string, error)func CreateChaincodeProposalWithTxIDNonceAndTransient(txid string, typ common.HeaderType, chainID string, cis *peer.ChaincodeInvocationSpec, nonce, creator []byte, transientMap map[string][]byte) (*peer.Proposal, string, error)func GetBytesProposalResponsePayload(hash []byte, response *peer.Response, result []byte, event []byte, ccid *peer.ChaincodeID) ([]byte, error)func GetBytesChaincodeProposalPayload(cpp *peer.ChaincodeProposalPayload) ([]byte, error)func GetBytesResponse(res *peer.Response) ([]byte, error)func GetBytesChaincodeEvent(event *peer.ChaincodeEvent) ([]byte, error) func GetBytesChaincodeActionPayload(cap *peer.ChaincodeActionPayload) ([]byte, error)func GetBytesProposalResponse(pr *peer.ProposalResponse) ([]byte, error) func GetBytesProposal(prop *peer.Proposal) ([]byte, error)func GetBytesHeader(hdr *common.Header) ([]byte, error)func GetBytesSignatureHeader(hdr *common.SignatureHeader) ([]byte, error) func GetBytesTransaction(tx *peer.Transaction) ([]byte, error)func GetBytesPayload(payl *common.Payload) ([]byte, error)func GetBytesEnvelope(env *common.Envelope) ([]byte, error)//从envBytes []byte中获取ChaincodeActionfunc GetActionFromEnvelope(envBytes []byte) (*peer.ChaincodeAction, error)func CreateProposalFromCIS(typ common.HeaderType, chainID string, cis*peer.ChaincodeInvocationSpec, creator []byte) (*peer.Proposal, string, error)func CreateInstallProposalFromCDS(ccpack proto.Message, creator []byte) (*peer.Proposal, string, error)//按ChaincodeDeploymentSpec创建DeployProposalfunc CreateDeployProposalFromCDS(chainID string, cds*peer.ChaincodeDeploymentSpec, creator []byte, policy []byte, escc []byte, vscc []byte) (*peer.Proposal, string, error)func CreateUpgradeProposalFromCDS(chainID string, cds*peer.ChaincodeDeploymentSpec, creator []byte, policy []byte, escc []byte, vscc []byte) (*peer.Proposal, string, error)func createProposalFromCDS(chainID string, msg proto.Message, creator []byte, policy []byte, escc []byte, vscc []byte, propType string)(*peer.Proposal, string, error)func ComputeProposalTxID(nonce, creator []byte) (string, error)func CheckProposalTxID(txid string, nonce, creator []byte) errorfunc ComputeProposalBinding(proposal *peer.Proposal) ([]byte, error) func computeProposalBindingInternal(nonce, creator []byte, epoch uint64) ([]byte, error)//代码在protos/utils/proputils.go```## 4、commonutils```gofunc MarshalOrPanic(pb proto.Message) []bytefunc Marshal(pb proto.Message) ([]byte, error)func CreateNonceOrPanic() []bytefunc CreateNonce() ([]byte, error)func UnmarshalPayloadOrPanic(encoded []byte) *cb.Payloadfunc UnmarshalPayload(encoded []byte) (*cb.Payload, error)func UnmarshalEnvelopeOrPanic(encoded []byte) *cb.Envelopefunc UnmarshalEnvelope(encoded []byte) (*cb.Envelope, error)func UnmarshalEnvelopeOfType(envelope *cb.Envelope, headerTypecb.HeaderType, message proto.Message) (*cb.ChannelHeader, error)func ExtractEnvelopeOrPanic(block *cb.Block, index int) *cb.Envelope func ExtractEnvelope(block *cb.Block, index int) (*cb.Envelope, error) func ExtractPayloadOrPanic(envelope *cb.Envelope) *cb.Payloadfunc ExtractPayload(envelope *cb.Envelope) (*cb.Payload, error)func MakeChannelHeader(headerType cb.HeaderType, version int32, chainID string, epoch uint64) *cb.ChannelHeaderfunc MakeSignatureHeader(serializedCreatorCertChain []byte, nonce []byte) *cb.SignatureHeaderfunc SetTxID(channelHeader *cb.ChannelHeader, signatureHeader*cb.SignatureHeader) errorfunc MakePayloadHeader(ch *cb.ChannelHeader, sh *cb.SignatureHeader)*cb.Headerfunc NewSignatureHeaderOrPanic(signer crypto.LocalSigner)*cb.SignatureHeaderfunc SignOrPanic(signer crypto.LocalSigner, msg []byte) []byte//[]byte反序列化为ChannelHeaderfunc UnmarshalChannelHeader(bytes []byte) (*cb.ChannelHeader, error) func UnmarshalChaincodeID(bytes []byte) (*pb.ChaincodeID, error)func IsConfigBlock(block *cb.Block) bool//代码在protos/utils/commonutils.go```## 5、blockutils```go//[]byte转换为Block,从Block中获取ChainID(即ChannelId)func GetChainIDFromBlockBytes(bytes []byte) (string, error)//从Block中获取ChainID(即ChannelId)func GetChainIDFromBlock(block *cb.Block) (string, error)//从Block中按index获取Metadatafunc GetMetadataFromBlock(block *cb.Block, index cb.BlockMetadataIndex) (*cb.Metadata, error)//从Block中按index获取Metadata,如果失败则Panicfunc GetMetadataFromBlockOrPanic(block *cb.Block, indexcb.BlockMetadataIndex) *cb.Metadata//从Block.Metadata.Metadata中获取LastConfigfunc GetLastConfigIndexFromBlock(block *cb.Block) (uint64, error)//从Block.Metadata.Metadata中获取LastConfig,如果失败则Panicfunc GetLastConfigIndexFromBlockOrPanic(block *cb.Block) uint64//[]byte转换为Blockfunc GetBlockFromBlockBytes(blockBytes []byte) (*cb.Block, error)//拷贝Block.Metadatafunc CopyBlockMetadata(src *cb.Block, dst *cb.Block)//初始化Block.Metadata.Metadatafunc InitBlockMetadata(block *cb.Block)//代码在protos/utils/blockutils.go```感谢关注兄弟连区块链教程分享!。

兄弟连区块链教程Fabric1.0源代码分析scc系统链码cscc通道相关

兄弟连区块链教程Fabric1.0源代码分析scc系统链码cscc通道相关

兄弟连区块链教程Fabric1.0源代码分析scc(系统链码)cscc(通道相关)兄弟连区块链教程Fabric1.0源代码分析scc(系统链码)cscc(通道相关),2018年下半年,区块链行业正逐渐褪去发展之初的浮躁、回归理性,表面上看相关人才需求与身价似乎正在回落。

但事实上,正是初期泡沫的渐退,让人们更多的关注点放在了区块链真正的技术之上。

# Fabric 1.0源代码笔记之 scc(系统链码) #cscc(通道相关)## 1、cscc概述cscc代码在core/scc/cscc/configure.go。

## 2、PeerConfiger结构体```gotype PeerConfiger struct {policyChecker policy.PolicyChecker}//代码在core/scc/cscc/configure.go```## 3、Init方法```gofunc (e *PeerConfiger) Init(stub shim.ChaincodeStubInterface) pb.Response {//初始化策略检查器,用于访问控制e.policyChecker = policy.NewPolicyChecker(peer.NewChannelPolicyManagerGetter(),mgmt.GetLocalMSP(),mgmt.NewLocalMSPPrincipalGetter(),)return shim.Success(nil)}//代码在core/scc/cscc/configure.go```## 4、Invoke方法```gofunc (e *PeerConfiger) Invoke(stub shim.ChaincodeStubInterface)pb.Response {//args[0]为JoinChain或GetChannelsargs := stub.GetArgs()fname := string(args[0]) //Invoke functionsp, err := stub.GetSignedProposal() //获取SignedProposalswitch fname {case JoinChain: //加入通道//此处args[1]为创世区块block, err := utils.GetBlockFromBlockBytes(args[1])cid, err := utils.GetChainIDFromBlock(block)err := validateConfigBlock(block)err = e.policyChecker.CheckPolicyNoChannel(mgmt.Admins, sp) return joinChain(cid, block)case GetConfigBlock:err = e.policyChecker.CheckPolicy(string(args[1]),policies.ChannelApplicationReaders, sp)return getConfigBlock(args[1])case GetChannels:err = e.policyChecker.CheckPolicyNoChannel(mgmt.Members, sp) return getChannels()}}//代码在core/scc/cscc/configure.go```## 5、其他方法```go//校验创世区块func validateConfigBlock(block *common.Block) errorfunc joinChain(chainID string, block *common.Block) pb.Responsefunc getConfigBlock(chainID []byte) pb.Responsefunc getChannels() pb.Response//代码在core/scc/cscc/configure.go```### 5.1、joinChain```gofunc joinChain(chainID string, block *common.Block) pb.Response {err := peer.CreateChainFromBlock(block) //创建chainpeer.InitChain(chainID)err := producer.SendProducerBlockEvent(block)return shim.Success(nil)}//代码在core/scc/cscc/configure.go```#### 5.1.1、创建Chain(或channel)peer.CreateChainFromBlock(block)代码如下:```gofunc CreateChainFromBlock(cb *common.Block) error {cid, err := utils.GetChainIDFromBlock(cb) //获取ChainIDvar l ledger.PeerLedgerl, err = ledgermgmt.CreateLedger(cb) //创建Ledgerreturn createChain(cid, l, cb)}//代码在core/peer/peer.go```createChain(cid, l, cb)代码如下:```gofunc createChain(cid string, ledger ledger.PeerLedger, cb *common.Block) error {envelopeConfig, err := utils.ExtractEnvelope(cb, 0) //获取配置Envelope configtxInitializer := configtx.NewInitializer() //type initializer structgossipEventer := service.GetGossipService().NewConfigEventer() //获取gossipServiceInstancegossipCallbackWrapper := func(cm configtxapi.Manager) {ac, ok := configtxInitializer.ApplicationConfig()if !ok {// TODO, handle a missing ApplicationConfig more gracefully ac = nil}gossipEventer.ProcessConfigUpdate(&chainSupport{Manager: cm,Application: ac,})service.GetGossipService().SuspectPeers(func(identityapi.PeerIdentityType) bool {// TODO: this is a place-holder that would somehow make the MSP layer suspect// that a given certificate is revoked, or its intermediate CA is revoked.// In the meantime, before we have such an ability, we return true in order// to suspect ALL identities in order to validate all of them. return true})}trustedRootsCallbackWrapper := func(cm configtxapi.Manager) {updateTrustedRoots(cm)}configtxManager, err := configtx.NewManagerImpl(envelopeConfig,configtxInitializer,[]func(cm configtxapi.Manager){gossipCallbackWrapper, trustedRootsCallbackWrapper},)if err != nil {return err}// TODO remove once all references to mspmgmt are gone from peer code mspmgmt.XXXSetMSPManager(cid, configtxManager.MSPManager())ac, ok := configtxInitializer.ApplicationConfig()if !ok {ac = nil}cs := &chainSupport{Manager: configtxManager,Application: ac, // TODO, refactor as this is accessible through Managerledger: ledger,}c := committer.NewLedgerCommitterReactive(ledger,txvalidator.NewTxValidator(cs), func(block *common.Block) error {chainID, err := utils.GetChainIDFromBlock(block)if err != nil {return err}return SetCurrConfigBlock(block, chainID)})ordererAddresses :=configtxManager.ChannelConfig().OrdererAddresses()if len(ordererAddresses) == 0 {return errors.New("No ordering service endpoint provided in configuration block")}service.GetGossipService().InitializeChannel(cs.ChainID(), c, ordererAddresses)chains.Lock()defer chains.Unlock()chains.list[cid] = &chain{cs: cs,cb: cb,committer: c,}return nil}//代码在core/peer/peer.go```补充initializer:```gotype initializer struct {*resourcesppr *policyProposerRoot}//代码在common/configtx/initializer.go```感谢关注兄弟连区块链教程分享!。

兄弟连区块链教程Fabric1.0源代码分析configtx#genesis

兄弟连区块链教程Fabric1.0源代码分析configtx#genesis

兄弟连区块链教程Fabric1.0源代码分析configtx#genesis兄弟连区块链教程Fabric1.0源代码分析configtx#genesis,2018年下半年,区块链行业正逐渐褪去发展之初的浮躁、回归理性,表面上看相关人才需求与身价似乎正在回落。

但事实上,正是初期泡沫的渐退,让人们更多的关注点放在了区块链真正的技术之上。

# Fabric 1.0源代码笔记之 configtx(配置交易) #genesis(系统通道创世区块)## 1、genesis概述genesis,即创世区块,此处特指系统通道的创世区块。

相关代码在common/genesis/genesis.go,即Factory接口及实现。

## 2、Factory接口定义```gotype Factory interface {Block(channelID string) (*cb.Block, error)}//代码在common/genesis/genesis.go```## 3、Factory接口实现```gomsgVersion = int32(1)epoch = 0type factory struct {template configtx.Template}func NewFactoryImpl(template configtx.Template) Factory {return &factory{template: template}}func (f *factory) Block(channelID string) (*cb.Block, error) {configEnv, err := f.template.Envelope(channelID)configUpdate := &cb.ConfigUpdate{}err = proto.Unmarshal(configEnv.ConfigUpdate, configUpdate)payloadChannelHeader := utils.MakeChannelHeader(cb.HeaderType_CONFIG, msgVersion, channelID, epoch)payloadSignatureHeader := utils.MakeSignatureHeader(nil,utils.CreateNonceOrPanic())utils.SetTxID(payloadChannelHeader, payloadSignatureHeader)payloadHeader := utils.MakePayloadHeader(payloadChannelHeader, payloadSignatureHeader)payload := &cb.Payload{Header: payloadHeader, Data:utils.MarshalOrPanic(&cb.ConfigEnvelope{Config: &cb.Config{ChannelGroup: configUpdate.WriteSet}})}envelope := &cb.Envelope{Payload: utils.MarshalOrPanic(payload), Signature: nil}block := cb.NewBlock(0, nil)block.Data = &cb.BlockData{Data:[][]byte{utils.MarshalOrPanic(envelope)}}block.Header.DataHash = block.Data.Hash()block.Metadata.Metadata[cb.BlockMetadataIndex_LAST_CONFIG] =utils.MarshalOrPanic(&cb.Metadata{Value: utils.MarshalOrPanic(&stConfig{Index: 0}),})return block, nil}//代码在common/genesis/genesis.go```。

兄弟连区块链教程Fabric1.0源代码分析Orderer localconfig

兄弟连区块链教程Fabric1.0源代码分析Orderer localconfig

兄弟连区块链教程Fabric1.0源代码分析Orderer localconfig兄弟连区块链教程Fabric1.0源代码笔记之Orderer #localconfig(Orderer配置文件定义),2018年下半年,区块链行业正逐渐褪去发展之初的浮躁、回归理性,表面上看相关人才需求与身价似乎正在回落。

但事实上,正是初期泡沫的渐退,让人们更多的关注点放在了区块链真正的技术之上。

# Fabric 1.0源代码笔记之 Orderer #localconfig(Orderer配置文件定义)## 1、配置文件定义```bashGeneral: #通用配置LedgerType: file #账本类型,包括ram、json和file,其中ram保存在内存中,生产环境推荐使用fileListenAddress: 127.0.0.1 #服务绑定的监听地址ListenPort: 7050 #服务绑定的监听端口TLS: #启用TLS时的相关配置Enabled: false #是否启用TLSPrivateKey: tls/server.key #Orderer签名私钥Certificate: tls/server.crt #Orderer身份证书RootCAs: #信任的根证书- tls/ca.crtClientAuthEnabled: false #是否对客户端也进行认证ClientRootCAs:LogLevel: info #日志级别LogFormat: '%{color}%{time:2006-01-02 15:04:05.000 MST}[%{module}] %{shortfunc}-> %{level:.4s} %{id:03x}%{color:reset} %{message}'GenesisMethod: provisional #初始区块的提供方式,支持provisional或file,前者基于GenesisProfile指定的configtx.yaml中Profile生成,后者基于指定的初始区块文件GenesisProfile: SampleInsecureSolo #provisional方式生成初始区块时采用的ProfileGenesisFile: genesisblock #使用现成的初始区块文件时,文件的路径LocalMSPDir: msp #本地msp文件的路径LocalMSPID: DEFAULT #MSP的IDProfile: #是否启用go profilingEnabled: falseAddress: 0.0.0.0:6060BCCSP: #密码库机制等,可以为SW(软件实现)或PKCS11(硬件安全模块)Default: SWSW:Hash: SHA2 #哈希算法类型Security: 256FileKeyStore: #本地私钥文件路径,默认指向<mspConfigPath>/keystoreKeyStore:FileLedger: #基于文件的账本的配置Location: /var/hyperledger/production/orderer #存放区块文件的位置,一般为/var/hyperledger/production/orderer/目录Prefix: hyperledger-fabric-ordererledger #如果不指定Location,则在临时目录下创建账本时使用的目录名称RAMLedger: #基于内存的账本最多保留的区块个数HistorySize: 1000Kafka: #Orderer使用Kafka集群作为后端时,Kafka的配置Retry: #Kafka未就绪时Orderer的重试配置,orderer会利用sarama客户端为channel创建一个producer、一个consumer,分别向Kafka写和读数据ShortInterval: 5s #操作失败后的快速重试阶段的间隔ShortTotal: 10m #快速重试阶段最多重试多长时间LongInterval: 5m #快速重试阶段仍然失败后进入慢重试阶段,慢重试阶段的时间间隔LongTotal: 12h #慢重试阶段最多重试多长时间NetworkTimeouts: #sarama网络超时时间DialTimeout: 10sReadTimeout: 10sWriteTimeout: 10sMetadata: #Kafka集群leader选举中的metadata请求参数RetryBackoff: 250msRetryMax: 3Producer: #发送消息到Kafka集群的超时RetryBackoff: 100msRetryMax: 3Consumer: #从Kafka集群读取消息的超时RetryBackoff: 2sVerbose: false #是否开启Kafka客户端的调试日志TLS: #Kafka集群的连接启用TLS时的相关配置Enabled: false #是否启用TLS,默认不开启PrivateKey: #Orderer证明身份用的签名私钥Certificate: #Kafka身份证书RootCAs: #验证Kafka证书时的CA证书Version: #Kafka版本号#代码在/etc/hyperledger/fabric/orderer.yaml```## 2、TopLevel结构体定义```gotype TopLevel struct {General GeneralFileLedger FileLedgerRAMLedger RAMLedgerKafka Kafka}type General struct {LedgerType stringListenAddress stringListenPort uint16TLS TLSGenesisMethod stringGenesisProfile stringGenesisFile stringProfile ProfileLogLevel stringLogFormat stringLocalMSPDir stringLocalMSPID stringBCCSP *bccsp.FactoryOpts }type TLS struct {Enabled boolPrivateKey stringCertificate stringRootCAs []stringClientAuthEnabled boolClientRootCAs []string}type Profile struct {Enabled boolAddress string}type FileLedger struct {Location stringPrefix string}type RAMLedger struct {HistorySize uint}type Kafka struct {Retry RetryVerbose boolVersion sarama.KafkaVersionTLS TLS}type Retry struct {ShortInterval time.DurationShortTotal time.DurationLongInterval time.DurationLongTotal time.DurationNetworkTimeouts NetworkTimeouts Metadata MetadataProducer ProducerConsumer Consumer}type NetworkTimeouts struct {DialTimeout time.DurationReadTimeout time.DurationWriteTimeout time.Duration}type Metadata struct {RetryMax intRetryBackoff time.Duration}type Producer struct {RetryMax intRetryBackoff time.Duration}type Consumer struct {RetryBackoff time.Duration}//代码在orderer/localconfig/config.go ```感谢关注兄弟连区块链教程分享!。

兄弟连区块链教程Fabric1.0源代码分析Orderer BroadcastServer

兄弟连区块链教程Fabric1.0源代码分析Orderer BroadcastServer

兄弟连区块链教程Fabric1.0源代码分析Orderer BroadcastServer兄弟连区块链教程Fabric1.0源代码分析Orderer BroadcastServer,2018年下半年,区块链行业正逐渐褪去发展之初的浮躁、回归理性,表面上看相关人才需求与身价似乎正在回落。

但事实上,正是初期泡沫的渐退,让人们更多的关注点放在了区块链真正的技术之上。

# Fabric 1.0源代码笔记之 Orderer #BroadcastServer(Broadcast服务端)## 1、BroadcastServer概述BroadcastServer相关代码在protos/orderer、orderer目录下。

protos/orderer/ab.pb.go,AtomicBroadcastServer接口定义。

orderer/server.go,go,AtomicBroadcastServer接口实现。

有个图## 2、AtomicBroadcastServer接口定义### 2.1、AtomicBroadcastServer接口定义```gotype AtomicBroadcastServer interface {Broadcast(AtomicBroadcast_BroadcastServer) errorDeliver(AtomicBroadcast_DeliverServer) error}//代码在protos/orderer/ab.pb.go···### 2.2、gRPC相关实现```govar _AtomicBroadcast_serviceDesc = grpc.ServiceDesc{ServiceName: "orderer.AtomicBroadcast",HandlerType: (*AtomicBroadcastServer)(nil),Methods: []grpc.MethodDesc{},Streams: []grpc.StreamDesc{{StreamName: "Broadcast",Handler: _AtomicBroadcast_Broadcast_Handler,ServerStreams: true,ClientStreams: true,},{StreamName: "Deliver",Handler: _AtomicBroadcast_Deliver_Handler,ServerStreams: true,ClientStreams: true,},},Metadata: "orderer/ab.proto",}func RegisterAtomicBroadcastServer(s *grpc.Server, srv AtomicBroadcastServer) {s.RegisterService(&_AtomicBroadcast_serviceDesc, srv)}func _AtomicBroadcast_Broadcast_Handler(srv interface{}, streamgrpc.ServerStream) error {returnsrv.(AtomicBroadcastServer).Broadcast(&atomicBroadcastBroadcastServer{s tream})}func _AtomicBroadcast_Deliver_Handler(srv interface{}, streamgrpc.ServerStream) error {returnsrv.(AtomicBroadcastServer).Deliver(&atomicBroadcastDeliverServer{strea m})}//代码在protos/orderer/ab.pb.go```## 3、AtomicBroadcastServer接口实现### 3.1、server结构体server结构体:```gotype server struct {bh broadcast.Handlerdh deliver.Handler}type broadcastSupport struct {multichain.Managerbroadcast.ConfigUpdateProcessor}//代码在orderer/server.go```broadcast.Handler:```gotype Handler interface {Handle(srv ab.AtomicBroadcast_BroadcastServer) error}type handlerImpl struct {sm SupportManager}func NewHandlerImpl(sm SupportManager) Handler {return &handlerImpl{sm: sm,}}type SupportManager interface {ConfigUpdateProcessorGetChain(chainID string) (Support, bool)}type ConfigUpdateProcessor interface { //处理通道配置更新Process(envConfigUpdate *cb.Envelope) (*cb.Envelope, error) }//代码在orderer/common/broadcast/broadcast.go```deliver.Handler:```gotype Handler interface {Handle(srv ab.AtomicBroadcast_DeliverServer) error}type deliverServer struct {sm SupportManager}type SupportManager interface {GetChain(chainID string) (Support, bool)}//代码在orderer/common/deliver/deliver.go```### 3.2、server结构体相关方法```go//构建server结构体func NewServer(ml multichain.Manager, signer crypto.LocalSigner)ab.AtomicBroadcastServer//s.bh.Handle(srv)func (s *server) Broadcast(srv ab.AtomicBroadcast_BroadcastServer) error //s.dh.Handle(srv)func (s *server) Deliver(srv ab.AtomicBroadcast_DeliverServer) error//代码在orderer/server.go```func NewServer(ml multichain.Manager, signer crypto.LocalSigner)ab.AtomicBroadcastServer代码如下:```gofunc NewServer(ml multichain.Manager, signer crypto.LocalSigner)ab.AtomicBroadcastServer {s := &server{dh: deliver.NewHandlerImpl(deliverSupport{Manager: ml}),bh: broadcast.NewHandlerImpl(broadcastSupport{Manager: ml,ConfigUpdateProcessor: configupdate.New(ml.SystemChannelID(), configUpdateSupport{Manager: ml}, signer),}),}return s}//代码在orderer/server.go```### 3.3、Broadcast服务端Broadcast处理流程Broadcast服务端Broadcast处理流程,即broadcast.handlerImpl.Handle方法。

兄弟连区块链技术培训Fabric 1.0源代码分析(27) Orderer #configupdate

兄弟连区块链技术培训Fabric 1.0源代码分析(27) Orderer #configupdate

兄弟连区块链技术培训Fabric 1.0源代码分析(27) Orderer #configupdate(处理通道配置更新)# Fabric 1.0源代码笔记之 Orderer #configupdate(处理通道配置更新)## 1、configupdate概述configupdate,用于接收配置交易,并处理通道配置更新。

相关代码在orderer/configupdate目录。

## 2、SupportManager接口定义及实现### 2.1、SupportManager接口定义```gotype SupportManager interface {GetChain(chainID string) (Support, bool)NewChannelConfig(envConfigUpdate *cb.Envelope) (configtxapi.Manage r, error)}//代码在orderer/configupdate/configupdate.go```### 2.2、SupportManager接口实现SupportManager接口实现,即configUpdateSupport结构体及方法。

```gotype configUpdateSupport struct {multichain.Manager //type multiLedger struct}func (cus configUpdateSupport) GetChain(chainID string) (configupdate.S upport, bool) {return cus.Manager.GetChain(chainID)}//代码在orderer/server.go```multichain.Manager接口及实现multiLedger,见[Fabric 1.0源代码笔记之 Order er #multichain(多链支持包)](multichain.md)## 3、Support接口定义及实现### 3.1、Support接口定义```gotype Support interface {ProposeConfigUpdate(env *cb.Envelope) (*cb.ConfigEnvelope, error) }//代码在orderer/configupdate/configupdate.go```### 3.2、Support接口实现Support接口实现,即configManager结构体及方法。

兄弟连区块链教程Fabric1.0源代码分析MSP成员关系服务提供者

兄弟连区块链教程Fabric1.0源代码分析MSP成员关系服务提供者

兄弟连区块链教程Fabric1.0源代码分析MSP成员关系服务提供者兄弟连区块链教程Fabric1.0源代码分析MSP成员关系服务提供者一兄弟连区块链教程Fabric1.0源代码分析MSP成员关系服务提供者一,2018年下半年,区块链行业正逐渐褪去发展之初的浮躁、回归理性,表面上看相关人才需求与身价似乎正在回落。

但事实上,正是初期泡沫的渐退,让人们更多的关注点放在了区块链真正的技术之上。

# Fabric 1.0源代码笔记之 MSP(成员关系服务提供者)## 1、MSP概述MSP,全称Membership Service Provider,即成员关系服务提供者,作用为管理Fabric 中的众多参与者。

成员服务提供者(MSP)是一个提供抽象化成员操作框架的组件。

MSP将颁发与校验证书,以及用户认证背后的所有密码学机制与协议都抽象了出来。

一个MSP可以自己定义身份,以及身份的管理(身份验证)与认证(生成与验证签名)规则。

一个Hyperledger Fabric区块链网络可以被一个或多个MSP管理。

MSP的核心代码在msp目录下,其他相关代码分布在common/config/msp、protos/msp 下。

目录结构如下:* msp目录* msp.go,定义接口MSP、MSPManager、Identity、SigningIdentity、IdentityDeserializer。

* mspimpl.go,实现MSP接口,即bccspmsp。

* mspmgrimpl.go,实现MSPManager接口,即mspManagerImpl。

* identities.go,实现Identity、SigningIdentity接口,即identity和signingidentity。

* configbuilder.go,提供读取证书文件并将其组装成MSP等接口所需的数据结构,以及转换配置结构体(FactoryOpts->MSPConfig)等工具函数。

兄弟连区块链教程Fabric1.0源代码分析Ledger historydb历史数据库

兄弟连区块链教程Fabric1.0源代码分析Ledger historydb历史数据库

兄弟连区块链教程Fabric1.0源代码分析Ledger historydb历史数据库兄弟连区块链教程Fabric1.0源代码分析Ledger historydb历史数据库,2018年下半年,区块链行业正逐渐褪去发展之初的浮躁、回归理性,表面上看相关人才需求与身价似乎正在回落。

但事实上,正是初期泡沫的渐退,让人们更多的关注点放在了区块链真正的技术之上。

## 1、historydb概述historydb,用于存储所有块读写集中写集的内容。

代码分布在core/ledger/kvledger/history/historydb目录下,目录结构如下:* historydb.go,定义核心接口HistoryDBProvider和HistoryDB。

* histmgr_helper.go,historydb工具函数。

* historyleveldb目录,historydb基于leveldb的实现。

* historyleveldb.go,HistoryDBProvider和HistoryDB接口实现,即historyleveldb.HistoryDBProvider和historyleveldb.historyDB结构体及方法。

* historyleveldb_query_executer.go,定义LevelHistoryDBQueryExecutor 和historyScanner结构体及方法。

## 2、核心接口定义HistoryDBProvider接口定义:```gotype HistoryDBProvider interface {GetDBHandle(id string) (HistoryDB, error) //获取HistoryDBClose() //关闭所有HistoryDB}//代码在core/ledger/kvledger/history/historydb/historydb.go```HistoryDB接口定义:```gotype HistoryDB interface {//构造 LevelHistoryDBQueryExecutorNewHistoryQueryExecutor(blockStore blkstorage.BlockStore)(ledger.HistoryQueryExecutor, error)//提交Block入historyDBCommit(block *common.Block) error//获取savePointKey,即version.HeightGetLastSavepoint() (*version.Height, error)//是否应该恢复,比较lastAvailableBlock和SavepointShouldRecover(lastAvailableBlock uint64) (bool, uint64, error)//提交丢失的块CommitLostBlock(block *common.Block) error}//代码在core/ledger/kvledger/history/historydb/historydb.go```补充ledger.HistoryQueryExecutor接口定义:执行历史记录查询。

兄弟连区块链教程Fabric1.0源代码分析gRPC Fabric中注册的gRPC Service二

兄弟连区块链教程Fabric1.0源代码分析gRPC Fabric中注册的gRPC Service二

兄弟连区块链教程Fabric1.0源代码分析gRPC(Fabric中注册的gRPC Service)二兄弟连区块链教程Fabric1.0源代码分析gRPC(Fabric中注册的gRPC Service)二。

### 1.3、Endorser Service(背书服务)#### 1.3.1、Endorser Service客户端```gotype EndorserClient interface {ProcessProposal(ctx context.Context, in *SignedProposal,opts ...grpc.CallOption) (*ProposalResponse, error)}type endorserClient struct {cc *grpc.ClientConn}func NewEndorserClient(cc *grpc.ClientConn) EndorserClient {return &endorserClient{cc}}func (c *endorserClient) ProcessProposal(ctx context.Context, in*SignedProposal, opts ...grpc.CallOption) (*ProposalResponse, error) {out := new(ProposalResponse)err := grpc.Invoke(ctx, "/protos.Endorser/ProcessProposal", in, out, , opts...)if err != nil {return nil, err}return out, nil}//代码在protos/peer/peer.pb.go```#### 1.3.2、Endorser Service服务端```gotype EndorserServer interface {ProcessProposal(context.Context, *SignedProposal) (*ProposalResponse, error)}func RegisterEndorserServer(s *grpc.Server, srv EndorserServer) {s.RegisterService(&_Endorser_serviceDesc, srv)}func _Endorser_ProcessProposal_Handler(srv interface{}, ctxcontext.Context, dec func(interface{}) error, interceptorgrpc.UnaryServerInterceptor) (interface{}, error) {in := new(SignedProposal)if err := dec(in); err != nil {return nil, err}if interceptor == nil {return srv.(EndorserServer).ProcessProposal(ctx, in)}info := &grpc.UnaryServerInfo{Server: srv,FullMethod: "/protos.Endorser/ProcessProposal",}handler := func(ctx context.Context, req interface{}) (interface{}, error) {return srv.(EndorserServer).ProcessProposal(ctx,req.(*SignedProposal))}return interceptor(ctx, in, info, handler)}var _Endorser_serviceDesc = grpc.ServiceDesc{ServiceName: "protos.Endorser",HandlerType: (*EndorserServer)(nil),Methods: []grpc.MethodDesc{{MethodName: "ProcessProposal",Handler: _Endorser_ProcessProposal_Handler,},},Streams: []grpc.StreamDesc{},Metadata: "peer/peer.proto",}//代码在protos/peer/peer.pb.go```### 1.4、ChaincodeSupport Service(链码支持服务)#### 1.4.1、ChaincodeSupport Service客户端```gotype ChaincodeSupportClient interface {Register(ctx context.Context, opts ...grpc.CallOption) (ChaincodeSupport_RegisterClient, error)}type chaincodeSupportClient struct {cc *grpc.ClientConn}func NewChaincodeSupportClient(cc *grpc.ClientConn) ChaincodeSupportClient {return &chaincodeSupportClient{cc}}func (c *chaincodeSupportClient) Register(ctx context.Context,opts ...grpc.CallOption) (ChaincodeSupport_RegisterClient, error) { stream, err := grpc.NewClientStream(ctx,&_ChaincodeSupport_serviceDesc.Streams[0], ,"/protos.ChaincodeSupport/Register", opts...)if err != nil {return nil, err}x := &chaincodeSupportRegisterClient{stream}return x, nil}//代码在protos/peer/peer.pb.go```#### 1.4.2、ChaincodeSupport Service服务端```gotype ChaincodeSupportServer interface {Register(ChaincodeSupport_RegisterServer) error}func RegisterChaincodeSupportServer(s *grpc.Server, srv ChaincodeSupportServer) {s.RegisterService(&_ChaincodeSupport_serviceDesc, srv)}func _ChaincodeSupport_Register_Handler(srv interface{}, streamgrpc.ServerStream) error {returnsrv.(ChaincodeSupportServer).Register(&chaincodeSupportRegisterServer{s tream})}var _ChaincodeSupport_serviceDesc = grpc.ServiceDesc{ServiceName: "protos.ChaincodeSupport",HandlerType: (*ChaincodeSupportServer)(nil),Methods: []grpc.MethodDesc{},Streams: []grpc.StreamDesc{{StreamName: "Register",Handler: _ChaincodeSupport_Register_Handler,ServerStreams: true,ClientStreams: true,},},Metadata: "peer/chaincode_shim.proto",}//代码在protos/peer/peer.pb.go```### 1.5、Gossip Service(Gossip服务)#### 1.5.1、Gossip Service客户端```gotype GossipClient interface {// GossipStream is the gRPC stream used for sending and receiving messagesGossipStream(ctx context.Context, opts ...grpc.CallOption)(Gossip_GossipStreamClient, error)// Ping is used to probe a remote peer's alivenessPing(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*Empty, error)}type gossipClient struct {cc *grpc.ClientConn}func NewGossipClient(cc *grpc.ClientConn) GossipClient {return &gossipClient{cc}}func (c *gossipClient) GossipStream(ctx context.Context,opts ...grpc.CallOption) (Gossip_GossipStreamClient, error) {stream, err := grpc.NewClientStream(ctx,&_Gossip_serviceDesc.Streams[0], , "/gossip.Gossip/GossipStream", opts...)if err != nil {return nil, err}x := &gossipGossipStreamClient{stream}return x, nil}type Gossip_GossipStreamClient interface {Send(*Envelope) errorRecv() (*Envelope, error)grpc.ClientStream}type gossipGossipStreamClient struct {grpc.ClientStream}func (x *gossipGossipStreamClient) Send(m *Envelope) error {return x.ClientStream.SendMsg(m)}func (x *gossipGossipStreamClient) Recv() (*Envelope, error) {m := new(Envelope)if err := x.ClientStream.RecvMsg(m); err != nil {return nil, err}return m, nil}func (c *gossipClient) Ping(ctx context.Context, in *Empty,opts ...grpc.CallOption) (*Empty, error) {out := new(Empty)err := grpc.Invoke(ctx, "/gossip.Gossip/Ping", in, out, , opts...) if err != nil {return nil, err}return out, nil}//代码在protos/gossip/message.pb.go```#### 1.5.2、Gossip Serviced服务端```gotype GossipServer interface {// GossipStream is the gRPC stream used for sending and receiving messagesGossipStream(Gossip_GossipStreamServer) error// Ping is used to probe a remote peer's alivenessPing(context.Context, *Empty) (*Empty, error)}func RegisterGossipServer(s *grpc.Server, srv GossipServer) {s.RegisterService(&_Gossip_serviceDesc, srv)}func _Gossip_GossipStream_Handler(srv interface{}, streamgrpc.ServerStream) error {returnsrv.(GossipServer).GossipStream(&gossipGossipStreamServer{stream})}type Gossip_GossipStreamServer interface {Send(*Envelope) errorRecv() (*Envelope, error)grpc.ServerStream}type gossipGossipStreamServer struct {grpc.ServerStream}func (x *gossipGossipStreamServer) Send(m *Envelope) error {return x.ServerStream.SendMsg(m)}func (x *gossipGossipStreamServer) Recv() (*Envelope, error) {m := new(Envelope)if err := x.ServerStream.RecvMsg(m); err != nil {return nil, err}return m, nil}func _Gossip_Ping_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {in := new(Empty)if err := dec(in); err != nil {return nil, err}if interceptor == nil {return srv.(GossipServer).Ping(ctx, in)}info := &grpc.UnaryServerInfo{Server: srv,FullMethod: "/gossip.Gossip/Ping",}handler := func(ctx context.Context, req interface{}) (interface{}, error) {return srv.(GossipServer).Ping(ctx, req.(*Empty))}return interceptor(ctx, in, info, handler)}var _Gossip_serviceDesc = grpc.ServiceDesc{ServiceName: "gossip.Gossip",HandlerType: (*GossipServer)(nil),Methods: []grpc.MethodDesc{{MethodName: "Ping",Handler: _Gossip_Ping_Handler,},},Streams: []grpc.StreamDesc{{StreamName: "GossipStream",Handler: _Gossip_GossipStream_Handler,ServerStreams: true,ClientStreams: true,},},Metadata: "gossip/message.proto",}//代码在protos/gossip/message.pb.go```## 2、Orderer节点中注册的gRPC Service### 2.1、AtomicBroadcast Service(广播服务)#### 2.1.1、AtomicBroadcast Service客户端```gotype AtomicBroadcastClient interface {// broadcast receives a reply of Acknowledgement for eachcommon.Envelope in order, indicating success or type of failureBroadcast(ctx context.Context, opts ...grpc.CallOption) (AtomicBroadcast_BroadcastClient, error)// deliver first requires an Envelope of type DELIVER_SEEK_INFO with Payload data as a mashaled SeekInfo message, then a stream of block replies is received.Deliver(ctx context.Context, opts ...grpc.CallOption) (AtomicBroadcast_DeliverClient, error)}type atomicBroadcastClient struct {cc *grpc.ClientConn}func NewAtomicBroadcastClient(cc *grpc.ClientConn) AtomicBroadcastClient {return &atomicBroadcastClient{cc}}func (c *atomicBroadcastClient) Broadcast(ctx context.Context,opts ...grpc.CallOption) (AtomicBroadcast_BroadcastClient, error) {stream, err := grpc.NewClientStream(ctx,&_AtomicBroadcast_serviceDesc.Streams[0], ,"/orderer.AtomicBroadcast/Broadcast", opts...)if err != nil {return nil, err}x := &atomicBroadcastBroadcastClient{stream}return x, nil}func (c *atomicBroadcastClient) Deliver(ctx context.Context,opts ...grpc.CallOption) (AtomicBroadcast_DeliverClient, error) {stream, err := grpc.NewClientStream(ctx,&_AtomicBroadcast_serviceDesc.Streams[1], ,"/orderer.AtomicBroadcast/Deliver", opts...)if err != nil {return nil, err}x := &atomicBroadcastDeliverClient{stream}return x, nil}//代码在protos/orderer/ab.pb.go```#### 2.1.2、AtomicBroadcast Service服务端```gotype AtomicBroadcastServer interface {// broadcast receives a reply of Acknowledgement for eachcommon.Envelope in order, indicating success or type of failureBroadcast(AtomicBroadcast_BroadcastServer) error// deliver first requires an Envelope of type DELIVER_SEEK_INFO with Payload data as a mashaled SeekInfo message, then a stream of block replies is received.Deliver(AtomicBroadcast_DeliverServer) error}func RegisterAtomicBroadcastServer(s *grpc.Server, srv AtomicBroadcastServer) {s.RegisterService(&_AtomicBroadcast_serviceDesc, srv)}func _AtomicBroadcast_Broadcast_Handler(srv interface{}, streamgrpc.ServerStream) error {returnsrv.(AtomicBroadcastServer).Broadcast(&atomicBroadcastBroadcastServer{s tream})}func _AtomicBroadcast_Deliver_Handler(srv interface{}, streamgrpc.ServerStream) error {returnsrv.(AtomicBroadcastServer).Deliver(&atomicBroadcastDeliverServer{strea m})}var _AtomicBroadcast_serviceDesc = grpc.ServiceDesc{ServiceName: "orderer.AtomicBroadcast",HandlerType: (*AtomicBroadcastServer)(nil),Methods: []grpc.MethodDesc{},Streams: []grpc.StreamDesc{{StreamName: "Broadcast",Handler: _AtomicBroadcast_Broadcast_Handler,ServerStreams: true,ClientStreams: true,},{StreamName: "Deliver",Handler: _AtomicBroadcast_Deliver_Handler,ServerStreams: true,ClientStreams: true,},},Metadata: "orderer/ab.proto",}//代码在protos/orderer/ab.pb.go```感谢关注兄弟连区块链教程分享!。

兄弟连区块链技术培训Fabric 1.0源代码分析(12)cryptogen(生成组织关系和身份证书)

兄弟连区块链技术培训Fabric 1.0源代码分析(12)cryptogen(生成组织关系和身份证书)

兄弟连区块链技术培训Fabric 1.0源代码分析(12)cryptoge n(生成组织关系和身份证书)# Fabric 1.0源代码笔记之 cryptogen(生成组织关系和身份证书)## 1、cryptogen概述cryptogen,用于生成组织关系和身份证书。

命令为:cryptogen generate --config=./crypto-config.yaml --output ./crypt o-config## 2、crypto-config.yaml文件示例```bashOrdererOrgs:- Name: OrdererDomain: Specs:- Hostname: ordererPeerOrgs:- Name: Org1Domain: Template:Count: 2Users:Count: 1- Name: Org2Domain: Template:Count: 2Users:Count: 1```## 3、组织关系和身份证书目录结构(简略版)```bashtree -L 5 crypto-configcrypto-config├── ordererOrganizations│└── │├── ca││├── 1366fb109b24c50e67c28b2ca4dca559eff79a85d53f833c8b9e89efdb4 f4818_sk││└── -cert.pem│├── msp││├── admincerts│││└── Admin@-cert.pem││├── cacerts│││└── -cert.pem││└── tlscacerts││└── -cert.pem│├── orderers││└── ││├── msp││└── tls│├── tlsca││├── 1a1c0f88ee3c8c49c4a48c711ee7467675ce34d92733b02fbf221834eab 4053b_sk││└── -cert.pem│└── users│└── Admin@│├── msp│└── tls└── peerOrganizations├── │├── ca││├── -cert.pem││└── db8cc18ebcac9670df5ec1c1e7fcdc359d70a0b1d82adeab012eea9f513 1850b_sk│├── msp││├── admincerts│││└── Admin@-cert.pem││├── cacerts│││└── 1.exam -cert.pem││└── tlscacerts││└── -cert.pem│├── peers││├── │││├── msp│││└── tls││└── ││├── msp││└── tls│├── tlsca││├── 57dcbe74092cb46f126f1e9a58f9fd225d728a1b9b5b87383ece059476d 48b40_sk││└── -cert.pem│└── users│├── Admin@││├── msp││└── tls│└── User1@│├── msp│└── tls└── ├── ca│├── 8a2b52e8deda65a3a6e16c68d86aa8c4a25f0c35921f53ce2959e9f2bca956c c_sk│└── -cert.pem├── msp│├── admincerts││└── Admin@-cert.pem│├── cacerts││└── -cert.pem│└── tlscacerts│└── -cert.pem├── peers│├── ││├── msp││└── tls│└── │├── msp│└── tls├── tlsca│├── acd26c09f5c89d891d3806c8d1d71e2c442ee9a58521d981980a1d45ab4ba66 6_sk│└── -cert.pem└── users├── Admin@│├── msp│└── tls└── User1@├── msp└── tls59 directories, 21 files```## 4、组织关系和身份证书目录结构(完整版)```bashtree crypto-configcrypto-config├── ordererOrganizations│└── │├── ca││├── 1366fb109b24c50e67c28b2ca4dca559eff79a85d53f833c8b9e89efdb4 f4818_sk││└── -cert.pem│├── msp││├── admincerts│││└── Admin@-cert.pem││├── cacerts│││└── -cert.pem││└── tlscacerts││└── -cert.pem│├── orderers││└── ││├── msp│││├── admincerts││││└── Admin@-cert.pem│││├── cacerts││││└── -cert.pem│││├── keystore││││└── 71a37b3827738ec705ae92cc69adcaee1661d2445501b4189c5 76db9443c1edd_sk│││├── signcerts││││└── or -cert.pem│││└── tlscacerts│││└── -cert.pem││└── tls││├── ca.crt││├── server.crt││└── server.key│├── tlsca││├── 1a1c0f88ee3c8c49c4a48c711ee7467675ce34d92733b02fbf221834eab 4053b_sk││└── -cert.pem│└── users│└── Admin@│├── msp││├── admincerts│││└── Admin@-cert.pem││├── cacerts│││└── -cert.pem││├── keystore│││└── 0830c91efdcf15869e4c8b1cb9de5774376eff5ef1b447f1c5642b8 c4ebef9d5_sk││├── signcerts│││└── Admin@-cert.pem││└── tlscacerts││└── -cert.pem│└── tls│├── ca.crt│├── server.crt│└── server.key└── peerOrganizations├── │├── ca││├── -cert.pem││└── db8cc18ebcac9670df5ec1c1e7fcdc359d70a0b1d82adeab012eea9f513 1850b_sk│├── msp││├── admincerts│││└── Admin@-cert.pem││├── cacerts│││└── -cert.pem││└── tlscacerts││└── -cert.pem│├── peers││├── │││├── msp││││├── admincerts│││││└── Admin@-cert.pem││││├── cacerts│││││└── -cert.pem││││├── keystore│││││└── 840f933728d2d1e2406768147f1c50d0f64fa0fd01901e5 bb07f622462fd6ab6_sk││││├── signcerts│││││└── -cert.pem││││└── tlscacerts││││└── -cert.pem│││└── tls│││├── ca.crt│││├── server.crt│││└── server.key││└── ││├── msp│││├── admincerts││││└── Admin@-cert.pem│││├── cacerts││││└── -cert.pem│││├── keystore││││└── 19b17095ed9a62378004727148aa5dfb70dfcd1275ce9a77d18 7fb84d1703971_sk│││├── signcerts││││└── -cert.pem│││└── tlscacerts│││└── -cert.pem││└── tls││├── ca.crt││├── server.crt││└── server.key│├── tlsca││├── 57dcbe74092cb46f126f1e9a58f9fd225d728a1b9b5b87383ece059476d 48b40_sk││└── -cert.pem│└── users│├── Admin@││├── msp│││├── admincerts││││└── Admin@-cert.pem│││├── cacerts││││└── -cert.pem│││├── keystore││││└── 2cb5be9ab061194b10d558302be57699516493dbe5b567e5cca dcd8157462601_sk│││├── signcerts││││└── Admin@-cert.pem│││└── tlscacerts│││└── -cert.pem││└── tls││├── ca.crt││├── server.crt││└── server.key│└── User1@│├── msp││├── admincerts│││└── User1@-cert.pem││├── cacerts│││└── -cert.pem││├── keystore│││└── 32c9696f3572dfc03eddb240ea4f0e8962a171ff86e60c42993b7f6 8eaaab123_sk││├── signcerts│││└── User1@-cert.pem││└── tlscacerts││└── -cert.pem│└── tls│├── ca.crt│├── server.crt│└── server.key└── ├── ca│├── 8a2b52e8deda65a3a6e16c68d86aa8c4a25f0c35921f53ce2959e9f2bca956c c_sk│└── -cert.pem├── msp│├── admincerts││└── Admin@-cert.pem│├── cacerts││└── -cert.pem│└── tlscacerts│└── -cert.pem├── peers│├── ││├── msp│││├── admincerts││││└── Admin@-cert.pem│││├── cacerts││││└── -cert.pem│││├── keystore││││└── 309fdb2f24b215f4cb097ade93b5b4c4dbda517fc646ddec572 b3d8e24fa3b6c_sk│││├── signcerts││││└── -cert.pem│││└── tlscacerts│││└── -cert.pem││└── tls││├── ca.crt││├── server.crt││└── server.key│└── │├── msp││├── admincerts│││└── Admin@-cert.pem││├── cacerts│││└── -cert.pem││├── keystore│││└── 97b1fdcaab782d0f768dbd9ef867fafe246c27fd471782330cba0d0 e36898516_sk││├── signcerts│││└── -cert.pem││└── tlscacerts││└── -cert.pem│└── tls│├── ca.crt│├── server.crt│└── server.key├── tlsca│├── acd26c09f5c89d891d3806c8d1d71e2c442ee9a58521d981980a1d45ab4ba66 6_sk│└── -cert.pem└── users├── Admin@│├── msp││├── admincerts│││└── Admin@-cert.pem││├── cacerts│││└── -cert.pem││├── keystore│││└── ea0f817adb699880824dbcefb7f88d439ee590c09e64a2f42ff3947 3c5cc1ea9_sk││├── signcerts│││└── Admin@-cert.pem││└── tlscacerts││└── -cert.pem│└── tls│├── ca.crt│├── server.crt│└── server.key└── User1@├── msp│├── admincerts││└── User1@-cert.pem│├── cacerts││└── -cert.pem│├── keystore││└── db11744d4c4a66ee04f783498d896099b275bd2cd2e2e2c188bde880041 d8b1e_sk│├── signcerts││└── User1@-cert.pem│└── tlscacerts│└── -cert.pem└── tls├── ca.crt├── server.crt└── server.key109 directories, 101 files```目录结构解读:* 每个组织下,都包括ca、tlsca、msp、peers(或orderers)、users5个目录。

兄弟连区块链技术培训Fabric 1.0源代码分析(31) Peer

兄弟连区块链技术培训Fabric 1.0源代码分析(31) Peer

兄弟连区块链技术培训Fabric 1.0源代码分析(31) Peer# Fabric 1.0源代码笔记之 Peer## 1、Peer概述在Fabric中,Peer(节点)是指在网络中负责接收交易请求、维护一致账本的各个fabr ic-peer实例。

节点之间彼此通过gRPC通信。

按角色划分,Peer包括两种类型:* Endorser(背书者):负责对来自客户端的交易提案进行检查和背书。

* Committer(提交者):负责检查交易请求,执行交易并维护区块链和账本结构。

Peer核心代码在peer目录下,其他相关代码分布在core/peer和protos/peer目录下。

目录结构如下:* peer目录:* main.go,peer命令入口。

* node目录,peer node命令及子命令peer node start和peer node status实现。

* node.go,peer node命令入口。

* start.go,peer node start子命令实现。

* status.go,peer node status子命令实现。

* channel目录,peer channel命令及子命令实现。

* chaincode目录,peer chaincode命令及子命令实现。

* clilogging目录,peer clilogging命令及子命令实现。

* version目录,peer version命令实现。

* common目录,peer相关通用代码。

* common.go,部分公共函数。

* ordererclient.go,BroadcastClient接口及实现。

* gossip目录,gossip最终一致性算法相关代码。

* core/peer目录:* config.go,Peer配置相关工具函数。

* peer.go,Peer服务相关工具函数。

* core/endorser目录:背书服务端。

如下为分节说明Peer代码:* [Fabric 1.0源代码笔记之 Peer #peer根命令入口及加载子命令](peer_main.md) * [Fabric 1.0源代码笔记之 Peer #peer node start命令实现](peer_node_start. md)* [Fabric 1.0源代码笔记之 Peer #peer channel命令及子命令实现](peer_chann el.md)* [Fabric 1.0源代码笔记之 Peer #peer chaincode命令及子命令实现](peer_cha incode.md)* [Fabric 1.0源代码笔记之 Peer #EndorserClient(Endorser客户端)](Endors erClient.md)* [Fabric 1.0源代码笔记之 Peer #EndorserServer(Endorser服务端)](Endors erServer.md)* [Fabric 1.0源代码笔记之 Peer #BroadcastClient(Broadcast客户端)](Broa dcastClient.md)* [Fabric 1.0源代码笔记之 Peer #committer(提交者)](committer.md)## 2、Peer配置相关工具函数```go//为全局变量localAddress和peerEndpoint赋值func CacheConfiguration() (err error)func cacheConfiguration() //调用CacheConfiguration()//获取localAddressfunc GetLocalAddress() (string, error)//获取peerEndpointfunc GetPeerEndpoint() (*pb.PeerEndpoint, error)//获取Peer安全配置func GetSecureConfig() (comm.SecureServerConfig, error)//代码在core/peer/config.go```PeerEndpoint结构体定义如下:```gotype PeerID struct {Name string}type PeerEndpoint struct {Id *PeerIDAddress string}//代码在protos/peer/peer.pb.go```SecureServerConfig结构体定义如下:```gotype SecureServerConfig struct {ServerCertificate []byte //签名公钥,取自peer.tls.cert.fileServerKey []byte //签名私钥,取自peer.tls.key.fileServerRootCAs [][]byte //根CA证书,取自peer.tls.rootcert.fileClientRootCAs [][]byteUseTLS bool //是否启用TLS,取自peer.tls.enabledRequireClientCert bool}//代码在core/comm/server.go```## 3、Peer服务相关工具函数```gofunc (cs *chainSupport) Ledger() ledger.PeerLedgerfunc (cs *chainSupport) GetMSPIDs(cid string) []stringfunc MockInitialize()func MockSetMSPIDGetter(mspIDGetter func(string) []string)func Initialize(init func(string)) //Peer初始化,并部署系统链码func InitChain(cid string)func getCurrConfigBlockFromLedger(ledger ledger.PeerLedger) (*common.Bl ock, error)func createChain(cid string, ledger ledger.PeerLedger, cb *common.Bloc k) errorfunc CreateChainFromBlock(cb *common.Block) errorfunc MockCreateChain(cid string) errorfunc GetLedger(cid string) ledger.PeerLedgerfunc GetPolicyManager(cid string) policies.Managerfunc GetCurrConfigBlock(cid string) *common.Blockfunc updateTrustedRoots(cm configtxapi.Manager)func buildTrustedRootsForChain(cm configtxapi.Manager)func GetMSPIDs(cid string) []stringfunc SetCurrConfigBlock(block *common.Block, cid string) errorfunc NewPeerClientConnection() (*grpc.ClientConn, error)func GetLocalIP() stringfunc NewPeerClientConnectionWithAddress(peerAddress string) (*grpc.Clie ntConn, error)func GetChannelsInfo() []*pb.ChannelInfo//构造type channelPolicyManagerGetter struct{}func NewChannelPolicyManagerGetter() policies.ChannelPolicyManagerGette rfunc (c *channelPolicyManagerGetter) Manager(channelID string) (policie s.Manager, bool)func CreatePeerServer(listenAddress string,secureConfig comm.SecureServ erConfig) (comm.GRPCServer, error)func GetPeerServer() comm.GRPCServer//代码在core/peer/peer.go。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

兄弟连区块链技术培训Fabric 1.0源代码分析(25) Ord erer# Fabric 1.0源代码笔记之 Orderer## 1、Orderer概述Orderer,为排序节点,对所有发往网络中的交易进行排序,将排序后的交易安排配置中的约定整理为块,之后提交给Committer进行处理。

Orderer代码分布在orderer目录,目录结构如下:* orderer目录* main.go,main入口。

* util.go,orderer工具函数。

* metadata目录,metadata.go实现获取版本信息。

* localconfig目录,config.go,本地配置相关实现。

* ledger目录,账本区块存储。

* file目录,账本区块文件存储。

* json目录,账本区块json文件存储。

* ram目录,账本区块内存存储。

* common目录,通用代码。

* bootstrap目录,初始区块的提供方式。

# Fabric 1.0源代码笔记之 Orderer #orderer start命令实现## 1、加载命令行工具并解析命令行参数orderer的命令行工具,基于gopkg.in/alecthomas/kingpin.v2实现,地址:http:/ /gopkg.in/alecthomas/kingpin.v2。

相关代码如下```govar (//创建kingpin.Applicationapp = kingpin.New("orderer", "Hyperledger Fabric orderer node")//创建子命令start和versionstart = mand("start", "Start the orderer node").Default()version = mand("version", "Show version information"))kingpin.Version("0.0.1")//解析命令行参数switch kingpin.MustParse(app.Parse(os.Args[1:])) {case start.FullCommand()://orderer start的命令实现,下文展开讲解case version.FullCommand()://输出版本信息fmt.Println(metadata.GetVersionInfo())}//代码在orderer/main.go```metadata.GetVersionInfo()代码如下:```gofunc GetVersionInfo() string {Version = common.Version //var Version string,全局变量if Version == "" {Version = "development build"}return fmt.Sprintf("%s:\n Version: %s\n Go version: %s\n OS/Arch: %s ",ProgramName, Version, runtime.Version(),fmt.Sprintf("%s/%s", runtime.GOOS, runtime.GOARCH))}//代码在orderer/metadata/metadata.go```## 2、加载配置文件配置文件的加载,基于viper实现,即https:///spf13/viper。

```goconf := config.Load()//代码在orderer/main.go```conf := config.Load()代码如下:```gofunc Load() *TopLevel {config := viper.New()//cf.InitViper作用为加载配置文件路径及设置配置文件名称cf.InitViper(config, configName) //configName = strings.ToLower(Pref ix),其中Prefix = "ORDERER"config.SetEnvPrefix(Prefix) //Prefix = "ORDERER"config.AutomaticEnv()replacer := strings.NewReplacer(".", "_")config.SetEnvKeyReplacer(replacer)err := config.ReadInConfig() //加载配置文件内容var uconf TopLevel//将配置文件内容输出到结构体中err = viperutil.EnhancedExactUnmarshal(config, &uconf)//完成初始化,即检查空项,并赋默认值pleteInitialization(filepath.Dir(config.ConfigFileUsed()))return &uconf}//代码在orderer/localconfig/config.go```TopLevel结构体及本地配置更详细内容,参考:[Fabric 1.0源代码笔记之 Orderer # localconfig(Orderer配置文件定义)](localconfig.md)## 3、初始化日志系统(日志输出、日志格式、日志级别、sarama日志)```goinitializeLoggingLevel(conf)//代码在orderer/main.go```initializeLoggingLevel(conf)代码如下:```gofunc initializeLoggingLevel(conf *config.TopLevel) {//初始化日志输出对象及输出格式flogging.InitBackend(flogging.SetFormat(conf.General.LogFormat), os. Stderr)//按初始化日志级别flogging.InitFromSpec(conf.General.LogLevel)if conf.Kafka.Verbose {//sarama为go语言版kafka客户端sarama.Logger = log.New(os.Stdout, "[sarama] ", log.Ldate|log.Lm icroseconds|log.Lshortfile)}}//代码在orderer/main.go```## 4、启动Go profiling服务(Go语言分析工具)```goinitializeProfilingService(conf)//代码在orderer/main.go```initializeProfilingService(conf)代码如下:```gofunc initializeProfilingService(conf *config.TopLevel) {if conf.General.Profile.Enabled { //是否启用Go profilinggo func() {//Go profiling绑定的监听地址和端口("Starting Go pprof profiling service on:", conf. General.Profile.Address)//启动Go profiling服务logger.Panic("Go pprof service failed:", http.ListenAndServe (conf.General.Profile.Address, nil))}()}}//代码在orderer/main.go```## 5、创建Grpc Server```gogrpcServer := initializeGrpcServer(conf)//代码在orderer/main.go```initializeGrpcServer(conf)代码如下:```gofunc initializeGrpcServer(conf *config.TopLevel) comm.GRPCServer {//按conf初始化安全服务器配置secureConfig := initializeSecureServerConfig(conf)//创建net.Listenlis, err := net.Listen("tcp", fmt.Sprintf("%s:%d", conf.General.List enAddress, conf.General.ListenPort))//创建GRPC ServergrpcServer, err := comm.NewGRPCServerFromListener(lis, secureConfig) return grpcServer}//代码在orderer/main.go```## 6、初始化本地MSP并获取签名```goinitializeLocalMsp(conf)signer := localmsp.NewSigner() //return &mspSigner{}//代码在orderer/main.go```initializeLocalMsp(conf)代码如下:```gofunc initializeLocalMsp(conf *config.TopLevel) {//从指定目录加载本地MSPerr := mspmgmt.LoadLocalMsp(conf.General.LocalMSPDir, conf.General.B CCSP, conf.General.LocalMSPID)}//代码在orderer/main.go```## 7、初始化MultiChain管理器(启动共识插件goroutine,接收和处理消息)```gomanager := initializeMultiChainManager(conf, signer)//代码在orderer/main.go```initializeMultiChainManager(conf, signer)代码如下:```gofunc initializeMultiChainManager(conf *config.TopLevel, signer crypto.Lo calSigner) multichain.Manager {lf, _ := createLedgerFactory(conf) //创建LedgerFactoryif len(lf.ChainIDs()) == 0 { //链不存在initializeBootstrapChannel(conf, lf) //初始化引导通道(获取初始区块、创建链、添加初始区块)} else {//链已存在}consenters := make(map[string]multichain.Consenter) //共识consenters["solo"] = solo.New()consenters["kafka"] = kafka.New(conf.Kafka.TLS, conf.Kafka.Retry, co nf.Kafka.Version)return multichain.NewManagerImpl(lf, consenters, signer) //LedgerFac tory、Consenter、签名}//代码在orderer/main.go```initializeBootstrapChannel(conf, lf)代码如下:```gofunc initializeBootstrapChannel(conf *config.TopLevel, lf ledger.Factory) {var genesisBlock *cb.Blockswitch conf.General.GenesisMethod { //初始区块的提供方式case "provisional": //根据GenesisProfile提供genesisBlock = provisional.New(genesisconfig.Load(conf.General.G enesisProfile)).GenesisBlock()case "file": //指定现成的初始区块文件genesisBlock = file.New(conf.General.GenesisFile).GenesisBlock() default:logger.Panic("Unknown genesis method:", conf.General.GenesisMeth od)}chainID, err := utils.GetChainIDFromBlock(genesisBlock) //获取ChainI Dgl, err := lf.GetOrCreate(chainID) //获取或创建chainerr = gl.Append(genesisBlock) //追加初始区块}//代码在orderer/main.go```## 8、注册orderer service并启动grpcServer```goserver := NewServer(manager, signer) //构造serverab.RegisterAtomicBroadcastServer(grpcServer.Server(), server) //service 注册到grpcServergrpcServer.Start()//代码在orderer/main.go```server := NewServer(manager, signer)代码如下:```gofunc NewServer(ml multichain.Manager, signer crypto.LocalSigner) ab.Atom icBroadcastServer {s := &server{dh: deliver.NewHandlerImpl(deliverSupport{Manager: ml}),bh: broadcast.NewHandlerImpl(broadcastSupport{Manager: ml,ConfigUpdateProcessor: configupdate.New(ml.SystemChannelID(), configUpdateSupport{Manager: ml}, signer),}),}return s}//代码在orderer/server.go```。

相关文档
最新文档