From 771f8a04f3fccea1e671f6c1138415c2bc928523 Mon Sep 17 00:00:00 2001 From: frog power 4000 Date: Mon, 12 Aug 2019 09:10:16 -0400 Subject: [PATCH] Merge PR #4865: Add security contact to Validator description --- .../improvements/modules/_4814-Add-security-c | 1 + client/lcd/swagger-ui/swagger.yaml | 2 + docs/spec/staking/01_state.md | 9 +- simapp/utils_test.go | 2 +- x/genutil/client/cli/migrate.go | 2 +- x/genutil/legacy/{v036 => v0_36}/migrate.go | 0 .../legacy/{v036 => v0_36}/migrate_test.go | 0 x/genutil/types/genesis_state_test.go | 4 +- x/gov/keeper/test_common.go | 6 +- x/gov/test_common.go | 2 +- x/slashing/app_test.go | 2 +- x/staking/app_test.go | 4 +- x/staking/client/cli/flags.go | 11 ++- x/staking/client/cli/tx.go | 17 ++-- x/staking/genesis_test.go | 8 +- x/staking/legacy/v0_37/migrate.go | 51 +++++++++++ x/staking/legacy/v0_37/types.go | 86 +++++++++++++++++++ x/staking/simulation/msgs.go | 23 +++-- x/staking/types/msg_test.go | 50 +++++------ x/staking/types/validator.go | 48 +++++++---- x/staking/types/validator_test.go | 1 + 21 files changed, 247 insertions(+), 82 deletions(-) create mode 100644 .pending/improvements/modules/_4814-Add-security-c rename x/genutil/legacy/{v036 => v0_36}/migrate.go (100%) rename x/genutil/legacy/{v036 => v0_36}/migrate_test.go (100%) create mode 100644 x/staking/legacy/v0_37/migrate.go create mode 100644 x/staking/legacy/v0_37/types.go diff --git a/.pending/improvements/modules/_4814-Add-security-c b/.pending/improvements/modules/_4814-Add-security-c new file mode 100644 index 000000000000..f661bc64fa07 --- /dev/null +++ b/.pending/improvements/modules/_4814-Add-security-c @@ -0,0 +1 @@ +#4814 Add security contact to Validator description \ No newline at end of file diff --git a/client/lcd/swagger-ui/swagger.yaml b/client/lcd/swagger-ui/swagger.yaml index 90ffc68bfd51..7ca74ed01558 100644 --- a/client/lcd/swagger-ui/swagger.yaml +++ b/client/lcd/swagger-ui/swagger.yaml @@ -2343,6 +2343,8 @@ definitions: type: string website: type: string + security_contact: + type: string details: type: string bond_height: diff --git a/docs/spec/staking/01_state.md b/docs/spec/staking/01_state.md index 0781f1a66264..8c0fb0cab11f 100644 --- a/docs/spec/staking/01_state.md +++ b/docs/spec/staking/01_state.md @@ -85,10 +85,11 @@ CommissionRates struct { } type Description struct { - Moniker string // name - Identity string // optional identity signature (ex. UPort or Keybase) - Website string // optional website link - Details string // optional details + Moniker string // name + Identity string // optional identity signature (ex. UPort or Keybase) + Website string // optional website link + SecurityContact string // optional email for security contact + Details string // optional details } ``` diff --git a/simapp/utils_test.go b/simapp/utils_test.go index c75e6d4684de..ce51e686d460 100644 --- a/simapp/utils_test.go +++ b/simapp/utils_test.go @@ -211,7 +211,7 @@ func TestDecodeStakingStore(t *testing.T) { bondTime := time.Now().UTC() - val := staking.NewValidator(valAddr1, delPk1, staking.NewDescription("test", "test", "test", "test")) + val := staking.NewValidator(valAddr1, delPk1, staking.NewDescription("test", "test", "test", "test", "test")) del := staking.NewDelegation(delAddr1, valAddr1, sdk.OneDec()) ubd := staking.NewUnbondingDelegation(delAddr1, valAddr1, 15, bondTime, sdk.OneInt()) red := staking.NewRedelegation(delAddr1, valAddr1, valAddr1, 12, bondTime, sdk.OneInt(), sdk.OneDec()) diff --git a/x/genutil/client/cli/migrate.go b/x/genutil/client/cli/migrate.go index 7a743f9be02d..68793642972f 100644 --- a/x/genutil/client/cli/migrate.go +++ b/x/genutil/client/cli/migrate.go @@ -12,7 +12,7 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/version" extypes "github.com/cosmos/cosmos-sdk/x/genutil" - v036 "github.com/cosmos/cosmos-sdk/x/genutil/legacy/v036" + v036 "github.com/cosmos/cosmos-sdk/x/genutil/legacy/v0_36" ) var migrationMap = extypes.MigrationMap{ diff --git a/x/genutil/legacy/v036/migrate.go b/x/genutil/legacy/v0_36/migrate.go similarity index 100% rename from x/genutil/legacy/v036/migrate.go rename to x/genutil/legacy/v0_36/migrate.go diff --git a/x/genutil/legacy/v036/migrate_test.go b/x/genutil/legacy/v0_36/migrate_test.go similarity index 100% rename from x/genutil/legacy/v036/migrate_test.go rename to x/genutil/legacy/v0_36/migrate_test.go diff --git a/x/genutil/types/genesis_state_test.go b/x/genutil/types/genesis_state_test.go index 2c340a35e905..aed7cd7f311e 100644 --- a/x/genutil/types/genesis_state_test.go +++ b/x/genutil/types/genesis_state_test.go @@ -18,7 +18,7 @@ var ( func TestValidateGenesisMultipleMessages(t *testing.T) { - desc := stakingtypes.NewDescription("testname", "", "", "") + desc := stakingtypes.NewDescription("testname", "", "", "", "") comm := stakingtypes.CommissionRates{} msg1 := stakingtypes.NewMsgCreateValidator(sdk.ValAddress(pk1.Address()), pk1, @@ -35,7 +35,7 @@ func TestValidateGenesisMultipleMessages(t *testing.T) { } func TestValidateGenesisBadMessage(t *testing.T) { - desc := stakingtypes.NewDescription("testname", "", "", "") + desc := stakingtypes.NewDescription("testname", "", "", "", "") msg1 := stakingtypes.NewMsgEditValidator(sdk.ValAddress(pk1.Address()), desc, nil, nil) diff --git a/x/gov/keeper/test_common.go b/x/gov/keeper/test_common.go index e822af3f6baa..459a6f7ed20c 100644 --- a/x/gov/keeper/test_common.go +++ b/x/gov/keeper/test_common.go @@ -14,9 +14,9 @@ import ( "github.com/tendermint/tendermint/crypto/ed25519" abci "github.com/tendermint/tendermint/abci/types" - dbm "github.com/tendermint/tm-db" "github.com/tendermint/tendermint/libs/log" tmtypes "github.com/tendermint/tendermint/types" + dbm "github.com/tendermint/tm-db" "github.com/cosmos/cosmos-sdk/codec" "github.com/cosmos/cosmos-sdk/store" @@ -61,7 +61,7 @@ var ( // TODO: remove dependency with staking var ( TestProposal = types.NewTextProposal("Test", "description") - TestDescription = staking.NewDescription("T", "E", "S", "T") + TestDescription = staking.NewDescription("T", "E", "S", "T", "Z") TestCommissionRates = staking.NewCommissionRates(sdk.ZeroDec(), sdk.ZeroDec(), sdk.ZeroDec()) ) @@ -153,7 +153,7 @@ func createTestInput(t *testing.T, isCheckTx bool, initPower int64) (sdk.Context AddRoute(types.RouterKey, types.ProposalHandler) keeper := NewKeeper(cdc, keyGov, pk.Subspace(types.DefaultParamspace).WithKeyTable(types.ParamKeyTable()), - supplyKeeper, sk, types.DefaultCodespace, rtr) + supplyKeeper, sk, types.DefaultCodespace, rtr) keeper.SetProposalID(ctx, types.DefaultStartingProposalID) keeper.SetDepositParams(ctx, types.DefaultDepositParams()) diff --git a/x/gov/test_common.go b/x/gov/test_common.go index 4462f0cda623..44fbe10fbff4 100644 --- a/x/gov/test_common.go +++ b/x/gov/test_common.go @@ -81,7 +81,7 @@ func getMockApp(t *testing.T, numGenAccs int, genState types.GenesisState, genAc sk := staking.NewKeeper(mApp.Cdc, keyStaking, tKeyStaking, supplyKeeper, pk.Subspace(staking.DefaultParamspace), staking.DefaultCodespace) keeper := keep.NewKeeper(mApp.Cdc, keyGov, pk.Subspace(DefaultParamspace).WithKeyTable(ParamKeyTable()), - supplyKeeper, sk, types.DefaultCodespace, rtr) + supplyKeeper, sk, types.DefaultCodespace, rtr) mApp.Router().AddRoute(types.RouterKey, NewHandler(keeper)) mApp.QueryRouter().AddRoute(types.QuerierRoute, keep.NewQuerier(keeper)) diff --git a/x/slashing/app_test.go b/x/slashing/app_test.go index 2d3373f67667..df71f0f7727c 100644 --- a/x/slashing/app_test.go +++ b/x/slashing/app_test.go @@ -127,7 +127,7 @@ func TestSlashingMsgs(t *testing.T) { accs := []auth.Account{acc1} mock.SetGenesis(mapp, accs) - description := staking.NewDescription("foo_moniker", "", "", "") + description := staking.NewDescription("foo_moniker", "", "", "", "") commission := staking.NewCommissionRates(sdk.ZeroDec(), sdk.ZeroDec(), sdk.ZeroDec()) createValidatorMsg := staking.NewMsgCreateValidator( diff --git a/x/staking/app_test.go b/x/staking/app_test.go index 8385f88f1eae..e40a18dcf761 100644 --- a/x/staking/app_test.go +++ b/x/staking/app_test.go @@ -136,7 +136,7 @@ func TestStakingMsgs(t *testing.T) { mock.CheckBalance(t, mApp, addr2, sdk.Coins{genCoin}) // create validator - description := NewDescription("foo_moniker", "", "", "") + description := NewDescription("foo_moniker", "", "", "", "") createValidatorMsg := NewMsgCreateValidator( sdk.ValAddress(addr1), priv1.PubKey(), bondCoin, description, commissionRates, sdk.OneInt(), ) @@ -157,7 +157,7 @@ func TestStakingMsgs(t *testing.T) { mApp.BeginBlock(abci.RequestBeginBlock{Header: header}) // edit the validator - description = NewDescription("bar_moniker", "", "", "") + description = NewDescription("bar_moniker", "", "", "", "") editValidatorMsg := NewMsgEditValidator(sdk.ValAddress(addr1), description, nil, nil) header = abci.Header{Height: mApp.LastBlockHeight() + 1} diff --git a/x/staking/client/cli/flags.go b/x/staking/client/cli/flags.go index 563598409c62..b57479583a3b 100644 --- a/x/staking/client/cli/flags.go +++ b/x/staking/client/cli/flags.go @@ -16,10 +16,11 @@ const ( FlagSharesAmount = "shares-amount" FlagSharesFraction = "shares-fraction" - FlagMoniker = "moniker" - FlagIdentity = "identity" - FlagWebsite = "website" - FlagDetails = "details" + FlagMoniker = "moniker" + FlagIdentity = "identity" + FlagWebsite = "website" + FlagSecurityContact = "security-contact" + FlagDetails = "details" FlagCommissionRate = "commission-rate" FlagCommissionMaxRate = "commission-max-rate" @@ -54,6 +55,7 @@ func init() { fsDescriptionCreate.String(FlagMoniker, "", "The validator's name") fsDescriptionCreate.String(FlagIdentity, "", "The optional identity signature (ex. UPort or Keybase)") fsDescriptionCreate.String(FlagWebsite, "", "The validator's (optional) website") + fsDescriptionCreate.String(FlagSecurityContact, "", "The validator's (optional) security contact email") fsDescriptionCreate.String(FlagDetails, "", "The validator's (optional) details") fsCommissionUpdate.String(FlagCommissionRate, "", "The new commission rate percentage") FsCommissionCreate.String(FlagCommissionRate, "", "The initial commission rate percentage") @@ -63,6 +65,7 @@ func init() { fsDescriptionEdit.String(FlagMoniker, types.DoNotModifyDesc, "The validator's name") fsDescriptionEdit.String(FlagIdentity, types.DoNotModifyDesc, "The (optional) identity signature (ex. UPort or Keybase)") fsDescriptionEdit.String(FlagWebsite, types.DoNotModifyDesc, "The validator's (optional) website") + fsDescriptionEdit.String(FlagSecurityContact, types.DoNotModifyDesc, "The validator's (optional) security contact email") fsDescriptionEdit.String(FlagDetails, types.DoNotModifyDesc, "The validator's (optional) details") fsValidator.String(FlagAddressValidator, "", "The Bech32 address of the validator") fsRedelegation.String(FlagAddressValidatorSrc, "", "The Bech32 address of the source validator") diff --git a/x/staking/client/cli/tx.go b/x/staking/client/cli/tx.go index 2c9e99845eb1..dd86aa7b8421 100644 --- a/x/staking/client/cli/tx.go +++ b/x/staking/client/cli/tx.go @@ -89,12 +89,13 @@ func GetCmdEditValidator(cdc *codec.Codec) *cobra.Command { cliCtx := context.NewCLIContext().WithCodec(cdc) valAddr := cliCtx.GetFromAddress() - description := types.Description{ - Moniker: viper.GetString(FlagMoniker), - Identity: viper.GetString(FlagIdentity), - Website: viper.GetString(FlagWebsite), - Details: viper.GetString(FlagDetails), - } + description := types.NewDescription( + viper.GetString(FlagMoniker), + viper.GetString(FlagIdentity), + viper.GetString(FlagWebsite), + viper.GetString(FlagSecurityContact), + viper.GetString(FlagDetails), + ) var newRate *sdk.Dec @@ -265,6 +266,7 @@ func CreateValidatorMsgHelpers(ipDefault string) (fs *flag.FlagSet, nodeIDFlag, fsCreateValidator.String(FlagIP, ipDefault, "The node's public IP") fsCreateValidator.String(FlagNodeID, "", "The node's NodeID") fsCreateValidator.String(FlagWebsite, "", "The validator's (optional) website") + fsCreateValidator.String(FlagSecurityContact, "", "The validator's (optional) security contact email") fsCreateValidator.String(FlagDetails, "", "The validator's (optional) details") fsCreateValidator.String(FlagIdentity, "", "The (optional) identity signature (ex. UPort or Keybase)") fsCreateValidator.AddFlagSet(FsCommissionCreate) @@ -297,6 +299,7 @@ func PrepareFlagsForTxCreateValidator( } website := viper.GetString(FlagWebsite) + securityContact := viper.GetString(FlagSecurityContact) details := viper.GetString(FlagDetails) identity := viper.GetString(FlagIdentity) @@ -307,6 +310,7 @@ func PrepareFlagsForTxCreateValidator( viper.Set(FlagPubKey, sdk.MustBech32ifyConsPub(valPubKey)) viper.Set(FlagMoniker, config.Moniker) viper.Set(FlagWebsite, website) + viper.Set(FlagSecurityContact, securityContact) viper.Set(FlagDetails, details) viper.Set(FlagIdentity, identity) @@ -350,6 +354,7 @@ func BuildCreateValidatorMsg(cliCtx context.CLIContext, txBldr auth.TxBuilder) ( viper.GetString(FlagMoniker), viper.GetString(FlagIdentity), viper.GetString(FlagWebsite), + viper.GetString(FlagSecurityContact), viper.GetString(FlagDetails), ) diff --git a/x/staking/genesis_test.go b/x/staking/genesis_test.go index 5e856664a422..2fb09f2facc7 100644 --- a/x/staking/genesis_test.go +++ b/x/staking/genesis_test.go @@ -28,13 +28,13 @@ func TestInitGenesis(t *testing.T) { // initialize the validators validators[0].OperatorAddress = sdk.ValAddress(keep.Addrs[0]) validators[0].ConsPubKey = keep.PKs[0] - validators[0].Description = NewDescription("hoop", "", "", "") + validators[0].Description = NewDescription("hoop", "", "", "", "") validators[0].Status = sdk.Bonded validators[0].Tokens = valTokens validators[0].DelegatorShares = valTokens.ToDec() validators[1].OperatorAddress = sdk.ValAddress(keep.Addrs[1]) validators[1].ConsPubKey = keep.PKs[1] - validators[1].Description = NewDescription("bloop", "", "", "") + validators[1].Description = NewDescription("bloop", "", "", "", "") validators[1].Status = sdk.Bonded validators[1].Tokens = valTokens validators[1].DelegatorShares = valTokens.ToDec() @@ -76,7 +76,7 @@ func TestInitGenesisLargeValidatorSet(t *testing.T) { for i := range validators { validators[i] = NewValidator(sdk.ValAddress(keep.Addrs[i]), - keep.PKs[i], NewDescription(fmt.Sprintf("#%d", i), "", "", "")) + keep.PKs[i], NewDescription(fmt.Sprintf("#%d", i), "", "", "", "")) validators[i].Status = sdk.Bonded @@ -102,7 +102,7 @@ func TestInitGenesisLargeValidatorSet(t *testing.T) { func TestValidateGenesis(t *testing.T) { genValidators1 := make([]types.Validator, 1, 5) pk := ed25519.GenPrivKey().PubKey() - genValidators1[0] = types.NewValidator(sdk.ValAddress(pk.Address()), pk, types.NewDescription("", "", "", "")) + genValidators1[0] = types.NewValidator(sdk.ValAddress(pk.Address()), pk, types.NewDescription("", "", "", "", "")) genValidators1[0].Tokens = sdk.OneInt() genValidators1[0].DelegatorShares = sdk.OneDec() diff --git a/x/staking/legacy/v0_37/migrate.go b/x/staking/legacy/v0_37/migrate.go new file mode 100644 index 000000000000..328f36f803b2 --- /dev/null +++ b/x/staking/legacy/v0_37/migrate.go @@ -0,0 +1,51 @@ +// DONTCOVER +// nolint +package v0_37 + +import ( + v036staking "github.com/cosmos/cosmos-sdk/x/staking/legacy/v0_36" +) + +// Migrate accepts exported genesis state from v0.34 and migrates it to v0.36 +// genesis state. All entries are identical except for validator slashing events +// which now include the period. +func Migrate(oldGenState v036staking.GenesisState) GenesisState { + return NewGenesisState( + oldGenState.Params, + oldGenState.LastTotalPower, + oldGenState.LastValidatorPowers, + migrateValidators(oldGenState.Validators), + oldGenState.Delegations, + oldGenState.UnbondingDelegations, + oldGenState.Redelegations, + oldGenState.Exported, + ) +} + +func migrateValidators(oldValidators v036staking.Validators) Validators { + validators := make(Validators, len(oldValidators)) + + for i, val := range oldValidators { + validators[i] = Validator{ + OperatorAddress: val.OperatorAddress, + ConsPubKey: val.ConsPubKey, + Jailed: val.Jailed, + Status: val.Status, + Tokens: val.Tokens, + DelegatorShares: val.DelegatorShares, + Description: NewDescription( + val.Description.Moniker, + val.Description.Identity, + val.Description.Website, + "", // security contact field + val.Description.Details, + ), + UnbondingHeight: val.UnbondingHeight, + UnbondingCompletionTime: val.UnbondingCompletionTime, + Commission: val.Commission, + MinSelfDelegation: val.MinSelfDelegation, + } + } + + return validators +} diff --git a/x/staking/legacy/v0_37/types.go b/x/staking/legacy/v0_37/types.go new file mode 100644 index 000000000000..ae1323fe9ec2 --- /dev/null +++ b/x/staking/legacy/v0_37/types.go @@ -0,0 +1,86 @@ +// DONTCOVER +// nolint +package v0_37 + +import ( + "time" + + "github.com/tendermint/tendermint/crypto" + + sdk "github.com/cosmos/cosmos-sdk/types" + v034staking "github.com/cosmos/cosmos-sdk/x/staking/legacy/v0_34" + v036staking "github.com/cosmos/cosmos-sdk/x/staking/legacy/v0_36" +) + +const ( + ModuleName = "staking" +) + +type ( + Description struct { + Moniker string `json:"moniker" yaml:"moniker"` + Identity string `json:"identity" yaml:"identity"` + Website string `json:"website" yaml:"website"` + SecurityContact string `json:"security_contact" yaml:"security_contact"` + Details string `json:"details" yaml:"details"` + } + + Validator struct { + OperatorAddress sdk.ValAddress `json:"operator_address" yaml:"operator_address"` + ConsPubKey crypto.PubKey `json:"consensus_pubkey" yaml:"consensus_pubkey"` + Jailed bool `json:"jailed" yaml:"jailed"` + Status sdk.BondStatus `json:"status" yaml:"status"` + Tokens sdk.Int `json:"tokens" yaml:"tokens"` + DelegatorShares sdk.Dec `json:"delegator_shares" yaml:"delegator_shares"` + Description Description `json:"description" yaml:"description"` + UnbondingHeight int64 `json:"unbonding_height" yaml:"unbonding_height"` + UnbondingCompletionTime time.Time `json:"unbonding_time" yaml:"unbonding_time"` + Commission v036staking.Commission `json:"commission" yaml:"commission"` + MinSelfDelegation sdk.Int `json:"min_self_delegation" yaml:"min_self_delegation"` + } + + Validators []Validator + + GenesisState struct { + Params v034staking.Params `json:"params"` + LastTotalPower sdk.Int `json:"last_total_power"` + LastValidatorPowers []v034staking.LastValidatorPower `json:"last_validator_powers"` + Validators Validators `json:"validators"` + Delegations v034staking.Delegations `json:"delegations"` + UnbondingDelegations []v034staking.UnbondingDelegation `json:"unbonding_delegations"` + Redelegations []v034staking.Redelegation `json:"redelegations"` + Exported bool `json:"exported"` + } +) + +// NewDescription creates a new Description object +func NewDescription(moniker, identity, website, + securityContact, details string) Description { + + return Description{ + Moniker: moniker, + Identity: identity, + Website: website, + SecurityContact: securityContact, + Details: details, + } +} + +// NewGenesisState creates a new GenesisState object +func NewGenesisState( + params v034staking.Params, lastTotalPower sdk.Int, lastValPowers []v034staking.LastValidatorPower, + validators Validators, delegations v034staking.Delegations, + ubds []v034staking.UnbondingDelegation, reds []v034staking.Redelegation, exported bool, +) GenesisState { + + return GenesisState{ + Params: params, + LastTotalPower: lastTotalPower, + LastValidatorPowers: lastValPowers, + Validators: validators, + Delegations: delegations, + UnbondingDelegations: ubds, + Redelegations: reds, + Exported: exported, + } +} diff --git a/x/staking/simulation/msgs.go b/x/staking/simulation/msgs.go index c16d4075cb48..f36a5e6d9802 100644 --- a/x/staking/simulation/msgs.go +++ b/x/staking/simulation/msgs.go @@ -20,9 +20,13 @@ func SimulateMsgCreateValidator(m auth.AccountKeeper, k staking.Keeper) simulati opMsg simulation.OperationMsg, fOps []simulation.FutureOperation, err error) { denom := k.GetParams(ctx).BondDenom - description := staking.Description{ - Moniker: simulation.RandStringOfLength(r, 10), - } + description := staking.NewDescription( + simulation.RandStringOfLength(r, 10), + simulation.RandStringOfLength(r, 10), + simulation.RandStringOfLength(r, 10), + simulation.RandStringOfLength(r, 10), + simulation.RandStringOfLength(r, 10), + ) maxCommission := sdk.NewDecWithPrec(r.Int63n(1000), 3) commission := staking.NewCommissionRates( @@ -67,12 +71,13 @@ func SimulateMsgEditValidator(k staking.Keeper) simulation.Operation { return func(r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, accs []simulation.Account) (opMsg simulation.OperationMsg, fOps []simulation.FutureOperation, err error) { - description := staking.Description{ - Moniker: simulation.RandStringOfLength(r, 10), - Identity: simulation.RandStringOfLength(r, 10), - Website: simulation.RandStringOfLength(r, 10), - Details: simulation.RandStringOfLength(r, 10), - } + description := staking.NewDescription( + simulation.RandStringOfLength(r, 10), + simulation.RandStringOfLength(r, 10), + simulation.RandStringOfLength(r, 10), + simulation.RandStringOfLength(r, 10), + simulation.RandStringOfLength(r, 10), + ) if len(k.GetAllValidators(ctx)) == 0 { return simulation.NoOpMsg(staking.ModuleName), nil, nil diff --git a/x/staking/types/msg_test.go b/x/staking/types/msg_test.go index a127e4df9c50..22914ec8aefa 100644 --- a/x/staking/types/msg_test.go +++ b/x/staking/types/msg_test.go @@ -20,27 +20,27 @@ func TestMsgCreateValidator(t *testing.T) { commission2 := NewCommissionRates(sdk.NewDec(5), sdk.NewDec(5), sdk.NewDec(5)) tests := []struct { - name, moniker, identity, website, details string - CommissionRates CommissionRates - minSelfDelegation sdk.Int - validatorAddr sdk.ValAddress - pubkey crypto.PubKey - bond sdk.Coin - expectPass bool + name, moniker, identity, website, securityContact, details string + CommissionRates CommissionRates + minSelfDelegation sdk.Int + validatorAddr sdk.ValAddress + pubkey crypto.PubKey + bond sdk.Coin + expectPass bool }{ - {"basic good", "a", "b", "c", "d", commission1, sdk.OneInt(), valAddr1, pk1, coinPos, true}, - {"partial description", "", "", "c", "", commission1, sdk.OneInt(), valAddr1, pk1, coinPos, true}, - {"empty description", "", "", "", "", commission2, sdk.OneInt(), valAddr1, pk1, coinPos, false}, - {"empty address", "a", "b", "c", "d", commission2, sdk.OneInt(), emptyAddr, pk1, coinPos, false}, - {"empty pubkey", "a", "b", "c", "d", commission1, sdk.OneInt(), valAddr1, emptyPubkey, coinPos, true}, - {"empty bond", "a", "b", "c", "d", commission2, sdk.OneInt(), valAddr1, pk1, coinZero, false}, - {"zero min self delegation", "a", "b", "c", "d", commission1, sdk.ZeroInt(), valAddr1, pk1, coinPos, false}, - {"negative min self delegation", "a", "b", "c", "d", commission1, sdk.NewInt(-1), valAddr1, pk1, coinPos, false}, - {"delegation less than min self delegation", "a", "b", "c", "d", commission1, coinPos.Amount.Add(sdk.OneInt()), valAddr1, pk1, coinPos, false}, + {"basic good", "a", "b", "c", "d", "e", commission1, sdk.OneInt(), valAddr1, pk1, coinPos, true}, + {"partial description", "", "", "c", "", "", commission1, sdk.OneInt(), valAddr1, pk1, coinPos, true}, + {"empty description", "", "", "", "", "", commission2, sdk.OneInt(), valAddr1, pk1, coinPos, false}, + {"empty address", "a", "b", "c", "d", "e", commission2, sdk.OneInt(), emptyAddr, pk1, coinPos, false}, + {"empty pubkey", "a", "b", "c", "d", "e", commission1, sdk.OneInt(), valAddr1, emptyPubkey, coinPos, true}, + {"empty bond", "a", "b", "c", "d", "e", commission2, sdk.OneInt(), valAddr1, pk1, coinZero, false}, + {"zero min self delegation", "a", "b", "c", "d", "e", commission1, sdk.ZeroInt(), valAddr1, pk1, coinPos, false}, + {"negative min self delegation", "a", "b", "c", "d", "e", commission1, sdk.NewInt(-1), valAddr1, pk1, coinPos, false}, + {"delegation less than min self delegation", "a", "b", "c", "d", "e", commission1, coinPos.Amount.Add(sdk.OneInt()), valAddr1, pk1, coinPos, false}, } for _, tc := range tests { - description := NewDescription(tc.moniker, tc.identity, tc.website, tc.details) + description := NewDescription(tc.moniker, tc.identity, tc.website, tc.securityContact, tc.details) msg := NewMsgCreateValidator(tc.validatorAddr, tc.pubkey, tc.bond, description, tc.CommissionRates, tc.minSelfDelegation) if tc.expectPass { require.Nil(t, msg.ValidateBasic(), "test: %v", tc.name) @@ -53,18 +53,18 @@ func TestMsgCreateValidator(t *testing.T) { // test ValidateBasic for MsgEditValidator func TestMsgEditValidator(t *testing.T) { tests := []struct { - name, moniker, identity, website, details string - validatorAddr sdk.ValAddress - expectPass bool + name, moniker, identity, website, securityContact, details string + validatorAddr sdk.ValAddress + expectPass bool }{ - {"basic good", "a", "b", "c", "d", valAddr1, true}, - {"partial description", "", "", "c", "", valAddr1, true}, - {"empty description", "", "", "", "", valAddr1, false}, - {"empty address", "a", "b", "c", "d", emptyAddr, false}, + {"basic good", "a", "b", "c", "d", "e", valAddr1, true}, + {"partial description", "", "", "c", "", "", valAddr1, true}, + {"empty description", "", "", "", "", "", valAddr1, false}, + {"empty address", "a", "b", "c", "d", "e", emptyAddr, false}, } for _, tc := range tests { - description := NewDescription(tc.moniker, tc.identity, tc.website, tc.details) + description := NewDescription(tc.moniker, tc.identity, tc.website, tc.securityContact, tc.details) newRate := sdk.ZeroDec() newMinSelfDelegation := sdk.OneInt() diff --git a/x/staking/types/validator.go b/x/staking/types/validator.go index 014ff84d3a54..df68c177e930 100644 --- a/x/staking/types/validator.go +++ b/x/staking/types/validator.go @@ -19,10 +19,11 @@ import ( // nolint const ( // TODO: Why can't we just have one string description which can be JSON by convention - MaxMonikerLength = 70 - MaxIdentityLength = 3000 - MaxWebsiteLength = 140 - MaxDetailsLength = 280 + MaxMonikerLength = 70 + MaxIdentityLength = 3000 + MaxWebsiteLength = 140 + MaxSecurityContactLength = 140 + MaxDetailsLength = 280 ) // Implements Validator interface @@ -260,19 +261,21 @@ const DoNotModifyDesc = "[do-not-modify]" // Description - description fields for a validator type Description struct { - Moniker string `json:"moniker" yaml:"moniker"` // name - Identity string `json:"identity" yaml:"identity"` // optional identity signature (ex. UPort or Keybase) - Website string `json:"website" yaml:"website"` // optional website link - Details string `json:"details" yaml:"details"` // optional details + Moniker string `json:"moniker" yaml:"moniker"` // name + Identity string `json:"identity" yaml:"identity"` // optional identity signature (ex. UPort or Keybase) + Website string `json:"website" yaml:"website"` // optional website link + SecurityContact string `json:"security_contact" yaml:"security_contact"` // optional security contact info + Details string `json:"details" yaml:"details"` // optional details } // NewDescription returns a new Description with the provided values. -func NewDescription(moniker, identity, website, details string) Description { +func NewDescription(moniker, identity, website, securityContact, details string) Description { return Description{ - Moniker: moniker, - Identity: identity, - Website: website, - Details: details, + Moniker: moniker, + Identity: identity, + Website: website, + SecurityContact: securityContact, + Details: details, } } @@ -288,16 +291,20 @@ func (d Description) UpdateDescription(d2 Description) (Description, sdk.Error) if d2.Website == DoNotModifyDesc { d2.Website = d.Website } + if d2.SecurityContact == DoNotModifyDesc { + d2.SecurityContact = d.SecurityContact + } if d2.Details == DoNotModifyDesc { d2.Details = d.Details } - return Description{ - Moniker: d2.Moniker, - Identity: d2.Identity, - Website: d2.Website, - Details: d2.Details, - }.EnsureLength() + return NewDescription( + d2.Moniker, + d2.Identity, + d2.Website, + d2.SecurityContact, + d2.Details, + ).EnsureLength() } // EnsureLength ensures the length of a validator's description. @@ -311,6 +318,9 @@ func (d Description) EnsureLength() (Description, sdk.Error) { if len(d.Website) > MaxWebsiteLength { return d, ErrDescriptionLength(DefaultCodespace, "website", len(d.Website), MaxWebsiteLength) } + if len(d.SecurityContact) > MaxSecurityContactLength { + return d, ErrDescriptionLength(DefaultCodespace, "security contact", len(d.SecurityContact), MaxSecurityContactLength) + } if len(d.Details) > MaxDetailsLength { return d, ErrDescriptionLength(DefaultCodespace, "details", len(d.Details), MaxDetailsLength) } diff --git a/x/staking/types/validator_test.go b/x/staking/types/validator_test.go index ddf078a586a9..6f8243efab4b 100644 --- a/x/staking/types/validator_test.go +++ b/x/staking/types/validator_test.go @@ -289,6 +289,7 @@ func TestValidatorMarshalYAML(t *testing.T) { moniker: "" identity: "" website: "" + security_contact: "" details: "" unbondingheight: 0 unbondingcompletiontime: 1970-01-01T00:00:00Z