Merge PR #2275: genesis: Ensure there are no duplicate accounts in genesis file

This also contains a light refactor of genesis state parsing, so that
the tests file didn't duplicate a lot of this code.
This commit is contained in:
Dev Ojha 2018-09-08 02:29:34 -07:00 committed by Christopher Goes
parent 4448d175ad
commit 1a700206b8
4 changed files with 107 additions and 28 deletions

View File

@ -95,6 +95,7 @@ IMPROVEMENTS
* [x/auth] Signature verification's gas cost now accounts for pubkey type. [#2046](https://github.com/tendermint/tendermint/pull/2046) * [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] [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) * [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.
* SDK * SDK
* [tools] Make get_vendor_deps deletes `.vendor-new` directories, in case scratch files are present. * [tools] Make get_vendor_deps deletes `.vendor-new` directories, in case scratch files are present.
* [spec] Added simple piggy bank distribution spec * [spec] Added simple piggy bank distribution spec

View File

@ -190,6 +190,11 @@ func (app *GaiaApp) initChainer(ctx sdk.Context, req abci.RequestInitChain) abci
slashing.InitGenesis(ctx, app.slashingKeeper, genesisState.StakeData) slashing.InitGenesis(ctx, app.slashingKeeper, genesisState.StakeData)
gov.InitGenesis(ctx, app.govKeeper, genesisState.GovData) gov.InitGenesis(ctx, app.govKeeper, genesisState.GovData)
err = GaiaValidateGenesisState(genesisState)
if err != nil {
// TODO find a way to do this w/o panics
panic(err)
}
return abci.ResponseInitChain{ return abci.ResponseInitChain{
Validators: validators, Validators: validators,

View File

@ -180,17 +180,25 @@ func GaiaAppGenState(cdc *wire.Codec, appGenTxs []json.RawMessage) (genesisState
} }
// create the genesis account, give'm few steaks and a buncha token with there name // create the genesis account, give'm few steaks and a buncha token with there name
accAuth := auth.NewBaseAccountWithAddress(genTx.Address) genaccs[i] = genesisAccountFromGenTx(genTx)
accAuth.Coins = sdk.Coins{
{genTx.Name + "Token", sdk.NewInt(1000)},
{"steak", freeFermionsAcc},
}
acc := NewGenesisAccount(&accAuth)
genaccs[i] = acc
stakeData.Pool.LooseTokens = stakeData.Pool.LooseTokens.Add(sdk.NewDecFromInt(freeFermionsAcc)) // increase the supply stakeData.Pool.LooseTokens = stakeData.Pool.LooseTokens.Add(sdk.NewDecFromInt(freeFermionsAcc)) // increase the supply
// add the validator // add the validator
if len(genTx.Name) > 0 { if len(genTx.Name) > 0 {
stakeData = addValidatorToStakeData(genTx, stakeData)
}
}
// create the final app state
genesisState = GenesisState{
Accounts: genaccs,
StakeData: stakeData,
GovData: gov.DefaultGenesisState(),
}
return
}
func addValidatorToStakeData(genTx GaiaGenTx, stakeData stake.GenesisState) stake.GenesisState {
desc := stake.NewDescription(genTx.Name, "", "", "") desc := stake.NewDescription(genTx.Name, "", "", "")
validator := stake.NewValidator( validator := stake.NewValidator(
sdk.ValAddress(genTx.Address), sdk.MustGetConsPubKeyBech32(genTx.PubKey), desc, sdk.ValAddress(genTx.Address), sdk.MustGetConsPubKeyBech32(genTx.PubKey), desc,
@ -212,14 +220,40 @@ func GaiaAppGenState(cdc *wire.Codec, appGenTxs []json.RawMessage) (genesisState
} }
stakeData.Bonds = append(stakeData.Bonds, delegation) stakeData.Bonds = append(stakeData.Bonds, delegation)
} return stakeData
} }
// create the final app state func genesisAccountFromGenTx(genTx GaiaGenTx) GenesisAccount {
genesisState = GenesisState{ accAuth := auth.NewBaseAccountWithAddress(genTx.Address)
Accounts: genaccs, accAuth.Coins = sdk.Coins{
StakeData: stakeData, {genTx.Name + "Token", sdk.NewInt(1000)},
GovData: gov.DefaultGenesisState(), {"steak", freeFermionsAcc},
}
return NewGenesisAccount(&accAuth)
}
// GaiaValidateGenesisState ensures that the genesis state obeys the expected invariants
// TODO: No validators are both bonded and revoked (#2088)
// TODO: Error if there is a duplicate validator (#1708)
// TODO: Ensure all state machine parameters are in genesis (#1704)
func GaiaValidateGenesisState(genesisState GenesisState) (err error) {
err = validateGenesisStateAccounts(genesisState.Accounts)
if err != nil {
return
}
return
}
// Ensures that there are no duplicate accounts in the genesis state,
func validateGenesisStateAccounts(accs []GenesisAccount) (err error) {
addrMap := make(map[string]bool, len(accs))
for i := 0; i < len(accs); i++ {
acc := accs[i]
strAddr := string(acc.Address)
if _, ok := addrMap[strAddr]; ok {
return fmt.Errorf("Duplicate account in genesis state: Address %v", acc.Address)
}
addrMap[strAddr] = true
} }
return return
} }

View File

@ -5,10 +5,36 @@ import (
sdk "github.com/cosmos/cosmos-sdk/types" sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/x/auth" "github.com/cosmos/cosmos-sdk/x/auth"
"github.com/cosmos/cosmos-sdk/x/gov"
stake "github.com/cosmos/cosmos-sdk/x/stake"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
"github.com/tendermint/tendermint/crypto/ed25519" "github.com/tendermint/tendermint/crypto/ed25519"
) )
func makeGenesisState(genTxs []GaiaGenTx) GenesisState {
// start with the default staking genesis state
stakeData := stake.DefaultGenesisState()
// get genesis flag account information
genaccs := make([]GenesisAccount, len(genTxs))
for i, genTx := range genTxs {
genaccs[i] = genesisAccountFromGenTx(genTx)
stakeData.Pool.LooseTokens = stakeData.Pool.LooseTokens.Add(sdk.NewDecFromInt(freeFermionsAcc)) // increase the supply
// add the validator
if len(genTx.Name) > 0 {
stakeData = addValidatorToStakeData(genTx, stakeData)
}
}
// create the final app state
return GenesisState{
Accounts: genaccs,
StakeData: stakeData,
GovData: gov.DefaultGenesisState(),
}
}
func TestToAccount(t *testing.T) { func TestToAccount(t *testing.T) {
priv := ed25519.GenPrivKey() priv := ed25519.GenPrivKey()
addr := sdk.AccAddress(priv.PubKey().Address()) addr := sdk.AccAddress(priv.PubKey().Address())
@ -34,3 +60,16 @@ func TestGaiaAppGenState(t *testing.T) {
// TODO test with both one and two genesis transactions: // TODO test with both one and two genesis transactions:
// TODO correct: genesis account created, canididates created, pool token variance // TODO correct: genesis account created, canididates created, pool token variance
} }
func TestGaiaGenesisValidation(t *testing.T) {
genTxs := make([]GaiaGenTx, 2)
privKey := ed25519.GenPrivKey()
pubKey := privKey.PubKey()
addr := pubKey.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)
}