fabric创建通道过程

2024-08-29 16:08
文章标签 创建 过程 通道 fabric

本文主要是介绍fabric创建通道过程,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

创建通道

  • 1. Client 处理过程
    • 1.1. 发送创建通道的交易
    • 1.2. 获取通道的创世区块
  • 2. Orderer 处理过程
    • 2.1. 处理消息
  • 3. 参考资料

创建通道的过程

Client Orderer 用户指定或从默认配置中生成创建通道的交易mychannel.tx, 该消息是Envelope结构的CONFIG_UPDATE类型消息 对mychannel.tx进行签名并封装 发送封装好的消息 接收消息 获取通道消息处理器,- 因为是创建通道,<br- >则调用默认的系统通- 道管理器 对消息进行重新封装, 头部消息类型为ORDERER_TRANSACTION, 内层消息类型为CONFIG,每次封装都会签名 返回处理结果 将配置交易消息构造成创世区块 并保存到新通道的数据文件中 获取区块号为0的创世区块 loop [Client每200毫秒请求一次] par [Orderer处理] [Client处理] 返回创世区块 保存创世区块 Client Orderer

1. Client 处理过程

internal/peer/channel/create.go

func executeCreate(cf *ChannelCmdFactory) error {// 发送创建通道的交易err := sendCreateChainTransaction(cf)if err != nil {return err}// 获取通道的创世区块block, err := getGenesisBlock(cf)if err != nil {return err}b, err := proto.Marshal(block)if err != nil {return err}file := channelID + ".block"if outputBlock != common.UndefinedParamValue {file = outputBlock}// 保存通道创世区块信息err = ioutil.WriteFile(file, b, 0o644)if err != nil {return err}return nil
}

1.1. 发送创建通道的交易

internal/peer/channel/create.go

func sendCreateChainTransaction(cf *ChannelCmdFactory) error {var err errorvar chCrtEnv *cb.Envelope// 如果传入创建通道的交易信息,则读取并解析if channelTxFile != "" {if chCrtEnv, err = createChannelFromConfigTx(channelTxFile); err != nil {return err}} else { // 如果没有传入,则根据默认的配置yaml进行创建if chCrtEnv, err = createChannelFromDefaults(cf); err != nil {return err}}// 对交易信息进行必要检查,通过后对消息进行签名if chCrtEnv, err = sanityCheckAndSignConfigTx(chCrtEnv, cf.Signer); err != nil {return err}var broadcastClient common.BroadcastClientbroadcastClient, err = cf.BroadcastFactory()if err != nil {return errors.WithMessage(err, "error getting broadcast client")}defer broadcastClient.Close()// 发送封装好的消息err = broadcastClient.Send(chCrtEnv)return err
}

1.2. 获取通道的创世区块

每隔 200 毫秒尝试从排序节点获取一次通道的创世区块,即区块号为 0 的区块。

internal/peer/channel/create.go

