hyperledger fabric v0.6 pbft 源码分析(一)requeststore.go

本贴最后更新于 2790 天前,其中的信息可能已经渤澥桑田

阅读 fabric 源码的共识机制部分,感觉源码难度还是有的,所以先从最简单的 requeststore 开始吧。

在阅读了部分超级账本的源码后,有一个经验就是,在阅读源码特别是大项目的源码时,可能会感到无所适从,其实这也是很正常的,我的经验是可以先从一条线开始理清代码的执行流。比如像 hyperledger 这样的平台,可以从 链码的执行 这条线来看源码,跟着调试一步步走,相信会简单不少。

但是对于那些不是很好调试的代码来说,还有一个简单的方法,就是看代码的单元测试的程序,体会它是怎么使用的,这其实也是一个比较好的方法,下面分析 pbft 的实现源码,就是使用这种方法来分析的。

pbft 实现起来不容易,这里从它最简单的部分入手,话不多说,看代码吧:

// consensus/pbft/requeststore_test.go func TestOrderedRequests(t *testing.T) { or := &orderedRequests{} or.empty() r1 := createPbftReq(2, 1) r2 := createPbftReq(2, 2) r3 := createPbftReq(19, 1) if or.has(or.wrapRequest(r1).key) { t.Errorf("should not have req") } or.add(r1) if !or.has(or.wrapRequest(r1).key) { t.Errorf("should have req") } if or.has(or.wrapRequest(r2).key) { t.Errorf("should not have req") } if or.remove(r2) { t.Errorf("should not have removed req") } if !or.remove(r1) { t.Errorf("should have removed req") } if or.remove(r1) { t.Errorf("should not have removed req") } if or.order.Len() != 0 || len(or.presence) != 0 { t.Errorf("should have 0 len") } or.adds([]*Request{r1, r2, r3}) if or.order.Back().Value.(requestContainer).req != r3 { t.Errorf("incorrect order") } } func BenchmarkOrderedRequests(b *testing.B) { or := &orderedRequests{} or.empty() Nreq := 100000 reqs := make(map[string]*Request) for i := 0; i < Nreq; i++ { rc := or.wrapRequest(createPbftReq(int64(i), 0)) reqs[rc.key] = rc.req } b.ResetTimer() b.N = 100 fmt.Printf("N is %d\n", b.N) for i := 0; i < b.N; i++ { for _, r := range reqs { or.add(r) } for k := range reqs { _ = or.has(k) } for _, r := range reqs { or.remove(r) } } }

requeststore_test.go 开始看,它测试了两个函数:

  • TestOrderedRequests(t *testing.T)
  • BenchmarkOrderedRequests(b *testing.B)

这里的第一个测试函数是普通的测试函数,第二个是 benchmark 测试函数(注意*testing.B)

先看 createPbftReq 这个函数:

// consensus/pbft/mock_utilities_test.go func createPbftReq(tag int64, replica uint64) (req *Request) { tx := createTx(tag) txPacked := marshalTx(tx) req = &Request{ Timestamp: tx.GetTimestamp(), ReplicaId: replica, Payload: txPacked, } return }

这里就是使用传过来的 tag 与 replica 构造了 Request 对象,其中 tx 的时间属性(Seconds)与 tag 有关,在 createTx 还给定了 tx 的 type,这些不是很重要,我们只要知道是通过 tag 和 replica 构造了一个请求就行了。

继续看 orderedRequests:

type orderedRequests struct { order list.List presence map[string]*list.Element }

它保存着一个列表,还有一个 map,这里的 map 键是 list 元素的 hash,值对应于 list 的元素。

继续看:wrapRequest 函数

func (a *orderedRequests) wrapRequest(req *Request) requestContainer { return requestContainer{ key: hash(req), req: req, } }

就是把 req 变成 (hash(req), req)对,是不是很简单。。
后面的测试逻辑就很简单了,所以总的逻辑是:

创建空的 orderedRequests 并初始化
创建 3 个 req
判断 or 有没有 req1(此时为空,当然没有)
添加 req1
判断 or 有没有 req1(刚添加上,当然有)
判断 or 有没有 req2(当然没有)
删掉 r2(所以这个时候就可以得到源码里 remove 的作用,删除成功返回 true,否则返回 false)
删除 r1(删除成功)
再删除 r1(已为空,删除不成功)
检查 or 是否为空(为空)
添加 r1,r2,r3 到 or
看最后一个是不是 r3(这也体现出 requeststore 是顺序表)

