hyperledger fabric PBFT算法简要解析

本文简要解析了Hyperledger Fabric中PBFT共识算法的架构,包括controller、executor、helper、noops、pbft和util模块的职责。重点介绍了PBFT算法的内部调用流程,如viewChange和timeout机制,以及事件管理和timer机制,揭示了其复杂的事件流和灵活性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

收获了什么和做了什么是一个重要的议题!
本文章仅是学习交流资料,个人总结。

hyperledger fabric pbft算法架构的简要解析

fabric的共识算法代码全部都在consensus文件夹里,consensus文件夹里主要分为controller,executor,helper,noops,pbft,util文件模块。
其中consensus.go 主要包含了算法插件内部对外部暴露的接口和hyperledger外部对算法内部暴露的接口。

  • controller:共识算法模块是可插拔的,在controller里面可以选择具体使用哪种共识算法。目前hyperledger它提供了一个pbft算法和一个比较简单的noops算法。
  • executor:executor和helper是两个相互依赖的模块,主要提供了共识算法和外部衔接的一块代码。主要负责事件处理的转接。
  • helper:这里面主要包含了对外部接口的一个调用,比如执行处理transaction,stateupdate,持久化一些对象等。
  • noops: noops means no operations!(更正)
  • pbft: pbft算法,下面会简单的介绍一下pbft算法的调用流程。
  • util: 一些交互需要的工具包,最主要的一个实现的功能就是它的消息机制。

下面简要介绍两点,一点pbft算法代码内部从头到尾的一个调用流程,一点是pbft算法内部的事件机制和timeout代码的一个简要解析。

内部调用流程

在engine.go里面有获取一个共识算法plugin

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")

            // The channel never closes, so this should never break
            for msg := range engine.consensusFan.GetOutChannel() {
                engine.consenter.RecvMsg(msg.Msg, msg.Sender)
            }
        }()
    })
    return engine, err
}

它初始化一个consenter和一个helper,并互相把一个句柄赋值给了对方。这样做的目的,就是为了可以让外部调用内部,内部可以调用外部。

首先看一下它是如何初始化一个共识模块的:

 1. 调用controller获取一个plugin,当选择是pbft算法时,它会调用pbft.go 里的 GetPlugin(c consensus.Stack)方法,在pbft.go里面把所有的外部参数读进算法内部。
func New(stack consensus.Stack) consensus
以下是Hyperledger FabricPBFT算法Go语言实现代码: ```go package pbft import ( "crypto/sha256" "encoding/hex" "encoding/json" "fmt" "sync" ) const ( // PbftPhaseNotStarted represents the state where PBFT is not started PbftPhaseNotStarted = iota // PbftPhasePrePrepare represents the state where PBFT is in the pre-prepare phase PbftPhasePrePrepare // PbftPhasePrepare represents the state where PBFT is in the prepare phase PbftPhasePrepare // PbftPhaseCommit represents the state where PBFT is in the commit phase PbftPhaseCommit ) // PbftMessage represents a message in the PBFT algorithm type PbftMessage struct { Phase int SequenceNum int View int Digest string Block []byte ReplicaID int } // Pbft represents a PBFT instance type Pbft struct { mux sync.Mutex replicaID int view int sequenceNum int state int digest string block []byte messages map[string]PbftMessage } // NewPbft creates a new PBFT instance with the specified replica ID func NewPbft(replicaID int) *Pbft { return &Pbft{ replicaID: replicaID, view: 0, state: PbftPhaseNotStarted, messages: make(map[string]PbftMessage), } } // Start starts the PBFT algorithm with the specified block func (p *Pbft) Start(block []byte) { p.mux.Lock() defer p.mux.Unlock() // Set the initial state p.view = 0 p.sequenceNum = 1 p.state = PbftPhasePrePrepare p.block = block // Compute the digest of the block digest := sha256.Sum256(block) p.digest = hex.EncodeToString(digest[:]) // Create and broadcast the pre-prepare message prePrepareMsg := PbftMessage{ Phase: PbftPhasePrePrepare, SequenceNum: p.sequenceNum, View: p.view, Digest: p.digest, Block: p.block, ReplicaID: p.replicaID, } p.broadcast(prePrepareMsg) } // HandleMessage handles an incoming PBFT message func (p *Pbft) HandleMessage(msg []byte) { p.mux.Lock() defer p.mux.Unlock() // Parse the message var pbftMsg PbftMessage err := json.Unmarshal(msg, &pbftMsg) if err != nil { fmt.Printf("Failed to parse PBFT message: %s\n", err) return } // Check if we have already seen this message key := p.getMessageKey(pbftMsg) if _, ok := p.messages[key]; ok { return } // Add the message to our list of seen messages p.messages[key] = pbftMsg switch p.state { case PbftPhasePrePrepare: p.handlePrePrepare(pbftMsg) case PbftPhasePrepare: p.handlePrepare(pbftMsg) case PbftPhaseCommit: p.handleCommit(pbftMsg) } } // broadcast broadcasts a PBFT message to all other replicas func (p *Pbft) broadcast(msg PbftMessage) { // TODO: implement broadcast } // handlePrePrepare handles a pre-prepare message func (p *Pbft) handlePrePrepare(msg PbftMessage) { if msg.View != p.view || msg.SequenceNum != p.sequenceNum || msg.Digest != p.digest { return } // Create and broadcast the prepare message prepareMsg := PbftMessage{ Phase: PbftPhasePrepare, SequenceNum: p.sequenceNum, View: p.view, Digest: p.digest, Block: p.block, ReplicaID: p.replicaID, } p.broadcast(prepareMsg) // Update state p.state = PbftPhasePrepare } // handlePrepare handles a prepare message func (p *Pbft) handlePrepare(msg PbftMessage) { if msg.View != p.view || msg.SequenceNum != p.sequenceNum || msg.Digest != p.digest { return } // Update state p.state = PbftPhaseCommit // Create and broadcast the commit message commitMsg := PbftMessage{ Phase: PbftPhaseCommit, SequenceNum: p.sequenceNum, View: p.view, Digest: p.digest, Block: p.block, ReplicaID: p.replicaID, } p.broadcast(commitMsg) } // handleCommit handles a commit message func (p *Pbft) handleCommit(msg PbftMessage) { if msg.View != p.view || msg.SequenceNum != p.sequenceNum || msg.Digest != p.digest { return } // TODO: validate the commit message } // getMessageKey returns a unique key for a PBFT message func (p *Pbft) getMessageKey(msg PbftMessage) string { return fmt.Sprintf("%d:%d:%s:%d", msg.View, msg.SequenceNum, msg.Digest, msg.ReplicaID) } ``` 注意,上述代码只是一个简单的示例,需要根据实际情况进行修改和扩展。另外,这里的广播机制还没有实现,需要根据实际情况选择适当的广播方式。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值