Skip to content

Commit

Permalink
vote: check consensus key match vote key before voting (#1858)
Browse files Browse the repository at this point in the history
  • Loading branch information
NathanBSC authored Sep 8, 2023
1 parent a0cb4d0 commit 6af6162
Show file tree
Hide file tree
Showing 6 changed files with 33 additions and 18 deletions.
2 changes: 1 addition & 1 deletion consensus/consensus.go
Original file line number Diff line number Diff line change
Expand Up @@ -155,5 +155,5 @@ type PoSA interface {
GetJustifiedNumberAndHash(chain ChainHeaderReader, header *types.Header) (uint64, common.Hash, error)
GetFinalizedHeader(chain ChainHeaderReader, header *types.Header) *types.Header
VerifyVote(chain ChainHeaderReader, vote *types.VoteEnvelope) error
IsActiveValidatorAt(chain ChainHeaderReader, header *types.Header) bool
IsActiveValidatorAt(chain ChainHeaderReader, header *types.Header, checkVoteKeyFn func(bLSPublicKey *types.BLSPublicKey) bool) bool
}
7 changes: 4 additions & 3 deletions consensus/parlia/parlia.go
Original file line number Diff line number Diff line change
Expand Up @@ -1205,16 +1205,17 @@ func (p *Parlia) FinalizeAndAssemble(chain consensus.ChainHeaderReader, header *
return blk, receipts, nil
}

func (p *Parlia) IsActiveValidatorAt(chain consensus.ChainHeaderReader, header *types.Header) bool {
func (p *Parlia) IsActiveValidatorAt(chain consensus.ChainHeaderReader, header *types.Header, checkVoteKeyFn func(bLSPublicKey *types.BLSPublicKey) bool) bool {
number := header.Number.Uint64()
snap, err := p.snapshot(chain, number-1, header.ParentHash, nil)
if err != nil {
log.Error("failed to get the snapshot from consensus", "error", err)
return false
}
validators := snap.Validators
_, ok := validators[p.val]
return ok
validatorInfo, ok := validators[p.val]

return ok && (checkVoteKeyFn == nil || (validatorInfo != nil && checkVoteKeyFn(&validatorInfo.VoteAddress)))
}

// VerifyVote will verify: 1. If the vote comes from valid validators 2. If the vote's sourceNumber and sourceHash are correct
Expand Down
18 changes: 16 additions & 2 deletions core/vote/vote_manager.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
package vote

import (
"bytes"
"fmt"
"sync"

"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/consensus"
Expand Down Expand Up @@ -97,6 +99,7 @@ func (voteManager *VoteManager) loop() {
dlEventCh := events.Chan()

startVote := true
var once sync.Once
for {
select {
case ev := <-dlEventCh:
Expand Down Expand Up @@ -132,11 +135,22 @@ func (voteManager *VoteManager) loop() {

curHead := cHead.Block.Header()
// Check if cur validator is within the validatorSet at curHead
if !voteManager.engine.IsActiveValidatorAt(voteManager.chain, curHead) {
if !voteManager.engine.IsActiveValidatorAt(voteManager.chain, curHead,
func(bLSPublicKey *types.BLSPublicKey) bool {
return bytes.Equal(voteManager.signer.PubKey[:], bLSPublicKey[:])
}) {
log.Debug("cur validator is not within the validatorSet at curHead")
continue
}

// Add VoteKey to `miner-info`
once.Do(func() {
minerInfo := metrics.Get("miner-info")
if minerInfo != nil {
minerInfo.(metrics.Label).Value()["VoteKey"] = common.Bytes2Hex(voteManager.signer.PubKey[:])
}
})

// Vote for curBlockHeader block.
vote := &types.VoteData{
TargetNumber: curHead.Number.Uint64(),
Expand Down Expand Up @@ -174,7 +188,7 @@ func (voteManager *VoteManager) loop() {
}
case event := <-voteManager.syncVoteCh:
voteMessage := event.Vote
if voteManager.eth.IsMining() || !voteManager.signer.UsingKey(&voteMessage.VoteAddress) {
if voteManager.eth.IsMining() || !bytes.Equal(voteManager.signer.PubKey[:], voteMessage.VoteAddress[:]) {
continue
}
if err := voteManager.journal.WriteVote(voteMessage); err != nil {
Expand Down
4 changes: 2 additions & 2 deletions core/vote/vote_pool_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -99,11 +99,11 @@ func (m *mockInvalidPOSA) VerifyVote(chain consensus.ChainHeaderReader, vote *ty
return nil
}

func (m *mockPOSA) IsActiveValidatorAt(chain consensus.ChainHeaderReader, header *types.Header) bool {
func (m *mockPOSA) IsActiveValidatorAt(chain consensus.ChainHeaderReader, header *types.Header, checkVoteKeyFn func(bLSPublicKey *types.BLSPublicKey) bool) bool {
return true
}

func (m *mockInvalidPOSA) IsActiveValidatorAt(chain consensus.ChainHeaderReader, header *types.Header) bool {
func (m *mockInvalidPOSA) IsActiveValidatorAt(chain consensus.ChainHeaderReader, header *types.Header, checkVoteKeyFn func(bLSPublicKey *types.BLSPublicKey) bool) bool {
return true
}

Expand Down
13 changes: 4 additions & 9 deletions core/vote/vote_signer.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package vote

import (
"bytes"
"context"
"fmt"
"io/ioutil"
Expand All @@ -28,7 +27,7 @@ var votesSigningErrorCounter = metrics.NewRegisteredCounter("votesSigner/error",

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

func NewVoteSigner(blsPasswordPath, blsWalletPath string) (*VoteSigner, error) {
Expand All @@ -39,7 +38,7 @@ func NewVoteSigner(blsPasswordPath, blsWalletPath string) (*VoteSigner, error) {
}
if !dirExists {
log.Error("BLS wallet did not exists.")
return nil, fmt.Errorf("BLS wallet did not exists.")
return nil, fmt.Errorf("BLS wallet did not exists")
}

walletPassword, err := ioutil.ReadFile(blsPasswordPath)
Expand Down Expand Up @@ -76,13 +75,13 @@ func NewVoteSigner(blsPasswordPath, blsWalletPath string) (*VoteSigner, error) {

return &VoteSigner{
km: &km,
pubKey: pubKeys[0],
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
pubKey := signer.PubKey
blsPubKey, err := bls.PublicKeyFromBytes(pubKey[:])
if err != nil {
return errors.Wrap(err, "convert public key from bytes to bls failed")
Expand All @@ -105,7 +104,3 @@ func (signer *VoteSigner) SignVote(vote *types.VoteEnvelope) error {
copy(vote.Signature[:], signature.Marshal()[:])
return nil
}

func (signer *VoteSigner) UsingKey(bLSPublicKey *types.BLSPublicKey) bool {
return bytes.Equal(signer.pubKey[:], bLSPublicKey[:])
}
7 changes: 6 additions & 1 deletion eth/backend.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ import (
"github.com/ethereum/go-ethereum/internal/ethapi"
"github.com/ethereum/go-ethereum/internal/shutdowncheck"
"github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/metrics"
"github.com/ethereum/go-ethereum/miner"
"github.com/ethereum/go-ethereum/node"
"github.com/ethereum/go-ethereum/p2p"
Expand Down Expand Up @@ -568,8 +569,12 @@ func (s *Ethereum) StartMining(threads int) error {
log.Error("Etherbase account unavailable locally", "err", err)
return fmt.Errorf("signer missing: %v", err)
}

parlia.Authorize(eb, wallet.SignData, wallet.SignTx)

minerInfo := metrics.Get("miner-info")
if minerInfo != nil {
minerInfo.(metrics.Label).Value()["Etherbase"] = eb.String()
}
}
// If mining is started, we can disable the transaction rejection mechanism
// introduced to speed sync times.
Expand Down

0 comments on commit 6af6162

Please sign in to comment.