From fcf61b80881a671a2eca69672bc47fee2e1c8034 Mon Sep 17 00:00:00 2001 From: Ethan Buchman Date: Wed, 6 Jun 2018 16:32:31 -0700 Subject: [PATCH] check addrs match pubkeys in abci Validator. version bump --- CHANGELOG.md | 16 ++++++++------ docs/spec/consensus/abci.md | 13 +++++++++++ state/execution.go | 43 +++++++++++-------------------------- types/protobuf.go | 11 +++++++++- version/version.go | 2 +- 5 files changed, 46 insertions(+), 39 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 019b8e04d..e7f9baf2b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,19 +4,21 @@ *June 6th, 2018* -BREAKING CHANGES - -- [abci] Upgrade to - [v0.11.0](https://github.com/tendermint/abci/blob/master/CHANGELOG.md#0110) -- [abci] Query path for filtering peers by node ID changed from - `p2p/filter/pubkey/` to `p2p/filter/id/` +This is the first in a series of breaking releases coming to Tendermint after +soliciting developer feedback and conducting security audits. -NOTE: this release does not break any blockchain data structures or +This release does not break any blockchain data structures or protocols other than the ABCI messages between Tendermint and the application. Applications that upgrade for ABCI v0.11.0 should be able to continue running Tendermint v0.20.0 on blockchains created with v0.19.X +BREAKING CHANGES + +- [abci] Upgrade to + [v0.11.0](https://github.com/tendermint/abci/blob/master/CHANGELOG.md#0110) +- [abci] Change Query path for filtering peers by node ID from + `p2p/filter/pubkey/` to `p2p/filter/id/` ## 0.19.9 diff --git a/docs/spec/consensus/abci.md b/docs/spec/consensus/abci.md index 2669a78e1..9c9e6a58b 100644 --- a/docs/spec/consensus/abci.md +++ b/docs/spec/consensus/abci.md @@ -92,6 +92,19 @@ following rules: set with the given power - if the validator does already exist, its power will be adjusted to the given power +## InitChain Validator Updates + +ResponseInitChain has the option to return a list of validators. +If the list is not empty, Tendermint will adopt it for the validator set. +This way the application can determine the initial validator set for the +blockchain. + +Note that if addressses are included in the returned validators, they must match +the address of the public key. + +ResponseInitChain also includes ConsensusParams, but these are presently +ignored. + ## Query Query is a generic message type with lots of flexibility to enable diverse sets diff --git a/state/execution.go b/state/execution.go index ec37e0d13..e6b94429e 100644 --- a/state/execution.go +++ b/state/execution.go @@ -1,7 +1,6 @@ package state import ( - "bytes" "fmt" fail "github.com/ebuchman/fail-test" @@ -271,38 +270,23 @@ func getBeginBlockValidatorInfo(block *types.Block, lastValSet *types.ValidatorS // If more or equal than 1/3 of total voting power changed in one block, then // a light client could never prove the transition externally. See // ./lite/doc.go for details on how a light client tracks validators. -func updateValidators(currentSet *types.ValidatorSet, updates []abci.Validator) error { - for _, v := range updates { - pubkey, err := types.PB2TM.PubKey(v.PubKey) - if err != nil { - return err - } - - address := pubkey.Address() - - // If the app provided an address too, it must match. - // This is just a sanity check. - if len(v.Address) > 0 { - if !bytes.Equal(address, v.Address) { - return fmt.Errorf("Validator.Address (%X) does not match PubKey.Address (%X)", - v.Address, address) - } - } - - power := int64(v.Power) - // mind the overflow from int64 - if power < 0 { - return fmt.Errorf("Power (%d) overflows int64", v.Power) - } +func updateValidators(currentSet *types.ValidatorSet, abciUpdates []abci.Validator) error { + updates, err := types.PB2TM.Validators(abciUpdates) + if err != nil { + return err + } + // these are tendermint types now + for _, valUpdate := range updates { + address := valUpdate.Address _, val := currentSet.GetByAddress(address) if val == nil { // add val - added := currentSet.Add(types.NewValidator(pubkey, power)) + added := currentSet.Add(valUpdate) if !added { - return fmt.Errorf("Failed to add new validator %X with voting power %d", address, power) + return fmt.Errorf("Failed to add new validator %v", valUpdate) } - } else if v.Power == 0 { + } else if valUpdate.VotingPower == 0 { // remove val _, removed := currentSet.Remove(address) if !removed { @@ -310,10 +294,9 @@ func updateValidators(currentSet *types.ValidatorSet, updates []abci.Validator) } } else { // update val - val.VotingPower = power - updated := currentSet.Update(val) + updated := currentSet.Update(valUpdate) if !updated { - return fmt.Errorf("Failed to update validator %X with voting power %d", address, power) + return fmt.Errorf("Failed to update validator %X to %v", address, valUpdate) } } } diff --git a/types/protobuf.go b/types/protobuf.go index 730c60052..90ec8dab3 100644 --- a/types/protobuf.go +++ b/types/protobuf.go @@ -1,6 +1,7 @@ package types import ( + "bytes" "fmt" "reflect" "time" @@ -175,8 +176,16 @@ func (pb2tm) Validators(vals []abci.Validator) ([]*Validator, error) { if err != nil { return nil, err } + // If the app provided an address too, it must match. + // This is just a sanity check. + if len(v.Address) > 0 { + if !bytes.Equal(pub.Address(), v.Address) { + return nil, fmt.Errorf("Validator.Address (%X) does not match PubKey.Address (%X)", + v.Address, pub.Address()) + } + } tmVals[i] = &Validator{ - Address: v.Address, + Address: pub.Address(), PubKey: pub, VotingPower: v.Power, } diff --git a/version/version.go b/version/version.go index 2c9c88c09..e6c1815b5 100644 --- a/version/version.go +++ b/version/version.go @@ -10,7 +10,7 @@ const ( var ( // Version is the current version of Tendermint // Must be a string because scripts like dist.sh read this file. - Version = "0.20.0-dev" + Version = "0.20.0" // GitCommit is the current HEAD set using ldflags. GitCommit string