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

合集下载

兄弟连区块链技术培训Fabric 1.0源代码分析(4) Chaincode(链码) platforms(链码语言平台)

兄弟连区块链技术培训Fabric 1.0源代码分析(4) Chaincode(链码) platforms(链码语言平台)

兄弟连区块链技术培训Fabric 1.0源代码分析(4)Chain code(链码)#platforms(链码语言平台)Fabric 1.0源代码笔记之 Chaincode(链码) #platforms(链码语言平台)## 1、platforms概述platforms代码集中在core/chaincode/platforms目录下。

* core/chaincode/platforms目录,链码的编写语言平台实现,如golang或java。

* platforms.go,Platform接口定义,及platforms相关工具函数。

* util目录,Docker相关工具函数。

* java目录,java语言平台实现。

* golang目录,golang语言平台实现。

## 2、Platform接口定义```gotype Platform interface {//验证ChaincodeSpecValidateSpec(spec *pb.ChaincodeSpec) error//验证ChaincodeDeploymentSpecValidateDeploymentSpec(spec *pb.ChaincodeDeploymentSpec) error//获取部署PayloadGetDeploymentPayload(spec *pb.ChaincodeSpec) ([]byte, error)//生成DockerfileGenerateDockerfile(spec *pb.ChaincodeDeploymentSpec) (string, erro r)//生成DockerBuildGenerateDockerBuild(spec *pb.ChaincodeDeploymentSpec, tw *tar.Write r) error}//代码在core/chaincode/platforms/platforms.go```## 3、platforms相关工具函数### 3.1、platforms相关工具函数```go//按链码类型构造Platform接口实例,如golang.Platform{}func Find(chaincodeType pb.ChaincodeSpec_Type) (Platform, error)//调取platform.GetDeploymentPayload(spec),获取部署Payloadfunc GetDeploymentPayload(spec *pb.ChaincodeSpec) ([]byte, error)//优先获取tls根证书,如无则获取tls证书func getPeerTLSCert() ([]byte, error)//调取platform.GenerateDockerfile(cds),创建Dockerfilefunc generateDockerfile(platform Platform, cds *pb.ChaincodeDeploymentS pec, tls bool) ([]byte, error)//调取platform.GenerateDockerBuild(cds, tw),创建DockerBuildfunc generateDockerBuild(platform Platform, cds *pb.ChaincodeDeployment Spec, inputFiles InputFiles, tw *tar.Writer) error//调取generateDockerfile(platform, cds, cert != nil)func GenerateDockerBuild(cds *pb.ChaincodeDeploymentSpec) (io.Reader, e rror)//代码在core/chaincode/platforms/platforms.go```### 3.2、Docker相关工具函数```go//contents+hash合并后再哈希func ComputeHash(contents []byte, hash []byte) []byte//哈希目录下文件并打包func HashFilesInDir(rootDir string, dir string, hash []byte, tw *tar.Wr iter) ([]byte, error)//目录是否存在func IsCodeExist(tmppath string) error//编译链码func DockerBuild(opts DockerBuildOptions) error//代码在core/chaincode/platforms/util/utils.go```func DockerBuild(opts DockerBuildOptions) error代码如下:```gotype DockerBuildOptions struct {Image stringEnv []stringCmd stringInputStream io.ReaderOutputStream io.Writer}func DockerBuild(opts DockerBuildOptions) error {client, err := cutil.NewDockerClient()if err != nil {return fmt.Errorf("Error creating docker client: %s", err)}if opts.Image == "" {//通用的本地编译环境opts.Image = cutil.GetDockerfileFromConfig("chaincode.builder") }//确认镜像是否存在或从远程拉取_, err = client.InspectImage(opts.Image)if err != nil {err = client.PullImage(docker.PullImageOptions{Repository: opts. Image}, docker.AuthConfiguration{})}//创建一个暂时的容器container, err := client.CreateContainer(docker.CreateContainerOpti ons{Config: &docker.Config{Image: opts.Image,Env: opts.Env,Cmd: []string{"/bin/sh", "-c", opts.Cmd},AttachStdout: true,AttachStderr: true,},})//删除容器defer client.RemoveContainer(docker.RemoveContainerOptions{ID: cont ainer.ID})//上传输入err = client.UploadToContainer(container.ID, docker.UploadToContain erOptions{Path: "/chaincode/input",InputStream: opts.InputStream,})stdout := bytes.NewBuffer(nil)_, err = client.AttachToContainerNonBlocking(docker.AttachToContain erOptions{Container: container.ID,OutputStream: stdout,ErrorStream: stdout,Logs: true,Stdout: true,Stderr: true,Stream: true,})//启动容器err = client.StartContainer(container.ID, nil)//等待容器返回retval, err := client.WaitContainer(container.ID)//获取容器输出err = client.DownloadFromContainer(container.ID, docker.DownloadFro mContainerOptions{Path: "/chaincode/output/.",OutputStream: opts.OutputStream,})return nil}//代码在core/chaincode/platforms/util/utils.go```## 4、golang语言平台实现### 4.1、golang.Platform结构体定义及方法Platform接口golang语言平台实现,即golang.Platform结构体定义及方法。

兄弟连区块链教程Fabric1.0源代码分析blockfile区块文件存储二

兄弟连区块链教程Fabric1.0源代码分析blockfile区块文件存储二

兄弟连区块链教程Fabric1.0源代码分析blockfile区块文件存储二兄弟连区块链教程Fabric1.0源代码分析blockfile区块文件存储二。

涉及方法如下:```go//构造blockIndexfunc newBlockIndex(indexConfig *blkstorage.IndexConfig, db*leveldbhelper.DBHandle) *blockIndex//获取最后一个块索引(或编号),取key为"indexCheckpointKey"的值,即为最新的区块编号func (index *blockIndex) getLastBlockIndexed() (uint64, error)func (index *blockIndex) indexBlock(blockIdxInfo *blockIdxInfo) error //索引区块//根据区块哈希,获取文件区块指针func (index *blockIndex) getBlockLocByHash(blockHash []byte)(*fileLocPointer, error)//根据区块编号,获取文件区块指针func (index *blockIndex) getBlockLocByBlockNum(blockNum uint64)(*fileLocPointer, error)//根据交易ID,获取文件交易指针func (index *blockIndex) getTxLoc(txID string) (*fileLocPointer, error) //根据交易ID,获取文件区块指针func (index *blockIndex) getBlockLocByTxID(txID string) (*fileLocPointer, error)//根据区块编号和交易编号,获取文件交易指针func (index *blockIndex) getTXLocByBlockNumTranNum(blockNum uint64, tranNum uint64) (*fileLocPointer, error)//根据交易ID,获取交易验证代码func (index *blockIndex) getTxValidationCodeByTxID(txID string)(peer.TxValidationCode, error)//代码在common/ledger/blkstorage/fsblkstorage/blockindex.go```补充blockIdxInfo结构体定义:块索引信息。

兄弟连区块链教程Fabric1.0源代码分析流言算法Gossip服务端

兄弟连区块链教程Fabric1.0源代码分析流言算法Gossip服务端

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

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

# Fabric 1.0源代码笔记之 gossip(流言算法) #GossipServer(Gossip服务端)## 1、GossipServer概述GossipServer相关代码,分布在protos/gossip、gossip/comm目录下。

目录结构如下:* protos/gossip目录:* message.pb.go,GossipClient接口定义及实现,GossipServer接口定义。

* gossip/comm目录:* comm.go,Comm接口定义。

* conn.go,connFactory接口定义,以及connectionStore结构体及方法。

* comm_impl.go,commImpl结构体及方法(同时实现GossipServer接口/Comm接口/connFactory接口)。

* demux.go,ChannelDeMultiplexer结构体及方法。

## 2、GossipClient接口定义及实现### 2.1、GossipClient接口定义```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)}//代码在protos/gossip/message.pb.go```### 2.2、GossipClient接口实现```gotype 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}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```### 2.3、Gossip_GossipStreamClient接口定义及实现```gotype 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}//代码在protos/gossip/message.pb.go```## 3、GossipServer接口定义### 3.1、GossipServer接口定义```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})}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```### 3.2、Gossip_GossipStreamServer接口定义及实现```gotype 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}//代码在protos/gossip/message.pb.go```## 4、Comm接口/connFactory接口定义### 4.1、Comm接口定义```gotype Comm interface {//返回此实例的 PKI idGetPKIid() common.PKIidType//向节点发送消息Send(msg *proto.SignedGossipMessage, peers ...*RemotePeer) //探测远程节点是否有响应Probe(peer *RemotePeer) error//握手验证远程节点Handshake(peer *RemotePeer) (api.PeerIdentityType, error) Accept(common.MessageAcceptor) <-chan proto.ReceivedMessage //获取怀疑脱机节点的只读通道PresumedDead() <-chan common.PKIidType//关闭到某个节点的连接CloseConn(peer *RemotePeer)//关闭Stop()}//代码在gossip/comm/comm.go```### 4.2、connFactory接口定义```gotype connFactory interface {createConnection(endpoint string, pkiID common.PKIidType)(*connection, error)}//代码在gossip/comm/conn.go```## 5、commImpl结构体及方法(同时实现GossipServer接口/Comm接口/connFactory 接口)### 5.1、commImpl结构体定义```gotype commImpl struct {selfCertHash []bytepeerIdentity api.PeerIdentityTypeidMapper identity.Mapperlogger *logging.Loggeropts []grpc.DialOptionsecureDialOpts func() []grpc.DialOptionconnStore *connectionStorePKIID []bytedeadEndpoints chan common.PKIidTypemsgPublisher *ChannelDeMultiplexerlock *sync.RWMutexlsnr net.ListenergSrv *grpc.ServerexitChan chan struct{}stopWG sync.WaitGroupsubscriptions []chan proto.ReceivedMessageport intstopping int32}//代码在gossip/comm/comm_impl.go```未完待续欢迎继续关注兄弟连区块链教程分享!。

