diff --git a/consensus/state.go b/consensus/state.go index 6cf9ab3da..44bb54382 100644 --- a/consensus/state.go +++ b/consensus/state.go @@ -1464,20 +1464,37 @@ func (cs *State) finalizeCommit(height int64) { func (cs *State) recordMetrics(height int64, block *types.Block) { cs.metrics.Validators.Set(float64(cs.Validators.Size())) cs.metrics.ValidatorsPower.Set(float64(cs.Validators.TotalVotingPower())) - missingValidators := 0 - missingValidatorsPower := int64(0) - for i, val := range cs.Validators.Validators { - if i >= len(block.LastCommit.Signatures) { - break + + var ( + missingValidators int + missingValidatorsPower int64 + ) + // height=0 -> MissingValidators and MissingValidatorsPower are both 0. + // Remember that the first LastCommit is intentionally empty, so it's not + // fair to increment missing validators number. + if height > 1 { + // Sanity check that commit size matches validator set size - only applies + // after first block. + var ( + commitSize = block.LastCommit.Size() + valSetLen = len(cs.LastValidators.Validators) + ) + if commitSize != valSetLen { + panic(fmt.Sprintf("commit size (%d) doesn't match valset length (%d) at height %d\n\n%v\n\n%v", + commitSize, valSetLen, block.Height, block.LastCommit.Signatures, cs.LastValidators.Validators)) } - commitSig := block.LastCommit.Signatures[i] - if commitSig.Absent() { - missingValidators++ - missingValidatorsPower += val.VotingPower + + for i, val := range cs.LastValidators.Validators { + commitSig := block.LastCommit.Signatures[i] + if commitSig.Absent() { + missingValidators++ + missingValidatorsPower += val.VotingPower + } } } cs.metrics.MissingValidators.Set(float64(missingValidators)) cs.metrics.MissingValidatorsPower.Set(float64(missingValidatorsPower)) + cs.metrics.ByzantineValidators.Set(float64(len(block.Evidence.Evidence))) byzantineValidatorsPower := int64(0) for _, ev := range block.Evidence.Evidence { diff --git a/state/execution.go b/state/execution.go index 1db515909..4025b6e7b 100644 --- a/state/execution.go +++ b/state/execution.go @@ -310,57 +310,51 @@ func execBlockOnProxyApp( func getBeginBlockValidatorInfo(block *types.Block, stateDB dbm.DB) (abci.LastCommitInfo, []abci.Evidence) { voteInfos := make([]abci.VoteInfo, block.LastCommit.Size()) - byzVals := make([]abci.Evidence, len(block.Evidence.Evidence)) - var lastValSet *types.ValidatorSet - var err error + // block.Height=1 -> LastCommitInfo.Votes are empty. + // Remember that the first LastCommit is intentionally empty, so it makes + // sense for LastCommitInfo.Votes to also be empty. if block.Height > 1 { - lastValSet, err = LoadValidators(stateDB, block.Height-1) + lastValSet, err := LoadValidators(stateDB, block.Height-1) if err != nil { - panic(err) // shouldn't happen + panic(err) } - // Sanity check that commit size matches validator set size - - // only applies after first block - commitSize := block.LastCommit.Size() - valSetLen := len(lastValSet.Validators) + // Sanity check that commit size matches validator set size - only applies + // after first block. + var ( + commitSize = block.LastCommit.Size() + valSetLen = len(lastValSet.Validators) + ) if commitSize != valSetLen { - // sanity check panic(fmt.Sprintf("commit size (%d) doesn't match valset length (%d) at height %d\n\n%v\n\n%v", commitSize, valSetLen, block.Height, block.LastCommit.Signatures, lastValSet.Validators)) } - } else { - lastValSet = types.NewValidatorSet(nil) - } - for i, val := range lastValSet.Validators { - if i >= len(block.LastCommit.Signatures) { - break - } - commitSig := block.LastCommit.Signatures[i] - voteInfo := abci.VoteInfo{ - Validator: types.TM2PB.Validator(val), - SignedLastBlock: !commitSig.Absent(), + for i, val := range lastValSet.Validators { + commitSig := block.LastCommit.Signatures[i] + voteInfos[i] = abci.VoteInfo{ + Validator: types.TM2PB.Validator(val), + SignedLastBlock: !commitSig.Absent(), + } } - voteInfos[i] = voteInfo } + byzVals := make([]abci.Evidence, len(block.Evidence.Evidence)) for i, ev := range block.Evidence.Evidence { // We need the validator set. We already did this in validateBlock. // TODO: Should we instead cache the valset in the evidence itself and add // `SetValidatorSet()` and `ToABCI` methods ? valset, err := LoadValidators(stateDB, ev.Height()) if err != nil { - panic(err) // shouldn't happen + panic(err) } byzVals[i] = types.TM2PB.Evidence(ev, valset, block.Time) } - commitInfo := abci.LastCommitInfo{ + return abci.LastCommitInfo{ Round: int32(block.LastCommit.Round), Votes: voteInfos, - } - return commitInfo, byzVals - + }, byzVals } func validateValidatorUpdates(abciUpdates []abci.ValidatorUpdate,