Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

vote: check consensus key match vote key before voting #1858

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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[:])
}
brilliant-lx marked this conversation as resolved.
Show resolved Hide resolved
})

// 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