兄弟连区块链教程Fabric1.0源代码分析Ledger(账本)二

兄弟连区块链教程Fabric1.0源代码分析Ledger(账本)二

兄弟连区块链教程Fabric1.0源代码分析Ledger(账本)二兄弟连区块链教程Fabric1.0源代码分析Ledger(账本)二。

# Fabric 1.0源代码笔记之 Ledger(账本)补充PeerLedger接口嵌入的commonledger.Ledger接口定义如下:```gotype Ledger interface {GetBlockchainInfo() (*common.BlockchainInfo, error) //获取blockchain 基本信息GetBlockByNumber(blockNumber uint64) (*common.Block, error) //按给定高度获取Block,给定math.MaxUint64将获取最新BlockGetBlocksIterator(startBlockNumber uint64) (ResultsIterator, error) //获取从startBlockNumber开始的迭代器(包含startBlockNumber),迭代器是阻塞迭代,直到ledger中下一个block可用Close() //关闭ledgerCommit(block *common.Block) error //提交新block}//代码在common/ledger/ledger_interface.go```ValidatedLedger接口暂未定义方法,从PeerLedger筛选出无效交易后,ValidatedLedger表示最终账本。

暂时忽略。

QueryExecutor接口定义:用于执行查询。

其中Get*方法用于支持KV-based数据模型,ExecuteQuery方法用于支持更丰富的数据和查询支持。

```gotype QueryExecutor interface {GetState(namespace string, key string) ([]byte, error) //按namespace 和key获取value,对于chaincode,chaincodeId即为namespaceGetStateMultipleKeys(namespace string, keys []string) ([][]byte, error) //一次调用获取多个key的值//获取迭代器,返回包括startKey、但不包括endKeyd的之间所有值GetStateRangeScanIterator(namespace string, startKey string, endKey string) (commonledger.ResultsIterator, error)ExecuteQuery(namespace, query string) (commonledger.ResultsIterator, error) //执行查询并返回迭代器,仅用于查询statedbDone() //释放QueryExecutor占用的资源}//代码在core/ledger/ledger_interface.go```HistoryQueryExecutor接口定义:执行历史记录查询。

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```感谢关注兄弟连区块链教程分享!。

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

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

兄弟连区块链技术培训Fabric 1.0源代码分析(37) Peer # DeliverClient(Deliver客户端)# Fabric 1.0源代码笔记之 Peer #DeliverClient(Deliver客户端)## 1、DeliverClient概述DeliverClient代码分布如下:* peer/channel/deliverclient.go,deliverClientIntf接口定义及实现,以及Del iverClient工具函数。

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

## 2、deliverClientIntf接口定义及实现### 2.1、DeliverClient工具函数```go//构造deliverClientfunc newDeliverClient(conn *grpc.ClientConn, client ab.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.Enve lope//r.client.Send(seekHelper(r.chainID, &ab.SeekPosition{Type: &ab.SeekPo sition_Specified{Specified: &ab.SeekSpecified{Number: blockNumber}}})) func (r *deliverClient) seekSpecified(blockNumber uint64) error//r.client.Send(seekHelper(r.chainID, &ab.SeekPosition{Type: &ab.SeekPo sition_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, e rror)//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.Enve lope代码如下:```gofunc seekHelper(chainID string, position *ab.SeekPosition) *common.Enve lope {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_UPD ATE, 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)。

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

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

兄弟连区块链技术培训Fabric 1.0源代码分析(11)consente r(共识插件)filter(过滤器)# Fabric 1.0源代码笔记之 consenter(共识插件) #filter(过滤器)## 1、filter概述filter代码分布在orderer/common/filter、orderer/common/configtxfilter、or derer/common/sizefilter、orderer/common/sigfilter、orderer/multichain目录下。

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

