群内分享
1.比特币运行原理-每一位投资者都应该知道20180409
2.区块链语言Solidity校验椭圆曲线加密数字签名
3.英国爱丁堡大学、美国MIT、斯坦福、伊利诺伊的区块链相关课程:
http://www.inf.ed.ac.uk/teaching/courses/bdl/
https://github.com/mit-dci/6.892-public
https://crypto.stanford.edu/cs251/
http://soc1024.ece.illinois.edu/teaching/ece398sc/spring2018/
4.基于以太坊的电子钱包开发分析
群内讨论
Fabric源码分析-共识模块
作者-趣链科技-清源
原文链接:https://zhuanlan.zhihu.com/p/35255567
正好这些天要有一个需求要帮客户魔改Fabric-v0.6,把一些hyperchain的高级特性移植过去,借此机会把之前看过的源码在梳理一下。
下面就是对Fabric共识模块的源码分析和梳理,代码都是以Fabric-v0.6-preview为例,在1.0及后续版本中都移除了PBFT部分,用了更好的SBFT,目前这一部分还在开发中。
目录结构
可以看到共识模块目录如下。
consensus
├── controller
├── executor
├── helper
│ └── persist
├── noops
├── pbft
└── util
└── events
目录含义如下
controller 用来控制Fabric选择什么样的共识算法,默认是noops。
executor 封装了消息队列中对交易的处理。
helper 对外提供接口调用和数据持久化接口。
noops 提供了如何编写Fabric共识算法的Demo。
pbft PBFT算法的具体实现。
util 实现了一个peer节点到共识算法的一个消息通道,和一个消息队列。
流程概览
Fabric网络通过一个EventLoop和共识算法进行交互,所有的操作都通过对事件循环中的事件监听进行推进。
整体流程如下图所示。
Consensus模块接口
fabric/consensus/consensus.go对外提供共识模块的方法调用。
其中最核心也是每个算法必须实现的接口是Consenter。
type ExecutionConsumer interface {
Executed(tag interface{})
Committed(tag interface{}, target *pb.BlockchainInfo)
RolledBack(tag interface{})
StateUpdated(tag interface{}, target *pb.BlockchainInfo)
}
type Consenter interface {
RecvMsg(msg *pb.Message, senderHandle *pb.PeerID) error
ExecutionConsumer
}
接口的具体实现在fabric/consensus/pbft/external.go。
因为对交易的操作都是异步的,所以必须手动实现Executed,Committed,RolledBack,StateUpdated方法来监听对应动作的完成。
RecvMsg方法用来从不用的peer节点接收消息。
初始化共识模块
共识算法引擎在peer启动的时候初始化,初始化的具体函数如下所示。
// consensus/helper/engine.go
func GetEngine(coord peer.MessageHandlerCoordinator) (peer.Engine, error) {
var err error
engineOnce.Do(func() {
engine = new(EngineImpl)
engine.helper = NewHelper(coord)
engine.consenter = controller.NewConsenter(engine.helper)
engine.helper.setConsenter(engine.consenter)
engine.peerEndpoint, err = coord.GetPeerEndpoint()
engine.consensusFan = util.NewMessageFan()
go func() {
logger.Debug("Starting up message thread for consenter")
for msg := range engine.consensusFan.GetOutChannel() {
engine.consenter.RecvMsg(msg.Msg, msg.Sender)
}
}()
})
return engine, err
}
GetEngine的作用是进行共识模块的初始化,同时启动一个goroutine等待消息进入。
具体的engine.consenter是在consensus/controller/controller.go里选择。
// consensus/controller/controller.go
func NewConsenter(stack consensus.Stack) consensus.Consenter {
plugin := strings.ToLower(viper.GetString("peer.validator.consensus.plugin"))
if plugin == "pbft" {
logger.Infof("Creating consensus plugin %s", plugin)
return pbft.GetPlugin(stack)
}
logger.Info("Creating default consensus plugin (noops)")
return noops.GetNoops(stack)
}
默认选择的是noops,如果需要添加自己编写的共识模块需要在这里自行添加判断。
noops 只是演示如何编写Fabric共识模块,不要用在生产环境。
如果选择了PBFT则会调用consensus/pbft/pbft.go进行初始化。
使用PBFT的batch模式启动时会调用newObcBatch进行PBFT算法初始化。
PBFT只有batch一种模式。
// consensus/pbft/batch.go
func newObcBatch(id uint64, config *viper.Viper, stack consensus.Stack) *obcBatch {
var err error
...
op.manager = events.NewManagerImpl()
op.manager.SetReceiver(op)
etf := events.NewTimerFactoryImpl(op.manager)
op.pbft = newPbftCore(id, config, op, etf)
op.manager.Start()
blockchainInfoBlob := stack.GetBlockchainInfoBlob()
op.externalEventReceiver.manager = op.manager
...
return op
}
newObcBatch主要做了这几项工作
初始化了eventLoop的消息队列。
设置了消息的接收者,用来处理对应的消息。
创建监听消息超时的定时器。
初始化pbft算法。
启动消息队列,不断监听事件的到来并且分发给接收者处理。
消息处理
Fabric的共识消息是通过eventLoop注射给对应处理函数的。
// consensus/util/events/events.go
func SendEvent(receiver Receiver, event Event) {
next := event
for {
next = receiver.ProcessEvent(next)
if next == nil {
break
}
}
}
func (em *managerImpl) Inject(event Event) {
if em.receiver != nil {
SendEvent(em.receiver, event)
}
}
func (em *managerImpl) eventLoop() {
for {
select {
case next := <-em.events:
em.Inject(next)
case <-em.exit:
logger.Debug("eventLoop told to exit")
return
}
}
}
eventLoop函数不断的从em.events里取出事件,通过Inject注射给对应的接收者,注意,通过SendEvent注射给接收者的ProcessEvent方法。
SendEvent函数实现非常有意思,如果receiver.ProcessEvent的返回不为nil则不断的调用receiver.ProcessEvent直到找到对应的消息处理函数,在ProcessEvent函数中,其余case均为事件处理函数,唯独pbftMessage依赖SendEvent发送消息给其余函数处理。
// consensus/pbft/pbft-core.go
func (instance *pbftCore) ProcessEvent(e events.Event) events.Event {
...
case *pbftMessage:
return pbftMessageEvent(*et)
case pbftMessageEvent:
msg := et
logger.Debugf("Replica %d received incoming message from %v", instance.id, msg.sender)
next, err := instance.recvMsg(msg.msg, msg.sender)
if err != nil {
break
}
return next
case *RequestBatch:
err = instance.recvRequestBatch(et)
case *PrePrepare:
err = instance.recvPrePrepare(et)
...
}
可以看到*pbftMessage和pbftMessageEvent这两个case通过recvMsg的返回值又把消息分发给其余case,非常巧妙。
PBFT算法的不同阶段都会按着上面的流程映射到不同的处理函数往前推进,本质上是一个状态机。
至此Fabric的Consensus模块主要流程已经梳理清楚,熟悉了这个流程以后再结合PBFT算法的过程就可以很容易在此基础上添加新的功能了。
欢迎大家关注我的博客 Qin Yuan 不定期更新区块链相关文章。
群内工作
《磨链入门区块链》共同参与写一些东西,目录大纲完善中,一个长期项目。
招募条件:
1.需要一定的区块链基础。
2.对上述任何一方面有较为深入理解。
3.每周能保证一定的空余时间来折腾。
4.了解github相关
5.人员进行筛选,时间周期比较长。
有意向联系我。
磨链在线课程
对自己擅长方面有一定的沉淀,愿意开设在线课程,会考虑和一些专业培训机构合作,要求有一定的一线经验,实实在在分享课程。有兴趣的联,有偿工作。
磨链(mochain)社区招募相关人员
编号社区内岗位具体工作内容
1.社区运营组每周有固定时间投入社区的建设,包括活动策划,社区门户的维护,相关分享文档编辑,每天社区分享在各个平台的发布,规划整个社区运行。
2核心活动组织者负责社区相关具体学习小组,线上线下活动,社区和合作社区、合作企业的具体合作。
3社区核心技术组社区核心技术输出,普及区块链是一个方面,具体实实在在做一些事情,包括社区内的具体实践项目
4编辑美工组建设良好的门面,一些宣传的内容的美工,一些文章的编辑。
PS:想加入磨链的,或者具体参与到磨链的建设中的,请加磨链组织者微信(jackyjin09)。并且注明自己的能参与的编号(1.2.3.4),欢迎每一位区块链技术爱好者加入磨链,一块琢磨区块链技术。
磨链招聘合作相关信息
若招聘过程中以担保或者其他任何名义向求职者收取财物(如办卡费、押金、培训费),扣押或以保管为名索要身份证、毕业证及其他证件等行为,均涉嫌违法,请您提高警惕并注意保护个人信息!
关于磨链和相关合作
磨链”---取磨炼之意,旨在普及区块链技术,磨炼技术,更好投身区块链行业。有兴趣一块琢磨区块链技术,联系笔者微信(jackyjin09)。
磨链社区是一个纯粹的技术社区,欢迎相关技术合作,在不违反原则的前提下,积极参与合作。
你可以在这里找到我们:
磨链社区公众号:
![qrcode_for_gh_ce38ae338981_344.jpg-8.7kB][7]
1. 磨链社区:http://mochain.info
2. Github : https://github.com/mochain
3. Gitter 聊天: https://gitter.im/mochain
4. 知识星球: https://t.zsxq.com/M3BMVZN
5. 知乎:https://www.zhihu.com/people/mochain
(持续更新中)
合作社区
趣链科技技术团队
HiBlock区块链社区