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

相关文章

JavaScript中的reduce方法执行过程、使用场景及进阶用法

《JavaScript中的reduce方法执行过程、使用场景及进阶用法》:本文主要介绍JavaScript中的reduce方法执行过程、使用场景及进阶用法的相关资料,reduce是JavaScri... 目录1. 什么是reduce2. reduce语法2.1 语法2.2 参数说明3. reduce执行过程

Android 悬浮窗开发示例((动态权限请求 | 前台服务和通知 | 悬浮窗创建 )

《Android悬浮窗开发示例((动态权限请求|前台服务和通知|悬浮窗创建)》本文介绍了Android悬浮窗的实现效果,包括动态权限请求、前台服务和通知的使用,悬浮窗权限需要动态申请并引导... 目录一、悬浮窗 动态权限请求1、动态请求权限2、悬浮窗权限说明3、检查动态权限4、申请动态权限5、权限设置完毕后

redis群集简单部署过程

《redis群集简单部署过程》文章介绍了Redis,一个高性能的键值存储系统,其支持多种数据结构和命令,它还讨论了Redis的服务器端架构、数据存储和获取、协议和命令、高可用性方案、缓存机制以及监控和... 目录Redis介绍1. 基本概念2. 服务器端3. 存储和获取数据4. 协议和命令5. 高可用性6.

Python创建Excel的4种方式小结

《Python创建Excel的4种方式小结》这篇文章主要为大家详细介绍了Python中创建Excel的4种常见方式,文中的示例代码简洁易懂,具有一定的参考价值,感兴趣的小伙伴可以学习一下... 目录库的安装代码1——pandas代码2——openpyxl代码3——xlsxwriterwww.cppcns.c

PLsql Oracle 下载安装图文过程详解

《PLsqlOracle下载安装图文过程详解》PL/SQLDeveloper是一款用于开发Oracle数据库的集成开发环境,可以通过官网下载安装配置,并通过配置tnsnames.ora文件及环境变... 目录一、PL/SQL Developer 简介二、PL/SQL Developer 安装及配置详解1.下

在Java中使用ModelMapper简化Shapefile属性转JavaBean实战过程

《在Java中使用ModelMapper简化Shapefile属性转JavaBean实战过程》本文介绍了在Java中使用ModelMapper库简化Shapefile属性转JavaBean的过程,对比... 目录前言一、原始的处理办法1、使用Set方法来转换2、使用构造方法转换二、基于ModelMapper

springboot启动流程过程

《springboot启动流程过程》SpringBoot简化了Spring框架的使用,通过创建`SpringApplication`对象,判断应用类型并设置初始化器和监听器,在`run`方法中,读取配... 目录springboot启动流程springboot程序启动入口1.创建SpringApplicat

本地搭建DeepSeek-R1、WebUI的完整过程及访问

《本地搭建DeepSeek-R1、WebUI的完整过程及访问》:本文主要介绍本地搭建DeepSeek-R1、WebUI的完整过程及访问的相关资料,DeepSeek-R1是一个开源的人工智能平台,主... 目录背景       搭建准备基础概念搭建过程访问对话测试总结背景       最近几年,人工智能技术

使用Python在Excel中创建和取消数据分组

《使用Python在Excel中创建和取消数据分组》Excel中的分组是一种通过添加层级结构将相邻行或列组织在一起的功能,当分组完成后,用户可以通过折叠或展开数据组来简化数据视图,这篇博客将介绍如何使... 目录引言使用工具python在Excel中创建行和列分组Python在Excel中创建嵌套分组Pyt

Linux部署jar包过程

《Linux部署jar包过程》文章介绍了在Linux系统上部署Java(jar)包时需要注意的几个关键点,包括统一JDK版本、添加打包插件、修改数据库密码以及正确执行jar包的方法... 目录linux部署jar包1.统一jdk版本2.打包插件依赖3.修改密码4.执行jar包总结Linux部署jar包部署