orderer/common/configtxfilter目录,configFilter结构体(实现Rule接口)及c onfigCommitter结构体(实现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, fil mitter) {msgData, err := utils.UnmarshalPayload(message.Payload) //获取Payloa dchdr, err := utils.UnmarshalChannelHeader(msgData.Header.ChannelHea der) //获取ChannelHeaderif chdr.Type != int32(cb.HeaderType_CONFIG) { //配置交易return filter.Forward, nil}configEnvelope, err := configtx.UnmarshalConfigEnvelope(msgData.Dat a) //获取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, filt 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.Ru le //构造sigFilterfunc (sf *sigFilter) Apply(message *cb.Envelope) (filter.Action, filter. Committer) {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.Ru le //构造systemChainFilterfunc (scf *systemChainFilter) Apply(env *cb.Envelope) (filter.Action, f mitter) {msgData := &cb.Payload{}err := proto.Unmarshal(env.Payload, msgData) //获取Payloadchdr, err := utils.UnmarshalChannelHeader(msgData.Header.ChannelHea der)if chdr.Type != int32(cb.HeaderType_ORDERER_TRANSACTION) { //ORDERE R_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.Ru leSet {return filter.NewRuleSet([]filter.Rule{filter.EmptyRejectRule, //EmptyRejectRulesizefilter.MaxBytesRule(ledgerResources.SharedConfig()), //size filtersigfilter.New(policies.ChannelWriters, ledgerResources.PolicyMa nager()), //sigfilterconfigtxfilter.NewFilter(ledgerResources), //configtxfilterfilter.AcceptRule, //AcceptRule})}//为系统链创建过滤器集func createSystemChainFilters(ml *multiLedger, ledgerResources *ledgerR esources) *filter.RuleSet {return filter.NewRuleSet([]filter.Rule{filter.EmptyRejectRule, //EmptyRejectRulesizefilter.MaxBytesRule(ledgerResources.SharedConfig()), //size filtersigfilter.New(policies.ChannelWriters, ledgerResources.PolicyMa nager()), //sigfilternewSystemChainFilter(ledgerResources, ml),configtxfilter.NewFilter(ledgerResources), //configtxfilterfilter.AcceptRule, //AcceptRule})}//代码在orderer/multichain/chainsupport.go```。

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

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

兄弟连区块链技术培训Fabric 1.0源代码分析(35)Peer #E ndorserServer(Endorser服务端)# Fabric 1.0源代码笔记之 Peer #EndorserServer(Endorser服务端)## 1、EndorserServer概述EndorserServer相关代码在protos/peer、core/endorser目录下。

* protos/peer/peer.pb.go,EndorserServer接口定义。

* core/endorser/endorser.go,EndorserServer接口实现,即Endorser结构体及方法,以及Endorser服务端ProcessProposal处理流程。

## 2、EndorserServer接口定义### 2.1、EndorserServer接口定义```gotype EndorserServer interface {ProcessProposal(context.Context, *SignedProposal) (*ProposalRespons e, error)}//代码在protos/peer/peer.pb.go```### 2.2、gRPC相关实现```govar _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",}func RegisterEndorserServer(s *grpc.Server, srv EndorserServer) {s.RegisterService(&_Endorser_serviceDesc, srv)}func _Endorser_ProcessProposal_Handler(srv interface{}, ctx context.Con text, dec func(interface{}) error, interceptor grpc.UnaryServerIntercep tor) (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.(*SignedPr oposal))}return interceptor(ctx, in, info, handler)}//代码在protos/peer/peer.pb.go```## 3、EndorserServer接口实现### 3.1、Endorser结构体及方法```gotype Endorser struct {policyChecker policy.PolicyChecker //策略检查器}//代码在core/endorser/endorser.go```涉及方法如下:```go//构造Endorserfunc NewEndorserServer() pb.EndorserServer//执行提案func (e *Endorser) ProcessProposal(ctx context.Context, signedProp *pb. SignedProposal) (*pb.ProposalResponse, error)//检查SignedProposal是否符合通道策略,调用e.policyChecker.CheckPolicy() func (e *Endorser) checkACL(signedProp *pb.SignedProposal, chdr *common. ChannelHeader, shdr *common.SignatureHeader, hdrext *pb.ChaincodeHeader Extension) error//检查Escc和Vscc,暂未实现func (*Endorser) checkEsccAndVscc(prop *pb.Proposal) error//获取账本的交易模拟器,调用peer.GetLedger(ledgername).NewTxSimulator() func (*Endorser) getTxSimulator(ledgername string) (ledger.TxSimulator, error)//获取账本历史交易查询器,调用peer.GetLedger(ledgername).NewHistoryQueryEx ecutor()func (*Endorser) getHistoryQueryExecutor(ledgername string) (ledger.His toryQueryExecutor, error)//执行链码func (e *Endorser) callChaincode(ctxt context.Context, chainID string, version string, txid string, signedProp *pb.SignedProposal, prop *pb.Pr oposal, cis *pb.ChaincodeInvocationSpec, cid *pb.ChaincodeID, txsim led ger.TxSimulator) (*pb.Response, *pb.ChaincodeEvent, error)func (e *Endorser) disableJavaCCInst(cid *pb.ChaincodeID, cis *pb.Chain codeInvocationSpec) error//通过调用chaincode来模拟提案func (e *Endorser) simulateProposal(ctx context.Context, chainID string, txid string, signedProp *pb.SignedProposal, prop *pb.Proposal, cid *pb. ChaincodeID, txsim ledger.TxSimulator) (*ccprovider.ChaincodeData, *pb. Response, []byte, *pb.ChaincodeEvent, error)//从LSCC获取链码数据func (e *Endorser) getCDSFromLSCC(ctx context.Context, chainID string, txid string, signedProp *pb.SignedProposal, prop *pb.Proposal, chaincod eID string, txsim ledger.TxSimulator) (*ccprovider.ChaincodeData, erro r)//提案背书func (e *Endorser) endorseProposal(ctx context.Context, chainID string, txid string, signedProp *pb.SignedProposal, proposal *pb.Proposal, res ponse *pb.Response, simRes []byte, event *pb.ChaincodeEvent, visibility []byte, ccid *pb.ChaincodeID, txsim ledger.TxSimulator, cd *ccprovider. ChaincodeData) (*pb.ProposalResponse, error)//提交模拟交易,仅测试使用func (e *Endorser) commitTxSimulation(proposal *pb.Proposal, chainID st ring, signer msp.SigningIdentity, pResp *pb.ProposalResponse, blockNumb er uint64) error//代码在core/endorser/endorser.go```### 3.2、Endorser服务端ProcessProposal处理流程Endorser服务端ProcessProposal处理流程,即func (e *Endorser) ProcessPropo sal(ctx context.Context, signedProp *pb.SignedProposal) (*pb.ProposalRe sponse, error)方法实现。

兄弟连区块链教程Fabric1.0源代码分析policy(背书策略)

兄弟连区块链教程Fabric1.0源代码分析policy(背书策略)

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

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

# Fabric 1.0源代码笔记之 policy(背书策略)## 1、policy概述policy代码分布在core/policy、core/policyprovider、common/policies目录下。

目录结构如下:* core/policy/policy.go,PolicyChecker接口定义及实现、PolicyCheckerFactory 接口定义。

* core/policyprovider/provider.go,PolicyChecker工厂默认实现。

* common/policies目录* policy.go,ChannelPolicyManagerGetter接口及实现。

* implicitmeta_util.go,通道策略工具函数。

## 2、PolicyChecker工厂### 2.1、PolicyCheckerFactory接口定义```gotype PolicyCheckerFactory interface {NewPolicyChecker() PolicyChecker //构造PolicyChecker实例}var pcFactory PolicyCheckerFactory //全局变量定义及赋值函数func RegisterPolicyCheckerFactory(f PolicyCheckerFactory) {pcFactory = f}//代码在core/policy/policy.go```### 2.2、PolicyCheckerFactory接口默认实现```gotype defaultFactory struct{}//构造policy.PolicyCheckerfunc (f *defaultFactory) NewPolicyChecker() policy.PolicyChecker {return policy.NewPolicyChecker(peer.NewChannelPolicyManagerGetter(),//&channelPolicyManagerGetter{}mgmt.GetLocalMSP(),mgmt.NewLocalMSPPrincipalGetter(),)}//获取policy.PolicyChecker,即调用policy.GetPolicyChecker()func GetPolicyChecker() policy.PolicyCheckerfunc init() { //初始化全局变量pcFactorypolicy.RegisterPolicyCheckerFactory(&defaultFactory{})}```## 3、PolicyChecker接口定义及实现### 3.1、PolicyChecker接口定义```gotype PolicyChecker interface {CheckPolicy(channelID, policyName string, signedProp*pb.SignedProposal) errorCheckPolicyBySignedData(channelID, policyName string, sd[]*common.SignedData) errorCheckPolicyNoChannel(policyName string, signedProp *pb.SignedProposal) error}//代码在core/policy/policy.go```### 3.2、PolicyChecker接口实现PolicyChecker接口实现,即policyChecker结构体及方法。

兄弟连区块链教程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源代码分析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 ```感谢关注兄弟连区块链教程分享!。

兄弟连区块链技术培训Fabric 1.0源代码分析(5)Chaincode(链码)体系总结

兄弟连区块链技术培训Fabric 1.0源代码分析(5)Chaincode(链码)体系总结

兄弟连区块链技术培训Fabric 1.0源代码分析(5)Chaincod e(链码)体系总结# Fabric 1.0源代码笔记之 Chaincode(链码)## 1、Chaincode概述Chaincode,即链码或智能合约,代码分布在protos/peer目录、core/chaincode和c ore/common/ccprovider目录,目录结构如下:* protos/peer目录:* chaincode.pb.go,ChaincodeDeploymentSpec、ChaincodeInvocationSpec 结构体定义。

* core/chaincode目录:* platforms目录,链码的编写语言平台实现,如golang或java。

* platforms.go,Platform接口定义,及部分工具函数。

* java目录,java语言平台实现。

* golang目录,golang语言平台实现。

* core/common/ccprovider目录:ccprovider相关实现。

## 2、protos相关结构体定义### 2.1、ChaincodeDeploymentSpec结构体定义(用于Chaincode部署)#### 2.1.1 ChaincodeDeploymentSpec结构体定义```gotype ChaincodeDeploymentSpec struct {ChaincodeSpec *ChaincodeSpec //ChaincodeSpec消息EffectiveDate *google_protobuf1.TimestampCodePackage []byte //链码文件打包ExecEnv ChaincodeDeploymentSpec_ExecutionEnvironment //链码执行环境,D OCKER或SYSTEM}type ChaincodeDeploymentSpec_ExecutionEnvironment int32const (ChaincodeDeploymentSpec_DOCKER ChaincodeDeploymentSpec_ExecutionEnv ironment = 0ChaincodeDeploymentSpec_SYSTEM ChaincodeDeploymentSpec_ExecutionEnv ironment = 1)//代码在protos/peer/chaincode.pb.go```#### 2.1.2、ChaincodeSpec结构体定义```gotype ChaincodeSpec struct {Type ChaincodeSpec_Type //链码的编写语言,GOLANG、JAVAChaincodeId *ChaincodeID //ChaincodeId,链码路径、链码名称、链码版本 Input *ChaincodeInput //链码的具体执行参数信息Timeout int32}type ChaincodeSpec_Type int32const (ChaincodeSpec_UNDEFINED ChaincodeSpec_Type = 0ChaincodeSpec_GOLANG ChaincodeSpec_Type = 1ChaincodeSpec_NODE ChaincodeSpec_Type = 2ChaincodeSpec_CAR ChaincodeSpec_Type = 3ChaincodeSpec_JAVA ChaincodeSpec_Type = 4)type ChaincodeID struct {Path stringName stringVersion string}type ChaincodeInput struct { //链码的具体执行参数信息Args [][]byte}//代码在protos/peer/chaincode.pb.go```### 2.2、ChaincodeInvocationSpec结构体定义```gotype ChaincodeInvocationSpec struct {ChaincodeSpec *ChaincodeSpec //参考本文2.2IdGenerationAlg string}//代码在protos/peer/chaincode.pb.go```## 3、ccprovider目录相关实现### 3.1、ChaincodeData结构体```gotype ChaincodeData struct {Name stringVersion stringEscc stringVscc stringPolicy []byte //chaincode 实例的背书策略Data []byteId []byteInstantiationPolicy []byte //实例化策略}//获取ChaincodeData,优先从缓存中读取func GetChaincodeData(ccname string, ccversion string) (*ChaincodeDat a, error)//代码在core/common/ccprovider/ccprovider.go```func GetChaincodeData(ccname string, ccversion string) (*ChaincodeData, error)代码如下:```govar ccInfoFSProvider = &CCInfoFSImpl{}var ccInfoCache = NewCCInfoCache(ccInfoFSProvider)func GetChaincodeData(ccname string, ccversion string) (*ChaincodeDat a, error) {//./peer/node/start.go: ccprovider.EnableCCInfoCache()//如果启用ccInfoCache,优先从缓存中读取ChaincodeDataif ccInfoCacheEnabled {return ccInfoCache.GetChaincodeData(ccname, ccversion)}ccpack, err := ccInfoFSProvider.GetChaincode(ccname, ccversion)return ccpack.GetChaincodeData(), nil}//代码在core/common/ccprovider/ccprovider.go```### 3.2、ccInfoCacheImpl结构体```gotype ccInfoCacheImpl struct {sync.RWMutexcache map[string]*ChaincodeData //ChaincodeDatacacheSupport CCCacheSupport}//构造ccInfoCacheImplfunc NewCCInfoCache(cs CCCacheSupport) *ccInfoCacheImpl//获取ChaincodeData,优先从c.cache中获取,如果c.cache中没有,则从c.cache Support(即CCInfoFSImpl)中获取并写入c.cachefunc (c *ccInfoCacheImpl) GetChaincodeData(ccname string, ccversion str ing) (*ChaincodeData, error)//代码在core/common/ccprovider/ccinfocache.go```func (c *ccInfoCacheImpl) GetChaincodeData(ccname string, ccversion str ing) (*ChaincodeData, error) 代码如下:```gofunc (c *ccInfoCacheImpl) GetChaincodeData(ccname string, ccversion str ing) (*ChaincodeData, error) {key := ccname + "/" + ccversionc.RLock()ccdata, in := c.cache[key] //优先从c.cache中获取c.RUnlock()if !in { //如果c.cache中没有var err error//从c.cacheSupport中获取ccpack, err := c.cacheSupport.GetChaincode(ccname, ccversion) c.Lock()//并写入c.cacheccdata = ccpack.GetChaincodeData()c.cache[key] = ccdatac.Unlock()}return ccdata, nil}//代码在core/common/ccprovider/ccinfocache.go```### 3.3、CCCacheSupport接口定义及实现#### 3.3.1、CCCacheSupport接口定义```gotype CCCacheSupport interface {//获取Chaincode包GetChaincode(ccname string, ccversion string) (CCPackage, error) }//代码在core/common/ccprovider/ccprovider.go```#### 3.3.2、CCCacheSupport接口实现(即CCInfoFSImpl结构体)```gotype CCInfoFSImpl struct{}//从文件系统中读取并构造CDSPackage或SignedCDSPackagefunc (*CCInfoFSImpl) GetChaincode(ccname string, ccversion string) (CCP ackage, error) {cccdspack := &CDSPackage{}_, _, err := cccdspack.InitFromFS(ccname, ccversion)if err != nil {//try signed CDSccscdspack := &SignedCDSPackage{}_, _, err = ccscdspack.InitFromFS(ccname, ccversion)if err != nil {return nil, err}return ccscdspack, nil}return cccdspack, nil}//将ChaincodeDeploymentSpec序列化后写入文件系统func (*CCInfoFSImpl) PutChaincode(depSpec *pb.ChaincodeDeploymentSpec) (CCPackage, error) {buf, err := proto.Marshal(depSpec)cccdspack := &CDSPackage{}_, err := cccdspack.InitFromBuffer(buf)err = cccdspack.PutChaincodeToFS()}//代码在core/common/ccprovider/ccprovider.go```### 3.4、CCPackage接口定义及实现#### 3.4.1、CCPackage接口定义```gotype CCPackage interface {//从字节初始化包InitFromBuffer(buf []byte) (*ChaincodeData, error)//从文件系统初始化包InitFromFS(ccname string, ccversion string) ([]byte, *pb.ChaincodeD eploymentSpec, error)//将chaincode包写入文件系统PutChaincodeToFS() error//从包中获取ChaincodeDeploymentSpecGetDepSpec() *pb.ChaincodeDeploymentSpec//从包中获取序列化的ChaincodeDeploymentSpecGetDepSpecBytes() []byte//校验ChaincodeDataValidateCC(ccdata *ChaincodeData) error//包转换为proto.MessageGetPackageObject() proto.Message//获取ChaincodeDataGetChaincodeData() *ChaincodeData//基于包计算获取chaincode IdGetId() []byte}//代码在core/common/ccprovider/ccprovider.go```#### 3.4.2、CCPackage接口实现(CDSPackage)```gotype CDSData struct {CodeHash []byte //ChaincodeDeploymentSpec.CodePackage哈希MetaDataHash []byte //和ChaincodeSpec. ChaincodeId.Version哈希}type CDSPackage struct {buf []byte //ChaincodeDeploymentSpec哈希depSpec *pb.ChaincodeDeploymentSpec //ChaincodeDeploymentSpecdata *CDSDatadatab []byteid []byte //id为CDSData.CodeHash和CDSData.MetaDataHash求哈希}//获取ccpack.idfunc (ccpack *CDSPackage) GetId() []byte//获取ccpack.depSpecfunc (ccpack *CDSPackage) GetDepSpec() *pb.ChaincodeDeploymentSpec//获取ccpack.buf,即ChaincodeDeploymentSpec哈希func (ccpack *CDSPackage) GetDepSpecBytes() []byte//获取ccpack.depSpecfunc (ccpack *CDSPackage) GetPackageObject() proto.Message//构造ChaincodeDatafunc (ccpack *CDSPackage) GetChaincodeData() *ChaincodeData//获取ChaincodeDeploymentSpec哈希、CDSData、idfunc (ccpack *CDSPackage) getCDSData(cds *pb.ChaincodeDeploymentSpec) ([]byte, []byte, *CDSData, error)//校验CDSPackage和ChaincodeDatafunc (ccpack *CDSPackage) ValidateCC(ccdata *ChaincodeData) error//[]byte反序列化为ChaincodeDeploymentSpec,构造CDSPackage,进而构造Chain codeDatafunc (ccpack *CDSPackage) InitFromBuffer(buf []byte) (*ChaincodeData, e rror)//从文件系统中获取ChaincodeData,即buf, err := GetChaincodePackage(ccname, ccversion)和_, err = ccpack.InitFromBuffer(buf)func (ccpack *CDSPackage) InitFromFS(ccname string, ccversion string) ([]byte, *pb.ChaincodeDeploymentSpec, error)//ccpack.buf写入文件,文件名为/var/hyperledger/production/chaincodes/Name. Versionfunc (ccpack *CDSPackage) PutChaincodeToFS() error//代码在core/common/ccprovider/cdspackage.go```### 3.5、CCContext结构体```gotype CCContext struct { //ChaincodeD上下文ChainID stringName stringVersion stringTxID stringSyscc boolSignedProposal *pb.SignedProposalProposal *pb.ProposalcanonicalName string}//构造CCContextfunc NewCCContext(cid, name, version, txid string, syscc bool, signedPr op *pb.SignedProposal, prop *pb.Proposal) *CCContext//name + ":" + versionfunc (cccid *CCContext) GetCanonicalName() string//代码在core/common/ccprovider/ccprovider.go```## 4、chaincode目录相关实现### 4.1、ChaincodeProviderFactory接口定义及实现#### 4.1.1、ChaincodeProviderFactory接口定义```gotype ChaincodeProviderFactory interface {//构造ChaincodeProvider实例NewChaincodeProvider() ChaincodeProvider}func RegisterChaincodeProviderFactory(ccfact ChaincodeProviderFactory) {ccFactory = ccfact}func GetChaincodeProvider() ChaincodeProvider {return ccFactory.NewChaincodeProvider()}//代码在core/common/ccprovider/ccprovider.go```#### 4.1.2、ChaincodeProviderFactory接口实现```gotype ccProviderFactory struct {}func (c *ccProviderFactory) NewChaincodeProvider() ccprovider.Chaincode Provider {return &ccProviderImpl{}}func init() {ccprovider.RegisterChaincodeProviderFactory(&ccProviderFactory{}) }//代码在core/chaincode/ccproviderimpl.go```### 4.2、ChaincodeProvider接口定义及实现#### 4.2.1、ChaincodeProvider接口定义```gotype ChaincodeProvider interface {GetContext(ledger ledger.PeerLedger) (context.Context, error)GetCCContext(cid, name, version, txid string, syscc bool, signedPro p *pb.SignedProposal, prop *pb.Proposal) interface{}GetCCValidationInfoFromLSCC(ctxt context.Context, txid string, sign edProp *pb.SignedProposal, prop *pb.Proposal, chainID string, chaincode ID string) (string, []byte, error)ExecuteChaincode(ctxt context.Context, cccid interface{}, args [][] byte) (*pb.Response, *pb.ChaincodeEvent, error)Execute(ctxt context.Context, cccid interface{}, spec interface{}) (*pb.Response, *pb.ChaincodeEvent, error)ExecuteWithErrorFilter(ctxt context.Context, cccid interface{}, spe c interface{}) ([]byte, *pb.ChaincodeEvent, error)Stop(ctxt context.Context, cccid interface{}, spec *pb.ChaincodeDep loymentSpec) errorReleaseContext()}//代码在core/common/ccprovider/ccprovider.go```#### 4.2.2、ChaincodeProvider接口实现```gotype ccProviderImpl struct {txsim ledger.TxSimulator //交易模拟器}type ccProviderContextImpl struct {ctx *Context}//获取context.Context,添加TXSimulatorKey绑定c.txsimfunc (c *ccProviderImpl) GetContext(ledger ledger.PeerLedger) (context. Context, error)//构造CCContext,并构造ccProviderContextImplfunc (c *ccProviderImpl) GetCCContext(cid, name, version, txid string, syscc bool, signedProp *pb.SignedProposal, prop *pb.Proposal) interface {}//调用GetChaincodeDataFromLSCC(ctxt, txid, signedProp, prop, chainID, ch aincodeID)获取ChaincodeData中Vscc和Policyfunc (c *ccProviderImpl) GetCCValidationInfoFromLSCC(ctxt context.Conte xt, txid string, signedProp *pb.SignedProposal, prop *pb.Proposal, chai nID string, chaincodeID string) (string, []byte, error)//调用ExecuteChaincode(ctxt, cccid.(*ccProviderContextImpl).ctx, args)执行上下文中指定的链码func (c *ccProviderImpl) ExecuteChaincode(ctxt context.Context, cccid i nterface{}, args [][]byte) (*pb.Response, *pb.ChaincodeEvent, error)//调用Execute(ctxt, cccid.(*ccProviderContextImpl).ctx, spec)func (c *ccProviderImpl) Execute(ctxt context.Context, cccid interface {}, spec interface{}) (*pb.Response, *pb.ChaincodeEvent, error)//调用ExecuteWithErrorFilter(ctxt, cccid.(*ccProviderContextImpl).ctx, s pec)func (c *ccProviderImpl) ExecuteWithErrorFilter(ctxt context.Context, c ccid interface{}, spec interface{}) ([]byte, *pb.ChaincodeEvent, error) //调用theChaincodeSupport.Stop(ctxt, cccid.(*ccProviderContextImpl).ctx, spec)func (c *ccProviderImpl) Stop(ctxt context.Context, cccid interface{}, spec *pb.ChaincodeDeploymentSpec) error//调用c.txsim.Done()func (c *ccProviderImpl) ReleaseContext() {//代码在core/chaincode/ccproviderimpl.go```### 4.3、ChaincodeSupport结构体ChaincodeSupport更详细内容,参考:[Fabric 1.0源代码笔记之 Chaincode(链码) #ChaincodeSupport(链码支持服务端)](ChaincodeSupport.md)### 4.4、ExecuteChaincode函数(执行链码)执行链码上下文中指定的链码。

兄弟连区块链教程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方法。

兄弟连区块链教程Fabric1.0源代码分析流言算法Gossip服务端二

兄弟连区块链教程Fabric1.0源代码分析流言算法Gossip服务端二

兄弟连区块链教程Fabric1.0源代码分析流言算法Gossip服务端二兄弟连区块链教程Fabric1.0源代码分析流言算法Gossip服务端二# Fabric 1.0源代码笔记之 gossip(流言算法) #GossipServer(Gossip服务端)### 5.2、commImpl结构体方法```go//conn.serviceConnection(),启动连接服务func (c *commImpl) GossipStream(stream proto.Gossip_GossipStreamServer) error//return &proto.Empty{}func (c *commImpl) Ping(context.Context, *proto.Empty) (*proto.Empty, error)func (c *commImpl) GetPKIid() common.PKIidType//向指定节点发送消息func (c *commImpl) Send(msg *proto.SignedGossipMessage,peers ...*RemotePeer)//探测远程节点是否有响应,_, err = cl.Ping(context.Background(),&proto.Empty{})func (c *commImpl) Probe(remotePeer *RemotePeer) error//握手验证远程节点,_, err = cl.Ping(context.Background(), &proto.Empty{}) func (c *commImpl) Handshake(remotePeer *RemotePeer) (api.PeerIdentityType, error)func (c *commImpl) Accept(acceptor common.MessageAcceptor) <-chanproto.ReceivedMessagefunc (c *commImpl) PresumedDead() <-chan common.PKIidTypefunc (c *commImpl) CloseConn(peer *RemotePeer)func (c *commImpl) Stop()//创建并启动gRPC Server,以及注册GossipServer实例func NewCommInstanceWithServer(port int, idMapper identity.Mapper, peerIdentity api.PeerIdentityType,//将GossipServer实例注册至peerServerfunc NewCommInstance(s *grpc.Server, cert *tls.Certificate, idStore identity.Mapper,func extractRemoteAddress(stream stream) stringfunc readWithTimeout(stream interface{}, timeout time.Duration, address string) (*proto.SignedGossipMessage, error)//创建gRPC Server,grpc.NewServer(serverOpts...)func createGRPCLayer(port int) (*grpc.Server, net.Listener,api.PeerSecureDialOpts, []byte)//创建与服务端连接func (c *commImpl) createConnection(endpoint string, expectedPKIID common.PKIidType) (*connection, error)//向指定节点发送消息func (c *commImpl) sendToEndpoint(peer *RemotePeer, msg*proto.SignedGossipMessage)//return atomic.LoadInt32(&c.stopping) == int32(1)func (c *commImpl) isStopping() boolfunc (c *commImpl) emptySubscriptions()func (c *commImpl) authenticateRemotePeer(stream stream)(*proto.ConnectionInfo, error)func (c *commImpl) disconnect(pkiID common.PKIidType)func (c *commImpl) createConnectionMsg(pkiID common.PKIidType, certHash []byte, cert api.PeerIdentityType, signer proto.Signer)(*proto.SignedGossipMessage, error)//代码在gossip/comm/comm_impl.go```#### 5.2.1、func NewCommInstanceWithServer(port int, idMapperidentity.Mapper, peerIdentity api.PeerIdentityType,secureDialOptsapi.PeerSecureDialOpts, dialOpts ...grpc.DialOption) (Comm, error)创建并启动gRPC Server,以及注册GossipServer实例```gofunc NewCommInstanceWithServer(port int, idMapper identity.Mapper, peerIdentity api.PeerIdentityType,secureDialOpts api.PeerSecureDialOpts, dialOpts ...grpc.DialOption) (Comm, error) {var ll net.Listenervar s *grpc.Servervar certHash []byteif len(dialOpts) == 0 {//peer.gossip.dialTimeout,gRPC连接拨号的超时dialOpts =[]grpc.DialOption{grpc.WithTimeout(util.GetDurationOrDefault("peer.goss ip.dialTimeout", defDialTimeout))}}if port > 0 {//创建gRPC Server,grpc.NewServer(serverOpts...)s, ll, secureDialOpts, certHash = createGRPCLayer(port)}commInst := &commImpl{selfCertHash: certHash,PKIID: idMapper.GetPKIidOfCert(peerIdentity),idMapper: idMapper,logger: util.GetLogger(util.LoggingCommModule,fmt.Sprintf("%d", port)),peerIdentity: peerIdentity,opts: dialOpts,secureDialOpts: secureDialOpts,port: port,lsnr: ll,gSrv: s,msgPublisher: NewChannelDemultiplexer(),lock: &sync.RWMutex{},deadEndpoints: make(chan common.PKIidType, 100),stopping: int32(0),exitChan: make(chan struct{}, 1),subscriptions: make([]chan proto.ReceivedMessage, 0),}commInst.connStore = newConnStore(commInst, commInst.logger)if port > 0 {commInst.stopWG.Add(1)go func() {defer commInst.stopWG.Done()s.Serve(ll) //启动gRPC Server}()//commInst注册到gRPC Serverproto.RegisterGossipServer(s, commInst)}return commInst, nil}//代码在gossip/comm/comm_impl.go```#### 5.2.2、func NewCommInstance(s *grpc.Server, cert *tls.Certificate, idStore identity.Mapper,peerIdentity api.PeerIdentityType, secureDialOpts api.PeerSecureDialOpts,dialOpts ...grpc.DialOption) (Comm, error)将GossipServer实例注册至peerServer```gofunc NewCommInstance(s *grpc.Server, cert *tls.Certificate, idStore identity.Mapper,peerIdentity api.PeerIdentityType, secureDialOptsapi.PeerSecureDialOpts,dialOpts ...grpc.DialOption) (Comm, error) {dialOpts = append(dialOpts,grpc.WithTimeout(util.GetDurationOrDefault("peer.gossip.dialTimeout", defDialTimeout)))//构造commImplcommInst, err := NewCommInstanceWithServer(-1, idStore, peerIdentity, secureDialOpts, dialOpts...)if cert != nil {inst := commInst.(*commImpl)inst.selfCertHash = certHashFromRawCert(cert.Certificate[0])}proto.RegisterGossipServer(s, commInst.(*commImpl))return commInst, nil}//代码在gossip/comm/comm_impl.go```//创建与服务端连接#### 5.2.3、func (c *commImpl) createConnection(endpoint string, expectedPKIID common.PKIidType) (*connection, error)```gofunc (c *commImpl) createConnection(endpoint string, expectedPKIID common.PKIidType) (*connection, error) {var err errorvar cc *grpc.ClientConnvar stream proto.Gossip_GossipStreamClientvar pkiID common.PKIidTypevar connInfo *proto.ConnectionInfovar dialOpts []grpc.DialOptiondialOpts = append(dialOpts, c.secureDialOpts()...)dialOpts = append(dialOpts, grpc.WithBlock())dialOpts = append(dialOpts, c.opts...)cc, err = grpc.Dial(endpoint, dialOpts...)cl := proto.NewGossipClient(cc)if _, err = cl.Ping(context.Background(), &proto.Empty{}); err != nil {cc.Close()return nil, err}ctx, cf := context.WithCancel(context.Background())stream, err = cl.GossipStream(ctx)connInfo, err = c.authenticateRemotePeer(stream)pkiID = connInfo.IDconn := newConnection(cl, cc, stream, nil)conn.pkiID = pkiID = connInfoconn.logger = c.loggerconn.cancel = cfh := func(m *proto.SignedGossipMessage) {c.msgPublisher.DeMultiplex(&ReceivedMessageImpl{conn: conn,lock: conn,SignedGossipMessage: m,connInfo: connInfo,})}conn.handler = hreturn conn, nil}//代码在gossip/comm/comm_impl.go```## 6、connectionStore和connection结构体及方法### 6.1、connection结构体及方法```gotype connection struct {cancel context.CancelFuncinfo *proto.ConnectionInfooutBuff chan *msgSendinglogger *logging.Logger // loggerpkiID common.PKIidType // pkiID of the remote endpointhandler handler // function to invoke upon a message receptionconn *grpc.ClientConn // gRPC connection to remote endpointcl proto.GossipClient // gRPC stub of remote endpointclientStream proto.Gossip_GossipStreamClient // client-side stream to remote endpointserverStream proto.Gossip_GossipStreamServer // server-side stream to remote endpointstopFlag int32 // indicates whether this connection is in process of stoppingstopChan chan struct{} // a method to stop the server-side gRPC call from a different go-routinesync.RWMutex // synchronizes access to shared variables}//构造connectionfunc newConnection(cl proto.GossipClient, c *grpc.ClientConn, csproto.Gossip_GossipStreamClient, ss proto.Gossip_GossipStreamServer)*connection//关闭connectionfunc (conn *connection) close()//atomic.LoadInt32(&(conn.stopFlag)) == int32(1)func (conn *connection) toDie() bool//conn.outBuff <- m,其中m为msgSending{envelope: msg.Envelope,onErr: onErr,}func (conn *connection) send(msg *proto.SignedGossipMessage, onErrfunc(error))//go conn.readFromStream(errChan, msgChan)、go conn.writeToStream(),同时msg := <-msgChan,conn.handler(msg)func (conn *connection) serviceConnection() error//循环不间断从conn.outBuff取数据,然后stream.Send(m.envelope)func (conn *connection) writeToStream()//循环不间断envelope, err := stream.Recv()、msg, err :=envelope.ToGossipMessage()、msgChan <- msgfunc (conn *connection) readFromStream(errChan chan error, msgChan chan *proto.SignedGossipMessage)//获取conn.serverStreamfunc (conn *connection) getStream() stream//代码在gossip/comm/conn.go```### 6.2、connectionStore结构体及方法```gotype connectionStore struct {logger *logging.Logger // loggerisClosing bool // whether this connection store is shutting downconnFactory connFactory // creates a connection to remote peersync.RWMutex // synchronize access to shared variablespki2Conn map[string]*connection //connection map, key为pkiID,value为connectiondestinationLocks map[string]*sync.RWMutex //mapping between pkiIDs and locks,// used to prevent concurrent connection establishment to the same remote endpoint}//构造connectionStorefunc newConnStore(connFactory connFactory, logger *logging.Logger)*connectionStore//从connection map中获取连接,如无则创建并启动连接,并写入connection map中func (cs *connectionStore) getConnection(peer *RemotePeer) (*connection, error)//连接数量func (cs *connectionStore) connNum() int//关闭指定连接func (cs *connectionStore) closeConn(peer *RemotePeer)//关闭所有连接func (cs *connectionStore) shutdown()func (cs *connectionStore) onConnected(serverStreamproto.Gossip_GossipStreamServer, connInfo *proto.ConnectionInfo)*connection//注册连接func (cs *connectionStore) registerConn(connInfo *proto.ConnectionInfo, serverStream proto.Gossip_GossipStreamServer) *connection//关闭指定连接func (cs *connectionStore) closeByPKIid(pkiID common.PKIidType)//代码在gossip/comm/conn.go```#### 6.2.1、func (cs *connectionStore) getConnection(peer *RemotePeer) (*connection, error)```gofunc (cs *connectionStore) getConnection(peer *RemotePeer) (*connection, error) {cs.RLock()isClosing := cs.isClosingcs.RUnlock()pkiID := peer.PKIIDendpoint := peer.Endpointcs.Lock()destinationLock, hasConnected := cs.destinationLocks[string(pkiID)] if !hasConnected {destinationLock = &sync.RWMutex{}cs.destinationLocks[string(pkiID)] = destinationLock}cs.Unlock()destinationLock.Lock()cs.RLock()//从connection map中获取conn, exists := cs.pki2Conn[string(pkiID)]if exists {cs.RUnlock()destinationLock.Unlock()return conn, nil}cs.RUnlock()//创建连接createdConnection, err := cs.connFactory.createConnection(endpoint, pkiID)destinationLock.Unlock()conn = createdConnectioncs.pki2Conn[string(createdConnection.pkiID)] = conngo conn.serviceConnection() //启动连接的消息接收处理、以及向对方节点发送消息return conn, nil}//代码在gossip/comm/conn.go```## 7、ChannelDeMultiplexer结构体及方法(多路复用器)```gotype ChannelDeMultiplexer struct {channels []*channellock *sync.RWMutexclosed int32}//构造ChannelDeMultiplexerfunc NewChannelDemultiplexer() *ChannelDeMultiplexer//atomic.LoadInt32(&m.closed) == int32(1)func (m *ChannelDeMultiplexer) isClosed() bool//关闭func (m *ChannelDeMultiplexer) Close()//添加通道func (m *ChannelDeMultiplexer) AddChannel(predicatecommon.MessageAcceptor) chan interface{}//挨个通道发送消息func (m *ChannelDeMultiplexer) DeMultiplex(msg interface{})//代码在```欢迎继续关注兄弟连区块链教程分享!。

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

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

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

## 3、MSP接口实现MSP接口实现,即bccspmsp结构体及方法,bccspmsp定义如下:```gotype bccspmsp struct {rootCerts []Identity //信任的CA证书列表intermediateCerts []Identity //信任的中间证书列表tlsRootCerts [][]byte //信任的CA TLS 证书列表tlsIntermediateCerts [][]byte //信任的中间TLS 证书列表certificationTreeInternalNodesMap map[string]bool //待定signer SigningIdentity //签名身份admins []Identity //管理身份列表bccsp bccsp.BCCSP //加密服务提供者name string //MSP名字opts *x509.VerifyOptions //MSP成员验证选项CRL []*pkix.CertificateList //证书吊销列表ouIdentifiers map[string][][]byte //组织列表cryptoConfig *m.FabricCryptoConfig //加密选项}//代码在msp/mspimpl.go```涉及方法如下:```gofunc NewBccspMsp() (MSP, error) //创建bccsp实例,以及创建并初始化bccspmsp 实例func (msp *bccspmsp) Setup(conf1 *m.MSPConfig) error ////根据MSPConfig设置MSP实例func (msp *bccspmsp) GetType() ProviderType //获取MSP类型,即FABRICfunc (msp *bccspmsp) GetIdentifier() (string, error) //获取MSP名字func (msp *bccspmsp) GetTLSRootCerts() [][]byte //获取信任的CA TLS 证书列表msp.tlsRootCertsfunc (msp *bccspmsp) GetTLSIntermediateCerts() [][]byte //获取信任的中间TLS 证书列表msp.tlsIntermediateCertsfunc (msp *bccspmsp) GetDefaultSigningIdentity() (SigningIdentity, error) ////获取默认的签名身份msp.signerfunc (msp *bccspmsp) GetSigningIdentity(identifier *IdentityIdentifier) (SigningIdentity, error) //暂未实现,可忽略func (msp *bccspmsp) Validate(id Identity) error //校验身份是否有效,调取msp.validateIdentity(id)实现func (msp *bccspmsp) DeserializeIdentity(serializedID []byte) (Identity, error) //身份反序列化func (msp *bccspmsp) SatisfiesPrincipal(id Identity, principal*m.MSPPrincipal) error //验证给定的身份与principal中所描述的类型是否相匹配//代码在msp/mspimpl.go```func (msp *bccspmsp) Setup(conf1 *m.MSPConfig) error代码如下:```goconf := &m.FabricMSPConfig{}err := proto.Unmarshal(conf1.Config, conf) //将conf1.Config []byte解码为FabricMSPConfig = err := msp.setupCrypto(conf) //设置加密选项msp.cryptoConfigerr := msp.setupCAs(conf) //设置MSP成员验证选项msp.opts,并添加信任的CA证书msp.rootCerts和信任的中间证书msp.intermediateCertserr := msp.setupAdmins(conf) //设置管理身份列表msp.adminserr := msp.setupCRLs(conf) //设置证书吊销列表msp.CRLerr := msp.finalizeSetupCAs(conf); err != nil //设置msp.certificationTreeInternalNodesMaperr := msp.setupSigningIdentity(conf) //设置签名身份msp.signererr := msp.setupOUs(conf) //设置组织列表msp.ouIdentifierserr := msp.setupTLSCAs(conf) //设置并添加信任的CA TLS 证书列表msp.tlsRootCerts,以及信任的CA TLS 证书列表msp.tlsIntermediateCertsfor i, admin := range msp.admins {err = admin.Validate() //确保管理员是有效的成员}//代码在msp/mspimpl.go```func (msp *bccspmsp) validateIdentity(id *identity)代码如下:```govalidationChain, err := msp.getCertificationChainForBCCSPIdentity(id) //获取BCCSP身份认证链err = msp.validateIdentityAgainstChain(id, validationChain) //根据链验证身份err = msp.validateIdentityOUs(id) //验证身份中所携带的组织信息有效//代码在msp/mspimpl.go```## 4、MSPManager接口实现结构体定义:```gotype mspManagerImpl struct {mspsMap map[string]MSP //MSP的映射up bool //是否正常启用}//代码在msp/mspmgrimpl.go```方法:```gofunc NewMSPManager() MSPManager //创建mspManagerImpl实例func (mgr *mspManagerImpl) Setup(msps []MSP) error //将msps装入mgr.mspsMap func (mgr *mspManagerImpl) GetMSPs() (map[string]MSP, error) //获取mgr.mspsMapfunc (mgr *mspManagerImpl) DeserializeIdentity(serializedID []byte) (Identity, error) //调用msp.DeserializeIdentity()实现身份反序列化//代码在msp/mspmgrimpl.go```## 5、Identity、SigningIdentity接口实现identity结构体定义(身份):```gotype identity struct {id *IdentityIdentifier //身份标识符(含Mspid和Id,均为string)cert *x509.Certificate //代表身份的x509证书pk bccsp.Key //身份公钥msp *bccspmsp //拥有此实例的MSP实例}//代码在msp/identities.go```补充IdentityIdentifier结构体定义(身份标识符):```gotype IdentityIdentifier struct {Mspid string //Msp idId string //Id}//代码在msp/msp.go```identity结构体涉及方法如下:```gofunc newIdentity(id *IdentityIdentifier, cert *x509.Certificate, pk bccsp.Key, msp *bccspmsp) (Identity, error) //创建identity实例func NewSerializedIdentity(mspID string, certPEM []byte) ([]byte, error) //新建身份SerializedIdentity并序列化func (id *identity) SatisfiesPrincipal(principal *msp.MSPPrincipal) error //调用msp的SatisfiesPrincipal检查身份与principal中所描述的类型是否匹配func (id *identity) GetIdentifier() *IdentityIdentifier //获取id.idfunc (id *identity) GetMSPIdentifier() string //获取id.id.Mspidfunc (id *identity) Validate() error //调取id.msp.Validate(id)校验身份是否有效func (id *identity) GetOrganizationalUnits() []*OUIdentifier //获取组织单元func (id *identity) Verify(msg []byte, sig []byte) error //用这个身份校验消息签名func (id *identity) Serialize() ([]byte, error)//身份序列化func (id *identity) getHashOpt(hashFamily string) (bccsp.HashOpts, error) //调取bccsp.GetHashOpt//代码在msp/identities.go```signingidentity结构体定义(签名身份):```gotype signingidentity struct {identity //嵌入identitysigner crypto.Signer //crypto标准库中Signer接口}//代码在msp/identities.go```signingidentity结构体涉及方法如下:```go//新建signingidentity实例func newSigningIdentity(id *IdentityIdentifier, cert *x509.Certificate, pk bccsp.Key, signer crypto.Signer, msp *bccspmsp) (SigningIdentity, error) func (id *signingidentity) Sign(msg []byte) ([]byte, error) //签名msg func (id *signingidentity) GetPublicVersion() Identity //获取id.identity //代码在msp/identities.go```## 6、MSPConfig相关结构体及方法MSPConfig相关结构体定义:FabricMSPConfig定义与bccspmsp接近,FabricMSPConfig序列化后以[]byte存入MSPConfig.Config中。

兄弟连区块链教程Fabric1.0Fabric 1.0源代码分析events(事件服务)

兄弟连区块链教程Fabric1.0Fabric 1.0源代码分析events(事件服务)

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

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

# Fabric 1.0源代码笔记之 events(事件服务)## 1、events概述events代码分布在events/producer和events/consumer目录下,目录结构如下:* events/producer目录:生产者,提供事件服务器。

* producer.go,EventsServer结构体及方法。

* events.go,eventProcessor结构体及方法,handlerList接口及实现。

* handler.go,handler结构体及方法。

* events/consumer目录:消费者,获取事件。

## 2、producer(生产者)### 2.1、EventsServer结构体及方法EventsServer结构体定义:(空)```gotype EventsServer struct {}//全局事件服务器globalEventsServervar globalEventsServer *EventsServer//代码在events/producer/producer.go```涉及方法如下:```go//globalEventsServer创建并初始化func NewEventsServer(bufferSize uint, timeout time.Duration) *EventsServer //接收消息并处理func (p *EventsServer) Chat(stream pb.Events_ChatServer) error//代码在events/producer/producer.go```### 2.2、eventProcessor结构体及方法(事件处理器)eventProcessor结构体定义:```gotype eventProcessor struct {sync.RWMutexeventConsumers map[pb.EventType]handlerListeventChannel chan *pb.Eventtimeout time.Duration //生产者发送事件的超时时间}//全局事件处理器gEventProcessorvar gEventProcessor *eventProcessor//代码在events/producer/events.go```涉及方法如下:```gofunc (ep *eventProcessor) start() //启动并处理事件,从ep.eventChannel通道接收消息并处理//初始化gEventProcessor,并添加消息类型,并发启动start()func initializeEvents(bufferSize uint, tout time.Duration)//添加消息类型至gEventProcessor.eventConsumers,并初始化handlerListfunc AddEventType(eventType pb.EventType) error//绑定Interest和handlerfunc registerHandler(ie *pb.Interest, h *handler) error//取消绑定Interest和handlerfunc deRegisterHandler(ie *pb.Interest, h *handler) errorfunc Send(e *pb.Event) error //Event发送至gEventProcessor.eventChannel //代码在events/producer/events.go```### 2.3、handlerList接口及实现#### 2.3.1、handlerList接口定义(handler列表)```gotype handlerList interface {add(ie *pb.Interest, h *handler) (bool, error) //添加del(ie *pb.Interest, h *handler) (bool, error) //删除foreach(ie *pb.Event, action func(h *handler)) //遍历}//代码在events/producer/events.go```#### 2.3.2、handlerList接口实现```gotype genericHandlerList struct {sync.RWMutexhandlers map[*handler]bool}type chaincodeHandlerList struct {sync.RWMutexhandlers map[string]map[string]map[*handler]bool}//代码在events/producer/events.go```### 2.4、handler结构体及方法handler结构体定义:```gotype handler struct {ChatStream pb.Events_ChatServerinterestedEvents map[string]*pb.Interest}//代码在events/producer/handler.go```补充pb.Events_ChatServer和pb.Interest(关注)定义:```gotype Events_ChatServer interface {Send(*Event) errorRecv() (*SignedEvent, error)grpc.ServerStream //type ServerStream interface}Interest struct {EventType EventType //type EventType int32RegInfo isInterest_RegInfo //type isInterest_RegInfo interface ChainID string}type EventType int32const (EventType_REGISTER EventType = 0EventType_BLOCK EventType = 1EventType_CHAINCODE EventType = 2EventType_REJECTION EventType = 3)//代码在protos/peer/events.pb.go```handler结构体方法如下:```gofunc newEventHandler(stream pb.Events_ChatServer) (*handler, error) //构造handlerfunc (d *handler) Stop() error //停止handler,取消所有handler注册func getInterestKey(interest pb.Interest) string //获取interest.EventType func (d *handler) register(iMsg []*pb.Interest) error //逐一绑定Interest 和handlerfunc (d *handler) deregister(iMsg []*pb.Interest) error //逐一取消绑定Interest和handlerfunc (d *handler) deregisterAll() //取消所有handler绑定func (d *handler) HandleMessage(msg *pb.SignedEvent) error //处理消息func (d *handler) SendMessage(msg *pb.Event) error //通过流向远程PEER发送消息func validateEventMessage(signedEvt *pb.SignedEvent) (*pb.Event, error) //验证事件消息//代码在events/producer/handler.go```补充pb.Event和pb.SignedEvent:```gotype Event struct {Event isEvent_Event //type isEvent_Event interfaceCreator []byte //事件创建者}SignedEvent struct {Signature []byte //在事件字节上的签名EventBytes []byte //事件对象序列化,即type Event struct}//代码在protos/peer/events.pb.go ```## 3、consumer(消费者)待补充。

兄弟连区块链技术培训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。

兄弟连区块链技术培训Fabric 1.0源代码分析(34) Peer #peer chaincode命令及子命令实现

兄弟连区块链技术培训Fabric 1.0源代码分析(34) Peer #peer chaincode命令及子命令实现

兄弟连区块链技术培训Fabric 1.0源代码分析(34) Peer #peer cha incode命令及子命令实现# Fabric 1.0源代码笔记之 Peer #peer chaincode命令及子命令实现## 1、peer chaincode install子命令实现(安装链码)### 1.0、peer chaincode install子命令概述peer chaincode install,将链码的源码和环境封装为一个链码安装打包文件,并传输到背书节点。

peer chaincode install支持如下两种方式:* 指定代码方式,peer chaincode install -n <链码名称> -v <链码版本> -p <链码路径>* 基于链码打包文件方式,peer chaincode install <链码打包文件>### 1.1、初始化Endorser客户端```gocf, err = InitCmdFactory(true, false)//代码在peer/chaincode/install.go```cf, err = InitCmdFactory(true, false)代码如下:```gofunc InitCmdFactory(isEndorserRequired, isOrdererRequired bool) (*Chainc odeCmdFactory, error) {var err errorvar endorserClient pb.EndorserClientif isEndorserRequired {//获取Endorser客户端endorserClient, err = common.GetEndorserClientFnc() //func GetEn dorserClient() (pb.EndorserClient, error)}//获取签名signer, err := common.GetDefaultSignerFnc()var broadcastClient common.BroadcastClientif isOrdererRequired {//此处未用到,暂略}//构造ChaincodeCmdFactoryreturn &ChaincodeCmdFactory{EndorserClient: endorserClient,Signer: signer,BroadcastClient: broadcastClient,}, nil}//代码在peer/chaincode/common.go```### 1.2、构造ChaincodeDeploymentSpec消息(链码信息及链码文件打包)```goif ccpackfile == "" { //指定代码方式,重新构造构造ChaincodeDeploymentSpec 消息ccpackmsg, err = genChaincodeDeploymentSpec(cmd, chaincodeName, chai ncodeVersion)} else { //基于链码打包文件方式,直接读取ChaincodeDeploymentSpec消息var cds *pb.ChaincodeDeploymentSpecccpackmsg, cds, err = getPackageFromFile(ccpackfile)}//代码在peer/chaincode/install.go```ccpackmsg, err = genChaincodeDeploymentSpec(cmd, chaincodeName, chaincod eVersion)代码如下:```gofunc genChaincodeDeploymentSpec(cmd *mand, chaincodeName, chain codeVersion string) (*pb.ChaincodeDeploymentSpec, error) {//已经存在,直接报错if existed, _ := ccprovider.ChaincodePackageExists(chaincodeName, ch aincodeVersion); existed {return nil, fmt.Errorf("chaincode %s:%s already exists", chainco deName, chaincodeVersion)}spec, err := getChaincodeSpec(cmd)cds, err := getChaincodeDeploymentSpec(spec, true)return cds, nil}//代码在peer/chaincode/install.go```spec, err := getChaincodeSpec(cmd)代码如下:```gofunc getChaincodeSpec(cmd *mand) (*pb.ChaincodeSpec, error) { spec := &pb.ChaincodeSpec{}err := checkChaincodeCmdParams(cmd) //检查参数合法性input := &pb.ChaincodeInput{}//flags.StringVarP(&chaincodeCtorJSON, "ctor", "c", "{}",ctor为链码具体执行参数信息,默认为{}err := json.Unmarshal([]byte(chaincodeCtorJSON), &input)//flags.StringVarP(&chaincodeLang, "lang", "l", "golang",lang为链码的编写语言,默认为golangchaincodeLang = strings.ToUpper(chaincodeLang)spec = &pb.ChaincodeSpec{Type: pb.ChaincodeSpec_Type(pb.ChaincodeSpec_Type_value[chaincod eLang]),ChaincodeId: &pb.ChaincodeID{Path: chaincodePath, Name: chaincod eName, Version: chaincodeVersion},Input: input,}return spec, nil}//代码在peer/chaincode/common.go```cds, err := getChaincodeDeploymentSpec(spec, true)代码如下:```gofunc getChaincodeDeploymentSpec(spec *pb.ChaincodeSpec, crtPkg bool) (*p b.ChaincodeDeploymentSpec, error) {var codePackageBytes []byteif chaincode.IsDevMode() == false && crtPkg {var err errorerr = checkSpec(spec) //检查spec合法性codePackageBytes, err = container.GetChaincodePackageBytes(spe c) //打包链码文件及依赖文件}//构造ChaincodeDeploymentSpecchaincodeDeploymentSpec := &pb.ChaincodeDeploymentSpec{ChaincodeSpec: spec, CodePackage: codePackageBytes}return chaincodeDeploymentSpec, nil//代码在peer/chaincode/common.go```### 1.3、创建lscc Proposal并签名```gocreator, err := cf.Signer.Serialize() //获取签名者//按ChaincodeDeploymentSpec构造Proposal,即链码ChaincodeDeploymentSpec消息作为参数传递给lscc系统链码并调用//调用createProposalFromCDS(chainID, cds, creator, policy, escc, vscc, " deploy")prop, _, err := utils.CreateInstallProposalFromCDS(msg, creator)var signedProp *pb.SignedProposalsignedProp, err = utils.GetSignedProposal(prop, cf.Signer) //签名提案//代码在peer/chaincode/install.go```createProposalFromCDS(chainID, cds, creator, policy, escc, vscc, "deploy ")代码如下:```gofunc createProposalFromCDS(chainID string, msg proto.Message, creator [] byte, policy []byte, escc []byte, vscc []byte, propType string) (*peer.P roposal, string, error) {var ccinp *peer.ChaincodeInputvar b []bytevar err errorb, err = proto.Marshal(msg)switch propType {case "deploy":fallthroughcase "upgrade":cds, ok := msg.(*peer.ChaincodeDeploymentSpec)ccinp = &peer.ChaincodeInput{Args: [][]byte{[]byte(propType), [] byte(chainID), b, policy, escc, vscc}}case "install":ccinp = &peer.ChaincodeInput{Args: [][]byte{[]byte(propType), b}}}lsccSpec := &peer.ChaincodeInvocationSpec{ //构造lscc ChaincodeInvoc ationSpecChaincodeSpec: &peer.ChaincodeSpec{Type: peer.ChaincodeSpec_GOLANG,ChaincodeId: &peer.ChaincodeID{Name: "lscc"},Input: ccinp}}return CreateProposalFromCIS(common.HeaderType_ENDORSER_TRANSACTION, chainID, lsccSpec, creator)}//代码在protos/utils/proputils.go```### 1.4、提交并处理Proposal```goproposalResponse, err := cf.EndorserClient.ProcessProposal(context.Backg round(), signedProp)//代码在peer/chaincode/install.go```## 2、peer chaincode instantiate子命令实现(实例化链码)### 2.0、peer chaincode instantiate概述peer chaincode instantiate命令通过构造生命周期管理系统链码(LSCC)的交易,将安装过的链码在指定通道上进行实例化调用。

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

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

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

# Fabric 1.0源代码笔记之 Peer #EndorserServer(Endorser服务端)## 1、EndorserServer概述EndorserServer相关代码在protos/peer、core/endorser目录下。

* protos/peer/peer.pb.go,EndorserServer接口定义。

* core/endorser/endorser.go,EndorserServer接口实现,即Endorser结构体及方法,以及Endorser服务端ProcessProposal处理流程。

## 2、EndorserServer接口定义### 2.1、EndorserServer接口定义```gotype EndorserServer interface {ProcessProposal(context.Context, *SignedProposal) (*ProposalResponse, error)}//代码在protos/peer/peer.pb.go```### 2.2、gRPC相关实现```govar _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",}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)}//代码在protos/peer/peer.pb.go```## 3、EndorserServer接口实现### 3.1、Endorser结构体及方法```gotype Endorser struct {policyChecker policy.PolicyChecker //策略检查器}//代码在core/endorser/endorser.go```涉及方法如下:```go//构造Endorserfunc NewEndorserServer() pb.EndorserServer//执行提案func (e *Endorser) ProcessProposal(ctx context.Context, signedProp*pb.SignedProposal) (*pb.ProposalResponse, error)//检查SignedProposal是否符合通道策略,调用e.policyChecker.CheckPolicy() func (e *Endorser) checkACL(signedProp *pb.SignedProposal, chdr*common.ChannelHeader, shdr *common.SignatureHeader, hdrext*pb.ChaincodeHeaderExtension) error//检查Escc和Vscc,暂未实现func (*Endorser) checkEsccAndVscc(prop *pb.Proposal) error//获取账本的交易模拟器,调用peer.GetLedger(ledgername).NewTxSimulator() func (*Endorser) getTxSimulator(ledgername string) (ledger.TxSimulator, error)//获取账本历史交易查询器,调用peer.GetLedger(ledgername).NewHistoryQueryExecutor()func (*Endorser) getHistoryQueryExecutor(ledgername string)(ledger.HistoryQueryExecutor, error)//执行链码func (e *Endorser) callChaincode(ctxt context.Context, chainID string, version string, txid string, signedProp *pb.SignedProposal, prop*pb.Proposal, cis *pb.ChaincodeInvocationSpec, cid *pb.ChaincodeID, txsim ledger.TxSimulator) (*pb.Response, *pb.ChaincodeEvent, error)func (e *Endorser) disableJavaCCInst(cid *pb.ChaincodeID, cis*pb.ChaincodeInvocationSpec) error//通过调用chaincode来模拟提案func (e *Endorser) simulateProposal(ctx context.Context, chainID string, txid string, signedProp *pb.SignedProposal, prop *pb.Proposal, cid*pb.ChaincodeID, txsim ledger.TxSimulator) (*ccprovider.ChaincodeData, *pb.Response, []byte, *pb.ChaincodeEvent, error)//从LSCC获取链码数据func (e *Endorser) getCDSFromLSCC(ctx context.Context, chainID string, txid string, signedProp *pb.SignedProposal, prop *pb.Proposal, chaincodeID string, txsim ledger.TxSimulator) (*ccprovider.ChaincodeData, error)//提案背书func (e *Endorser) endorseProposal(ctx context.Context, chainID string, txid string, signedProp *pb.SignedProposal, proposal *pb.Proposal, response *pb.Response, simRes []byte, event *pb.ChaincodeEvent, visibility []byte, ccid *pb.ChaincodeID, txsim ledger.TxSimulator, cd*ccprovider.ChaincodeData) (*pb.ProposalResponse, error)//提交模拟交易,仅测试使用func (e *Endorser) commitTxSimulation(proposal *pb.Proposal, chainID string, signer msp.SigningIdentity, pResp *pb.ProposalResponse, blockNumber uint64) error//代码在core/endorser/endorser.go```### 3.2、Endorser服务端ProcessProposal处理流程Endorser服务端ProcessProposal处理流程,即func (e *Endorser) ProcessProposal(ctx context.Context, signedProp *pb.SignedProposal)(*pb.ProposalResponse, error)方法实现。

![](EndorserServer_ProcessProposal.png)#### 3.2.1、校验SignedProposal合法性,并获取ChannelHeader和SignatureHeader```go//校验SignedProposal合法性prop, hdr, hdrExt, err := validation.ValidateProposalMessage(signedProp) //获取ChannelHeaderchdr, err := putils.UnmarshalChannelHeader(hdr.ChannelHeader)//获取SignatureHeadershdr, err := putils.GetSignatureHeader(hdr.SignatureHeader)//代码在core/endorser/endorser.go```validation.ValidateProposalMessage(signedProp)代码如下:```gofunc ValidateProposalMessage(signedProp *pb.SignedProposal) (*pb.Proposal, *common.Header, *pb.ChaincodeHeaderExtension, error) {prop, err := utils.GetProposal(signedProp.ProposalBytes) //获取type Proposal structhdr, err := utils.GetHeader(prop.Header) //获取Proposal.Headerchdr, shdr, err := validateCommonHeader(hdr) //校验Proposal.Header//检查来自创建者的签名err = checkSignatureFromCreator(shdr.Creator, signedProp.Signature, signedProp.ProposalBytes, chdr.ChannelId)//校验交易TxID,TxID由Nonce和Creator构成err = utils.CheckProposalTxID(chdr.TxId, //ChannelHeader.TxIdshdr.Nonce, //SignatureHeader.Nonceshdr.Creator) //SignatureHeader.Creatorswitch common.HeaderType(chdr.Type) {case common.HeaderType_CONFIG:fallthroughcase common.HeaderType_ENDORSER_TRANSACTION://校验ChaincodeHeaderExtensionchaincodeHdrExt, err := validateChaincodeProposalMessage(prop, hdr)return prop, hdr, chaincodeHdrExt, errdefault:return nil, nil, nil, fmt.Errorf("Unsupported proposal type %d", common.HeaderType(chdr.Type))}}//代码在core/common/validation/msgvalidation.go```#### 3.2.2、校验是否系统链码且提案不可调用,获取chainID和TxId,获取Ledger并校验txid是否已存在,非系统链码校验提案权限(是否符合通道策略)```go//校验是否系统链码且提案不可调用if syscc.IsSysCCAndNotInvokableExternal() {//如果是系统链码且提案不可调用}//获取chainID,即ChannelIdchainID := chdr.ChannelId//获取交易TxIdtxid := chdr.TxIdif chainID != "" {//获取Ledgerlgr := peer.GetLedger(chainID)//校验txid是否已存在_, err := lgr.GetTransactionByID(txid)//非系统链码校验提案权限(是否符合通道策略)if !syscc.IsSysCC() {err = e.checkACL(signedProp, chdr, shdr, hdrExt)}}//代码在core/endorser/endorser.go```#### 3.2.3、获取账本的交易模拟器和历史记录查询器,并模拟提案执行```govar txsim ledger.TxSimulatorvar historyQueryExecutor ledger.HistoryQueryExecutorif chainID != "" {//获取账本的交易模拟器txsim, err = e.getTxSimulator(chainID)//获取历史记录查询器historyQueryExecutor, err = e.getHistoryQueryExecutor(chainID)//HistoryQueryExecutorKey key = "historyqueryexecutorkey"//context.WithValue,将Key与对象建立关系ctx = context.WithValue(ctx, chaincode.HistoryQueryExecutorKey, historyQueryExecutor)}//模拟提案执行cd, res, simulationResult, ccevent, err := e.simulateProposal(ctx, chainID, txid, signedProp, prop, hdrExt.ChaincodeId, txsim)//代码在core/endorser/endorser.go```e.simulateProposal(ctx, chainID, txid, signedProp, prop,hdrExt.ChaincodeId, txsim)代码如下:模拟提案执行。

相关文档
最新文档