mirror of
https://github.com/tendermint/tendermint.git
synced 2026-01-08 22:23:11 +00:00
* rename adjusted to adjacent Refs https://github.com/tendermint/tendermint/pull/3989#discussion_r352140829 * rename ErrTooMuchChange to ErrNotEnoughVotingPowerSigned Refs https://github.com/tendermint/tendermint/pull/3989#discussion_r352142785 * verify commit is properly signed * remove no longer trusted headers * restore trustedHeader and trustedNextVals * check trustedHeader using options Refs https://github.com/tendermint/tendermint/pull/4209#issuecomment-562462165 * use correct var when checking if headers are adjacent in bisection func + replace TODO with a comment https://github.com/tendermint/tendermint/pull/3989#discussion_r352125455 * return header in VerifyHeaderAtHeight because that way we avoid DB call + add godoc comments + check if there are no headers yet in AutoClient https://github.com/tendermint/tendermint/pull/3989#pullrequestreview-315454506 * TestVerifyAdjacentHeaders: add 2 more test-cases + add TestVerifyReturnsErrorIfTrustLevelIsInvalid * lite: avoid overflow when parsing key in db store! * lite: rename AutoClient#Err to Errs * lite: add a test for AutoClient * lite: fix keyPattern and call itr.Next in db store * lite: add two tests for db store * lite: add TestClientRemovesNoLongerTrustedHeaders * lite: test Client#Cleanup * lite: test restoring trustedHeader https://github.com/tendermint/tendermint/pull/4209#issuecomment-562462165 * lite: comment out unused code in test_helpers * fix TestVerifyReturnsErrorIfTrustLevelIsInvalid after merge * change defaultRemoveNoLongerTrustedHeadersPeriod and add docs * write more doc * lite: uncomment testable examples * use stdlog.Fatal to stop AutoClient tests * make lll linter happy * separate errors for 2 cases - the validator set of a skipped header cannot be trusted, i.e. <1/3rd of h1 validator set has signed (new error, something like ErrNewValSetCantBeTrusted) - the validator set is trusted but < 2/3rds has signed (ErrNewHeaderCantBeTrusted) https://github.com/tendermint/tendermint/pull/4209#discussion_r360331253 * remove all headers (even the last one) that are outside of the trusting period. By doing this, we avoid checking the trustedHeader's hash in checkTrustedHeaderUsingOptions (case #1). https://github.com/tendermint/tendermint/pull/4209#discussion_r360332460 * explain restoreTrustedHeaderAndNextVals better https://github.com/tendermint/tendermint/pull/4209#discussion_r360602328 * add ConfirmationFunction option for optionally prompting for user input Y/n before removing headers Refs https://github.com/tendermint/tendermint/pull/4209#discussion_r360602945 * make cleaning optional https://github.com/tendermint/tendermint/pull/4209#discussion_r364838189 * return error when user refused to remove headers * check for double votes in VerifyCommitTrusting * leave only ErrNewValSetCantBeTrusted error to differenciate between h2Vals.VerifyCommit and h1NextVals.VerifyCommitTrusting * fix example tests * remove unnecessary if condition https://github.com/tendermint/tendermint/pull/4209#discussion_r365171847 It will be handled by the above switch. * verifyCommitBasic does not depend on vals Co-authored-by: Marko <marbar3778@yahoo.com>
This commit is contained in:
@@ -631,7 +631,7 @@ func (vals *ValidatorSet) VerifyCommit(chainID string, blockID BlockID,
|
||||
if vals.Size() != len(commit.Signatures) {
|
||||
return NewErrInvalidCommitSignatures(vals.Size(), len(commit.Signatures))
|
||||
}
|
||||
if err := vals.verifyCommitBasic(commit, height, blockID); err != nil {
|
||||
if err := verifyCommitBasic(commit, height, blockID); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -661,7 +661,7 @@ func (vals *ValidatorSet) VerifyCommit(chainID string, blockID BlockID,
|
||||
}
|
||||
|
||||
if got, needed := talliedVotingPower, vals.TotalVotingPower()*2/3; got <= needed {
|
||||
return ErrTooMuchChange{Got: got, Needed: needed}
|
||||
return ErrNotEnoughVotingPowerSigned{Got: got, Needed: needed}
|
||||
}
|
||||
|
||||
return nil
|
||||
@@ -738,7 +738,7 @@ func (vals *ValidatorSet) VerifyFutureCommit(newSet *ValidatorSet, chainID strin
|
||||
}
|
||||
|
||||
if got, needed := oldVotingPower, oldVals.TotalVotingPower()*2/3; got <= needed {
|
||||
return ErrTooMuchChange{Got: got, Needed: needed}
|
||||
return ErrNotEnoughVotingPowerSigned{Got: got, Needed: needed}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -755,11 +755,15 @@ func (vals *ValidatorSet) VerifyCommitTrusting(chainID string, blockID BlockID,
|
||||
panic(fmt.Sprintf("trustLevel must be within [1/3, 1], given %v", trustLevel))
|
||||
}
|
||||
|
||||
if err := vals.verifyCommitBasic(commit, height, blockID); err != nil {
|
||||
if err := verifyCommitBasic(commit, height, blockID); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
talliedVotingPower := int64(0)
|
||||
var (
|
||||
talliedVotingPower int64
|
||||
seenVals = make(map[int]int, len(commit.Signatures)) // validator index -> commit index
|
||||
)
|
||||
|
||||
for idx, commitSig := range commit.Signatures {
|
||||
if commitSig.Absent() {
|
||||
continue // OK, some signatures can be absent.
|
||||
@@ -767,8 +771,16 @@ func (vals *ValidatorSet) VerifyCommitTrusting(chainID string, blockID BlockID,
|
||||
|
||||
// We don't know the validators that committed this block, so we have to
|
||||
// check for each vote if its validator is already known.
|
||||
_, val := vals.GetByAddress(commitSig.ValidatorAddress)
|
||||
valIdx, val := vals.GetByAddress(commitSig.ValidatorAddress)
|
||||
|
||||
if firstIndex, ok := seenVals[valIdx]; ok { // double vote
|
||||
secondIndex := idx
|
||||
return errors.Errorf("double vote from %v (%d and %d)", val, firstIndex, secondIndex)
|
||||
}
|
||||
|
||||
if val != nil {
|
||||
seenVals[valIdx] = idx
|
||||
|
||||
// Validate signature.
|
||||
voteSignBytes := commit.VoteSignBytes(chainID, idx)
|
||||
if !val.PubKey.VerifyBytes(voteSignBytes, commitSig.Signature) {
|
||||
@@ -789,13 +801,13 @@ func (vals *ValidatorSet) VerifyCommitTrusting(chainID string, blockID BlockID,
|
||||
got := talliedVotingPower
|
||||
needed := (vals.TotalVotingPower() * trustLevel.Numerator) / trustLevel.Denominator
|
||||
if got <= needed {
|
||||
return ErrTooMuchChange{Got: got, Needed: needed}
|
||||
return ErrNotEnoughVotingPowerSigned{Got: got, Needed: needed}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (vals *ValidatorSet) verifyCommitBasic(commit *Commit, height int64, blockID BlockID) error {
|
||||
func verifyCommitBasic(commit *Commit, height int64, blockID BlockID) error {
|
||||
if err := commit.ValidateBasic(); err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -810,23 +822,23 @@ func (vals *ValidatorSet) verifyCommitBasic(commit *Commit, height int64, blockI
|
||||
}
|
||||
|
||||
//-----------------
|
||||
// ErrTooMuchChange
|
||||
|
||||
// IsErrTooMuchChange returns true if err is related to changes in validator
|
||||
// set exceeding max limit.
|
||||
func IsErrTooMuchChange(err error) bool {
|
||||
_, ok := errors.Cause(err).(ErrTooMuchChange)
|
||||
// IsErrNotEnoughVotingPowerSigned returns true if err is
|
||||
// ErrNotEnoughVotingPowerSigned.
|
||||
func IsErrNotEnoughVotingPowerSigned(err error) bool {
|
||||
_, ok := errors.Cause(err).(ErrNotEnoughVotingPowerSigned)
|
||||
return ok
|
||||
}
|
||||
|
||||
// ErrTooMuchChange indicates that changes in the validator set exceeded max limit.
|
||||
type ErrTooMuchChange struct {
|
||||
// ErrNotEnoughVotingPowerSigned is returned when not enough validators signed
|
||||
// a commit.
|
||||
type ErrNotEnoughVotingPowerSigned struct {
|
||||
Got int64
|
||||
Needed int64
|
||||
}
|
||||
|
||||
func (e ErrTooMuchChange) Error() string {
|
||||
return fmt.Sprintf("invalid commit -- insufficient old voting power: got %d, needed more than %d", e.Got, e.Needed)
|
||||
func (e ErrNotEnoughVotingPowerSigned) Error() string {
|
||||
return fmt.Sprintf("invalid commit -- insufficient voting power: got %d, needed more than %d", e.Got, e.Needed)
|
||||
}
|
||||
|
||||
//----------------
|
||||
|
||||
Reference in New Issue
Block a user