Skip to content

Commit

Permalink
Merge pull request #8 from calmbeing/vote_part_ff
Browse files Browse the repository at this point in the history
Resolved comments
  • Loading branch information
calmbeing authored Apr 26, 2022
2 parents b5b42ee + 3c41d30 commit 838d08d
Show file tree
Hide file tree
Showing 11 changed files with 81 additions and 72 deletions.
2 changes: 1 addition & 1 deletion cmd/geth/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -168,7 +168,7 @@ var (
utils.CatalystFlag,
utils.BlockAmountReserved,
utils.CheckSnapshotWithMPT,
utils.BLSPassWordFileFlag,
utils.BLSPasswordFileFlag,
utils.BLSWalletDirFlag,
utils.VoteJournalDirFlag,
}
Expand Down
2 changes: 1 addition & 1 deletion cmd/geth/usage.go
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ var AppHelpFlagGroups = []flags.FlagGroup{
utils.TriesInMemoryFlag,
utils.BlockAmountReserved,
utils.CheckSnapshotWithMPT,
utils.BLSPassWordFileFlag,
utils.BLSPasswordFileFlag,
utils.BLSWalletDirFlag,
utils.VoteJournalDirFlag,
},
Expand Down
6 changes: 3 additions & 3 deletions cmd/utils/flags.go
Original file line number Diff line number Diff line change
Expand Up @@ -843,7 +843,7 @@ var (
Usage: "Enable checking between snapshot and MPT ",
}

