diff --git a/consensus/reactor.go b/consensus/reactor.go index 88557185..be6745d3 100644 --- a/consensus/reactor.go +++ b/consensus/reactor.go @@ -629,6 +629,7 @@ OUTER_LOOP: // Load the block commit for prs.Height, // which contains precommit signatures for prs.Height. commit := conR.conS.blockStore.LoadBlockCommit(prs.Height) + commit.AddAddresses(conR.conS.Validators.GetAddresses()) if ps.PickSendVote(commit) { logger.Debug("Picked Catchup commit to send", "height", prs.Height) continue OUTER_LOOP diff --git a/consensus/state.go b/consensus/state.go index 71a49197..2ec7a5a0 100644 --- a/consensus/state.go +++ b/consensus/state.go @@ -452,14 +452,13 @@ func (cs *ConsensusState) reconstructLastCommit(state sm.State) { return } seenCommit := cs.blockStore.LoadSeenCommit(state.LastBlockHeight) + seenCommit.AddAddresses(cs.Validators.GetAddresses()) lastPrecommits := types.NewVoteSet(state.ChainID, state.LastBlockHeight, seenCommit.Round(), types.VoteTypePrecommit, state.LastValidators) for idx := 0; idx < len(seenCommit.Precommits); idx++ { if seenCommit.Precommits[idx] == nil { continue } - addr, _ := state.LastValidators.GetByIndex(idx) vote := seenCommit.GetByIndex(idx) - vote.ValidatorAddress = addr added, err := lastPrecommits.AddVote(vote) if !added || err != nil { cmn.PanicCrisis(fmt.Sprintf("Failed to reconstruct LastCommit: %v", err)) diff --git a/lite/client/provider.go b/lite/client/provider.go index e0c0a331..292c5f74 100644 --- a/lite/client/provider.go +++ b/lite/client/provider.go @@ -129,6 +129,7 @@ func (p *provider) fillFullCommit(signedHeader types.SignedHeader) (fc lite.Full if err != nil { return lite.FullCommit{}, err } + signedHeader.Commit.AddAddresses(valset.GetAddresses()) return lite.NewFullCommit(signedHeader, valset, nextValset), nil } diff --git a/lite/dbprovider.go b/lite/dbprovider.go index cab695b4..80b23c17 100644 --- a/lite/dbprovider.go +++ b/lite/dbprovider.go @@ -177,6 +177,7 @@ func (dbp *DBProvider) fillFullCommit(sh types.SignedHeader) (FullCommit, error) if err != nil { return FullCommit{}, err } + sh.Commit.AddAddresses(valset.GetAddresses()) // Return filled FullCommit. return FullCommit{ SignedHeader: sh, diff --git a/lite/helpers.go b/lite/helpers.go index a4a22a3a..88830b4e 100644 --- a/lite/helpers.go +++ b/lite/helpers.go @@ -83,7 +83,7 @@ func (pkz privKeys) signHeader(header *types.Header, first, last int) *types.Com } 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 { diff --git a/types/block.go b/types/block.go index 3f02420b..57fa1986 100644 --- a/types/block.go +++ b/types/block.go @@ -300,18 +300,20 @@ type Commit struct { RoundNum int BlockID BlockID `json:"block_id"` Precommits []*CommitSig `json:"precommits"` + addresses []Address // Volatile hash cmn.HexBytes 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{ HeightNum: height, RoundNum: round, BlockID: blockID, 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 { - return fmt.Sprintf("Vote{%v:%X %v/%02d/%v(%v) %X %X @ %s}", - index, cmn.Fingerprint(address), - height, round, VoteTypePrecommit, "Precommit", - cmn.Fingerprint(blockID.Hash), +func (commitSig *CommitSig) String() string { + return fmt.Sprintf("CommitSig{%X @ %s}", cmn.Fingerprint(commitSig.Signature), 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{ - ValidatorIndex: index, - Height: height, - Round: round, - Timestamp: commitSig.Timestamp, - Type: VoteTypePrecommit, - BlockID: blockID, - Signature: commitSig.Signature, + ValidatorIndex: index, + ValidatorAddress: address, + Height: height, + Round: round, + Timestamp: commitSig.Timestamp, + Type: VoteTypePrecommit, + BlockID: blockID, + Signature: commitSig.Signature, } } @@ -384,9 +384,13 @@ func (commit *Commit) BitArray() *cmn.BitArray { return commit.bitArray } +func (commit *Commit) AddAddresses(addresses []Address) { + commit.addresses = addresses +} + // GetByIndex returns the vote corresponding to a given validator index 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 @@ -427,9 +431,8 @@ func (commit *Commit) StringIndented(indent string) string { return "nil-Commit" } precommitStrings := make([]string, len(commit.Precommits)) - for i, precommit := range commit.Precommits { - precommitStrings[i] = precommit.String(i, []byte("---"), - commit.HeightNum, commit.RoundNum, commit.BlockID) + for i := 0; i < len(commit.Precommits); i++ { + precommitStrings[i] = commit.GetByIndex(i).String() } return fmt.Sprintf(`Commit{ %s BlockID: %v diff --git a/types/block_test.go b/types/block_test.go index fbba2515..a7304551 100644 --- a/types/block_test.go +++ b/types/block_test.go @@ -203,9 +203,7 @@ func TestCommit(t *testing.T) { require.NotNil(t, commit.BitArray()) assert.Equal(t, cmn.NewBitArray(10).Size(), commit.BitArray().Size()) - cv := commit.GetByIndex(0) - cv.ValidatorAddress = voteSet.GetByIndex(0).ValidatorAddress - assert.Equal(t, voteSet.GetByIndex(0), cv) + assert.Equal(t, voteSet.GetByIndex(0), commit.GetByIndex(0)) assert.True(t, commit.IsCommit()) } diff --git a/types/validator_set.go b/types/validator_set.go index 50254824..24a1a0d3 100644 --- a/types/validator_set.go +++ b/types/validator_set.go @@ -121,6 +121,14 @@ func (vals *ValidatorSet) GetByAddress(address []byte) (index int, val *Validato 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. // It returns nil values if index is less than 0 or greater or equal to // len(ValidatorSet.Validators). @@ -270,22 +278,16 @@ func (vals *ValidatorSet) VerifyCommit(chainID string, blockID BlockID, height i } talliedVotingPower := int64(0) - - baseVote := Vote{ - Height: height, - Round: commit.Round(), - Type: VoteTypePrecommit, - BlockID: blockID, - } + commit.AddAddresses(vals.GetAddresses()) for idx, precommit := range commit.Precommits { if precommit == nil { continue // OK, some precommits can be missing. } _, val := vals.GetByIndex(idx) - baseVote.Timestamp = precommit.Timestamp + vote := commit.GetByIndex(idx) // Validate signature. - precommitSignBytes := baseVote.SignBytes(chainID) + precommitSignBytes := vote.SignBytes(chainID) if !val.PubKey.VerifyBytes(precommitSignBytes, precommit.Signature) { 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. oldVotingPower := int64(0) seen := map[int]bool{} - baseVote := Vote{ - Height: height, - Round: commit.Round(), - Type: VoteTypePrecommit, - BlockID: blockID, - } for idx, precommit := range commit.Precommits { if precommit == nil { continue } + vote := commit.GetByIndex(idx) // See if this validator is in oldVals. adr, _ := newSet.GetByIndex(idx) idx, val := oldVals.GetByAddress(adr) @@ -362,8 +359,7 @@ func (vals *ValidatorSet) VerifyFutureCommit(newSet *ValidatorSet, chainID strin seen[idx] = true // Validate signature. - baseVote.Timestamp = precommit.Timestamp - precommitSignBytes := baseVote.SignBytes(chainID) + precommitSignBytes := vote.SignBytes(chainID) if !val.PubKey.VerifyBytes(precommitSignBytes, precommit.Signature) { return cmn.NewError("Invalid commit -- invalid signature: %v", precommit) } diff --git a/types/validator_set_test.go b/types/validator_set_test.go index b00e4048..97bd21b7 100644 --- a/types/validator_set_test.go +++ b/types/validator_set_test.go @@ -396,6 +396,7 @@ func TestValidatorSetVerifyCommit(t *testing.T) { Precommits: []*CommitSig{NewCommitSig(sig, vote.Timestamp)}, HeightNum: height, RoundNum: 0, + addresses: []Address{v1.Address}, } badChainID := "notmychainID" diff --git a/types/vote_set.go b/types/vote_set.go index 59205206..78951c8f 100644 --- a/types/vote_set.go +++ b/types/vote_set.go @@ -550,7 +550,7 @@ func (voteSet *VoteSet) MakeCommit() *Commit { precommits[i] = v.ToCommitSig() } } - return NewCommit(voteSet.height, voteSet.round, blockID, precommits) + return NewCommit(voteSet.height, voteSet.round, blockID, precommits, voteSet.valSet.GetAddresses()) } //--------------------------------------------------------------------------------