func getGenesisBlock(cf *ChannelCmdFactory) (*cb.Block, error) {timer := time.NewTimer(timeout)defer timer.Stop()for {select {case <-timer.C:cf.DeliverClient.Close()return nil, errors.New("timeout waiting for channel creation")default:// 获取创世区块if block, err := cf.DeliverClient.GetSpecifiedBlock(0); err != nil {cf.DeliverClient.Close()cf, err = InitCmdFactory(EndorserNotRequired, PeerDeliverNotRequired, OrdererRequired)if err != nil {return nil, errors.WithMessage(err, "failed connecting")}// 休眠 200 毫秒time.Sleep(200 * time.Millisecond)} else {cf.DeliverClient.Close()return block, nil}}}
}

2. Orderer 处理过程

orderer/common/broadcast/broadcast.go

// Handle reads requests from a Broadcast stream, processes them, and returns the responses to the stream
func (bh *Handler) Handle(srv ab.AtomicBroadcast_BroadcastServer) error {addr := util.ExtractRemoteAddress(srv.Context())logger.Debugf("Starting new broadcast loop for %s", addr)for {// 接收消息msg, err := srv.Recv()if err == io.EOF {logger.Debugf("Received EOF from %s, hangup", addr)return nil}if err != nil {logger.Warningf("Error reading from %s: %s", addr, err)return err}// 处理消息resp := bh.ProcessMessage(msg, addr)// 发送处理结果err = srv.Send(resp)if resp.Status != cb.Status_SUCCESS {return err}if err != nil {logger.Warningf("Error sending to %s: %s", addr, err)return err}}
}

2.1. 处理消息

orderer/common/broadcast/broadcast.go

// ProcessMessage validates and enqueues a single message
func (bh *Handler) ProcessMessage(msg *cb.Envelope, addr string) (resp *ab.BroadcastResponse) {tracker := &MetricsTracker{ChannelID: "unknown",TxType:    "unknown",Metrics:   bh.Metrics,}defer func() {// This looks a little unnecessary, but if done directly as// a defer, resp gets the (always nil) current state of resp// and not the return valuetracker.Record(resp)}()tracker.BeginValidate()// 获取通道消息处理器,如果是创建通道,则调用默认的系统通道管理器chdr, isConfig, processor, err := bh.SupportRegistrar.BroadcastChannelSupport(msg)if chdr != nil {tracker.ChannelID = chdr.ChannelIdtracker.TxType = cb.HeaderType(chdr.Type).String()}if err != nil {logger.Warningf("[channel: %s] Could not get message processor for serving %s: %s", tracker.ChannelID, addr, err)return &ab.BroadcastResponse{Status: cb.Status_BAD_REQUEST, Info: err.Error()}}if !isConfig {logger.Debugf("[channel: %s] Broadcast is processing normal message from %s with txid '%s' of type %s", chdr.ChannelId, addr, chdr.TxId, cb.HeaderType_name[chdr.Type])configSeq, err := processor.ProcessNormalMsg(msg)if err != nil {logger.Warningf("[channel: %s] Rejecting broadcast of normal message from %s because of error: %s", chdr.ChannelId, addr, err)return &ab.BroadcastResponse{Status: ClassifyError(err), Info: err.Error()}}tracker.EndValidate()tracker.BeginEnqueue()if err = processor.WaitReady(); err != nil {logger.Warningf("[channel: %s] Rejecting broadcast of message from %s with SERVICE_UNAVAILABLE: rejected by Consenter: %s", chdr.ChannelId, addr, err)return &ab.BroadcastResponse{Status: cb.Status_SERVICE_UNAVAILABLE, Info: err.Error()}}err = processor.Order(msg, configSeq)if err != nil {logger.Warningf("[channel: %s] Rejecting broadcast of normal message from %s with SERVICE_UNAVAILABLE: rejected by Order: %s", chdr.ChannelId, addr, err)return &ab.BroadcastResponse{Status: cb.Status_SERVICE_UNAVAILABLE, Info: err.Error()}}} else { // 对于创建通道,isConfig 值为 true,执行以下逻辑logger.Debugf("[channel: %s] Broadcast is processing config update message from %s", chdr.ChannelId, addr)// 对消息进行重新封装,头部消息类型为ORDERER_TRANSACTION,内层消息类型为CONFIGconfig, configSeq, err := processor.ProcessConfigUpdateMsg(msg)if err != nil {logger.Warningf("[channel: %s] Rejecting broadcast of config message from %s because of error: %s", chdr.ChannelId, addr, err)return &ab.BroadcastResponse{Status: ClassifyError(err), Info: err.Error()}}tracker.EndValidate()tracker.BeginEnqueue()if err = processor.WaitReady(); err != nil {logger.Warningf("[channel: %s] Rejecting broadcast of message from %s with SERVICE_UNAVAILABLE: rejected by Consenter: %s", chdr.ChannelId, addr, err)return &ab.BroadcastResponse{Status: cb.Status_SERVICE_UNAVAILABLE, Info: err.Error()}}// 将配置更新消息进行广播err = processor.Configure(config, configSeq)if err != nil {logger.Warningf("[channel: %s] Rejecting broadcast of config message from %s with SERVICE_UNAVAILABLE: rejected by Configure: %s", chdr.ChannelId, addr, err)return &ab.BroadcastResponse{Status: cb.Status_SERVICE_UNAVAILABLE, Info: err.Error()}}}logger.Debugf("[channel: %s] Broadcast has successfully enqueued message of type %s from %s", chdr.ChannelId, cb.HeaderType_name[chdr.Type], addr)return &ab.BroadcastResponse{Status: cb.Status_SUCCESS}
}

3. 参考资料

  • Fabric创建通道流程解析

这篇关于fabric创建通道过程的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1118329

相关文章

浅析Spring Security认证过程

类图 为了方便理解Spring Security认证流程,特意画了如下的类图,包含相关的核心认证类 概述 核心验证器 AuthenticationManager 该对象提供了认证方法的入口,接收一个Authentiaton对象作为参数; public interface AuthenticationManager {Authentication authenticate(Authenti

作业提交过程之HDFSMapReduce

作业提交全过程详解 (1)作业提交 第1步:Client调用job.waitForCompletion方法,向整个集群提交MapReduce作业。 第2步:Client向RM申请一个作业id。 第3步:RM给Client返回该job资源的提交路径和作业id。 第4步:Client提交jar包、切片信息和配置文件到指定的资源提交路径。 第5步:Client提交完资源后,向RM申请运行MrAp

【Python编程】Linux创建虚拟环境并配置与notebook相连接

1.创建 使用 venv 创建虚拟环境。例如,在当前目录下创建一个名为 myenv 的虚拟环境: python3 -m venv myenv 2.激活 激活虚拟环境使其成为当前终端会话的活动环境。运行: source myenv/bin/activate 3.与notebook连接 在虚拟环境中,使用 pip 安装 Jupyter 和 ipykernel: pip instal

【机器学习】高斯过程的基本概念和应用领域以及在python中的实例

引言 高斯过程(Gaussian Process,简称GP)是一种概率模型,用于描述一组随机变量的联合概率分布,其中任何一个有限维度的子集都具有高斯分布 文章目录 引言一、高斯过程1.1 基本定义1.1.1 随机过程1.1.2 高斯分布 1.2 高斯过程的特性1.2.1 联合高斯性1.2.2 均值函数1.2.3 协方差函数(或核函数) 1.3 核函数1.4 高斯过程回归(Gauss

在cscode中通过maven创建java项目

在cscode中创建java项目 可以通过博客完成maven的导入 建立maven项目 使用快捷键 Ctrl + Shift + P 建立一个 Maven 项目 1 Ctrl + Shift + P 打开输入框2 输入 "> java create"3 选择 maven4 选择 No Archetype5 输入 域名6 输入项目名称7 建立一个文件目录存放项目,文件名一般为项目名8 确定

Java 创建图形用户界面(GUI)入门指南(Swing库 JFrame 类)概述

概述 基本概念 Java Swing 的架构 Java Swing 是一个为 Java 设计的 GUI 工具包,是 JAVA 基础类的一部分,基于 Java AWT 构建,提供了一系列轻量级、可定制的图形用户界面(GUI)组件。 与 AWT 相比,Swing 提供了许多比 AWT 更好的屏幕显示元素,更加灵活和可定制,具有更好的跨平台性能。 组件和容器 Java Swing 提供了许多

MOLE 2.5 分析分子通道和孔隙

软件介绍 生物大分子通道和孔隙在生物学中发挥着重要作用,例如在分子识别和酶底物特异性方面。 我们介绍了一种名为 MOLE 2.5 的高级软件工具,该工具旨在分析分子通道和孔隙。 与其他可用软件工具的基准测试表明,MOLE 2.5 相比更快、更强大、功能更丰富。作为一项新功能,MOLE 2.5 可以估算已识别通道的物理化学性质。 软件下载 https://pan.quark.cn/s/57

顺序表之创建,判满,插入,输出

文章目录 🍊自我介绍🍊创建一个空的顺序表,为结构体在堆区分配空间🍊插入数据🍊输出数据🍊判断顺序表是否满了,满了返回值1,否则返回0🍊main函数 你的点赞评论就是对博主最大的鼓励 当然喜欢的小伙伴可以:点赞+关注+评论+收藏(一键四连)哦~ 🍊自我介绍   Hello,大家好,我是小珑也要变强(也是小珑),我是易编程·终身成长社群的一名“创始团队·嘉宾”

Maven创建项目中的groupId, artifactId, 和 version的意思

文章目录 groupIdartifactIdversionname groupId 定义:groupId 是 Maven 项目坐标的第一个部分,它通常表示项目的组织或公司的域名反转写法。例如,如果你为公司 example.com 开发软件,groupId 可能是 com.example。作用:groupId 被用来组织和分组相关的 Maven artifacts,这样可以避免

批处理以当前时间为文件名创建文件

批处理以当前时间为文件名创建文件 批处理创建空文件 有时候,需要创建以当前时间命名的文件,手动输入当然可以,但是有更省心的方法吗? 假设我是 windows 操作系统,打开命令行。 输入以下命令试试: echo %date:~0,4%_%date:~5,2%_%date:~8,2%_%time:~0,2%_%time:~3,2%_%time:~6,2% 输出类似: 2019_06