The core protocol of WoopChain
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
woop/consensus/pbft_log.go

179 lines
5.7 KiB

package consensus
import (
"sync"
mapset "github.com/deckarep/golang-set"
"github.com/ethereum/go-ethereum/common"
msg_pb "github.com/harmony-one/harmony/api/proto/message"
"github.com/harmony-one/harmony/core/types"
)
// PbftLog represents the log stored by a node during PBFT process
type PbftLog struct {
blocks mapset.Set //store blocks received in PBFT
messages mapset.Set // store messages received in PBFT
maxLogSize uint32
mutex sync.Mutex
}
// PbftMessage is the record of pbft messages received by a node during PBFT process
type PbftMessage struct {
MessageType msg_pb.MessageType
ConsensusID uint32
SeqNum uint64
BlockHash common.Hash
SenderPubkey []byte
Payload []byte
}
// NewPbftLog returns new instance of PbftLog
func NewPbftLog() *PbftLog {
blocks := mapset.NewSet()
messages := mapset.NewSet()
logSize := maxLogSize
pbftLog := PbftLog{blocks: blocks, messages: messages, maxLogSize: logSize}
return &pbftLog
}
// Blocks return the blocks stored in the log
func (log *PbftLog) Blocks() mapset.Set {
return log.blocks
}
// Messages return the messages stored in the log
func (log *PbftLog) Messages() mapset.Set {
return log.messages
}
// AddBlock add a new block into the log
func (log *PbftLog) AddBlock(block *types.Block) {
log.blocks.Add(block)
}
// GetBlockByHash returns the block matches the given block hash
func (log *PbftLog) GetBlockByHash(hash common.Hash) *types.Block {
var found *types.Block
it := log.Blocks().Iterator()
for block := range it.C {
if block.(*types.Block).Header().Hash() == hash {
found = block.(*types.Block)
it.Stop()
}
}
return found
}
// GetBlocksByNumber returns the blocks match the given block number
func (log *PbftLog) GetBlocksByNumber(number uint64) []*types.Block {
found := []*types.Block{}
it := log.Blocks().Iterator()
for block := range it.C {
if block.(*types.Block).NumberU64() == number {
found = append(found, block.(*types.Block))
}
}
return found
}
// DeleteBlocksByNumber deletes blocks match given block number
func (log *PbftLog) DeleteBlocksByNumber(number uint64) {
found := mapset.NewSet()
it := log.Blocks().Iterator()
for block := range it.C {
if block.(*types.Block).NumberU64() == number {
found.Add(block)
}
}
log.blocks = log.blocks.Difference(found)
}
// DeleteMessagesByNumber deletes messages match given block number
func (log *PbftLog) DeleteMessagesByNumber(number uint64) {
found := mapset.NewSet()
it := log.Messages().Iterator()
for msg := range it.C {
if msg.(*PbftMessage).SeqNum == number {
found.Add(msg)
}
}
log.messages = log.messages.Difference(found)
}
// AddMessage adds a pbft message into the log
func (log *PbftLog) AddMessage(msg *PbftMessage) {
log.messages.Add(msg)
}
// GetMessagesByTypeSeqViewHash returns pbft messages with matching type, seqNum, consensusID and blockHash
func (log *PbftLog) GetMessagesByTypeSeqViewHash(typ msg_pb.MessageType, seqNum uint64, consensusID uint32, blockHash common.Hash) []*PbftMessage {
found := []*PbftMessage{}
it := log.Messages().Iterator()
for msg := range it.C {
if msg.(*PbftMessage).MessageType == typ && msg.(*PbftMessage).SeqNum == seqNum && msg.(*PbftMessage).ConsensusID == consensusID && msg.(*PbftMessage).BlockHash == blockHash {
found = append(found, msg.(*PbftMessage))
}
}
return found
}
// GetMessagesByTypeSeq returns pbft messages with matching type, seqNum
func (log *PbftLog) GetMessagesByTypeSeq(typ msg_pb.MessageType, seqNum uint64) []*PbftMessage {
found := []*PbftMessage{}
it := log.Messages().Iterator()
for msg := range it.C {
if msg.(*PbftMessage).MessageType == typ && msg.(*PbftMessage).SeqNum == seqNum {
found = append(found, msg.(*PbftMessage))
}
}
return found
}
// GetMessagesByTypeSeqHash returns pbft messages with matching type, seqNum
func (log *PbftLog) GetMessagesByTypeSeqHash(typ msg_pb.MessageType, seqNum uint64, blockHash common.Hash) []*PbftMessage {
found := []*PbftMessage{}
it := log.Messages().Iterator()
for msg := range it.C {
if msg.(*PbftMessage).MessageType == typ && msg.(*PbftMessage).SeqNum == seqNum && msg.(*PbftMessage).BlockHash == blockHash {
found = append(found, msg.(*PbftMessage))
}
}
return found
}
// HasMatchingAnnounce returns whether the log contains announce type message with given seqNum, consensusID and blockHash
func (log *PbftLog) HasMatchingAnnounce(seqNum uint64, consensusID uint32, blockHash common.Hash) bool {
found := log.GetMessagesByTypeSeqViewHash(msg_pb.MessageType_ANNOUNCE, seqNum, consensusID, blockHash)
return len(found) == 1
}
// GetMessagesByTypeSeqView returns pbft messages with matching type, seqNum and consensusID
func (log *PbftLog) GetMessagesByTypeSeqView(typ msg_pb.MessageType, seqNum uint64, consensusID uint32) []*PbftMessage {
found := []*PbftMessage{}
it := log.Messages().Iterator()
for msg := range it.C {
if msg.(*PbftMessage).MessageType != typ || msg.(*PbftMessage).SeqNum != seqNum || msg.(*PbftMessage).ConsensusID != consensusID {
continue
}
found = append(found, msg.(*PbftMessage))
}
return found
}
// ParsePbftMessage parses PBFT message into PbftMessage structure
func ParsePbftMessage(msg *msg_pb.Message) (*PbftMessage, error) {
pbftMsg := PbftMessage{}
pbftMsg.MessageType = msg.GetType()
consensusMsg := msg.GetConsensus()
pbftMsg.ConsensusID = consensusMsg.ConsensusId
pbftMsg.SeqNum = consensusMsg.SeqNum
pbftMsg.BlockHash = common.Hash{}
copy(pbftMsg.BlockHash[:], consensusMsg.BlockHash[:])
pbftMsg.Payload = make([]byte, len(consensusMsg.Payload))
copy(pbftMsg.Payload[:], consensusMsg.Payload[:])
pbftMsg.SenderPubkey = make([]byte, len(consensusMsg.SenderPubkey))
copy(pbftMsg.SenderPubkey[:], consensusMsg.SenderPubkey[:])
return &pbftMsg, nil
}