区块链教程Fabric1.0源代码分析Peer peer channel命令及子命令实现
兄弟连区块链教程Fabric1.0源代码分析Peer peer channel命令及子命令实现,2018年下半年,区块链行业正逐渐褪去发展之初的浮躁、回归理性,表面上看相关人才需求与身价似乎正在回落。但事实上,正是初期泡沫的渐退,让人们更多的关注点放在了区块链真正的技术之上。
Fabric1.0源代码笔记之Peer peer channel命令及子命令实现
1、peer channel create子命令实现(创建通道)
1.1、初始化Orderer客户端
const ( EndorserRequired EndorserRequirement = true EndorserNotRequired EndorserRequirement = false OrdererRequired OrdererRequirement = true OrdererNotRequired OrdererRequirement = false ) cf, err = InitCmdFactory(EndorserNotRequired, OrdererRequired) //代码在peer/channel/create.go
cf, err = InitCmdFactory(EndorserNotRequired, OrdererRequired)代码如下:
type ChannelCmdFactory struct { EndorserClient pb.EndorserClient //EndorserClient Signer msp.SigningIdentity //Signer BroadcastClient common.BroadcastClient //BroadcastClient DeliverClient deliverClientIntf //DeliverClient BroadcastFactory BroadcastClientFactory //BroadcastClientFactory,type BroadcastClientFactory func() (common.BroadcastClient, error) } func InitCmdFactory(isEndorserRequired EndorserRequirement, isOrdererRequired OrdererRequirement) (*ChannelCmdFactory, error) { var err error cmdFact := &ChannelCmdFactory{} cmdFact.Signer, err = common.GetDefaultSignerFnc() //GetDefaultSignerFnc = GetDefaultSigner cmdFact.BroadcastFactory = func() (common.BroadcastClient, error) { return common.GetBroadcastClientFnc(orderingEndpoint, tls, caFile) //GetBroadcastClientFnc = GetBroadcastClient } //peer channel join或list需要endorser,本处暂未使用 if isEndorserRequired { cmdFact.EndorserClient, err = common.GetEndorserClientFnc() } //peer channel create或fetch需要orderer if isOrdererRequired { var opts []grpc.DialOption if tls { if caFile != "" { creds, err := credentials.NewClientTLSFromFile(caFile, "") opts = append(opts, grpc.WithTransportCredentials(creds)) } } else { opts = append(opts, grpc.WithInsecure()) } conn, err := grpc.Dial(orderingEndpoint, opts...) client, err := ab.NewAtomicBroadcastClient(conn).Deliver(context.TODO()) cmdFact.DeliverClient = newDeliverClient(conn, client, chainID) //构造deliverClient } return cmdFact, nil } //代码在peer/channel/channel.go
1.2、发送创建区块链的交易
err = sendCreateChainTransaction(cf) //代码在peer/channel/create.go
sendCreateChainTransaction(cf)代码如下:
func sendCreateChainTransaction(cf *ChannelCmdFactory) error { var err error var chCrtEnv *cb.Envelope if channelTxFile != "" { //peer channel create -f指定通道交易配置文件 chCrtEnv, err = createChannelFromConfigTx(channelTxFile) //获取创世区块 } else { chCrtEnv, err = createChannelFromDefaults(cf) //没有指定通道交易配置文件 } chCrtEnv, err = sanityCheckAndSignConfigTx(chCrtEnv) //检查和签名交易配置 var broadcastClient common.BroadcastClient broadcastClient, err = cf.BroadcastFactory() defer broadcastClient.Close() err = broadcastClient.Send(chCrtEnv) return err } //代码在peer/channel/create.go
1.3、获取创世区块并写入文件
var block *cb.Block block, err = getGenesisBlock(cf) //获取创世区块 b, err := proto.Marshal(block) //块序列化 err = ioutil.WriteFile(file, b, 0644) //写入文件 //代码在peer/channel/create.go
2、peer channel join子命令实现(加入通道)
2.1、初始化Endorser客户端
cf, err = InitCmdFactory(EndorserRequired, OrdererNotRequired) //代码在peer/channel/join.go
2.2、构造ChaincodeInvocationSpec消息(cscc.JoinChain)
spec, err := getJoinCCSpec() invocation := &pb.ChaincodeInvocationSpec{ChaincodeSpec: spec} //代码在peer/channel/join.go
spec, err := getJoinCCSpec()代码如下:
func getJoinCCSpec() (*pb.ChaincodeSpec, error) { gb, err := ioutil.ReadFile(genesisBlockPath) input := &pb.ChaincodeInput{Args: [][]byte{[]byte(cscc.JoinChain), gb}} spec := &pb.ChaincodeSpec{ Type: pb.ChaincodeSpec_Type(pb.ChaincodeSpec_Type_value["GOLANG"]), ChaincodeId: &pb.ChaincodeID{Name: "cscc"}, Input: input, } return spec, nil } //代码在peer/channel/join.go
2.3、创建cscc Proposal并签名
creator, err := cf.Signer.Serialize() //从CIS创建Proposal,CIS即ChaincodeInvocationSpec //调用CreateChaincodeProposal(typ, chainID, cis, creator) //而后调用CreateChaincodeProposalWithTransient(typ, chainID, cis, creator, nil) prop, _, err = putils.CreateProposalFromCIS(pcommon.HeaderType_CONFIG, "", invocation, creator) var signedProp *pb.SignedProposal signedProp, err = putils.GetSignedProposal(prop, cf.Signer) //代码在peer/channel/join.go
CreateChaincodeProposalWithTransient(typ, chainID, cis, creator, nil)代码如下:
func CreateChaincodeProposalWithTransient(typ common.HeaderType, chainID string, cis *peer.ChaincodeInvocationSpec, creator []byte, transientMap map[string][]byte) (*peer.Proposal, str ing, error) { //创建随机Nonce nonce, err := crypto.GetRandomNonce() //计算交易ID //digest, err := factory.GetDefault().Hash(append(nonce, creator...),&bccsp.SHA256Opts{}) txid, err := ComputeProposalTxID(nonce, creator) return CreateChaincodeProposalWithTxIDNonceAndTransient(txid, typ, chainID, cis, nonce, creator, transientMap) } //代码在protos/utils/proputils.go
CreateChaincodeProposalWithTxIDNonceAndTransient(txid, typ, chainID, cis, nonce, creator, transientMap)代码如下:
func CreateChaincodeProposalWithTxIDNonceAndTransient(txid string, typ common.HeaderType, chainID string, cis *peer.ChaincodeInvocationSpec, nonce, creator []byte, transientMap map[string][]byte) (*peer.Proposal, string, error) { ccHdrExt := &peer.ChaincodeHeaderExtension{ChaincodeId: cis.ChaincodeSpec.ChaincodeId} ccHdrExtBytes, err := proto.Marshal(ccHdrExt) cisBytes, err := proto.Marshal(cis) ccPropPayload := &peer.ChaincodeProposalPayload{Input: cisBytes, TransientMap: transientMap} ccPropPayloadBytes, err := proto.Marshal(ccPropPayload) var epoch uint64 = 0 timestamp := util.CreateUtcTimestamp() hdr := &common.Header{ChannelHeader: MarshalOrPanic(&common.ChannelHeader{ Type: int32(typ), TxId: txid, Timestamp: timestamp, ChannelId: chainID, Extension: ccHdrExtBytes, Epoch: epoch}), SignatureHeader: MarshalOrPanic(&common.SignatureHeader{Nonce: nonce, Creator: creator})} hdrBytes, err := proto.Marshal(hdr) return &peer.Proposal{Header: hdrBytes, Payload: ccPropPayloadBytes}, txid, nil } //代码在protos/utils/proputils.go
2.4、提交并处理Proposal
var proposalResp *pb.ProposalResponse proposalResp, err = cf.EndorserClient.ProcessProposal(context.Background(), signedProp) //代码在peer/channel/join.go
3、peer channel update(更新锚节点配置)
cf, err = InitCmdFactory(EndorserNotRequired, OrdererRequired) fileData, err := ioutil.ReadFile(channelTxFile) ctxEnv, err := utils.UnmarshalEnvelope(fileData) sCtxEnv, err := sanityCheckAndSignConfigTx(ctxEnv) var broadcastClient common.BroadcastClient broadcastClient, err = cf.BroadcastFactory() defer broadcastClient.Close() return broadcastClient.Send(sCtxEnv) //代码在peer/channel
感谢关注兄弟连区块链教程分享!
低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
VMware ubuntu 添加新的挂载盘
一,导语 在使用VMware虚拟机时,磁盘空间不足,发现在原有的磁盘上扩充并不会扩充ubuntu的文件空间,只能通过添加新的磁盘,然后挂载。 二,VMware操作 1.点击虚拟及设置 2.在硬件中点击添加,添加一个新的硬盘。 三, Ubuntu操作 1.查看磁盘命令 sudo fdisk -l zwj@ubuntu:~/java$ sudo fdisk -l Disk /dev/sda: 32.2 GB, 32212254720 bytes 255 heads, 63 sectors/track, 3916 cylinders, total 62914560 sectors Units = sectors of 1 * 512 = 512 bytes Sector size (logical/physical): 512 bytes / 512 bytes I/O size (minimum/optimal): 512 bytes / 512 bytes Disk identifier: 0x000415a6 Device Boot Start End...
- 下一篇
如何在Go的函数中得到调用者函数名?
有时候在Go的函数调用的过程中,我们需要知道函数被谁调用,比如打印日志信息等。例如下面的函数,我们希望在日志中打印出调用者的名字。 1func Foo() { 2 fmt.Println("谁在调用我?") 3 bar() 4} 5func Bar() { 6 fmt.Println("谁又在调用我?") 7} 首先打印函数本身的名称 最简单的方式就是硬编码。 因为在编译之前,我们肯定知道打印的时候所在哪个函数,但是更好的方式是编写一个通用的函数,比如下面的例子: 1package main 2import ( 3"fmt" 4"runtime" 5) 6func main() { 7 Foo() 8} 9func Foo() { 10 fmt.Printf("我是 %s, 谁在调用我?\n", printMyName()) 11 Bar() 12} 13
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
推荐阅读
最新文章
- CentOS8,CentOS7,CentOS6编译安装Redis5.0.7
- CentOS7,CentOS8安装Elasticsearch6.8.6
- Docker使用Oracle官方镜像安装(12C,18C,19C)
- Jdk安装(Linux,MacOS,Windows),包含三大操作系统的最全安装
- Linux系统CentOS6、CentOS7手动修改IP地址
- CentOS7安装Docker,走上虚拟化容器引擎之路
- CentOS7编译安装Cmake3.16.3,解决mysql等软件编译问题
- SpringBoot2全家桶,快速入门学习开发网站教程
- CentOS7设置SWAP分区,小内存服务器的救世主
- Docker快速安装Oracle11G,搭建oracle11g学习环境