Section2.3.5 stack

Stackconsensus里一个主要的接口, 包含了consensus.go里定义的除自身和Consenter之外的所有接口.

pbft内部, 也定义了一个与此对应的接口innerStack, 用于内部使用.

对于Stack里一些方法的介绍在前面各部分已经提到了一部分, 这里综合地描述下Stack的各个部分.

Stack is the set of stack-facing methods available to the consensus plugin

type Stack interface {
    NetworkStack
    SecurityUtils
    Executor
    LegacyExecutor
    LedgerManager
    ReadOnlyLedger
    StatePersistor
}

Vars

虽然在注释中地提到了在consensus/helper/handler.go中定义的ConsensusHandler也实现了Stack, 但是查找代码会发现, 其实只有consensus/helper/helper.go中定义的Helper实现了Stack. 所以下面只会讨论Helper.

Helper contains the reference to the peer's MessageHandlerCoordinator

type Helper struct {
    consenter    consensus.Consenter
    coordinator  peer.MessageHandlerCoordinator
    secOn        bool
    valid        bool // Whether we believe the state is up to date
    secHelper    crypto.Peer
    curBatch     []*pb.Transaction       // TODO, remove after issue 579
    curBatchErrs []*pb.TransactionResult // TODO, remove after issue 579
    persist.Helper

    executor consensus.Executor
}

consenter

consenter成员变量的类型为Consenter, 即consensus里定义的Consenter接口. 注意到, Stack并不包括Consenter.

// ExecutionConsumer allows callbacks from asycnhronous execution and statetransfer
type ExecutionConsumer interface {
    Executed(tag interface{})                                // Called whenever Execute completes
    Committed(tag interface{}, target *pb.BlockchainInfo)    // Called whenever Commit completes
    RolledBack(tag interface{})                              // Called whenever a Rollback completes
    StateUpdated(tag interface{}, target *pb.BlockchainInfo) // Called when state transfer completes, if target is nil, this indicates a failure and a new target should be supplied
}

// Consenter is used to receive messages from the network
// Every consensus plugin needs to implement this interface
type Consenter interface {
    RecvMsg(msg *pb.Message, senderHandle *pb.PeerID) error // Called serially with incoming messages from gRPC
    ExecutionConsumer
}

Engine的初始化过程中, 会先创建Helper, 然后用Helper作为参数创建obcBatch(即Consenter的实现), 然后再把obcBatch赋给Helper, 整个过程下来, HelperConsenter两者会互相包含对方作为成员变量.

Helper中仅使用consenter来实现ExecutionConsumer接口. 在ExecutionConsumer已经提到. 这些方法将会在executor中被使用.

coordinator

coordinator类型为peer.MessageHandlerCoordinator, 定义在peer中, 是初始化engine时的唯一参数, 也可以说是和节点联系的途径. engine使用它获得PeerEndpoint(本节点), 然后将它传给Helper用于初始化, 自己并不保存这个变量. Helper会保存该变量, 并用它来实现了NetworkStack里的功能, 包括获取节点信息, 广播, 单播, 另外还包括获取区块链长度.

h.coordinator.GetPeerEndpoint()
h.coordinator.GetPeers()
h.coordinator.Broadcast(msg, peerType)
h.coordinator.Unicast(msg, receiverHandle)
h.coordinator.GetBlockchainSize()

ConsensusHandler中也保存了该类型变量, 但并未使用.

该变量也会被传给executor, 将在后面提到.

secOn

一个类型为bool的简单变量, 判断是否对消息进行加密(Sign&Verify), 由配置信息决定取值, 且在程序运行时不再改变.

valid

类型为bool. 用于标记是否当前状态是否为最新.

Whether we believe the state is up to date

用于实现LedgerManager接口, 在LedgerManager中已经提到了使用情况.

engine执行func ProcessTransactionMsg()Helper执行func UpdateState()时会检查valid的取值.

secHelper

用于实现SecurityUtils接口, 类型为crypto.Peer, 通过调用coordinator.GetSecHelper()生成. 在消息传递前会进行加密, 接收后进行解密.

实际上, 在pbft中并没有直接使用SecurityUtils接口, 而是进行了封装, 但主要还是SecurityUtils接口部分.

curBatch & curBatchErrs

类型分别为[]*pb.Transaction[]*pb.TransactionResult, 储存Tx和Tx的执行结果, 注释中提到, 这两个变量将被删去.

curBatch     []*pb.Transaction       // TODO, remove after issue 579
curBatchErrs []*pb.TransactionResult // TODO, remove after issue 579

这两个变量将会在记录产生的Tx, 然后通过func CommitTxBatch()提交.

persist.Helper

Help继承了persist.Helper, 用于实现StatePersistor接口. 暂不关注.

executor

类型为consensus.Executor, 用于实现Executor接口. 通过executor.NewImpl(h, h, mhc)初始化, 这里, h是指Helper自身, mhc则是前面提到的peer.MessageHandlerCoordinator. 这里mhc是作为statetransfer.PartialStack使用的, statetransfer定义在core/peer/statetransfer/statetransfer.go, 用来转换状态, 具体地, 在executor里除了调用外func Start(), func Halt()只是在收到stateUpdateEvent后调用func SyncToTarget()来将区块链更新到目标状态.

前面已经提到过executor的执行模式, 即把所有消息都发送给event.Manager后经event.Manager调用func ProcessEvent()来执行. executor也不具体规定执行动作, 而只是把Helper里的方法(即接口ExecutionConsumerLegacyExecutor)封装起来, 实际动作是在后面那两个接口里定义的.

func

前面围绕着各个变量已经提到了一部分函数, 除此之外还定义了一些函数用于实现接口.

Executor

针对这个接口, 主要函数是通过executor实现的, 特别的, Executor定义了func Start(), func Halt(), 而这两个函数对于Helper来说是无意义的, 所以, 仅仅为了实现Executor, Helper中定义了两个空函数, 这样做只是为了满足编程语言规范. 另外, executor实际实现了Executor接口, 所以也定义了这两个函数, 在这两个函数中分别启动和停止event.Managerstatetransfer. 而executor本身的启动, 是在func setConsenter()里进行的. (由于Helper的初始化后紧接着就执行了func setConsenter(), 所以也可以理解成Helper初始化时边启动了executor.

ReadOnlyLedger

这些部分是由HelperLedger等交互实现的, 在ReadOnlyLedger里已经提到, 不再重复.

Last updated

Was this helpful?