各种Store - Agzs/geth-pbft-study GitHub Wiki
xxxStore
pbftCore的成员变量xxxStore:blockStore、certStore、viewChangeStore、newViewStore、checkpointStore。这些store主要用于recvXXX()函数保存接收到的消息。
blockStore
define
blockStore map[string]*types.Block // track request batches
blockStore为字典类型,key是block的hash值,为string类型,一般由string(preprep.BlockHash)或hash(preprep.GetBlockMsg())获得key值;value为block类型,采用ethereum中已定义的block,如下:
// Block represents an entire block in the Ethereum blockchain.
type Block struct {
header *Header
uncles []*Header
transactions Transactions
// caches
hash atomic.Value
size atomic.Value
// Td is used by package core to store the total difficulty of the chain up to and including the block.
td *big.Int
// These fields are used by package eth to track inter-peer block relay.
ReceivedAt time.Time
ReceivedFrom interface{}
}
Usage
block将fabric中的requestBatch替换,并且用blockStore替换reqBatchStore
原reqBatchStore主要用于request请求的打包,现在简化为Block,不需要做任何处理,走一遍共识过程就ok了。
certStore
define
certStore map[msgID]*msgCert // track quorum certificates for requests
certStore为字典类型,key为msgID,{v,n}一般通过{view,SequenceNumber}赋值;value为msgCert,msgCert用于三阶段协议(prePrepare、prepare、commit)消息数目的统计
type msgID struct { // our index through certStore
v uint64
n uint64
}
type msgCert struct {
digest string // 保存block的hash的string形式
prePrepare *types.PrePrepare // 保存prePrepare消息,注意为指针类型,可在其他函数中修改prepare
sentPrepare bool // 标记是否已发送prepare消息
prepare []*types.Prepare // 保存来自各个VP的Prepare消息,用于后期统计prepare消息的数目
sentCommit bool // 标记是否已发送commit消息
commit []*types.Commit // 保存来自各个VP的commit消息,用于后期统计commit消息的数目
}
prePrepare、prepare、commit结构如下:
type PrePrepare struct {
View uint64 `protobuf:"varint,1,opt,name=view" json:"view,omitempty"`
SequenceNumber uint64 `protobuf:"varint,2,opt,name=sequence_number,json=sequenceNumber" json:"sequence_number,omitempty"`
BlockHash []byte `protobuf:"bytes,3,opt,name=block_hash,json=blockHash,proto3" json:"block_hash,omitempty"`
Block *Block `protobuf:"bytes,4,opt,name=block_msg,json=blockMsg" json:"block_msg,omitempty"`
ReplicaId uint64 `protobuf:"varint,5,opt,name=replica_id,json=replicaId" json:"replica_id,omitempty"`
}
type Prepare struct {
View uint64 `protobuf:"varint,1,opt,name=view" json:"view,omitempty"`
SequenceNumber uint64 `protobuf:"varint,2,opt,name=sequence_number,json=sequenceNumber" json:"sequence_number,omitempty"`
BlockHash []byte `protobuf:"bytes,3,opt,name=block_hash,json=blockHash,proto3" json:"block_hash,omitempty"`
ReplicaId uint64 `protobuf:"varint,4,opt,name=replica_id,json=replicaId" json:"replica_id,omitempty"`
}
type Commit struct {
View uint64 `protobuf:"varint,1,opt,name=view" json:"view,omitempty"`
SequenceNumber uint64 `protobuf:"varint,2,opt,name=sequence_number,json=sequenceNumber" json:"sequence_number,omitempty"`
BlockHash []byte `protobuf:"bytes,3,opt,name=block_hash,json=blockHash,proto3" json:"block_hash,omitempty"`
ReplicaId uint64 `protobuf:"varint,4,opt,name=replica_id,json=replicaId" json:"replica_id,omitempty"`
}
值得注意的是,同一个区块的prePrepare、prepare、commit中相同变量保存的数值都是相同的,比如SequenceNumber在三个结构体中保存的都是同一个数值。
Usage
根据{view,seqNo}组成的msgID获取cert,注意到只在func (instance *pbftCore) getCert(v uint64, n uint64) (cert *msgCert)中添加新的cert.其他处的调用只是获取cert,然后使用cert的成员变量判断条件,进行其他操作。
viewChangeStore
define
viewChangeStore map[vcidx]*types.ViewChange // track view-change messages
type vcidx struct {
v uint64
id uint64
}
type ViewChange struct {
View uint64 `protobuf:"varint,1,opt,name=view" json:"view,omitempty"`
H uint64 `protobuf:"varint,2,opt,name=h" json:"h,omitempty"`
Cset []*ViewChange_C `protobuf:"bytes,3,rep,name=cset" json:"cset,omitempty"`
Pset []*ViewChange_PQ `protobuf:"bytes,4,rep,name=pset" json:"pset,omitempty"`
Qset []*ViewChange_PQ `protobuf:"bytes,5,rep,name=qset" json:"qset,omitempty"`
ReplicaId uint64 `protobuf:"varint,6,opt,name=replica_id,json=replicaId" json:"replica_id,omitempty"`
Signature []byte `protobuf:"bytes,7,opt,name=signature,proto3" json:"signature,omitempty"`
Signer common.Address `protobuf:"bytes,8,opt,name=signer,proto3" json:"signature,omitempty"` //=> add Signer used for verifying signature --Agzs
}
Usage
viewchangeStore用于保存viewchange的信息,且仅在recvViewChange(vc *ViewChange)中被赋值,语句为instance.viewChangeStore[vcidx{vc.View, vc.ReplicaId}] = vc,其它的调用都只是获取其中的viewChange信息
newViewStore
define
newViewStore map[uint64]*types.NewView // track last new-view we received or sent
type NewView struct {
View uint64 `protobuf:"varint,1,opt,name=view" json:"view,omitempty"`
Vset []*ViewChange `protobuf:"bytes,2,rep,name=vset" json:"vset,omitempty"`
Xset map[uint64]string `protobuf:"bytes,3,rep,name=xset" json:"xset,omitempty" protobuf_key:"varint,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"`
ReplicaId uint64 `protobuf:"varint,4,opt,name=replica_id,json=replicaId" json:"replica_id,omitempty"`
}
Usage
newViewStore用于保存NewView,当同一个view的viewchange到达一定的的数量(instance.N - instance.f)后,就会产生viewChangeQuorumEvent,在收到 viewChangeQuorumEvent事件后, 会产生NewView的send操作
viewChangeQuorumEvent is returned to the event loop when a new ViewChange message is received which is part of a quorum cert
newViewStore的赋值操作只在下面两个函数中进行:
func (instance *pbftCore) sendNewView() events.Event {
...
nv := &NewView{
View: instance.view,
Vset: vset,
Xset: msgList,
ReplicaId: instance.id,
}
...
instance.newViewStore[instance.view] = nv
return instance.processNewView()
}
func (instance *pbftCore) recvNewView(nv *NewView) events.Event {
logger.Infof("Replica %d received new-view %d",instance.id, nv.View)
...
instance.newViewStore[nv.View] = nv
return instance.processNewView()
}
checkpointStore
define
checkpointStore map[Checkpoint]bool // track checkpoints as set
type Checkpoint struct {
SequenceNumber uint64 `protobuf:"varint,1,opt,name=sequence_number,json=sequenceNumber" json:"sequence_number,omitempty"`
ReplicaId uint64 `protobuf:"varint,2,opt,name=replica_id,json=replicaId" json:"replica_id,omitempty"`
Id string `protobuf:"bytes,3,opt,name=id" json:"id,omitempty"` //=>checkpoint's name
}
Usage
checkpointStore用于保存checkpoint, checkpoint主要用于垃圾回收和viewchange中:
我们一连执行了K条请求,在第K条请求执行完时,向全网发起广播,告诉大家它已经将这K条执行完毕,要是大家反馈说这K条我们也执行完毕了,那就可以删除这K条的信息了,接下来再执行K条,完成后再发起一次广播,即每隔K条发起一次全网共识,这个概念叫checkpoint,每隔K条去征求一下大家的意见,要是获得了大多数的认同(a quorum certificate with 2 f + 1 CHECKPOINT messages (including its own)),就形成了一个 stable checkpoint(记录在第K条的编号)
We refer to the states produced by the execution of these requests as checkpoints and we say that a checkpoint with a proof is a stable checkpoint.
checkpointStore的赋值操作仅在recvCheckpoint()函数中:
func (instance *pbftCore) recvCheckpoint(chkpt *Checkpoint) events.Event {
logger.Debugf("Replica %d received checkpoint from replica %d, seqNo %d, digest %s", instance.id, chkpt.ReplicaId, chkpt.SequenceNumber, chkpt.Id)
...
instance.checkpointStore[*chkpt] = true
...
logger.Debugf("Replica %d found checkpoint quorum for seqNo %d, digest %s", instance.id, chkpt.SequenceNumber, chkpt.Id)
instance.moveWatermarks(chkpt.SequenceNumber)
return instance.processNewView()
}