diff --git a/consensus/checks.go b/consensus/checks.go index e65c90425..ac9848660 100644 --- a/consensus/checks.go +++ b/consensus/checks.go @@ -3,6 +3,7 @@ package consensus import ( msg_pb "github.com/harmony-one/harmony/api/proto/message" "github.com/harmony-one/harmony/core/types" + "github.com/harmony-one/harmony/crypto/bls" "github.com/harmony-one/harmony/internal/chain" "github.com/harmony-one/harmony/shard" ) @@ -20,17 +21,21 @@ func (consensus *Consensus) validatorSanityChecks(msg *msg_pb.Message) bool { Uint64("viewID", msg.GetConsensus().ViewId). Str("msgType", msg.Type.String()). Msg("[validatorSanityChecks] Checking new message") - senderKey, err := consensus.verifySenderKey(msg) + err := consensus.verifySenderKey(msg) if err != nil { if err == shard.ErrValidNotInCommittee { consensus.getLogger().Info(). + Hex("senderKey", msg.GetConsensus().SenderPubkey). Msg("sender key not in this slot's subcommittee") } else { consensus.getLogger().Error().Err(err).Msg("VerifySenderKey failed") } return false } - + senderKey, err := bls.BytesToBLSPublicKey(msg.GetConsensus().SenderPubkey) + if err != nil { + return false + } if !senderKey.IsEqual(consensus.LeaderPubKey) && consensus.current.Mode() == Normal && !consensus.ignoreViewIDCheck { consensus.getLogger().Warn().Msgf( @@ -60,10 +65,11 @@ func (consensus *Consensus) leaderSanityChecks(msg *msg_pb.Message) bool { Uint64("viewID", msg.GetConsensus().ViewId). Str("msgType", msg.Type.String()). Msg("[leaderSanityChecks] Checking new message") - senderKey, err := consensus.verifySenderKey(msg) + err := consensus.verifySenderKey(msg) if err != nil { if err == shard.ErrValidNotInCommittee { - consensus.getLogger().Info().Msgf( + consensus.getLogger().Info(). + Hex("senderKey", msg.GetConsensus().SenderPubkey).Msgf( "[%s] sender key not in this slot's subcommittee", msg.GetType().String(), ) @@ -75,6 +81,10 @@ func (consensus *Consensus) leaderSanityChecks(msg *msg_pb.Message) bool { } return false } + senderKey, err := bls.BytesToBLSPublicKey(msg.GetConsensus().SenderPubkey) + if err != nil { + return false + } if err = verifyMessageSig(senderKey, msg); err != nil { consensus.getLogger().Error().Err(err).Msgf( "[%s] Failed to verify sender's signature", @@ -197,7 +207,8 @@ func (consensus *Consensus) viewChangeSanityCheck(msg *msg_pb.Message) bool { senderKey, err := consensus.verifyViewChangeSenderKey(msg) if err != nil { if err == shard.ErrValidNotInCommittee { - consensus.getLogger().Info().Msgf( + consensus.getLogger().Info(). + Hex("senderKey", msg.GetConsensus().SenderPubkey).Msgf( "[%s] sender key not in this slot's subcommittee", msg.GetType().String(), ) diff --git a/consensus/consensus_service.go b/consensus/consensus_service.go index 5bad092c2..52056f151 100644 --- a/consensus/consensus_service.go +++ b/consensus/consensus_service.go @@ -167,6 +167,15 @@ func (consensus *Consensus) ToggleConsensusCheck() { // IsValidatorInCommittee returns whether the given validator BLS address is part of my committee func (consensus *Consensus) IsValidatorInCommittee(pubKey *bls.PublicKey) bool { + pubKeyBytes := shard.FromLibBLSPublicKeyUnsafe(pubKey) + if pubKeyBytes == nil { + return false + } + return consensus.Decider.IndexOf(*pubKeyBytes) != -1 +} + +// IsValidatorInCommitteeBytes returns whether the given validator BLS address is part of my committee +func (consensus *Consensus) IsValidatorInCommitteeBytes(pubKey shard.BLSPublicKey) bool { return consensus.Decider.IndexOf(pubKey) != -1 } @@ -193,17 +202,14 @@ func verifyMessageSig(signerPubKey *bls.PublicKey, message *msg_pb.Message) erro } // verifySenderKey verifys the message senderKey is properly signed and senderAddr is valid -func (consensus *Consensus) verifySenderKey(msg *msg_pb.Message) (*bls.PublicKey, error) { - consensusMsg := msg.GetConsensus() - senderKey, err := bls_cosi.BytesToBLSPublicKey(consensusMsg.SenderPubkey) - if err != nil { - return nil, err - } +func (consensus *Consensus) verifySenderKey(msg *msg_pb.Message) error { + senderKey := shard.BLSPublicKey{} - if !consensus.IsValidatorInCommittee(senderKey) { - return nil, shard.ErrValidNotInCommittee + copy(senderKey[:], msg.GetConsensus().SenderPubkey[:]) + if !consensus.IsValidatorInCommitteeBytes(senderKey) { + return shard.ErrValidNotInCommittee } - return senderKey, nil + return nil } func (consensus *Consensus) verifyViewChangeSenderKey(msg *msg_pb.Message) (*bls.PublicKey, error) { diff --git a/consensus/consensus_v2.go b/consensus/consensus_v2.go index 41d0bfada..a242acfd5 100644 --- a/consensus/consensus_v2.go +++ b/consensus/consensus_v2.go @@ -175,7 +175,6 @@ func (consensus *Consensus) finalizeCommits() { Uint64("epochNum", block.Epoch().Uint64()). Uint64("ViewId", block.Header().ViewID().Uint64()). Str("blockHash", block.Hash().String()). - Int("index", consensus.Decider.IndexOf(consensus.LeaderPubKey)). Int("numTxns", len(block.Transactions())). Int("numStakingTxns", len(block.StakingTransactions())). Msg("HOORAY!!!!!!! CONSENSUS REACHED!!!!!!!") diff --git a/consensus/quorum/quorum.go b/consensus/quorum/quorum.go index 0c0960a23..b0280b9d7 100644 --- a/consensus/quorum/quorum.go +++ b/consensus/quorum/quorum.go @@ -3,6 +3,7 @@ package quorum import ( "fmt" "math/big" + "sync" "github.com/ethereum/go-ethereum/common" "github.com/harmony-one/bls/ffi/go/bls" @@ -69,7 +70,7 @@ func (p Policy) String() string { type ParticipantTracker interface { Participants() []*bls.PublicKey ParticipantsKeyBytes() []shard.BLSPublicKey - IndexOf(*bls.PublicKey) int + IndexOf(shard.BLSPublicKey) int ParticipantsCount() int64 NextAfter(*bls.PublicKey) (bool, *bls.PublicKey) UpdateParticipants(pubKeys []*bls.PublicKey) @@ -148,6 +149,7 @@ type cIdentities struct { // Public keys of the committee including leader and validators publicKeys []*bls.PublicKey publicKeysByte []shard.BLSPublicKey + keyIndexMap sync.Map prepare *votepower.Round commit *votepower.Round // viewIDSigs: every validator @@ -174,20 +176,19 @@ func (s *cIdentities) AggregateVotes(p Phase) *bls.Sign { return bls_cosi.AggregateSig(sigs) } -func (s *cIdentities) IndexOf(pubKey *bls.PublicKey) int { - idx := -1 - for k, v := range s.publicKeys { - if v.IsEqual(pubKey) { - idx = k - break - } +func (s *cIdentities) IndexOf(pubKey shard.BLSPublicKey) int { + if index, ok := s.keyIndexMap.Load(pubKey); ok { + return index.(int) } - return idx + return -1 } func (s *cIdentities) NextAfter(pubKey *bls.PublicKey) (bool, *bls.PublicKey) { found := false - idx := s.IndexOf(pubKey) + pubKeyByte := shard.BLSPublicKey{} + pubKeyByte.FromLibBLSPublicKey(pubKey) + + idx := s.IndexOf(pubKeyByte) if idx != -1 { found = true } @@ -205,14 +206,23 @@ func (s *cIdentities) ParticipantsKeyBytes() []shard.BLSPublicKey { func (s *cIdentities) UpdateParticipants(pubKeys []*bls.PublicKey) { keyBytes := []shard.BLSPublicKey{} + keyIndexMap := map[shard.BLSPublicKey]int{} for i := range pubKeys { k := shard.BLSPublicKey{} k.FromLibBLSPublicKey(pubKeys[i]) keyBytes = append(keyBytes, k) + keyIndexMap[k] = i } s.publicKeys = append(pubKeys[:0:0], pubKeys...) + + for _, pubKey := range s.publicKeysByte { + s.keyIndexMap.Delete(pubKey) + } s.publicKeysByte = keyBytes + for i, pubKey := range s.publicKeysByte { + s.keyIndexMap.Store(pubKey, i) + } } func (s *cIdentities) ParticipantsCount() int64 { @@ -319,6 +329,7 @@ func newBallotsBackedSignatureReader() *cIdentities { return &cIdentities{ publicKeys: []*bls.PublicKey{}, publicKeysByte: []shard.BLSPublicKey{}, + keyIndexMap: sync.Map{}, prepare: votepower.NewRound(), commit: votepower.NewRound(), viewChange: votepower.NewRound(),