超级账本hyperledger fabric第五集:共识排序及源码阅读

一.共识机制

达成共识需要3个阶段,交易背书,交易排序,交易验证

  • 交易背书:模拟的
  • 交易排序:确定交易顺序,最终将排序好的交易打包区块分发
  • 交易验证:区块存储前要进行一下交易验证

二.orderer节点的作用

  • 交易排序
    1. 目的:保证系统的最终一致性(有限状态机)
    2. solo:单节点排序
    3. kafka:外置的分布式消息队列
  • 区块分发
    1. orderer中的区块并不是最终持久化的区块
    2. 是一个中间状态的区块
    3. 包含了所有交易,不管是有效还是无效,都会打包传给组织的锚节点
  • 多通道的数据隔离
    1. 客户端可以使用某个通道,发送交易

三.源码目录

  • 从goland中阅读

  • 源码目录
    1. bccsp:与密码学相关的,加密,数字签名,证书,将密码学中的函数抽象成了接口,方便调用和扩展
    2. bddtests:行为驱动开发,从需求直接到开发
    3. common:公共库、错误处理、日志出项,账本存储,相关工具
    4. core:是fabric的核心库,子目录是各个模块的目录 /  comm:网络通信相关
    5. devenv:官方提供的开发环境,使用的是Vagrant
    6. docs:文档
    7. events:事件监听机制
    8. examples:例子程序
    9. gossip:通信协议,组织内部的通信,区块同步
    10. gotools:用于编译
    11. images:docker镜像相关
    12. msp:成员服务管理,member serivce provider,读取证书做签名
    13. orderer:排序节点
    14. peer:peer节点
    15. proposals:用于扩展,新功能的提案
    16. protos:数据结构的定义

四.共识机制源码

orderer节点的源码

  • 首先看orderer目录下的main.go ,main.go里有一个NewServer可以进入server.go

main.go中func main() 主要起到判断作用,如果接收到的是start命令,就加载和初始化各种配置,如果接收到的是version指令,就打印版本号;之后在下面定义了上面的各种方法。

func main() {

	kingpin.Version("0.0.1")
	//判断接受到的参数Args
	switch kingpin.MustParse(app.Parse(os.Args[1:])) {

	// 如果接受到"start" command
	case start.FullCommand():
		logger.Infof("Starting %s", metadata.GetVersionInfo())
		//加载配置
		conf := config.Load()
		//初始化日志级别
		//生产环境下日志级别调高
		initializeLoggingLevel(conf)
		//初始化profile,go内置的观察程序运行的工具
		//可以通过http调用
		initializeProfilingService(conf)
		//初始化grpc服务端
		grpcServer := initializeGrpcServer(conf)
		//加载msp签名证书
		initializeLocalMsp(conf)
		//msp证书给签名者实例化
		signer := localmsp.NewSigner()
		//初始化链的管理者(也就是主节点)
		manager := initializeMultiChainManager(conf, signer)
		//实例化服务
		server := NewServer(manager, signer)
		//绑定服务
		ab.RegisterAtomicBroadcastServer(grpcServer.Server(), server)
		logger.Info("Beginning to serve requests")
		//启动服务
		grpcServer.Start()
	// 如果接受到"version" command
	case version.FullCommand():
		//打印版本号
		fmt.Println(metadata.GetVersionInfo())
	}

}

我们来看下初始化管理者的代码

func initializeMultiChainManager(conf *config.TopLevel, signer crypto.LocalSigner) multichain.Manager {
	//创建账本工厂,产生临时区块
	lf, _ := createLedgerFactory(conf)
	//判断链是否存在
	if len(lf.ChainIDs()) == 0 {
		//链不存在
		//启动引导链
		initializeBootstrapChannel(conf, lf)
	} else {
		logger.Info("Not bootstrapping because of existing chains")
	}
	//实例化共识机制
	//有solo和kafka两种模式
	consenters := make(map[string]multichain.Consenter)
	consenters["solo"] = solo.New()
	consenters["kafka"] = kafka.New(conf.Kafka.TLS, conf.Kafka.Retry, conf.Kafka.Version)

	return multichain.NewManagerImpl(lf, consenters, signer)
}
  • orderer的配置文件在orderer.yaml中,监听的地址是127.0.0.1;监听的端口是7050;BCCSP是密码学,账本存储最终还是存储到硬盘中。
  • 接下来咱们看下实例化服务server.go,这里面定义了交易收集和广播区块。
type server struct {
	//交易收集
	bh broadcast.Handler
	//广播区块
	dh deliver.Handler
}

我们具体看下交易收集:broadcast.go

func (bh *handlerImpl) Handle(srv ab.AtomicBroadcast_BroadcastServer) error {
	logger.Debugf("Starting new broadcast loop")
	for {
		//接收交易
		msg, err := srv.Recv()
		if err == io.EOF {
			logger.Debugf("Received EOF, hangup")
			return nil
		}
		if err != nil {
			logger.Warningf("Error reading from stream: %s", err)
			return err
		}

		payload, err := utils.UnmarshalPayload(msg.Payload)
		if err != nil {
			logger.Warningf("Received malformed message, dropping connection: %s", err)
			return srv.Send(&ab.BroadcastResponse{Status: cb.Status_BAD_REQUEST})
		}

		//验证消息体的内容,有错误则返回Status_
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值