From e8edc4e72551323ff1d460f659ce4614ee73f976 Mon Sep 17 00:00:00 2001 From: ValarDragon Date: Sat, 8 Sep 2018 10:55:15 -0700 Subject: [PATCH] genesis: Ensure no dup validators, or bonded and revoked validators ref #2229 --- PENDING.md | 3 ++- cmd/gaia/app/genesis.go | 21 +++++++++++++++++++++ cmd/gaia/app/genesis_test.go | 36 ++++++++++++++++++++++++++++++++---- 3 files changed, 55 insertions(+), 5 deletions(-) diff --git a/PENDING.md b/PENDING.md index 3b6033b9e489..ecfa01e6aedb 100644 --- a/PENDING.md +++ b/PENDING.md @@ -95,7 +95,8 @@ IMPROVEMENTS * [x/auth] Signature verification's gas cost now accounts for pubkey type. [#2046](https://github.com/tendermint/tendermint/pull/2046) * [x/stake] [x/slashing] Ensure delegation invariants to jailed validators [#1883](https://github.com/cosmos/cosmos-sdk/issues/1883). * [x/stake] Improve speed of GetValidator, which was shown to be a performance bottleneck. [#2046](https://github.com/tendermint/tendermint/pull/2200) - * [genesis] \#2229 Ensure that there are no duplicate accounts in the genesis state. + * [genesis] \#2229 Ensure that there are no duplicate accounts or validators in the genesis state. + * SDK * [tools] Make get_vendor_deps deletes `.vendor-new` directories, in case scratch files are present. * [spec] Added simple piggy bank distribution spec diff --git a/cmd/gaia/app/genesis.go b/cmd/gaia/app/genesis.go index 4967361b14d5..10c7e4126e21 100644 --- a/cmd/gaia/app/genesis.go +++ b/cmd/gaia/app/genesis.go @@ -13,6 +13,7 @@ import ( "github.com/cosmos/cosmos-sdk/x/auth" "github.com/cosmos/cosmos-sdk/x/gov" "github.com/cosmos/cosmos-sdk/x/stake" + stakeTypes "github.com/cosmos/cosmos-sdk/x/stake/types" "github.com/spf13/pflag" @@ -241,6 +242,26 @@ func GaiaValidateGenesisState(genesisState GenesisState) (err error) { if err != nil { return } + err = validateGenesisStateValidators(genesisState.StakeData.Validators) + if err != nil { + return + } + return +} + +func validateGenesisStateValidators(validators []stakeTypes.Validator) (err error) { + addrMap := make(map[string]bool, len(validators)) + for i := 0; i < len(validators); i++ { + val := validators[i] + strKey := string(val.ConsPubKey.Bytes()) + if _, ok := addrMap[strKey]; ok { + return fmt.Errorf("Duplicate validator in genesis state: moniker %v, Address %v", val.Description.Moniker, val.ConsAddress()) + } + if val.Jailed && val.Status == sdk.Bonded { + return fmt.Errorf("Validator is bonded and revoked in genesis state: moniker %v, Address %v", val.Description.Moniker, val.ConsAddress()) + } + addrMap[strKey] = true + } return } diff --git a/cmd/gaia/app/genesis_test.go b/cmd/gaia/app/genesis_test.go index 755a90ebe790..f671bebb41d7 100644 --- a/cmd/gaia/app/genesis_test.go +++ b/cmd/gaia/app/genesis_test.go @@ -6,11 +6,25 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/x/auth" "github.com/cosmos/cosmos-sdk/x/gov" - stake "github.com/cosmos/cosmos-sdk/x/stake" + "github.com/cosmos/cosmos-sdk/x/stake" + stakeTypes "github.com/cosmos/cosmos-sdk/x/stake/types" "github.com/stretchr/testify/require" + "github.com/tendermint/tendermint/crypto" "github.com/tendermint/tendermint/crypto/ed25519" ) +var ( + pk1 = ed25519.GenPrivKey().PubKey() + pk2 = ed25519.GenPrivKey().PubKey() + pk3 = ed25519.GenPrivKey().PubKey() + addr1 = sdk.ValAddress(pk1.Address()) + addr2 = sdk.ValAddress(pk2.Address()) + addr3 = sdk.ValAddress(pk3.Address()) + + emptyAddr sdk.ValAddress + emptyPubkey crypto.PubKey +) + func makeGenesisState(genTxs []GaiaGenTx) GenesisState { // start with the default staking genesis state stakeData := stake.DefaultGenesisState() @@ -63,13 +77,27 @@ func TestGaiaAppGenState(t *testing.T) { func TestGaiaGenesisValidation(t *testing.T) { genTxs := make([]GaiaGenTx, 2) - privKey := ed25519.GenPrivKey() - pubKey := privKey.PubKey() - addr := pubKey.Address() + addr := pk1.Address() // Test duplicate accounts fails genTxs[0] = GaiaGenTx{"", sdk.AccAddress(addr), ""} genTxs[1] = GaiaGenTx{"", sdk.AccAddress(addr), ""} genesisState := makeGenesisState(genTxs) err := GaiaValidateGenesisState(genesisState) require.NotNil(t, err) + // Test bonded + revoked validator fails + genesisState = makeGenesisState(genTxs[:1]) + val1 := stakeTypes.NewValidator(addr1, pk1, stakeTypes.Description{Moniker: "test #2"}) + val1.Jailed = true + val1.Status = sdk.Bonded + genesisState.StakeData.Validators = append(genesisState.StakeData.Validators, val1) + err = GaiaValidateGenesisState(genesisState) + require.NotNil(t, err) + // Test duplicate validator fails + val1.Jailed = false + genesisState = makeGenesisState(genTxs[:1]) + val2 := stakeTypes.NewValidator(addr1, pk1, stakeTypes.Description{Moniker: "test #3"}) + genesisState.StakeData.Validators = append(genesisState.StakeData.Validators, val1) + genesisState.StakeData.Validators = append(genesisState.StakeData.Validators, val2) + err = GaiaValidateGenesisState(genesisState) + require.NotNil(t, err) }