兄弟连区块链教程Fabric1.0源代码分析Peer peer chaincode命令及子命令实现
兄弟连区块链技术培训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区块文件存储二。
涉及方法如下:```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源代码分析Proposal(提案)
兄弟连区块链教程Fabric1.0源代码分析Proposal(提案)兄弟连区块链教程Fabric1.0源代码分析Proposal(提案),2018年下半年,区块链行业正逐渐褪去发展之初的浮躁、回归理性,表面上看相关人才需求与身价似乎正在回落。
但事实上,正是初期泡沫的渐退,让人们更多的关注点放在了区块链真正的技术之上。
# Fabric1.0源代码笔记之Proposal(提案)## 1、Proposal概述Proposal,即向Endorser发起的提案。
Proposal代码分布在protos/utils、protos/peer目录下,目录结构如下:protos/utils目录:proputils.go,Proposal工具函数。
txutils.go,Proposal工具函数。
protos/peer目录:proposal.pb.go,Proposal相关结构体定义。
## 2、Proposal相关结构体定义有个图3### 2.1、SignedProposal定义```gotype SignedProposal struct {ProposalBytes []byte //Proposal序列化,即type Proposal structSignature []byte //signer.Sign(ProposalBytes)}//代码在protos/peer/proposal.pb.go```### 2.2、Proposal定义```gotype Proposal struct {Header []byte //Header序列化,即type Header structPayload []byte //ChaincodeProposalPayload序列化,即type ChaincodeProposalPayload structExtension []byte //扩展}//代码在protos/peer/proposal.pb.go```Header更详细内容,参考:Fabric 1.0源代码笔记之 Tx(Transaction 交易)### 2.3、ChaincodeProposalPayload定义```gotype ChaincodeProposalPayload struct {Input []byte //ChaincodeInvocationSpec序列化,即type ChaincodeInvocationSpec structTransientMap map[string][]byte //瞬态映射}//代码在protos/peer/proposal.pb.go```ChaincodeInvocationSpec更详细内容,参考:Fabric 1.0源代码笔记之 Chaincode (链码)## 3、ProposalResponse结构体定义### 3.1、ProposalResponse定义```gotype ProposalResponse struct {Version int32Timestamp *google_protobuf1.TimestampResponse *Response //type Response struct,peer.Response{Status: 200, Message: "OK"}}Payload []byteEndorsement *Endorsement //type Endorsement struct}//代码在protos/peer/proposal_response.pb.go```### 3.2、Response定义```gotype Response struct { //peer.Response{Status: 200, Message: "OK"}}Status int32Message stringPayload []byte}//代码在protos/peer/proposal_response.pb.go```### 3.3、Endorsement定义```gotype Endorsement struct {Endorser []byte //bccspmsp.signerSignature []byte}//代码在protos/peer/proposal_response.pb.go ```感谢关注兄弟连区块链教程分享!。
兄弟连区块链教程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客户端),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命令实现,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根命令入口及加载子命令,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)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```。
兄弟连区块链教程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源代码分析配置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工具包),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(通道相关),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源代码分析scc(系统链码)
兄弟连区块链教程Fabric1.0源代码分析scc(系统链码)兄弟连区块链教程Fabric1.0源代码分析scc(系统链码),2018年下半年,区块链行业正逐渐褪去发展之初的浮躁、回归理性,表面上看相关人才需求与身价似乎正在回落。
但事实上,正是初期泡沫的渐退,让人们更多的关注点放在了区块链真正的技术之上。
# Fabric 1.0源代码笔记之 scc(系统链码)## 1、scc概述scc,system chain codes,即系统链码。
包括:* cscc,configuration system chaincode,处理在peer通道配置。
* escc,endorser system chaincode,对交易申请的应答信息进行签名,来提供背书功能。
* lscc,lifecycle system chaincode,处理生命周期请求,如chaincode的安装,实例化,升级,卸载。
* qscc,querier system chaincode,提供账本查询,如获取块和交易信息。
* vscc,validator system chaincode,处理交易校验,包括检查背书策略和版本在并发时的控制。
scc代码分布在core/common/sysccprovider和core/scc目录下,目录结构如下:* core/common/sysccprovider目录:* sysccprovider.go,SystemChaincodeProvider和SystemChaincodeProviderFactory接口定义。
* core/scc目录:* sysccapi.go,SystemChaincode结构体及方法。
* sccproviderimpl.go,SystemChaincodeProvider和SystemChaincodeProviderFactory接口实现,即sccProviderFactory和sccProviderImpl结构体及方法。
兄弟连区块链技术培训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源代码分析流言算法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源代码分析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源代码分析(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 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)的交易,将安装过的链码在指定通道上进行实例化调用。
兄弟连区块链教程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中。
兄弟连区块链技术培训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。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
兄弟连区块链教程Fabric1.0源代码分析Peer peer chaincode命令及子命令实现兄弟连区块链教程Fabric1.0源代码分析Peer peer chaincode命令及子命令实现,2018年下半年,区块链行业正逐渐褪去发展之初的浮躁、回归理性,表面上看相关人才需求与身价似乎正在回落。
但事实上,正是初期泡沫的渐退,让人们更多的关注点放在了区块链真正的技术之上。
# 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 <链码打包文件>有个图3### 1.1、初始化Endorser客户端```gocf, err = InitCmdFactory(true, false)//代码在peer/chaincode/install.go```cf, err = InitCmdFactory(true, false)代码如下:```gofunc InitCmdFactory(isEndorserRequired, isOrdererRequired bool)(*ChaincodeCmdFactory, error) {var err errorvar endorserClient pb.EndorserClientif isEndorserRequired {//获取Endorser客户端endorserClient, err = common.GetEndorserClientFnc() //func GetEndorserClient() (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, chaincodeVersion)} else { //基于链码打包文件方式,直接读取ChaincodeDeploymentSpec消息var cds *pb.ChaincodeDeploymentSpecccpackmsg, cds, err = getPackageFromFile(ccpackfile)}//代码在peer/chaincode/install.go```ccpackmsg, err = genChaincodeDeploymentSpec(cmd, chaincodeName, chaincodeVersion)代码如下:```gofunc genChaincodeDeploymentSpec(cmd *mand, chaincodeName, chaincodeVersion string) (*pb.ChaincodeDeploymentSpec, error) {//已经存在,直接报错if existed, _ := ccprovider.ChaincodePackageExists(chaincodeName, chaincodeVersion); existed {return nil, fmt.Errorf("chaincode %s:%s already exists", chaincodeName, 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[chaincodeLang]),ChaincodeId: &pb.ChaincodeID{Path: chaincodePath, Name: chaincodeName, Version: chaincodeVersion},Input: input,}return spec, nil}//代码在peer/chaincode/common.go```cds, err := getChaincodeDeploymentSpec(spec, true)代码如下:```gofunc getChaincodeDeploymentSpec(spec *pb.ChaincodeSpec, crtPkg bool)(*pb.ChaincodeDeploymentSpec, error) {var codePackageBytes []byteif chaincode.IsDevMode() == false && crtPkg {var err errorerr = checkSpec(spec) //检查spec合法性codePackageBytes, err = container.GetChaincodePackageBytes(spec) //打包链码文件及依赖文件}//构造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.Proposal, 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 ChaincodeInvocationSpecChaincodeSpec: &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.Background(), signedProp)//代码在peer/chaincode/install.go```## 2、peer chaincode instantiate子命令实现(实例化链码)### 2.0、peer chaincode instantiate概述peer chaincode instantiate命令通过构造生命周期管理系统链码(LSCC)的交易,将安装过的链码在指定通道上进行实例化调用。