第一个测试逻辑非常简单,但是可以让我们快速对源代码文件有了一定了解。

下一个测试函数是一个 benchmark 函数,本身非常的简单,我接触 golang 不久,要提的主要是 b.N 是函数执行的次数,golang 会使用不同的 N 来调用函数,多次测试取平均嘛,这个挺方便的。

另外测试结束后会提示:

100 1031034650 ns/op

它表示函数执行了 100 次,平次一次执行时间是 1031034650 纳秒。

测试到此就结束了,再看源码文件,测试没覆盖到的主要是:

type requestStore struct { outstandingRequests *orderedRequests pendingRequests *orderedRequests }

其他的函数基本上都是非常简单的,除了:

// getNextNonPending returns up to the next n outstanding, but not pending requests func (rs *requestStore) getNextNonPending(n int) (result []*Request) { for oreqc := rs.outstandingRequests.order.Front(); oreqc != nil; oreqc = oreqc.Next() { oreq := oreqc.Value.(requestContainer) if rs.pendingRequests.has(oreq.key) { continue } result = append(result, oreq.req) if len(result) == n { break } } return result }

这个函数主要是从 outstandingRequests 拿出不在 pendingRequests 的 n 个 request。

上面就是这部分的内容,非常简单的代码,关键是看代码的一个思路,后面会对 pbft 其他部分进行分析。

  • hyperledger
    3 引用
  • golang

    Go 语言是 Google 推出的一种全新的编程语言,可以在不损失应用程序性能的情况下降低代码的复杂性。谷歌首席软件工程师罗布派克(Rob Pike)说:我们之所以开发 Go,是因为过去 10 多年间软件开发的难度令人沮丧。Go 是谷歌 2009 发布的第二款编程语言。

    500 引用 • 1396 回帖 • 251 关注

相关帖子

欢迎来到这里!

我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。

注册 关于
请输入回帖内容 ...