BLSPassWordFileFlag = cli.StringFlag{
BLSPasswordFileFlag = cli.StringFlag{
Name: "blspassword",
Usage: "File for the BLS password",
}
Expand Down Expand Up @@ -1340,8 +1340,8 @@ func SetNodeConfig(ctx *cli.Context, cfg *node.Config) {
cfg.InsecureUnlockAllowed = ctx.GlobalBool(InsecureUnlockAllowedFlag.Name)
}

if ctx.GlobalIsSet(BLSPassWordFileFlag.Name) {
cfg.BLSPassWordFile = ctx.GlobalString(BLSPassWordFileFlag.Name)
if ctx.GlobalIsSet(BLSPasswordFileFlag.Name) {
cfg.BLSPasswordFile = ctx.GlobalString(BLSPasswordFileFlag.Name)
}
}

Expand Down
2 changes: 1 addition & 1 deletion consensus/consensus.go
Original file line number Diff line number Diff line change
Expand Up @@ -153,5 +153,5 @@ type PoSA interface {
GetHighestFinalizedNumber(chain ChainHeaderReader, header *types.Header) uint64
VerifyVote(chain ChainHeaderReader, vote *types.VoteEnvelope) bool
SetVotePool(votePool VotePool)
IsWithInSnapShot(chain ChainHeaderReader, header *types.Header) bool
WithinValidatorSet(chain ChainHeaderReader, header *types.Header) bool
}
16 changes: 8 additions & 8 deletions consensus/parlia/parlia.go
Original file line number Diff line number Diff line change
Expand Up @@ -1143,7 +1143,7 @@ func (p *Parlia) FinalizeAndAssemble(chain consensus.ChainHeaderReader, header *
return blk, receipts, nil
}

func (p *Parlia) IsWithInSnapShot(chain consensus.ChainHeaderReader, header *types.Header) bool {
func (p *Parlia) WithinValidatorSet(chain consensus.ChainHeaderReader, header *types.Header) bool {
number := header.Number.Uint64()
snap, err := p.snapshot(chain, number-1, header.ParentHash, nil)
if err != nil {
Expand All @@ -1159,20 +1159,20 @@ func (p *Parlia) IsWithInSnapShot(chain consensus.ChainHeaderReader, header *typ

// VerifyVote will verify: 1. If the vote comes from valid validators 2. If the vote's sourceNumber and sourceHash are correct
func (p *Parlia) VerifyVote(chain consensus.ChainHeaderReader, vote *types.VoteEnvelope) bool {
voteBlockNumber := vote.Data.TargetNumber
voteBlockHash := vote.Data.TargetHash
header := chain.GetHeaderByHash(voteBlockHash)
targetNumber := vote.Data.TargetNumber
targetHash := vote.Data.TargetHash
header := chain.GetHeaderByHash(targetHash)
if header == nil {
log.Warn("BlockHeader at current voteBlockNumber is nil", "blockNumber", voteBlockNumber, "blockHash", voteBlockHash)
log.Warn("BlockHeader at current voteBlockNumber is nil", "targetNumber", targetNumber, "targetHash", targetHash)
return false
}

curHighestJustifiedHeader := p.GetHighestJustifiedHeader(chain, header)
if curHighestJustifiedHeader == nil {
justifiedHeader := p.GetHighestJustifiedHeader(chain, header)
if justifiedHeader == nil {
log.Error("failed to get the highest justified header", "headerNumber", header.Number, "headerHash", header.Hash())
return false
}
if vote.Data.SourceNumber != curHighestJustifiedHeader.Number.Uint64() || vote.Data.SourceHash != curHighestJustifiedHeader.Hash() {
if vote.Data.SourceNumber != justifiedHeader.Number.Uint64() || vote.Data.SourceHash != justifiedHeader.Hash() {
return false
}

Expand Down
52 changes: 29 additions & 23 deletions core/vote/vote_manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ type VoteManager struct {
get getHighestJustifiedHeader
}

func NewVoteManager(mux *event.TypeMux, chainconfig *params.ChainConfig, chain *core.BlockChain, pool *VotePool, journalPath, bLSPassWordPath, bLSWalletPath string, engine consensus.PoSA, get getHighestJustifiedHeader) (*VoteManager, error) {
func NewVoteManager(mux *event.TypeMux, chainconfig *params.ChainConfig, chain *core.BlockChain, pool *VotePool, journalPath, blsPasswordPath, blsWalletPath string, engine consensus.PoSA, get getHighestJustifiedHeader) (*VoteManager, error) {
voteManager := &VoteManager{
mux: mux,

Expand All @@ -56,23 +56,25 @@ func NewVoteManager(mux *event.TypeMux, chainconfig *params.ChainConfig, chain *
get: get,
}

dirExists, err := wallet.Exists(bLSWalletPath)
dirExists, err := wallet.Exists(blsWalletPath)
if err != nil {
log.Error("Check BLS wallet exists error: %v.", err)
return nil, err
}
if !dirExists {
log.Error("BLS wallet did not exists.")
return nil, fmt.Errorf("BLS wallet did not exists.")
}

walletPassword, err := ioutil.ReadFile(bLSPassWordPath)
walletPassword, err := ioutil.ReadFile(blsPasswordPath)
if err != nil {
log.Error("Read BLS wallet password error: %v.", err)
return nil, err
}
log.Info("Read BLS wallet password successfully")

w, err := wallet.OpenWallet(context.Background(), &wallet.Config{
WalletDir: bLSWalletPath,
WalletDir: blsWalletPath,
WalletPassword: string(walletPassword),
})
if err != nil {
Expand All @@ -88,19 +90,21 @@ func NewVoteManager(mux *event.TypeMux, chainconfig *params.ChainConfig, chain *
}
log.Info("Initialized keymanager successfully")

voteJournal, err := NewVoteJournal(journalPath)
// Create voteSigner
voteSigner, err := NewVoteSigner(&km)
if err != nil {
return nil, err
}
log.Info("Create voteJournal successfully")
voteManager.journal = voteJournal
log.Info("Create voteSigner successfully")
voteManager.signer = voteSigner

voteSigner, err := NewVoteSigner(&km)
// Create voteJournal
voteJournal, err := NewVoteJournal(journalPath)
if err != nil {
return nil, err
}
log.Info("Create voteSigner successfully")
voteManager.signer = voteSigner
log.Info("Create voteJournal successfully")
voteManager.journal = voteJournal

// Subscribe to chain head event.
voteManager.chainHeadSub = voteManager.chain.SubscribeChainHeadEvent(voteManager.chainHeadCh)
Expand Down Expand Up @@ -142,7 +146,7 @@ func (voteManager *VoteManager) loop() {

curHead := cHead.Block.Header()
// Check if cur validator is within the validatorSet at curHead
if !voteManager.engine.IsWithInSnapShot(voteManager.chain, curHead) {
if !voteManager.engine.WithinValidatorSet(voteManager.chain, curHead) {
continue
}

Expand Down Expand Up @@ -179,6 +183,8 @@ func (voteManager *VoteManager) loop() {
voteManager.pool.PutVote(voteMessage)
votesManagerMetric(vote.TargetNumber, vote.TargetHash).Inc(1)
}
case <-voteManager.chainHeadSub.Err():
return
}
}
}
Expand All @@ -188,15 +194,15 @@ func (voteManager *VoteManager) loop() {
// A validator must not vote within the span of its other votes . (Rule 2)
// Validators always vote for their canonical chain’s latest block. (Rule 3)
func (voteManager *VoteManager) UnderRules(header *types.Header) (bool, uint64, common.Hash) {
curHighestJustifiedHeader := voteManager.get(voteManager.chain, header)
if curHighestJustifiedHeader == nil {
log.Error("curHighestJustifiedHeader is nil")
return true, 0, common.Hash{}
justifiedHeader := voteManager.get(voteManager.chain, header)
if justifiedHeader == nil {
log.Error("highestJustifiedHeader is nil")
return false, 0, common.Hash{}
}

sourceBlockNumber := curHighestJustifiedHeader.Number.Uint64()
sourceBlockHash := curHighestJustifiedHeader.Hash()
targetBlockNumber := header.Number.Uint64()
sourceNumber := justifiedHeader.Number.Uint64()
sourceHash := justifiedHeader.Hash()
targetNumber := header.Number.Uint64()

journal := voteManager.journal
walLog := journal.walLog
Expand All @@ -219,7 +225,7 @@ func (voteManager *VoteManager) UnderRules(header *types.Header) (bool, uint64,
}
if journalLatestVote == nil {
// Indicate there's no vote before in local node, so it must be under rules.
return true, sourceBlockNumber, sourceBlockHash
return true, sourceNumber, sourceHash
}

for index := lastIndex; index >= firstIndex; index-- {
Expand All @@ -232,21 +238,21 @@ func (voteManager *VoteManager) UnderRules(header *types.Header) (bool, uint64,
return false, 0, common.Hash{}
}

if targetBlockNumber == vote.Data.TargetNumber {
if targetNumber == vote.Data.TargetNumber {
return false, 0, common.Hash{}
}

if vote.Data.SourceNumber > sourceBlockNumber && vote.Data.TargetNumber < targetBlockNumber {
if vote.Data.SourceNumber > sourceNumber && vote.Data.TargetNumber < targetNumber {
log.Warn("curHeader's vote source and target are within its other votes")
return false, 0, common.Hash{}
}
if vote.Data.SourceNumber < sourceBlockNumber && vote.Data.TargetNumber > targetBlockNumber {
if vote.Data.SourceNumber < sourceNumber && vote.Data.TargetNumber > targetNumber {
log.Warn("Other votes source and target are within curHeader's")
return false, 0, common.Hash{}
}
}

return true, sourceBlockNumber, sourceBlockHash
return true, sourceNumber, sourceHash
}

// Metrics to monitor if voteManager worked in the expetected logic.
Expand Down
35 changes: 17 additions & 18 deletions core/vote/vote_pool.go
Original file line number Diff line number Diff line change
Expand Up @@ -119,21 +119,21 @@ func (pool *VotePool) PutVote(vote *types.VoteEnvelope) {
}

func (pool *VotePool) putIntoVotePool(vote *types.VoteEnvelope) bool {
voteBlockNumber := vote.Data.TargetNumber
voteBlockHash := vote.Data.TargetHash
targetNumber := vote.Data.TargetNumber
targetHash := vote.Data.TargetHash
header := pool.chain.CurrentBlock().Header()
headNumber := header.Number.Uint64()

voteData := &types.VoteData{
TargetNumber: voteBlockNumber,
TargetHash: voteBlockHash,
TargetNumber: targetNumber,
TargetHash: targetHash,
}

var votes map[common.Hash]*VoteBox
var votesPq *votesPriorityQueue
isFutureVote := false

voteBlock := pool.chain.GetHeaderByHash(voteBlockHash)
voteBlock := pool.chain.GetHeaderByHash(targetHash)
if voteBlock == nil {
votes = pool.futureVotes
votesPq = pool.futureVotesPq
Expand Down Expand Up @@ -175,22 +175,22 @@ func (pool *VotePool) SubscribeNewVoteEvent(ch chan<- core.NewVoteEvent) event.S
}

func (pool *VotePool) putVote(m map[common.Hash]*VoteBox, votesPq *votesPriorityQueue, vote *types.VoteEnvelope, voteData *types.VoteData, voteHash common.Hash, isFutureVote bool) {
voteBlockHash := vote.Data.TargetHash
voteBlockNumber := vote.Data.TargetNumber
targetHash := vote.Data.TargetHash
targetNumber := vote.Data.TargetNumber

log.Info("The vote info to put is:", "voteBlockNumber", voteBlockNumber, "voteBlockHash", voteBlockHash)
log.Info("The vote info to put is:", "voteBlockNumber", targetNumber, "voteBlockHash", targetHash)

pool.mu.Lock()
defer pool.mu.Unlock()
if _, ok := m[voteBlockHash]; !ok {
if _, ok := m[targetHash]; !ok {
// Push into votes priorityQueue if not exist in corresponding votes Map.
// To be noted: will not put into priorityQueue if exists in map to avoid duplicate element with the same voteData.
heap.Push(votesPq, voteData)
voteBox := &VoteBox{
blockNumber: voteBlockNumber,
blockNumber: targetNumber,
voteMessages: make([]*types.VoteEnvelope, 0, maxCurVoteAmountPerBlock),
}
m[voteBlockHash] = voteBox
m[targetHash] = voteBox

if isFutureVote {
localFutureVotesPqGauge.Inc(1)
Expand All @@ -200,7 +200,7 @@ func (pool *VotePool) putVote(m map[common.Hash]*VoteBox, votesPq *votesPriority
}

// Put into corresponding votes map.
m[voteBlockHash].voteMessages = append(m[voteBlockHash].voteMessages, vote)
m[targetHash].voteMessages = append(m[targetHash].voteMessages, vote)
// Add into received vote to avoid future duplicated vote comes.
pool.receivedVotes.Add(voteHash)
log.Info("VoteHash put into votepool is:", "voteHash", voteHash)
Expand All @@ -210,7 +210,7 @@ func (pool *VotePool) putVote(m map[common.Hash]*VoteBox, votesPq *votesPriority
} else {
localCurVotesGauge.Inc(1)
}
votesPerBlockHashMetric(voteBlockHash).Inc(1)
votesPerBlockHashMetric(targetHash).Inc(1)
localReceivedVotesGauge.Inc(1)
}

Expand Down Expand Up @@ -330,12 +330,11 @@ func (pool *VotePool) FetchVoteByHash(blockHash common.Hash) []*types.VoteEnvelo
return pool.curVotes[blockHash].voteMessages
}
return nil
//TODO: More strict condition is needed.
}

func (pool *VotePool) basicVerify(vote *types.VoteEnvelope, headNumber uint64, m map[common.Hash]*VoteBox, isFutureVote bool, voteHash common.Hash) bool {
voteBlockNumber := vote.Data.TargetNumber
voteBlockHash := vote.Data.TargetHash
targetNumber := vote.Data.TargetNumber
targetHash := vote.Data.TargetHash

pool.mu.RLock()
defer pool.mu.RUnlock()
Expand All @@ -346,7 +345,7 @@ func (pool *VotePool) basicVerify(vote *types.VoteEnvelope, headNumber uint64, m
return false
}
// Make sure in the range currentHeight-256~currentHeight+13.
if voteBlockNumber+lowerLimitOfVoteBlockNumber-1 < headNumber || voteBlockNumber > headNumber+upperLimitOfVoteBlockNumber {
if targetNumber+lowerLimitOfVoteBlockNumber-1 < headNumber || targetNumber > headNumber+upperLimitOfVoteBlockNumber {
log.Warn("BlockNumber of vote is outside the range of header-256~header+13")
return false
}
Expand All @@ -356,7 +355,7 @@ func (pool *VotePool) basicVerify(vote *types.VoteEnvelope, headNumber uint64, m
if isFutureVote {
maxVoteAmountPerBlock = maxFutureVoteAmountPerBlock
}
if voteBox, ok := m[voteBlockHash]; ok {
if voteBox, ok := m[targetHash]; ok {
return len(voteBox.voteMessages) <= maxVoteAmountPerBlock
}
return true
Expand Down
2 changes: 1 addition & 1 deletion core/vote/vote_pool_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ func (m *mockPOSA) VerifyVote(chain consensus.ChainHeaderReader, vote *types.Vot
func (m *mockPOSA) SetVotePool(votePool consensus.VotePool) {
}

func (m *mockPOSA) IsWithInSnapShot(chain consensus.ChainHeaderReader, header *types.Header) bool {
func (m *mockPOSA) WithinValidatorSet(chain consensus.ChainHeaderReader, header *types.Header) bool {
return true
}

Expand Down
28 changes: 16 additions & 12 deletions core/vote/vote_signer.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,33 +21,37 @@ const (
)

type VoteSigner struct {
km *keymanager.IKeymanager
km *keymanager.IKeymanager
pubKey [48]byte
}

func NewVoteSigner(km *keymanager.IKeymanager) (*VoteSigner, error) {
return &VoteSigner{
km: km,
}, nil
}

func (signer *VoteSigner) SignVote(vote *types.VoteEnvelope) error {
// Sign the vote
ctx, cancel := context.WithTimeout(context.Background(), voteSignerTimeout)
defer cancel()

pubKeys, err := (*signer.km).FetchValidatingPublicKeys(ctx)
pubKeys, err := (*km).FetchValidatingPublicKeys(ctx)
if err != nil {
return errors.Wrap(err, "could not fetch validating public keys")
return nil, errors.Wrap(err, "could not fetch validating public keys")
}
// Fetch the first pubKey as validator's bls public key.
pubKey := pubKeys[0]
return &VoteSigner{
km: km,
pubKey: pubKeys[0],
}, nil
}

func (signer *VoteSigner) SignVote(vote *types.VoteEnvelope) error {
// Sign the vote, fetch the first pubKey as validator's bls public key.
pubKey := signer.pubKey
blsPubKey, err := bls.PublicKeyFromBytes(pubKey[:])
if err != nil {
return errors.Wrap(err, "convert public key from bytes to bls failed")
}

voteDataHash := vote.Data.Hash()

ctx, cancel := context.WithTimeout(context.Background(), voteSignerTimeout)
defer cancel()

signature, err := (*signer.km).Sign(ctx, &validatorpb.SignRequest{
PublicKey: pubKey[:],
SigningRoot: voteDataHash[:],
Expand Down
Loading

0 comments on commit 838d08d

Please sign in to comment.