Make vote.ValidatorAddress consistent when extracted from commit

This commit is contained in:
Jeremiah Andrews 2018-08-19 20:04:30 -07:00
parent 170364a472
commit f403195f67
10 changed files with 42 additions and 42 deletions

View File

@ -629,6 +629,7 @@ OUTER_LOOP:
// Load the block commit for prs.Height, // Load the block commit for prs.Height,
// which contains precommit signatures for prs.Height. // which contains precommit signatures for prs.Height.
commit := conR.conS.blockStore.LoadBlockCommit(prs.Height) commit := conR.conS.blockStore.LoadBlockCommit(prs.Height)
commit.AddAddresses(conR.conS.Validators.GetAddresses())
if ps.PickSendVote(commit) { if ps.PickSendVote(commit) {
logger.Debug("Picked Catchup commit to send", "height", prs.Height) logger.Debug("Picked Catchup commit to send", "height", prs.Height)
continue OUTER_LOOP continue OUTER_LOOP

View File

@ -452,14 +452,13 @@ func (cs *ConsensusState) reconstructLastCommit(state sm.State) {
return return
} }
seenCommit := cs.blockStore.LoadSeenCommit(state.LastBlockHeight) seenCommit := cs.blockStore.LoadSeenCommit(state.LastBlockHeight)
seenCommit.AddAddresses(cs.Validators.GetAddresses())
lastPrecommits := types.NewVoteSet(state.ChainID, state.LastBlockHeight, seenCommit.Round(), types.VoteTypePrecommit, state.LastValidators) lastPrecommits := types.NewVoteSet(state.ChainID, state.LastBlockHeight, seenCommit.Round(), types.VoteTypePrecommit, state.LastValidators)
for idx := 0; idx < len(seenCommit.Precommits); idx++ { for idx := 0; idx < len(seenCommit.Precommits); idx++ {
if seenCommit.Precommits[idx] == nil { if seenCommit.Precommits[idx] == nil {
continue continue
} }
addr, _ := state.LastValidators.GetByIndex(idx)
vote := seenCommit.GetByIndex(idx) vote := seenCommit.GetByIndex(idx)
vote.ValidatorAddress = addr
added, err := lastPrecommits.AddVote(vote) added, err := lastPrecommits.AddVote(vote)
if !added || err != nil { if !added || err != nil {
cmn.PanicCrisis(fmt.Sprintf("Failed to reconstruct LastCommit: %v", err)) cmn.PanicCrisis(fmt.Sprintf("Failed to reconstruct LastCommit: %v", err))

View File

@ -129,6 +129,7 @@ func (p *provider) fillFullCommit(signedHeader types.SignedHeader) (fc lite.Full
if err != nil { if err != nil {
return lite.FullCommit{}, err return lite.FullCommit{}, err
} }
signedHeader.Commit.AddAddresses(valset.GetAddresses())
return lite.NewFullCommit(signedHeader, valset, nextValset), nil return lite.NewFullCommit(signedHeader, valset, nextValset), nil
} }

View File

@ -177,6 +177,7 @@ func (dbp *DBProvider) fillFullCommit(sh types.SignedHeader) (FullCommit, error)
if err != nil { if err != nil {
return FullCommit{}, err return FullCommit{}, err
} }
sh.Commit.AddAddresses(valset.GetAddresses())
// Return filled FullCommit. // Return filled FullCommit.
return FullCommit{ return FullCommit{
SignedHeader: sh, SignedHeader: sh,

View File

@ -83,7 +83,7 @@ func (pkz privKeys) signHeader(header *types.Header, first, last int) *types.Com
} }
blockID := types.BlockID{Hash: header.Hash()} blockID := types.BlockID{Hash: header.Hash()}
return types.NewCommit(header.Height, 1, blockID, commitSigs) return types.NewCommit(header.Height, 1, blockID, commitSigs, vset.GetAddresses())
} }
func makeVote(header *types.Header, valset *types.ValidatorSet, key crypto.PrivKey) *types.Vote { func makeVote(header *types.Header, valset *types.ValidatorSet, key crypto.PrivKey) *types.Vote {

View File

@ -300,18 +300,20 @@ type Commit struct {
RoundNum int RoundNum int
BlockID BlockID `json:"block_id"` BlockID BlockID `json:"block_id"`
Precommits []*CommitSig `json:"precommits"` Precommits []*CommitSig `json:"precommits"`
addresses []Address
// Volatile // Volatile
hash cmn.HexBytes hash cmn.HexBytes
bitArray *cmn.BitArray bitArray *cmn.BitArray
} }
func NewCommit(height int64, round int, blockID BlockID, precommits []*CommitSig) *Commit { func NewCommit(height int64, round int, blockID BlockID, precommits []*CommitSig, addresses []Address) *Commit {
return &Commit{ return &Commit{
HeightNum: height, HeightNum: height,
RoundNum: round, RoundNum: round,
BlockID: blockID, BlockID: blockID,
Precommits: precommits, Precommits: precommits,
addresses: addresses,
} }
} }
@ -327,24 +329,22 @@ func NewCommitSig(signature []byte, timestamp time.Time) *CommitSig {
} }
} }
func (commitSig *CommitSig) String(index int, address Address, height int64, round int, blockID BlockID) string { func (commitSig *CommitSig) String() string {
return fmt.Sprintf("Vote{%v:%X %v/%02d/%v(%v) %X %X @ %s}", return fmt.Sprintf("CommitSig{%X @ %s}",
index, cmn.Fingerprint(address),
height, round, VoteTypePrecommit, "Precommit",
cmn.Fingerprint(blockID.Hash),
cmn.Fingerprint(commitSig.Signature), cmn.Fingerprint(commitSig.Signature),
CanonicalTime(commitSig.Timestamp)) CanonicalTime(commitSig.Timestamp))
} }
func (commitSig *CommitSig) ToVote(index int, height int64, round int, blockID BlockID) *Vote { func (commitSig *CommitSig) ToVote(index int, address Address, height int64, round int, blockID BlockID) *Vote {
return &Vote{ return &Vote{
ValidatorIndex: index, ValidatorIndex: index,
Height: height, ValidatorAddress: address,
Round: round, Height: height,
Timestamp: commitSig.Timestamp, Round: round,
Type: VoteTypePrecommit, Timestamp: commitSig.Timestamp,
BlockID: blockID, Type: VoteTypePrecommit,
Signature: commitSig.Signature, BlockID: blockID,
Signature: commitSig.Signature,
} }
} }
@ -384,9 +384,13 @@ func (commit *Commit) BitArray() *cmn.BitArray {
return commit.bitArray return commit.bitArray
} }
func (commit *Commit) AddAddresses(addresses []Address) {
commit.addresses = addresses
}
// GetByIndex returns the vote corresponding to a given validator index // GetByIndex returns the vote corresponding to a given validator index
func (commit *Commit) GetByIndex(index int) *Vote { func (commit *Commit) GetByIndex(index int) *Vote {
return commit.Precommits[index].ToVote(index, commit.Height(), commit.Round(), commit.BlockID) return commit.Precommits[index].ToVote(index, commit.addresses[index], commit.Height(), commit.Round(), commit.BlockID)
} }
// IsCommit returns true if there is at least one vote // IsCommit returns true if there is at least one vote
@ -427,9 +431,8 @@ func (commit *Commit) StringIndented(indent string) string {
return "nil-Commit" return "nil-Commit"
} }
precommitStrings := make([]string, len(commit.Precommits)) precommitStrings := make([]string, len(commit.Precommits))
for i, precommit := range commit.Precommits { for i := 0; i < len(commit.Precommits); i++ {
precommitStrings[i] = precommit.String(i, []byte("---"), precommitStrings[i] = commit.GetByIndex(i).String()
commit.HeightNum, commit.RoundNum, commit.BlockID)
} }
return fmt.Sprintf(`Commit{ return fmt.Sprintf(`Commit{
%s BlockID: %v %s BlockID: %v

View File

@ -203,9 +203,7 @@ func TestCommit(t *testing.T) {
require.NotNil(t, commit.BitArray()) require.NotNil(t, commit.BitArray())
assert.Equal(t, cmn.NewBitArray(10).Size(), commit.BitArray().Size()) assert.Equal(t, cmn.NewBitArray(10).Size(), commit.BitArray().Size())
cv := commit.GetByIndex(0) assert.Equal(t, voteSet.GetByIndex(0), commit.GetByIndex(0))
cv.ValidatorAddress = voteSet.GetByIndex(0).ValidatorAddress
assert.Equal(t, voteSet.GetByIndex(0), cv)
assert.True(t, commit.IsCommit()) assert.True(t, commit.IsCommit())
} }

View File

@ -121,6 +121,14 @@ func (vals *ValidatorSet) GetByAddress(address []byte) (index int, val *Validato
return -1, nil return -1, nil
} }
func (vals *ValidatorSet) GetAddresses() []Address {
addresses := make([]Address, len(vals.Validators))
for i := 0; i < len(vals.Validators); i++ {
addresses[i] = vals.Validators[i].Address
}
return addresses
}
// GetByIndex returns the validator's address and validator itself by index. // GetByIndex returns the validator's address and validator itself by index.
// It returns nil values if index is less than 0 or greater or equal to // It returns nil values if index is less than 0 or greater or equal to
// len(ValidatorSet.Validators). // len(ValidatorSet.Validators).
@ -270,22 +278,16 @@ func (vals *ValidatorSet) VerifyCommit(chainID string, blockID BlockID, height i
} }
talliedVotingPower := int64(0) talliedVotingPower := int64(0)
commit.AddAddresses(vals.GetAddresses())
baseVote := Vote{
Height: height,
Round: commit.Round(),
Type: VoteTypePrecommit,
BlockID: blockID,
}
for idx, precommit := range commit.Precommits { for idx, precommit := range commit.Precommits {
if precommit == nil { if precommit == nil {
continue // OK, some precommits can be missing. continue // OK, some precommits can be missing.
} }
_, val := vals.GetByIndex(idx) _, val := vals.GetByIndex(idx)
baseVote.Timestamp = precommit.Timestamp vote := commit.GetByIndex(idx)
// Validate signature. // Validate signature.
precommitSignBytes := baseVote.SignBytes(chainID) precommitSignBytes := vote.SignBytes(chainID)
if !val.PubKey.VerifyBytes(precommitSignBytes, precommit.Signature) { if !val.PubKey.VerifyBytes(precommitSignBytes, precommit.Signature) {
return fmt.Errorf("Invalid commit -- invalid signature: %v", precommit) return fmt.Errorf("Invalid commit -- invalid signature: %v", precommit)
} }
@ -342,17 +344,12 @@ func (vals *ValidatorSet) VerifyFutureCommit(newSet *ValidatorSet, chainID strin
// Check old voting power. // Check old voting power.
oldVotingPower := int64(0) oldVotingPower := int64(0)
seen := map[int]bool{} seen := map[int]bool{}
baseVote := Vote{
Height: height,
Round: commit.Round(),
Type: VoteTypePrecommit,
BlockID: blockID,
}
for idx, precommit := range commit.Precommits { for idx, precommit := range commit.Precommits {
if precommit == nil { if precommit == nil {
continue continue
} }
vote := commit.GetByIndex(idx)
// See if this validator is in oldVals. // See if this validator is in oldVals.
adr, _ := newSet.GetByIndex(idx) adr, _ := newSet.GetByIndex(idx)
idx, val := oldVals.GetByAddress(adr) idx, val := oldVals.GetByAddress(adr)
@ -362,8 +359,7 @@ func (vals *ValidatorSet) VerifyFutureCommit(newSet *ValidatorSet, chainID strin
seen[idx] = true seen[idx] = true
// Validate signature. // Validate signature.
baseVote.Timestamp = precommit.Timestamp precommitSignBytes := vote.SignBytes(chainID)
precommitSignBytes := baseVote.SignBytes(chainID)
if !val.PubKey.VerifyBytes(precommitSignBytes, precommit.Signature) { if !val.PubKey.VerifyBytes(precommitSignBytes, precommit.Signature) {
return cmn.NewError("Invalid commit -- invalid signature: %v", precommit) return cmn.NewError("Invalid commit -- invalid signature: %v", precommit)
} }

View File

@ -396,6 +396,7 @@ func TestValidatorSetVerifyCommit(t *testing.T) {
Precommits: []*CommitSig{NewCommitSig(sig, vote.Timestamp)}, Precommits: []*CommitSig{NewCommitSig(sig, vote.Timestamp)},
HeightNum: height, HeightNum: height,
RoundNum: 0, RoundNum: 0,
addresses: []Address{v1.Address},
} }
badChainID := "notmychainID" badChainID := "notmychainID"

View File

@ -550,7 +550,7 @@ func (voteSet *VoteSet) MakeCommit() *Commit {
precommits[i] = v.ToCommitSig() precommits[i] = v.ToCommitSig()
} }
} }
return NewCommit(voteSet.height, voteSet.round, blockID, precommits) return NewCommit(voteSet.height, voteSet.round, blockID, precommits, voteSet.valSet.GetAddresses())
} }
//-------------------------------------------------------------------------------- //--------------------------------------------------------------------------------