推荐标签 标签

  • Ngui

    Ngui 是一个 GUI 的排版显示引擎和跨平台的 GUI 应用程序开发框架,基于
    Node.js / OpenGL。目标是在此基础上开发 GUI 应用程序可拥有开发 WEB 应用般简单与速度同时兼顾 Native 应用程序的性能与体验。

    7 引用 • 9 回帖 • 407 关注
  • Quicker

    Quicker 您的指尖工具箱!操作更少,收获更多!

    37 引用 • 157 回帖 • 1 关注
  • Unity

    Unity 是由 Unity Technologies 开发的一个让开发者可以轻松创建诸如 2D、3D 多平台的综合型游戏开发工具,是一个全面整合的专业游戏引擎。

    25 引用 • 7 回帖 • 118 关注
  • Redis

    Redis 是一个开源的使用 ANSI C 语言编写、支持网络、可基于内存亦可持久化的日志型、Key-Value 数据库,并提供多种语言的 API。从 2010 年 3 月 15 日起,Redis 的开发工作由 VMware 主持。从 2013 年 5 月开始,Redis 的开发由 Pivotal 赞助。

    284 引用 • 248 回帖
  • SpaceVim

    SpaceVim 是一个社区驱动的模块化 vim/neovim 配置集合,以模块的方式组织管理插件以
    及相关配置,为不同的语言开发量身定制了相关的开发模块,该模块提供代码自动补全,
    语法检查、格式化、调试、REPL 等特性。用户仅需载入相关语言的模块即可得到一个开箱
    即用的 Vim-IDE。

    3 引用 • 31 回帖 • 111 关注
  • 招聘

    哪里都缺人,哪里都不缺人。

    188 引用 • 1057 回帖 • 2 关注
  • FreeMarker

    FreeMarker 是一款好用且功能强大的 Java 模版引擎。

    23 引用 • 20 回帖 • 469 关注
  • C++

    C++ 是在 C 语言的基础上开发的一种通用编程语言,应用广泛。C++ 支持多种编程范式,面向对象编程、泛型编程和过程化编程。

    108 引用 • 153 回帖
  • 安装

    你若安好,便是晴天。

    132 引用 • 1184 回帖 • 2 关注
  • 一些有用的避坑指南。

    69 引用 • 93 回帖 • 1 关注
  • jQuery

    jQuery 是一套跨浏览器的 JavaScript 库,强化 HTML 与 JavaScript 之间的操作。由 John Resig 在 2006 年 1 月的 BarCamp NYC 上释出第一个版本。全球约有 28% 的网站使用 jQuery,是非常受欢迎的 JavaScript 库。

    63 引用 • 134 回帖 • 735 关注
  • 导航

    各种网址链接、内容导航。

    45 引用 • 177 回帖 • 1 关注
  • iOS

    iOS 是由苹果公司开发的移动操作系统,最早于 2007 年 1 月 9 日的 Macworld 大会上公布这个系统,最初是设计给 iPhone 使用的,后来陆续套用到 iPod touch、iPad 以及 Apple TV 等产品上。iOS 与苹果的 Mac OS X 操作系统一样,属于类 Unix 的商业操作系统。

    89 引用 • 150 回帖 • 4 关注
  • Laravel

    Laravel 是一套简洁、优雅的 PHP Web 开发框架。它采用 MVC 设计,是一款崇尚开发效率的全栈框架。

    19 引用 • 23 回帖 • 739 关注
  • 星云链

    星云链是一个开源公链,业内简单的将其称为区块链上的谷歌。其实它不仅仅是区块链搜索引擎,一个公链的所有功能,它基本都有,比如你可以用它来开发部署你的去中心化的 APP,你可以在上面编写智能合约,发送交易等等。3 分钟快速接入星云链 (NAS) 测试网

    3 引用 • 16 回帖 • 3 关注
  • 区块链

    区块链是分布式数据存储、点对点传输、共识机制、加密算法等计算机技术的新型应用模式。所谓共识机制是区块链系统中实现不同节点之间建立信任、获取权益的数学算法 。

    92 引用 • 752 回帖 • 2 关注
  • Vue.js

    Vue.js(读音 /vju ː/,类似于 view)是一个构建数据驱动的 Web 界面库。Vue.js 的目标是通过尽可能简单的 API 实现响应的数据绑定和组合的视图组件。

    268 引用 • 666 回帖 • 3 关注
  • 知乎

    知乎是网络问答社区,连接各行各业的用户。用户分享着彼此的知识、经验和见解,为中文互联网源源不断地提供多种多样的信息。

    10 引用 • 66 回帖
  • Anytype
    3 引用 • 31 回帖 • 28 关注
  • IBM

    IBM(国际商业机器公司)或万国商业机器公司,简称 IBM(International Business Machines Corporation),总公司在纽约州阿蒙克市。1911 年托马斯·沃森创立于美国,是全球最大的信息技术和业务解决方案公司,拥有全球雇员 30 多万人,业务遍及 160 多个国家和地区。

    17 引用 • 53 回帖 • 143 关注
  • WiFiDog

    WiFiDog 是一套开源的无线热点认证管理工具,主要功能包括:位置相关的内容递送;用户认证和授权;集中式网络监控。

    1 引用 • 7 回帖 • 615 关注
  • 小说

    小说是以刻画人物形象为中心,通过完整的故事情节和环境描写来反映社会生活的文学体裁。

    32 引用 • 108 回帖 • 2 关注
  • Swagger

    Swagger 是一款非常流行的 API 开发工具,它遵循 OpenAPI Specification(这是一种通用的、和编程语言无关的 API 描述规范)。Swagger 贯穿整个 API 生命周期,如 API 的设计、编写文档、测试和部署。

    26 引用 • 35 回帖 • 2 关注
  • CloudFoundry

    Cloud Foundry 是 VMware 推出的业界第一个开源 PaaS 云平台,它支持多种框架、语言、运行时环境、云平台及应用服务,使开发人员能够在几秒钟内进行应用程序的部署和扩展,无需担心任何基础架构的问题。

    4 引用 • 16 回帖 • 196 关注
  • AWS
    11 引用 • 28 回帖 • 7 关注
  • Vim

    Vim 是类 UNIX 系统文本编辑器 Vi 的加强版本,加入了更多特性来帮助编辑源代码。Vim 的部分增强功能包括文件比较(vimdiff)、语法高亮、全面的帮助系统、本地脚本(Vimscript)和便于选择的可视化模式。

    29 引用 • 66 回帖
  • 笔记

    好记性不如烂笔头。

    311 引用 • 794 回帖