From c757364c4f532a8f7b9d17531f189c41cde90b14 Mon Sep 17 00:00:00 2001 From: sampocs Date: Thu, 20 Oct 2022 15:55:56 -0500 Subject: [PATCH] Add Validator through Governance (#305) Co-authored-by: Riley Edmunds Co-authored-by: riley-stride <104941670+riley-stride@users.noreply.github.com> --- app/app.go | 29 +- cmd/strided/config/config.go | 2 +- go.mod | 11 +- go.sum | 18 +- proto/stakeibc/gov.proto | 17 + proto/stakeibc/params.proto | 3 +- scripts-local/init_stride.sh | 5 - scripts-local/vesting/README.md | 68 -- scripts-local/vesting/add_vesting_accts.sh | 26 - scripts-local/vesting/vesting_accts.csv | 3 - x/stakeibc/client/cli/tx.go | 2 +- x/stakeibc/client/cli/tx_add_validator.go | 4 - .../client/cli/tx_add_validator_proposal.go | 114 ++++ x/stakeibc/client/cli/tx_delete_validator.go | 13 +- x/stakeibc/client/proposal_handler.go | 12 + x/stakeibc/client/rest/tx.go | 20 + x/stakeibc/handler.go | 26 + x/stakeibc/keeper/gov.go | 17 + x/stakeibc/keeper/host_zone.go | 57 ++ x/stakeibc/keeper/keeper.go | 32 + x/stakeibc/keeper/msg_server_add_validator.go | 35 +- .../msg_server_change_validator_weight.go | 14 +- .../msg_server_delete_validator_test.go | 6 +- x/stakeibc/proposal_handler.go | 27 + x/stakeibc/types/codec.go | 7 + x/stakeibc/types/errors.go | 1 + x/stakeibc/types/gov.go | 66 ++ x/stakeibc/types/gov.pb.go | 579 ++++++++++++++++++ x/stakeibc/types/params.go | 6 + x/stakeibc/types/params.pb.go | 118 ++-- 30 files changed, 1119 insertions(+), 219 deletions(-) create mode 100644 proto/stakeibc/gov.proto delete mode 100644 scripts-local/vesting/README.md delete mode 100644 scripts-local/vesting/add_vesting_accts.sh delete mode 100644 scripts-local/vesting/vesting_accts.csv create mode 100644 x/stakeibc/client/cli/tx_add_validator_proposal.go create mode 100644 x/stakeibc/client/proposal_handler.go create mode 100644 x/stakeibc/client/rest/tx.go create mode 100644 x/stakeibc/keeper/gov.go create mode 100644 x/stakeibc/proposal_handler.go create mode 100644 x/stakeibc/types/gov.go create mode 100644 x/stakeibc/types/gov.pb.go diff --git a/app/app.go b/app/app.go index 347d2f5257..b7d399bfbf 100644 --- a/app/app.go +++ b/app/app.go @@ -118,6 +118,7 @@ import ( recordsmodulekeeper "github.com/Stride-Labs/stride/x/records/keeper" recordsmoduletypes "github.com/Stride-Labs/stride/x/records/types" stakeibcmodule "github.com/Stride-Labs/stride/x/stakeibc" + stakeibcclient "github.com/Stride-Labs/stride/x/stakeibc/client" stakeibcmodulekeeper "github.com/Stride-Labs/stride/x/stakeibc/keeper" stakeibcmoduletypes "github.com/Stride-Labs/stride/x/stakeibc/types" // this line is used by starport scaffolding # stargate/app/moduleImport @@ -142,6 +143,7 @@ func getGovProposalHandlers() []govclient.ProposalHandler { upgradeclient.CancelProposalHandler, ibcclientclient.UpdateClientProposalHandler, ibcclientclient.UpgradeProposalHandler, + stakeibcclient.AddValidatorProposalHandler, // this line is used by starport scaffolding # stargate/app/govProposalHandler ) @@ -380,14 +382,6 @@ func NewStrideApp( appCodec, keys[ibchost.StoreKey], app.GetSubspace(ibchost.ModuleName), app.StakingKeeper, app.UpgradeKeeper, scopedIBCKeeper, ) - // register the proposal types - govRouter := govtypes.NewRouter() - govRouter.AddRoute(govtypes.RouterKey, govtypes.ProposalHandler). - AddRoute(paramproposal.RouterKey, params.NewParamChangeProposalHandler(app.ParamsKeeper)). - AddRoute(distrtypes.RouterKey, distr.NewCommunityPoolSpendProposalHandler(app.DistrKeeper)). - AddRoute(upgradetypes.RouterKey, upgrade.NewSoftwareUpgradeProposalHandler(app.UpgradeKeeper)). - AddRoute(ibcclienttypes.RouterKey, ibcclient.NewClientProposalHandler(app.IBCKeeper.ClientKeeper)) - // Create Transfer Keepers app.TransferKeeper = ibctransferkeeper.NewKeeper( appCodec, keys[ibctransfertypes.StoreKey], app.GetSubspace(ibctransfertypes.ModuleName), @@ -404,11 +398,6 @@ func NewStrideApp( // If evidence needs to be handled for the app, set routes in router here and seal app.EvidenceKeeper = *evidenceKeeper - app.GovKeeper = govkeeper.NewKeeper( - appCodec, keys[govtypes.StoreKey], app.GetSubspace(govtypes.ModuleName), app.AccountKeeper, app.BankKeeper, - &stakingKeeper, govRouter, - ) - // TODO(TEST-20): look for all lines that include 'monitoring' in this file! there are a few places this // is commented out // scopedMonitoringKeeper := app.CapabilityKeeper.ScopeToModule(monitoringptypes.ModuleName) @@ -487,6 +476,20 @@ func NewStrideApp( stakeibcModule := stakeibcmodule.NewAppModule(appCodec, app.StakeibcKeeper, app.AccountKeeper, app.BankKeeper) stakeibcIBCModule := stakeibcmodule.NewIBCModule(app.StakeibcKeeper) + // Register Gov (must be registerd after stakeibc) + govRouter := govtypes.NewRouter() + govRouter.AddRoute(govtypes.RouterKey, govtypes.ProposalHandler). + AddRoute(paramproposal.RouterKey, params.NewParamChangeProposalHandler(app.ParamsKeeper)). + AddRoute(distrtypes.RouterKey, distr.NewCommunityPoolSpendProposalHandler(app.DistrKeeper)). + AddRoute(upgradetypes.RouterKey, upgrade.NewSoftwareUpgradeProposalHandler(app.UpgradeKeeper)). + AddRoute(ibcclienttypes.RouterKey, ibcclient.NewClientProposalHandler(app.IBCKeeper.ClientKeeper)). + AddRoute(stakeibcmoduletypes.RouterKey, stakeibcmodule.NewStakeibcProposalHandler(app.StakeibcKeeper)) + + app.GovKeeper = govkeeper.NewKeeper( + appCodec, keys[govtypes.StoreKey], app.GetSubspace(govtypes.ModuleName), app.AccountKeeper, app.BankKeeper, + &stakingKeeper, govRouter, + ) + // Register ICQ callbacks err := app.InterchainqueryKeeper.SetCallbackHandler(stakeibcmoduletypes.ModuleName, app.StakeibcKeeper.CallbackHandler()) if err != nil { diff --git a/cmd/strided/config/config.go b/cmd/strided/config/config.go index f028e158e0..d3f5434b00 100644 --- a/cmd/strided/config/config.go +++ b/cmd/strided/config/config.go @@ -27,7 +27,7 @@ const ( const ( HumanReadableCoinUnit = "STRD" - BaseCoinUnit = "strd" + BaseCoinUnit = "ustrd" DefaultBondDenom = BaseCoinUnit ) diff --git a/go.mod b/go.mod index d970f1272e..6c572f6e6b 100644 --- a/go.mod +++ b/go.mod @@ -16,8 +16,8 @@ require ( github.com/stretchr/testify v1.8.0 github.com/tendermint/tendermint v0.34.21 github.com/tendermint/tm-db v0.6.7 - google.golang.org/genproto v0.0.0-20220822174746-9e6da59bd2fc - google.golang.org/grpc v1.48.0 + google.golang.org/genproto v0.0.0-20221014213838-99cd37c6964a + google.golang.org/grpc v1.50.1 google.golang.org/protobuf v1.28.1 gopkg.in/yaml.v2 v2.4.0 ) @@ -62,6 +62,7 @@ require ( github.com/golang/glog v1.0.0 // indirect github.com/golang/snappy v0.0.4 // indirect github.com/google/btree v1.1.2 // indirect + github.com/google/go-cmp v0.5.9 // indirect github.com/google/gofuzz v1.2.0 // indirect github.com/google/orderedcode v0.0.1 // indirect github.com/gorilla/handlers v1.5.1 // indirect @@ -118,10 +119,10 @@ require ( go.etcd.io/bbolt v1.3.6 // indirect golang.org/x/crypto v0.0.0-20220525230936-793ad666bf5e // indirect golang.org/x/exp v0.0.0-20220722155223-a9213eeb770e // indirect - golang.org/x/net v0.0.0-20220726230323-06994584191e // indirect - golang.org/x/sys v0.0.0-20220727055044-e65921a090b8 // indirect + golang.org/x/net v0.0.0-20220909164309-bea034e7d591 // indirect + golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10 // indirect golang.org/x/term v0.0.0-20220722155259-a9ba230a4035 // indirect - golang.org/x/text v0.3.7 // indirect + golang.org/x/text v0.3.8 // indirect gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect gopkg.in/ini.v1 v1.66.6 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect diff --git a/go.sum b/go.sum index ee63bd30f4..77a861052f 100644 --- a/go.sum +++ b/go.sum @@ -349,7 +349,8 @@ github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE= -github.com/google/go-cmp v0.5.8 h1:e6P7q2lk1O+qJJb4BtCQXlK8vWEO8V1ZeuEdJNOqZyg= +github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= +github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/gofuzz v0.0.0-20170612174753-24818f796faf/go.mod h1:HP5RmnzzSNb993RKQDq4+1A4ia9nllfqcQFTQJedwGI= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/gofuzz v1.1.1-0.20200604201612-c04b05f3adfa/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= @@ -926,8 +927,8 @@ golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qx golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= -golang.org/x/net v0.0.0-20220726230323-06994584191e h1:wOQNKh1uuDGRnmgF0jDxh7ctgGy/3P4rYWQRVJD4/Yg= -golang.org/x/net v0.0.0-20220726230323-06994584191e/go.mod h1:AaygXjzTFtRAg2ttMY5RMuhpJ3cNnI0XpyFJD1iQRSM= +golang.org/x/net v0.0.0-20220909164309-bea034e7d591 h1:D0B/7al0LLrVC8aWF4+oxpv/m8bc7ViFfVS8/gXGdqI= +golang.org/x/net v0.0.0-20220909164309-bea034e7d591/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -1020,8 +1021,8 @@ golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220727055044-e65921a090b8 h1:dyU22nBWzrmTQxtNrr4dzVOvaw35nUYE279vF9UmsI8= -golang.org/x/sys v0.0.0-20220727055044-e65921a090b8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10 h1:WIoqL4EROvwiPdUtaip4VcDdpZ4kha7wBWZrbVKCIZg= +golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.0.0-20220722155259-a9ba230a4035 h1:Q5284mrmYTpACcm+eAKjKJH48BBwSyfJqmmGDTtT8Vc= @@ -1033,8 +1034,9 @@ golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= +golang.org/x/text v0.3.8 h1:nAL+RVCQ9uMn3vJZbV+MRnydTJFPf8qqY42YiA6MrqY= +golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ= golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= @@ -1167,8 +1169,8 @@ google.golang.org/genproto v0.0.0-20201214200347-8c77b98c765d/go.mod h1:FWY/as6D google.golang.org/genproto v0.0.0-20210108203827-ffc7fda8c3d7/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20210126160654-44e461bb6506/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20210226172003-ab064af71705/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20220822174746-9e6da59bd2fc h1:Nf+EdcTLHR8qDNN/KfkQL0u0ssxt9OhbaWCl5C0ucEI= -google.golang.org/genproto v0.0.0-20220822174746-9e6da59bd2fc/go.mod h1:dbqgFATTzChvnt+ujMdZwITVAJHFtfyN1qUhDqEiIlk= +google.golang.org/genproto v0.0.0-20221014213838-99cd37c6964a h1:GH6UPn3ixhWcKDhpnEC55S75cerLPdpp3hrhfKYjZgw= +google.golang.org/genproto v0.0.0-20221014213838-99cd37c6964a/go.mod h1:1vXfmgAz9N9Jx0QA82PqRVauvCz1SGSz739p0f183jM= google.golang.org/grpc v1.33.2 h1:EQyQC3sa8M+p6Ulc8yy9SWSS2GVwyRc83gAbG8lrl4o= google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= diff --git a/proto/stakeibc/gov.proto b/proto/stakeibc/gov.proto new file mode 100644 index 0000000000..d061f2de15 --- /dev/null +++ b/proto/stakeibc/gov.proto @@ -0,0 +1,17 @@ +syntax = "proto3"; +package Stridelabs.stride.stakeibc; +import "cosmos_proto/cosmos.proto"; +import "gogoproto/gogo.proto"; +option go_package = "github.com/Stride-Labs/stride/x/stakeibc/types"; + +message AddValidatorProposal { + option (gogoproto.equal) = true; + option (gogoproto.goproto_getters) = false; + option (gogoproto.goproto_stringer) = false; + + string title = 1; + string description = 2; + string host_zone = 3; + string validator_name = 4; + string validator_address = 5 [ (cosmos_proto.scalar) = "cosmos.AddressString" ]; +} diff --git a/proto/stakeibc/params.proto b/proto/stakeibc/params.proto index 56bd094352..b3aa6c5b52 100644 --- a/proto/stakeibc/params.proto +++ b/proto/stakeibc/params.proto @@ -6,7 +6,7 @@ import "gogoproto/gogo.proto"; option go_package = "github.com/Stride-Labs/stride/x/stakeibc/types"; // Params defines the parameters for the module. -// next id: 16 +// next id: 18 message Params { option (gogoproto.goproto_stringer) = false; @@ -32,4 +32,5 @@ message Params { uint64 safety_min_redemption_rate_threshold = 14; uint64 safety_max_redemption_rate_threshold = 15; uint64 ibc_transfer_timeout_nanos = 16; + uint64 safety_num_validators = 17; } \ No newline at end of file diff --git a/scripts-local/init_stride.sh b/scripts-local/init_stride.sh index c437770d02..71376f5cfe 100755 --- a/scripts-local/init_stride.sh +++ b/scripts-local/init_stride.sh @@ -143,11 +143,6 @@ $STRIDE_CMD add-genesis-account ${val_addr} 500000000000ustrd # actually set this account as a validator $STRIDE_CMD gentx $STRIDE_VAL_ACCT 100000000000ustrd --chain-id $STRIDE_CHAIN 2> /dev/null -# add vesting accounts -bash $SCRIPT_DIR/vesting/add_vesting_accts.sh - -# source $SCRIPT_DIR/genesis.sh - # Add hermes relayer account echo $HERMES_STRIDE_MNEMONIC | $STRIDE_CMD keys add $HERMES_STRIDE_ACCT --recover --keyring-backend=test >> $KEYS_LOGS 2>&1 HERMES_STRIDE_ADDRESS=$($STRIDE_CMD keys show $HERMES_STRIDE_ACCT --keyring-backend test -a) diff --git a/scripts-local/vesting/README.md b/scripts-local/vesting/README.md deleted file mode 100644 index efecf44221..0000000000 --- a/scripts-local/vesting/README.md +++ /dev/null @@ -1,68 +0,0 @@ -## Vesting Module - -### Custom Implementations - -Evmos x/vesting (from Agoric) -- Osmosis' clawback vesting, in the _auth_ module https://github.com/osmosis-labs/cosmos-sdk/tree/osmosis-main/x/auth/vesting -- https://docs.evmos.org/modules/vesting/ -- https://github.com/evmos/evmos/blob/main/x/vesting/spec/README.md (removes all vesting account types other than clawback type) -- https://docs.cosmos.network/main/modules/auth/05_vesting.html -- https://github.com/Agoric/agoric-sdk/issues/4085 -- https://github.com/agoric-labs/cosmos-sdk/tree/Agoric/x/auth/vesting/cmd/vestcalc -- Misc Terra vesting upgrades to cosmos-sdk/x/vesting https://github.com/terra-money/core/blob/beeff192329372e2bb993f897b8c866fd8be917d/app/upgrade.go#L24 - - -### Cosmos SDK Vesting Module - -The Cosmos Hub's vesting account needs to be initialized during genesis with a starting balance `X` and a vesting end time `ET`. Optional parameters are vesting start time `ST` and number of vesting periods `P`. -Owners of vesting accounts can freely delegate and undelegate from validators but they cannot transfer the unvested tokens to another account. -There are a few types of vesting accounts: -- Delayed vesting: all coins vest once `ET` is reached. Can be created after genesis. -- Continuous vesting, where coins vest linearly between `ST` and `ET`. Can be created after genesis. -- Periodic vesting, where coins vest periodically based on some period between `ST` and `ET` (in batches). Must be created AT GENESIS, or as part of a manual network upgrade. -The current spec does not allow for clawbacks or conditional vesting (e.g. stop the vest if x condition triggers) - - -## Testing Delayed Vesting - -To test delayed vesting, let's vest `1000strd` to the `val1` account with a 2 minute cliff and 5 minute linear continuous vest. - -The vesting setup needs to occur during genesis. In `scripts-local/init_stride.sh:36`, replace the current `add-genesis-account` command with the following commands, which contain flags to set up delayed vesting to the account. - -``` -VESTING_START_TIME=$(($(date +%s)+120)) # <= unix time start of vesting period (2 minutes from now) -VESTING_END_TIME=$((VESTING_START_TIME+300)) # <= unix time end of vesting period (7 minutes from now) -VESTING_AMT="1000000000ustrd" # <= amount of tokens to vest to the account -$STRIDE_CMD add-genesis-account ${val_addr} 500000000000ustrd --vesting-start-time $VESTING_START_TIME --vesting-end-time $VESTING_END_TIME --vesting-amount $VESTING_AMT -``` - -_Note that the amount vested is taken out of the total amount genesis'd to the account, it is NOT additional to the amount genesis'd (in this case, that means the account will have `500000000000ustrd` total tokens, of which `1000000000ustrd` will be vesting)_ - -A simple way to check how much has vested is to look at the account on the block explorer (with our local ping.pub, setup from https://github.com/Stride-Labs/explorer, that's http://localhost:8080/stride/account/stride1uk4ze0x4nvh4fk0xm4jdud58eqn4yxhrt52vv7). Another way is to attempt to bank send the full acct balance to another addr before the vest has completed. Inspecting that failed tx will show you how much is available to send (which tells you how much has vested thus far) - -``` -build/strided --home ./scripts-local/state/stride tx bank send val1 stride1ft20pydau82pgesyl9huhhux307s9h3078692y 499000000000ustrd --chain-id STRIDE --keyring-backend test -y -build/strided --home ./scripts-local/state/stride q tx -``` - -Once vesting completes 7 min from genesis, bank sending the full account balance should succeed! - - -## Our approach - -We want delayed vesting for all vesting accounts. We simply need to, for each acct -1. calc the amount to vest -2. have the recipient set up an addr on testnet, save their seed phrase and send us the address -3. set up vesting for that account with the following params - ``` - VESTING_START_TIME=1685592000 # June 1st 2023 - VESTING_END_TIME=1748768365 # June 1st 2025 - VESTING_AMT='XXXustrd' - VESTER_ADDR='YYY' - $STRIDE_CMD add-genesis-account $VESTER_ADDR $VESTING_AMT --vesting-start-time $VESTING_START_TIME --vesting-end-time $VESTING_END_TIME --vesting-amount $VESTING_AMT - ``` - - -Open questions: -- Should we switch to using Osmosis' version? -- Do we want/need clawbacks? \ No newline at end of file diff --git a/scripts-local/vesting/add_vesting_accts.sh b/scripts-local/vesting/add_vesting_accts.sh deleted file mode 100644 index 0cd1a5f5bc..0000000000 --- a/scripts-local/vesting/add_vesting_accts.sh +++ /dev/null @@ -1,26 +0,0 @@ -#!/bin/bash - -convertsecs() { - h=$(bc <<< "${1}/3600") - m=$(bc <<< "(${1}%3600)/60") - s=$(bc <<< "${1}%60") - printf "%02dD:%02dM:%05.2fS\n" $h $m $s -} - -SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd ) -# import dependencies -source $SCRIPT_DIR/../vars.sh - -# vesting params -CLIFF=120 -DURATION=300 -VESTING_START_TIME=$(($(date +%s)+$CLIFF)) # <= unix time start of vesting period (2 minutes from now) -VESTING_END_TIME=$((VESTING_START_TIME+$DURATION)) # <= unix time end of vesting period (7 minutes from now) - -echo "VESTING ACCOUNTS:" >> $TX_LOGS 2>&1 -while IFS=, read -r addr amt -do - echo "Vesting $amt to $addr, with a $(convertsecs $CLIFF) cliff, then linearly over $(convertsecs $DURATION)." >> $TX_LOGS 2>&1 - $STRIDE_CMD add-genesis-account ${addr} $amt --vesting-start-time $VESTING_START_TIME --vesting-end-time $VESTING_END_TIME --vesting-amount $amt # actually set this account as a validator -done < $SCRIPT_DIR/vesting/vesting_accts.csv - diff --git a/scripts-local/vesting/vesting_accts.csv b/scripts-local/vesting/vesting_accts.csv deleted file mode 100644 index 857a82ea99..0000000000 --- a/scripts-local/vesting/vesting_accts.csv +++ /dev/null @@ -1,3 +0,0 @@ -stride1ze3jp6ut8ce9qrxtthh9r5cy632mn9rqchp8qy, 100000000ustrd -stride1qj0jws6fycdhxcja27tfwazdp26pq8mwpyt829, 50000000000ustrd -stride1qcrp9lefnnmtgx60nrm5quc6x88xp0u9ha7wp2, 350000000ustrd diff --git a/x/stakeibc/client/cli/tx.go b/x/stakeibc/client/cli/tx.go index 23d607677f..967baa6ab0 100644 --- a/x/stakeibc/client/cli/tx.go +++ b/x/stakeibc/client/cli/tx.go @@ -8,7 +8,7 @@ import ( "github.com/spf13/cobra" "github.com/cosmos/cosmos-sdk/client" - // "github.com/cosmos/cosmos-sdk/client/flags" + "github.com/Stride-Labs/stride/x/stakeibc/types" ) diff --git a/x/stakeibc/client/cli/tx_add_validator.go b/x/stakeibc/client/cli/tx_add_validator.go index 5c235740f5..85cd3714be 100644 --- a/x/stakeibc/client/cli/tx_add_validator.go +++ b/x/stakeibc/client/cli/tx_add_validator.go @@ -1,8 +1,6 @@ package cli import ( - "strconv" - "github.com/cosmos/cosmos-sdk/client" "github.com/cosmos/cosmos-sdk/client/flags" "github.com/cosmos/cosmos-sdk/client/tx" @@ -12,8 +10,6 @@ import ( "github.com/Stride-Labs/stride/x/stakeibc/types" ) -var _ = strconv.Itoa(0) - func CmdAddValidator() *cobra.Command { cmd := &cobra.Command{ Use: "add-validator [host-zone] [name] [address] [commission] [weight]", diff --git a/x/stakeibc/client/cli/tx_add_validator_proposal.go b/x/stakeibc/client/cli/tx_add_validator_proposal.go new file mode 100644 index 0000000000..a365c80587 --- /dev/null +++ b/x/stakeibc/client/cli/tx_add_validator_proposal.go @@ -0,0 +1,114 @@ +package cli + +import ( + "fmt" + "os" + "strings" + + "github.com/cosmos/cosmos-sdk/codec" + + "github.com/cosmos/cosmos-sdk/client" + "github.com/cosmos/cosmos-sdk/client/tx" + sdk "github.com/cosmos/cosmos-sdk/types" + sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" + "github.com/cosmos/cosmos-sdk/version" + govcli "github.com/cosmos/cosmos-sdk/x/gov/client/cli" + govtypes "github.com/cosmos/cosmos-sdk/x/gov/types" + "github.com/spf13/cobra" + + "github.com/Stride-Labs/stride/x/stakeibc/types" +) + +func parseAddValidatorProposalFile(cdc codec.JSONCodec, proposalFile string) (types.AddValidatorProposal, error) { + + proposal := types.AddValidatorProposal{} + + contents, err := os.ReadFile(proposalFile) + if err != nil { + return proposal, err + } + + if err = cdc.UnmarshalJSON(contents, &proposal); err != nil { + return proposal, err + } + + proposal.Title = fmt.Sprintf("Add %s validator %s (address: %s)", + proposal.HostZone, proposal.ValidatorName, proposal.ValidatorAddress) + + return proposal, nil +} + +func CmdAddValidatorProposal() *cobra.Command { + + cmd := &cobra.Command{ + Use: "add-validator [proposal-file]", + Short: "Submit an add-validator proposal", + Long: strings.TrimSpace( + fmt.Sprintf(`Submit an add-validator proposal along with an initial deposit. +The proposal details must be supplied via a JSON file. + +Example: +$ %s tx gov submit-proposal add-validator --from= + +Where proposal.json contains: +{ + "description": "Proposal to add Imperator because they contribute in XYZ ways!", + "hostZone": "GAIA", + "validatorName": "Imperator", + "validatorAddress": "cosmosvaloper1v5y0tg0jllvxf5c3afml8s3awue0ymju89frut", + "deposit": "64000000ustrd" +} +`, version.AppName), + ), + Args: cobra.ExactArgs(1), + RunE: func(cmd *cobra.Command, args []string) (err error) { + clientCtx, err := client.GetClientTxContext(cmd) + if err != nil { + return err + } + + proposal, err := parseAddValidatorProposalFile(clientCtx.Codec, args[0]) + if err != nil { + return err + } + + from := clientCtx.GetFromAddress() + + depositFromFlags, err := cmd.Flags().GetString(govcli.FlagDeposit) + if err != nil { + return err + } + + // if deposit from flags is not empty, it overrides the deposit from proposal + if depositFromFlags != "" { + proposal.Deposit = depositFromFlags + } + deposit, err := sdk.ParseCoinsNormalized(proposal.Deposit) + if err != nil { + return err + } + + strideDenom, err := sdk.GetBaseDenom() + if err != nil { + return err + } + + if len(deposit) != 1 || deposit.GetDenomByIndex(0) != strideDenom { + return sdkerrors.Wrapf(sdkerrors.ErrInvalidCoins, "Deposit token denom must be %s", strideDenom) + } + + msg, err := govtypes.NewMsgSubmitProposal(&proposal, deposit, from) + if err != nil { + return err + } + if err := msg.ValidateBasic(); err != nil { + return err + } + return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), msg) + }, + } + + cmd.Flags().String(govcli.FlagDeposit, "", "deposit of proposal") + + return cmd +} diff --git a/x/stakeibc/client/cli/tx_delete_validator.go b/x/stakeibc/client/cli/tx_delete_validator.go index c580e1c05c..fbd44b17b7 100644 --- a/x/stakeibc/client/cli/tx_delete_validator.go +++ b/x/stakeibc/client/cli/tx_delete_validator.go @@ -1,25 +1,22 @@ package cli import ( - "strconv" - - "github.com/Stride-Labs/stride/x/stakeibc/types" "github.com/cosmos/cosmos-sdk/client" "github.com/cosmos/cosmos-sdk/client/flags" "github.com/cosmos/cosmos-sdk/client/tx" "github.com/spf13/cobra" -) -var _ = strconv.Itoa(0) + "github.com/Stride-Labs/stride/x/stakeibc/types" +) func CmdDeleteValidator() *cobra.Command { cmd := &cobra.Command{ - Use: "delete-validator [host-zone] [name]", + Use: "delete-validator [host-zone] [address]", Short: "Broadcast message delete-validator", Args: cobra.ExactArgs(2), RunE: func(cmd *cobra.Command, args []string) (err error) { argHostZone := args[0] - argName := args[1] + argAddress := args[1] clientCtx, err := client.GetClientTxContext(cmd) if err != nil { @@ -29,7 +26,7 @@ func CmdDeleteValidator() *cobra.Command { msg := types.NewMsgDeleteValidator( clientCtx.GetFromAddress().String(), argHostZone, - argName, + argAddress, ) if err := msg.ValidateBasic(); err != nil { return err diff --git a/x/stakeibc/client/proposal_handler.go b/x/stakeibc/client/proposal_handler.go new file mode 100644 index 0000000000..4a10a2c6ed --- /dev/null +++ b/x/stakeibc/client/proposal_handler.go @@ -0,0 +1,12 @@ +package client + +import ( + "github.com/Stride-Labs/stride/x/stakeibc/client/cli" + "github.com/Stride-Labs/stride/x/stakeibc/client/rest" + + govclient "github.com/cosmos/cosmos-sdk/x/gov/client" +) + +var ( + AddValidatorProposalHandler = govclient.NewProposalHandler(cli.CmdAddValidatorProposal, rest.ProposalAddValidatorRESTHandler) +) diff --git a/x/stakeibc/client/rest/tx.go b/x/stakeibc/client/rest/tx.go new file mode 100644 index 0000000000..e93b230d4d --- /dev/null +++ b/x/stakeibc/client/rest/tx.go @@ -0,0 +1,20 @@ +package rest + +import ( + "net/http" + + "github.com/cosmos/cosmos-sdk/client" + govrest "github.com/cosmos/cosmos-sdk/x/gov/client/rest" +) + +func ProposalAddValidatorRESTHandler(clientCtx client.Context) govrest.ProposalRESTHandler { + return govrest.ProposalRESTHandler{ + SubRoute: "add-validator", + Handler: newAddValidatorProposalHandler(clientCtx), + } +} + +func newAddValidatorProposalHandler(clientCtx client.Context) http.HandlerFunc { + return func(w http.ResponseWriter, r *http.Request) { + } +} diff --git a/x/stakeibc/handler.go b/x/stakeibc/handler.go index 3b1dbd5b01..1aef77c5b4 100644 --- a/x/stakeibc/handler.go +++ b/x/stakeibc/handler.go @@ -6,6 +6,8 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" + govtypes "github.com/cosmos/cosmos-sdk/x/gov/types" + "github.com/Stride-Labs/stride/x/stakeibc/keeper" "github.com/Stride-Labs/stride/x/stakeibc/types" ) @@ -59,3 +61,27 @@ func NewHandler(k keeper.Keeper) sdk.Handler { } } } + +// NewAddValidatorHandler creates a new governance Handler for a AddValidatorProposal +func NewAddValidatorProposalHandler(k keeper.Keeper) govtypes.Handler { + msgServer := keeper.NewMsgServerImpl(k) + + return func(ctx sdk.Context, content govtypes.Content) error { + switch c := content.(type) { + case *types.AddValidatorProposal: + _, err := msgServer.AddValidator(sdk.WrapSDKContext(ctx), &types.MsgAddValidator{ + Creator: "GOV", + HostZone: c.HostZone, + Name: c.ValidatorName, + Address: c.ValidatorAddress, + }) + if err != nil { + return err + } + return nil + + default: + return sdkerrors.Wrapf(sdkerrors.ErrUnknownRequest, "unrecognized addValidator proposal content type: %T", c) + } + } +} diff --git a/x/stakeibc/keeper/gov.go b/x/stakeibc/keeper/gov.go new file mode 100644 index 0000000000..0ad9ccef32 --- /dev/null +++ b/x/stakeibc/keeper/gov.go @@ -0,0 +1,17 @@ +package keeper + +import ( + sdk "github.com/cosmos/cosmos-sdk/types" + + "github.com/Stride-Labs/stride/x/stakeibc/types" +) + +func (k Keeper) AddValidatorProposal(ctx sdk.Context, msg *types.AddValidatorProposal) error { + addValMsg := &types.MsgAddValidator{ + HostZone: msg.HostZone, + Name: msg.ValidatorName, + Address: msg.ValidatorAddress, + Commission: 0, // TODO: Remove commission field from validator + } + return k.AddValidatorToHostZone(ctx, addValMsg, true) +} diff --git a/x/stakeibc/keeper/host_zone.go b/x/stakeibc/keeper/host_zone.go index 76dcccad5f..a5ea4f0142 100644 --- a/x/stakeibc/keeper/host_zone.go +++ b/x/stakeibc/keeper/host_zone.go @@ -4,6 +4,7 @@ import ( "encoding/binary" "errors" "fmt" + "math" "github.com/cosmos/cosmos-sdk/store/prefix" sdk "github.com/cosmos/cosmos-sdk/types" @@ -124,6 +125,62 @@ func (k Keeper) AddDelegationToValidator(ctx sdk.Context, hostZone types.HostZon return false } +func (k Keeper) AddValidatorToHostZone(ctx sdk.Context, msg *types.MsgAddValidator, fromGovernance bool) error { + // Get the corresponding host zone + hostZone, found := k.GetHostZone(ctx, msg.HostZone) + if !found { + errMsg := fmt.Sprintf("Host Zone (%s) not found", msg.HostZone) + k.Logger(ctx).Error(errMsg) + return sdkerrors.Wrap(types.ErrHostZoneNotFound, errMsg) + } + + // Get max number of validators and confirm we won't exceed it + err := k.ConfirmValSetHasSpace(ctx, hostZone.Validators) + if err != nil { + return sdkerrors.Wrap(types.ErrMaxNumValidators, "cannot add validator on host zone") + } + + // Check that we don't already have this validator + // Grab the minimum weight in the process (to assign to validator's added through governance) + var minWeight uint64 = math.MaxUint64 + for _, validator := range hostZone.Validators { + if validator.Address == msg.Address { + errMsg := fmt.Sprintf("Validator address (%s) already exists on Host Zone (%s)", msg.Address, msg.HostZone) + k.Logger(ctx).Error(errMsg) + return sdkerrors.Wrap(types.ErrValidatorAlreadyExists, errMsg) + } + if validator.Name == msg.Name { + errMsg := fmt.Sprintf("Validator name (%s) already exists on Host Zone (%s)", msg.Name, msg.HostZone) + k.Logger(ctx).Error(errMsg) + return sdkerrors.Wrap(types.ErrValidatorAlreadyExists, errMsg) + } + // Store the min weight to assign to new validator added through governance (ignore zero-weight validators) + if validator.Weight < minWeight && validator.Weight > 0 { + minWeight = validator.Weight + } + } + + // If the validator was added via governance, set the weight to the min validator weight of the host zone + valWeight := msg.Weight + if fromGovernance { + valWeight = minWeight + } + + // Finally, add the validator to the host + hostZone.Validators = append(hostZone.Validators, &types.Validator{ + Name: msg.Name, + Address: msg.Address, + Status: types.Validator_Active, + CommissionRate: msg.Commission, + DelegationAmt: 0, + Weight: valWeight, + }) + + k.SetHostZone(ctx, hostZone) + + return nil +} + func (k Keeper) RemoveValidatorFromHostZone(ctx sdk.Context, chainId string, validatorAddress string) error { hostZone, found := k.GetHostZone(ctx, chainId) if !found { diff --git a/x/stakeibc/keeper/keeper.go b/x/stakeibc/keeper/keeper.go index d787a2f7d4..450145ae77 100644 --- a/x/stakeibc/keeper/keeper.go +++ b/x/stakeibc/keeper/keeper.go @@ -260,3 +260,35 @@ func (k Keeper) IsRedemptionRateWithinSafetyBounds(ctx sdk.Context, zone types.H } return true, nil } + +// Check the max number of validators to confirm we won't exceed it when adding a new validator +// Types of additions: +// * change a weight from zero to non-zero +// * add a new validator with non-zero weight +func (k Keeper) ConfirmValSetHasSpace(ctx sdk.Context, validators []*types.Validator) error { + + // get max val parameter + maxNumVals, err := cast.ToIntE(k.GetParam(ctx, types.KeySafetyNumValidators)) + if err != nil { + errMsg := fmt.Sprintf("Error getting safety max num validators | err: %s", err.Error()) + k.Logger(ctx).Error(errMsg) + return sdkerrors.Wrap(types.ErrMaxNumValidators, errMsg) + } + + // count up the number of validators with non-zero weights + numNonzeroWgtValidators := 0 + for _, validator := range validators { + if validator.Weight > 0 { + numNonzeroWgtValidators++ + } + } + + // check if the number of validators with non-zero weights is below than the max + if numNonzeroWgtValidators >= maxNumVals { + errMsg := fmt.Sprintf("Attempting to add new validator but already reached max number of validators (%d)", maxNumVals) + k.Logger(ctx).Error(errMsg) + return sdkerrors.Wrap(types.ErrMaxNumValidators, errMsg) + } + + return nil +} diff --git a/x/stakeibc/keeper/msg_server_add_validator.go b/x/stakeibc/keeper/msg_server_add_validator.go index 780b53e10c..d7114db862 100644 --- a/x/stakeibc/keeper/msg_server_add_validator.go +++ b/x/stakeibc/keeper/msg_server_add_validator.go @@ -2,47 +2,18 @@ package keeper import ( "context" - "fmt" sdk "github.com/cosmos/cosmos-sdk/types" - sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" "github.com/Stride-Labs/stride/x/stakeibc/types" ) func (k msgServer) AddValidator(goCtx context.Context, msg *types.MsgAddValidator) (*types.MsgAddValidatorResponse, error) { - // TODO TEST-129 restrict this to governance module. add gov module whitelist hooks more broadly ctx := sdk.UnwrapSDKContext(goCtx) - hostZone, found := k.GetHostZone(ctx, msg.HostZone) - if !found { - errMsg := fmt.Sprintf("Host Zone (%s) not found", msg.HostZone) - k.Logger(ctx).Error(errMsg) - return nil, sdkerrors.Wrap(types.ErrHostZoneNotFound, errMsg) + err := k.AddValidatorToHostZone(ctx, msg, false) + if err != nil { + return nil, err } - validators := hostZone.Validators - // check that we don't already have this validator - for _, validator := range validators { - if validator.GetAddress() == msg.Address { - errMsg := fmt.Sprintf("Validator address (%s) already exists on Host Zone (%s)", msg.Address, msg.HostZone) - k.Logger(ctx).Error(errMsg) - return nil, sdkerrors.Wrap(types.ErrValidatorAlreadyExists, errMsg) - } - if validator.Name == msg.Name { - errMsg := fmt.Sprintf("Validator name (%s) already exists on Host Zone (%s)", msg.Name, msg.HostZone) - k.Logger(ctx).Error(errMsg) - return nil, sdkerrors.Wrap(types.ErrValidatorAlreadyExists, errMsg) - } - } - // add the validator - hostZone.Validators = append(validators, &types.Validator{ - Name: msg.Name, - Address: msg.Address, - Status: types.Validator_Active, - CommissionRate: msg.Commission, - DelegationAmt: 0, - Weight: msg.Weight, - }) - k.SetHostZone(ctx, hostZone) return &types.MsgAddValidatorResponse{}, nil } diff --git a/x/stakeibc/keeper/msg_server_change_validator_weight.go b/x/stakeibc/keeper/msg_server_change_validator_weight.go index 4e22fd9281..372d7e1882 100644 --- a/x/stakeibc/keeper/msg_server_change_validator_weight.go +++ b/x/stakeibc/keeper/msg_server_change_validator_weight.go @@ -4,8 +4,10 @@ import ( "context" "fmt" - "github.com/Stride-Labs/stride/x/stakeibc/types" sdk "github.com/cosmos/cosmos-sdk/types" + sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" + + "github.com/Stride-Labs/stride/x/stakeibc/types" ) func (k msgServer) ChangeValidatorWeight(goCtx context.Context, msg *types.MsgChangeValidatorWeight) (*types.MsgChangeValidatorWeightResponse, error) { @@ -16,12 +18,22 @@ func (k msgServer) ChangeValidatorWeight(goCtx context.Context, msg *types.MsgCh k.Logger(ctx).Error(fmt.Sprintf("Host Zone %s not found", msg.HostZone)) return nil, types.ErrInvalidHostZone } + validators := hostZone.Validators for _, validator := range validators { if validator.GetAddress() == msg.ValAddr { + + // when changing a weight from 0 to non-zero, make sure we have space in the val set for this new validator + if validator.Weight == 0 && msg.Weight > 0 { + err := k.ConfirmValSetHasSpace(ctx, validators) + if err != nil { + return nil, sdkerrors.Wrap(types.ErrMaxNumValidators, "cannot set val weight from zero to nonzero on host zone") + } + } validator.Weight = msg.Weight k.SetHostZone(ctx, hostZone) return &types.MsgChangeValidatorWeightResponse{}, nil + } } diff --git a/x/stakeibc/keeper/msg_server_delete_validator_test.go b/x/stakeibc/keeper/msg_server_delete_validator_test.go index eb83420d40..240d1c9439 100644 --- a/x/stakeibc/keeper/msg_server_delete_validator_test.go +++ b/x/stakeibc/keeper/msg_server_delete_validator_test.go @@ -93,7 +93,7 @@ func (s *KeeperTestSuite) TestDeleteValidator_HostZoneNotFound() { s.Require().EqualError(err, errMsg) } -func (s *KeeperTestSuite) TestAddValidator_AddressNotFound() { +func (s *KeeperTestSuite) TestDeleteValidator_AddressNotFound() { tc := s.SetupDeleteValidator() // Build message with a validator address that does not exist @@ -107,7 +107,7 @@ func (s *KeeperTestSuite) TestAddValidator_AddressNotFound() { s.Require().EqualError(err, errMsg) } -func (s *KeeperTestSuite) TestAddValidator_NonZeroDelegation() { +func (s *KeeperTestSuite) TestDeleteValidator_NonZeroDelegation() { tc := s.SetupDeleteValidator() // Update val1 to have a non-zero delegation @@ -122,7 +122,7 @@ func (s *KeeperTestSuite) TestAddValidator_NonZeroDelegation() { s.Require().EqualError(err, errMsg) } -func (s *KeeperTestSuite) TestAddValidator_NonZeroWeight() { +func (s *KeeperTestSuite) TestDeleteValidator_NonZeroWeight() { tc := s.SetupDeleteValidator() // Update val1 to have a non-zero weight diff --git a/x/stakeibc/proposal_handler.go b/x/stakeibc/proposal_handler.go new file mode 100644 index 0000000000..29e7e48a4e --- /dev/null +++ b/x/stakeibc/proposal_handler.go @@ -0,0 +1,27 @@ +package stakeibc + +import ( + sdk "github.com/cosmos/cosmos-sdk/types" + sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" + govtypes "github.com/cosmos/cosmos-sdk/x/gov/types" + + "github.com/Stride-Labs/stride/x/stakeibc/keeper" + + "github.com/Stride-Labs/stride/x/stakeibc/types" +) + +func NewStakeibcProposalHandler(k keeper.Keeper) govtypes.Handler { + return func(ctx sdk.Context, content govtypes.Content) error { + switch c := content.(type) { + case *types.AddValidatorProposal: + return handleAddValidatorProposal(ctx, k, c) + + default: + return sdkerrors.Wrapf(sdkerrors.ErrUnknownRequest, "unrecognized stakeibc proposal content type: %T", c) + } + } +} + +func handleAddValidatorProposal(ctx sdk.Context, k keeper.Keeper, proposal *types.AddValidatorProposal) error { + return k.AddValidatorProposal(ctx, proposal) +} diff --git a/x/stakeibc/types/codec.go b/x/stakeibc/types/codec.go index e80c98d859..bf5266be48 100644 --- a/x/stakeibc/types/codec.go +++ b/x/stakeibc/types/codec.go @@ -6,6 +6,7 @@ import ( cryptocodec "github.com/cosmos/cosmos-sdk/crypto/codec" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/types/msgservice" + govtypes "github.com/cosmos/cosmos-sdk/x/gov/types" ) func RegisterCodec(cdc *codec.LegacyAmino) { @@ -17,6 +18,7 @@ func RegisterCodec(cdc *codec.LegacyAmino) { cdc.RegisterConcrete(&MsgAddValidator{}, "stakeibc/AddValidator", nil) cdc.RegisterConcrete(&MsgChangeValidatorWeight{}, "stakeibc/ChangeValidatorWeight", nil) cdc.RegisterConcrete(&MsgDeleteValidator{}, "stakeibc/DeleteValidator", nil) + cdc.RegisterConcrete(&AddValidatorProposal{}, "stakeibc/AddValidatorProposal", nil) cdc.RegisterConcrete(&MsgRestoreInterchainAccount{}, "stakeibc/RestoreInterchainAccount", nil) cdc.RegisterConcrete(&MsgUpdateValidatorSharesExchRate{}, "stakeibc/UpdateValidatorSharesExchRate", nil) // this line is used by starport scaffolding # 2 @@ -36,6 +38,11 @@ func RegisterInterfaces(registry cdctypes.InterfaceRegistry) { &MsgRestoreInterchainAccount{}, &MsgUpdateValidatorSharesExchRate{}, ) + + registry.RegisterImplementations((*govtypes.Content)(nil), + &AddValidatorProposal{}, + ) + // this line is used by starport scaffolding # 3 msgservice.RegisterMsgServiceDesc(registry, &_Msg_serviceDesc) diff --git a/x/stakeibc/types/errors.go b/x/stakeibc/types/errors.go index b870a7448a..0621515297 100644 --- a/x/stakeibc/types/errors.go +++ b/x/stakeibc/types/errors.go @@ -46,4 +46,5 @@ var ( ErrInvalidEpoch = sdkerrors.Register(ModuleName, 1536, "invalid epoch tracker") ErrHostZoneICAAccountNotFound = sdkerrors.Register(ModuleName, 1537, "host zone's ICA account not found") ErrNoValidatorAmts = sdkerrors.Register(ModuleName, 1538, "could not fetch validator amts") + ErrMaxNumValidators = sdkerrors.Register(ModuleName, 1539, "max number of validators reached") ) diff --git a/x/stakeibc/types/gov.go b/x/stakeibc/types/gov.go new file mode 100644 index 0000000000..ffce1af2c5 --- /dev/null +++ b/x/stakeibc/types/gov.go @@ -0,0 +1,66 @@ +package types + +import ( + "fmt" + + govtypes "github.com/cosmos/cosmos-sdk/x/gov/types" +) + +const ( + ProposalTypeAddValidator = "AddValidator" +) + +func init() { + govtypes.RegisterProposalType(ProposalTypeAddValidator) + govtypes.RegisterProposalTypeCodec(&AddValidatorProposal{}, "stakeibc/AddValidatorProposal") +} + +var ( + _ govtypes.Content = &AddValidatorProposal{} +) + +func NewAddValidatorProposal(title, description, hostZone, name, address string) govtypes.Content { + return &AddValidatorProposal{ + Title: title, + Description: description, + HostZone: hostZone, + ValidatorName: name, + ValidatorAddress: address, + } +} + +func (p *AddValidatorProposal) GetTitle() string { return p.Title } + +func (p *AddValidatorProposal) GetDescription() string { return p.Description } + +func (p *AddValidatorProposal) ProposalRoute() string { return RouterKey } + +func (p *AddValidatorProposal) ProposalType() string { + return ProposalTypeAddValidator +} + +func (p *AddValidatorProposal) ValidateBasic() error { + err := govtypes.ValidateAbstract(p) + if err != nil { + return err + } + + if len(p.ValidatorAddress) == 0 { + return ErrRequiredFieldEmpty + } + if len(p.ValidatorName) == 0 { + return ErrRequiredFieldEmpty + } + + return nil +} + +func (p AddValidatorProposal) String() string { + return fmt.Sprintf(`Add Validator Proposal: + Title: %s + Description: %s + HostZone: %s + ValidatorName: %s + ValidatorAddress: %s + `, p.Title, p.Description, p.HostZone, p.ValidatorName, p.ValidatorAddress) +} diff --git a/x/stakeibc/types/gov.pb.go b/x/stakeibc/types/gov.pb.go new file mode 100644 index 0000000000..c73d565594 --- /dev/null +++ b/x/stakeibc/types/gov.pb.go @@ -0,0 +1,579 @@ +// Code generated by protoc-gen-gogo. DO NOT EDIT. +// source: stakeibc/gov.proto + +package types + +import ( + fmt "fmt" + _ "github.com/cosmos/cosmos-proto" + _ "github.com/gogo/protobuf/gogoproto" + proto "github.com/gogo/protobuf/proto" + io "io" + math "math" + math_bits "math/bits" +) + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the proto package it is being compiled against. +// A compilation error at this line likely means your copy of the +// proto package needs to be updated. +const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package + +type AddValidatorProposal struct { + Title string `protobuf:"bytes,1,opt,name=title,proto3" json:"title,omitempty"` + Description string `protobuf:"bytes,2,opt,name=description,proto3" json:"description,omitempty"` + HostZone string `protobuf:"bytes,3,opt,name=host_zone,json=hostZone,proto3" json:"host_zone,omitempty"` + ValidatorName string `protobuf:"bytes,4,opt,name=validator_name,json=validatorName,proto3" json:"validator_name,omitempty"` + ValidatorAddress string `protobuf:"bytes,5,opt,name=validator_address,json=validatorAddress,proto3" json:"validator_address,omitempty"` + Deposit string `protobuf:"bytes,6,opt,name=deposit,proto3" json:"deposit,omitempty" yaml:"deposit"` +} + +func (m *AddValidatorProposal) Reset() { *m = AddValidatorProposal{} } +func (*AddValidatorProposal) ProtoMessage() {} +func (*AddValidatorProposal) Descriptor() ([]byte, []int) { + return fileDescriptor_9a196ca60a38004b, []int{0} +} +func (m *AddValidatorProposal) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *AddValidatorProposal) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_AddValidatorProposal.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *AddValidatorProposal) XXX_Merge(src proto.Message) { + xxx_messageInfo_AddValidatorProposal.Merge(m, src) +} +func (m *AddValidatorProposal) XXX_Size() int { + return m.Size() +} +func (m *AddValidatorProposal) XXX_DiscardUnknown() { + xxx_messageInfo_AddValidatorProposal.DiscardUnknown(m) +} + +var xxx_messageInfo_AddValidatorProposal proto.InternalMessageInfo + +func init() { + proto.RegisterType((*AddValidatorProposal)(nil), "Stridelabs.stride.stakeibc.AddValidatorProposal") +} + +func init() { proto.RegisterFile("stakeibc/gov.proto", fileDescriptor_9a196ca60a38004b) } + +var fileDescriptor_9a196ca60a38004b = []byte{ + // 351 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x4c, 0x91, 0xb1, 0x4a, 0x2b, 0x41, + 0x14, 0x86, 0x77, 0x73, 0x6f, 0x72, 0x6f, 0xe6, 0x5e, 0x83, 0x0e, 0x5b, 0x8c, 0x11, 0x76, 0x43, + 0x40, 0xb0, 0x30, 0xbb, 0x85, 0x5d, 0xba, 0x04, 0x04, 0x0b, 0x11, 0x89, 0x60, 0x91, 0x26, 0xcc, + 0xee, 0x0c, 0x9b, 0xc1, 0xdd, 0x3d, 0xcb, 0xce, 0x18, 0x8c, 0x4f, 0x60, 0x69, 0x23, 0x58, 0xe6, + 0x21, 0x7c, 0x08, 0xcb, 0x60, 0x65, 0x25, 0x92, 0x34, 0xd6, 0x3e, 0x81, 0xec, 0x4c, 0x12, 0xed, + 0xce, 0xf9, 0xfe, 0xef, 0x30, 0xcc, 0x39, 0x08, 0x4b, 0x45, 0xaf, 0xb8, 0x08, 0xa3, 0x20, 0x86, + 0x89, 0x9f, 0x17, 0xa0, 0x00, 0x37, 0x2f, 0x54, 0x21, 0x18, 0x4f, 0x68, 0x28, 0x7d, 0xa9, 0x4b, + 0x7f, 0x6d, 0x35, 0x77, 0x23, 0x90, 0x29, 0xc8, 0x91, 0x36, 0x03, 0xd3, 0x98, 0xb1, 0xa6, 0x13, + 0x43, 0x0c, 0x86, 0x97, 0x95, 0xa1, 0xed, 0x87, 0x0a, 0x72, 0x7a, 0x8c, 0x5d, 0xd2, 0x44, 0x30, + 0xaa, 0xa0, 0x38, 0x2f, 0x20, 0x07, 0x49, 0x13, 0xec, 0xa0, 0xaa, 0x12, 0x2a, 0xe1, 0xc4, 0x6e, + 0xd9, 0x07, 0xf5, 0x81, 0x69, 0x70, 0x0b, 0xfd, 0x63, 0x5c, 0x46, 0x85, 0xc8, 0x95, 0x80, 0x8c, + 0x54, 0x74, 0xf6, 0x13, 0xe1, 0x3d, 0x54, 0x1f, 0x83, 0x54, 0xa3, 0x5b, 0xc8, 0x38, 0xf9, 0xa5, + 0xf3, 0xbf, 0x25, 0x18, 0x42, 0xc6, 0xf1, 0x3e, 0x6a, 0x4c, 0xd6, 0x2f, 0x8d, 0x32, 0x9a, 0x72, + 0xf2, 0x5b, 0x1b, 0x5b, 0x1b, 0x7a, 0x46, 0x53, 0x8e, 0x8f, 0xd1, 0xce, 0xb7, 0x46, 0x19, 0x2b, + 0xb8, 0x94, 0xa4, 0x5a, 0x9a, 0x7d, 0xf2, 0xf2, 0xd4, 0x71, 0x56, 0xff, 0xea, 0x99, 0xa4, 0x5c, + 0x47, 0x16, 0x0f, 0xb6, 0x37, 0x23, 0x2b, 0x8e, 0x0f, 0xd1, 0x1f, 0xc6, 0x73, 0x90, 0x42, 0x91, + 0x9a, 0x1e, 0xc6, 0x9f, 0x6f, 0x5e, 0x63, 0x4a, 0xd3, 0xa4, 0xdb, 0x5e, 0x05, 0xed, 0xc1, 0x5a, + 0xe9, 0xfe, 0xbf, 0x9b, 0x79, 0xd6, 0xe3, 0xcc, 0xb3, 0x3e, 0x66, 0x9e, 0xdd, 0x3f, 0x79, 0x5e, + 0xb8, 0xf6, 0x7c, 0xe1, 0xda, 0xef, 0x0b, 0xd7, 0xbe, 0x5f, 0xba, 0xd6, 0x7c, 0xe9, 0x5a, 0xaf, + 0x4b, 0xd7, 0x1a, 0xfa, 0xb1, 0x50, 0xe3, 0xeb, 0xd0, 0x8f, 0x20, 0x0d, 0xcc, 0x25, 0x3a, 0xa7, + 0x34, 0x94, 0x81, 0x39, 0x45, 0x70, 0x13, 0x6c, 0x4e, 0xa6, 0xa6, 0x39, 0x97, 0x61, 0x4d, 0x2f, + 0xfa, 0xe8, 0x2b, 0x00, 0x00, 0xff, 0xff, 0x3a, 0x78, 0x29, 0xee, 0xcb, 0x01, 0x00, 0x00, +} + +func (this *AddValidatorProposal) Equal(that interface{}) bool { + if that == nil { + return this == nil + } + + that1, ok := that.(*AddValidatorProposal) + if !ok { + that2, ok := that.(AddValidatorProposal) + if ok { + that1 = &that2 + } else { + return false + } + } + if that1 == nil { + return this == nil + } else if this == nil { + return false + } + if this.Title != that1.Title { + return false + } + if this.Description != that1.Description { + return false + } + if this.HostZone != that1.HostZone { + return false + } + if this.ValidatorName != that1.ValidatorName { + return false + } + if this.ValidatorAddress != that1.ValidatorAddress { + return false + } + if this.Deposit != that1.Deposit { + return false + } + return true +} +func (m *AddValidatorProposal) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *AddValidatorProposal) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *AddValidatorProposal) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.Deposit) > 0 { + i -= len(m.Deposit) + copy(dAtA[i:], m.Deposit) + i = encodeVarintGov(dAtA, i, uint64(len(m.Deposit))) + i-- + dAtA[i] = 0x32 + } + if len(m.ValidatorAddress) > 0 { + i -= len(m.ValidatorAddress) + copy(dAtA[i:], m.ValidatorAddress) + i = encodeVarintGov(dAtA, i, uint64(len(m.ValidatorAddress))) + i-- + dAtA[i] = 0x2a + } + if len(m.ValidatorName) > 0 { + i -= len(m.ValidatorName) + copy(dAtA[i:], m.ValidatorName) + i = encodeVarintGov(dAtA, i, uint64(len(m.ValidatorName))) + i-- + dAtA[i] = 0x22 + } + if len(m.HostZone) > 0 { + i -= len(m.HostZone) + copy(dAtA[i:], m.HostZone) + i = encodeVarintGov(dAtA, i, uint64(len(m.HostZone))) + i-- + dAtA[i] = 0x1a + } + if len(m.Description) > 0 { + i -= len(m.Description) + copy(dAtA[i:], m.Description) + i = encodeVarintGov(dAtA, i, uint64(len(m.Description))) + i-- + dAtA[i] = 0x12 + } + if len(m.Title) > 0 { + i -= len(m.Title) + copy(dAtA[i:], m.Title) + i = encodeVarintGov(dAtA, i, uint64(len(m.Title))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func encodeVarintGov(dAtA []byte, offset int, v uint64) int { + offset -= sovGov(v) + base := offset + for v >= 1<<7 { + dAtA[offset] = uint8(v&0x7f | 0x80) + v >>= 7 + offset++ + } + dAtA[offset] = uint8(v) + return base +} +func (m *AddValidatorProposal) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Title) + if l > 0 { + n += 1 + l + sovGov(uint64(l)) + } + l = len(m.Description) + if l > 0 { + n += 1 + l + sovGov(uint64(l)) + } + l = len(m.HostZone) + if l > 0 { + n += 1 + l + sovGov(uint64(l)) + } + l = len(m.ValidatorName) + if l > 0 { + n += 1 + l + sovGov(uint64(l)) + } + l = len(m.ValidatorAddress) + if l > 0 { + n += 1 + l + sovGov(uint64(l)) + } + l = len(m.Deposit) + if l > 0 { + n += 1 + l + sovGov(uint64(l)) + } + return n +} + +func sovGov(x uint64) (n int) { + return (math_bits.Len64(x|1) + 6) / 7 +} +func sozGov(x uint64) (n int) { + return sovGov(uint64((x << 1) ^ uint64((int64(x) >> 63)))) +} +func (m *AddValidatorProposal) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGov + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: AddValidatorProposal: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: AddValidatorProposal: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Title", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGov + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthGov + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthGov + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Title = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Description", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGov + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthGov + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthGov + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Description = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field HostZone", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGov + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthGov + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthGov + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.HostZone = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 4: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ValidatorName", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGov + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthGov + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthGov + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.ValidatorName = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 5: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ValidatorAddress", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGov + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthGov + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthGov + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.ValidatorAddress = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 6: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Deposit", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGov + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthGov + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthGov + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Deposit = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipGov(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthGov + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func skipGov(dAtA []byte) (n int, err error) { + l := len(dAtA) + iNdEx := 0 + depth := 0 + for iNdEx < l { + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowGov + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + wireType := int(wire & 0x7) + switch wireType { + case 0: + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowGov + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + iNdEx++ + if dAtA[iNdEx-1] < 0x80 { + break + } + } + case 1: + iNdEx += 8 + case 2: + var length int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowGov + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + length |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if length < 0 { + return 0, ErrInvalidLengthGov + } + iNdEx += length + case 3: + depth++ + case 4: + if depth == 0 { + return 0, ErrUnexpectedEndOfGroupGov + } + depth-- + case 5: + iNdEx += 4 + default: + return 0, fmt.Errorf("proto: illegal wireType %d", wireType) + } + if iNdEx < 0 { + return 0, ErrInvalidLengthGov + } + if depth == 0 { + return iNdEx, nil + } + } + return 0, io.ErrUnexpectedEOF +} + +var ( + ErrInvalidLengthGov = fmt.Errorf("proto: negative length found during unmarshaling") + ErrIntOverflowGov = fmt.Errorf("proto: integer overflow") + ErrUnexpectedEndOfGroupGov = fmt.Errorf("proto: unexpected end of group") +) diff --git a/x/stakeibc/types/params.go b/x/stakeibc/types/params.go index d5ce69ca68..11bdbac30a 100644 --- a/x/stakeibc/types/params.go +++ b/x/stakeibc/types/params.go @@ -26,6 +26,7 @@ var ( DefaultSafetyMaxRedemptionRateThreshold uint64 = 150 // divide by 100, so 150 = 1.5 DefaultMaxStakeICACallsPerEpoch uint64 = 100 DefaultIBCTransferTimeoutNanos uint64 = 1800000000000 // 30 minutes + DefaultSafetyNumValidators uint64 = 35 // KeyDepositInterval is store's key for the DepositInterval option KeyDepositInterval = []byte("DepositInterval") @@ -43,6 +44,7 @@ var ( KeySafetyMaxRedemptionRateThreshold = []byte("SafetyMaxRedemptionRateThreshold") KeyMaxStakeICACallsPerEpoch = []byte("MaxStakeICACallsPerEpoch") KeyIBCTransferTimeoutNanos = []byte("IBCTransferTimeoutNanos") + KeySafetyNumValidators = []byte("SafetyNumValidators") ) var _ paramtypes.ParamSet = (*Params)(nil) @@ -69,6 +71,7 @@ func NewParams( safety_min_redemption_rate_threshold uint64, safety_max_redemption_rate_threshold uint64, ibc_transfer_timeout_nanos uint64, + safety_num_validators uint64, ) Params { return Params{ DepositInterval: deposit_interval, @@ -86,6 +89,7 @@ func NewParams( SafetyMinRedemptionRateThreshold: safety_min_redemption_rate_threshold, SafetyMaxRedemptionRateThreshold: safety_max_redemption_rate_threshold, IbcTransferTimeoutNanos: ibc_transfer_timeout_nanos, + SafetyNumValidators: safety_num_validators, } } @@ -107,6 +111,7 @@ func DefaultParams() Params { DefaultSafetyMinRedemptionRateThreshold, DefaultSafetyMaxRedemptionRateThreshold, DefaultIBCTransferTimeoutNanos, + DefaultSafetyNumValidators, ) } @@ -128,6 +133,7 @@ func (p *Params) ParamSetPairs() paramtypes.ParamSetPairs { paramtypes.NewParamSetPair(KeySafetyMinRedemptionRateThreshold, &p.SafetyMinRedemptionRateThreshold, validMinRedemptionRateThreshold), paramtypes.NewParamSetPair(KeySafetyMaxRedemptionRateThreshold, &p.SafetyMaxRedemptionRateThreshold, validMaxRedemptionRateThreshold), paramtypes.NewParamSetPair(KeyIBCTransferTimeoutNanos, &p.IbcTransferTimeoutNanos, validTimeoutNanos), + paramtypes.NewParamSetPair(KeySafetyNumValidators, &p.SafetyNumValidators, isPositive), } } diff --git a/x/stakeibc/types/params.pb.go b/x/stakeibc/types/params.pb.go index 21bb3cb529..a6276e1ed8 100644 --- a/x/stakeibc/types/params.pb.go +++ b/x/stakeibc/types/params.pb.go @@ -24,7 +24,7 @@ var _ = math.Inf const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package // Params defines the parameters for the module. -// next id: 16 +// next id: 18 type Params struct { // define epoch lengths, in stride_epochs RewardsInterval uint64 `protobuf:"varint,1,opt,name=rewards_interval,json=rewardsInterval,proto3" json:"rewards_interval,omitempty"` @@ -47,6 +47,7 @@ type Params struct { SafetyMinRedemptionRateThreshold uint64 `protobuf:"varint,14,opt,name=safety_min_redemption_rate_threshold,json=safetyMinRedemptionRateThreshold,proto3" json:"safety_min_redemption_rate_threshold,omitempty"` SafetyMaxRedemptionRateThreshold uint64 `protobuf:"varint,15,opt,name=safety_max_redemption_rate_threshold,json=safetyMaxRedemptionRateThreshold,proto3" json:"safety_max_redemption_rate_threshold,omitempty"` IbcTransferTimeoutNanos uint64 `protobuf:"varint,16,opt,name=ibc_transfer_timeout_nanos,json=ibcTransferTimeoutNanos,proto3" json:"ibc_transfer_timeout_nanos,omitempty"` + SafetyNumValidators uint64 `protobuf:"varint,17,opt,name=safety_num_validators,json=safetyNumValidators,proto3" json:"safety_num_validators,omitempty"` } func (m *Params) Reset() { *m = Params{} } @@ -193,6 +194,13 @@ func (m *Params) GetIbcTransferTimeoutNanos() uint64 { return 0 } +func (m *Params) GetSafetyNumValidators() uint64 { + if m != nil { + return m.SafetyNumValidators + } + return 0 +} + func init() { proto.RegisterType((*Params)(nil), "Stridelabs.stride.stakeibc.Params") proto.RegisterMapType((map[string]string)(nil), "Stridelabs.stride.stakeibc.Params.ZoneComAddressEntry") @@ -201,46 +209,47 @@ func init() { func init() { proto.RegisterFile("stakeibc/params.proto", fileDescriptor_41f5fe1d2f7ac763) } var fileDescriptor_41f5fe1d2f7ac763 = []byte{ - // 615 bytes of a gzipped FileDescriptorProto + // 638 bytes of a gzipped FileDescriptorProto 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x7c, 0x94, 0xcf, 0x4f, 0x13, 0x41, - 0x14, 0xc7, 0x5b, 0x7e, 0xca, 0xa0, 0x50, 0x56, 0xd4, 0x4d, 0x13, 0x0a, 0x31, 0x1e, 0x40, 0x74, - 0x9b, 0x68, 0x62, 0x08, 0x1c, 0x0c, 0x10, 0x8c, 0x24, 0x4a, 0xc8, 0xc2, 0x89, 0xcb, 0xf8, 0x76, - 0xf6, 0xb5, 0x9d, 0xb0, 0x3b, 0xb3, 0x99, 0x99, 0xd6, 0xb6, 0x7f, 0x85, 0x47, 0x8f, 0xfe, 0x39, - 0x1e, 0x39, 0x7a, 0x34, 0x70, 0xf1, 0xcf, 0x30, 0x3b, 0xd3, 0x6e, 0x59, 0x03, 0xde, 0xa6, 0xdf, - 0xf7, 0x79, 0xdf, 0xbe, 0xf9, 0xe6, 0xcd, 0x92, 0x27, 0xda, 0xc0, 0x25, 0xf2, 0x88, 0x35, 0x33, - 0x50, 0x90, 0xea, 0x20, 0x53, 0xd2, 0x48, 0xaf, 0x7e, 0x66, 0x14, 0x8f, 0x31, 0x81, 0x48, 0x07, - 0xda, 0x1e, 0x83, 0x31, 0x58, 0x5f, 0x6d, 0xcb, 0xb6, 0xb4, 0x58, 0x33, 0x3f, 0xb9, 0x8e, 0xe7, - 0x7f, 0xe6, 0xc9, 0xdc, 0xa9, 0xb5, 0xf0, 0xb6, 0x48, 0x4d, 0xe1, 0x57, 0x50, 0xb1, 0xa6, 0x5c, - 0x18, 0x54, 0x3d, 0x48, 0xfc, 0xea, 0x46, 0x75, 0x73, 0x26, 0x5c, 0x1e, 0xe9, 0xc7, 0x23, 0xd9, - 0xdb, 0x26, 0x2b, 0x31, 0x26, 0xd8, 0x06, 0x83, 0x13, 0x76, 0xce, 0xb2, 0xb5, 0x71, 0xa1, 0x80, - 0xb7, 0x48, 0x2d, 0xc6, 0x4c, 0x6a, 0x6e, 0x26, 0xec, 0x94, 0xf3, 0x1d, 0xe9, 0x05, 0xba, 0x43, - 0x7c, 0x85, 0x31, 0xa6, 0x99, 0xe1, 0x52, 0x50, 0x55, 0xb2, 0x9f, 0xb6, 0x2d, 0x4f, 0x27, 0xf5, - 0xf0, 0xf6, 0x9f, 0x6c, 0x93, 0x15, 0x77, 0x61, 0xca, 0x64, 0x9a, 0x72, 0xad, 0xb9, 0x14, 0xfe, - 0x8c, 0x9b, 0xc8, 0x15, 0x0e, 0x0b, 0xdd, 0xfb, 0x42, 0x6a, 0x43, 0x29, 0x2c, 0x4a, 0x21, 0x8e, - 0x15, 0x6a, 0xed, 0xcf, 0x6e, 0x4c, 0x6f, 0x2e, 0xbe, 0x79, 0x17, 0xdc, 0x9f, 0x60, 0xe0, 0x72, - 0x0a, 0x2e, 0xa4, 0xc8, 0xcd, 0xf6, 0x5d, 0xe3, 0x91, 0x30, 0x6a, 0x10, 0x2e, 0x0d, 0x4b, 0x62, - 0x3e, 0x8e, 0x42, 0x2e, 0x7a, 0xa8, 0x6f, 0x5d, 0x7a, 0xde, 0x8d, 0x33, 0x2e, 0x14, 0xb3, 0x7f, - 0x20, 0xeb, 0x3d, 0x48, 0x78, 0x0c, 0x46, 0x2a, 0xaa, 0x30, 0x82, 0x04, 0x04, 0xe3, 0xa2, 0x4d, - 0x4d, 0x47, 0xa1, 0xee, 0xc8, 0x24, 0xf6, 0x1f, 0xd8, 0xd6, 0xb5, 0x02, 0x0b, 0x27, 0xd4, 0xf9, - 0x18, 0xf2, 0x5e, 0x92, 0x15, 0xce, 0x80, 0x1a, 0x9e, 0xa2, 0xec, 0x1a, 0x2a, 0x40, 0x48, 0xed, - 0x2f, 0xb8, 0xa4, 0x39, 0x83, 0x73, 0xa7, 0x9f, 0xe4, 0xb2, 0xb7, 0x4e, 0x16, 0xa3, 0x6e, 0xab, - 0x85, 0x8a, 0x6a, 0x3e, 0x44, 0x9f, 0x58, 0x8a, 0x38, 0xe9, 0x8c, 0x0f, 0xd1, 0x7b, 0x45, 0x3c, - 0x1e, 0xb1, 0xc2, 0x2c, 0x4a, 0x24, 0xbb, 0xd4, 0xfe, 0xa2, 0xbb, 0x02, 0x8f, 0xd8, 0xc8, 0xed, - 0xc0, 0xea, 0xde, 0x1e, 0xa9, 0xb7, 0x10, 0xa9, 0x51, 0x20, 0x74, 0x6e, 0x5a, 0x9e, 0xe1, 0xa1, - 0xed, 0x7a, 0xd6, 0x42, 0x3c, 0x1f, 0x01, 0xa5, 0x59, 0xde, 0x93, 0xb5, 0x14, 0xfa, 0xd4, 0xe6, - 0x4c, 0xf3, 0x1b, 0x30, 0x48, 0x12, 0x4d, 0x33, 0x54, 0x14, 0x33, 0xc9, 0x3a, 0xfe, 0x23, 0xdb, - 0xef, 0xa7, 0xd0, 0x3f, 0xcb, 0x99, 0x63, 0x06, 0x87, 0x39, 0x71, 0x8a, 0xea, 0x28, 0xaf, 0x7b, - 0x27, 0xe4, 0x85, 0x86, 0x16, 0x9a, 0x01, 0x4d, 0xb9, 0xa0, 0xff, 0x6e, 0xd0, 0x24, 0xc5, 0x25, - 0xeb, 0xb3, 0xe1, 0xd8, 0xcf, 0x5c, 0x84, 0xa5, 0x5d, 0x9a, 0x04, 0x79, 0xcb, 0x0f, 0xfa, 0xff, - 0xf1, 0x5b, 0x2e, 0xf9, 0x41, 0xff, 0x3e, 0xbf, 0x3d, 0x52, 0xb7, 0x59, 0xde, 0x9d, 0x4e, 0xcd, - 0xa5, 0x93, 0x67, 0x7a, 0x47, 0x3a, 0xf5, 0x7d, 0xf2, 0xf8, 0x8e, 0x8d, 0xf3, 0x6a, 0x64, 0xfa, - 0x12, 0x07, 0xf6, 0x81, 0x2e, 0x84, 0xf9, 0xd1, 0x5b, 0x25, 0xb3, 0x3d, 0x48, 0xba, 0x68, 0x1f, - 0xd7, 0x42, 0xe8, 0x7e, 0xec, 0x4e, 0xed, 0x54, 0x77, 0x67, 0xbe, 0xff, 0x58, 0xaf, 0x1c, 0x7c, - 0xfc, 0x79, 0xdd, 0xa8, 0x5e, 0x5d, 0x37, 0xaa, 0xbf, 0xaf, 0x1b, 0xd5, 0x6f, 0x37, 0x8d, 0xca, - 0xd5, 0x4d, 0xa3, 0xf2, 0xeb, 0xa6, 0x51, 0xb9, 0x08, 0xda, 0xdc, 0x74, 0xba, 0x51, 0xc0, 0x64, - 0xda, 0x74, 0xfb, 0xff, 0xfa, 0x13, 0x44, 0xba, 0xe9, 0x1e, 0x40, 0xb3, 0xdf, 0x2c, 0xbe, 0x36, - 0x66, 0x90, 0xa1, 0x8e, 0xe6, 0xec, 0xb7, 0xe3, 0xed, 0xdf, 0x00, 0x00, 0x00, 0xff, 0xff, 0xc9, - 0xda, 0xf5, 0x09, 0x86, 0x04, 0x00, 0x00, + 0x14, 0xc7, 0x5b, 0x7e, 0x09, 0x83, 0x42, 0xbb, 0x80, 0x6e, 0x9a, 0x50, 0x88, 0xf1, 0x00, 0xa2, + 0xdb, 0x04, 0x13, 0x43, 0xe0, 0x60, 0x80, 0x60, 0x24, 0x51, 0x42, 0x16, 0xe2, 0x81, 0xcb, 0xf8, + 0x76, 0xf7, 0xb5, 0x9d, 0xb0, 0x3b, 0xb3, 0x99, 0x99, 0xd6, 0xb6, 0x7f, 0x85, 0x47, 0x0f, 0x1e, + 0xfc, 0x73, 0x3c, 0x72, 0xf4, 0x68, 0xe0, 0x1f, 0x31, 0x3b, 0xd3, 0x6e, 0x59, 0x53, 0xbc, 0x4d, + 0xbf, 0xef, 0xf3, 0xbe, 0x7d, 0xf3, 0xcd, 0xbc, 0x25, 0x6b, 0x4a, 0xc3, 0x35, 0xb2, 0x20, 0x6c, + 0xa4, 0x20, 0x21, 0x51, 0x5e, 0x2a, 0x85, 0x16, 0x4e, 0xed, 0x42, 0x4b, 0x16, 0x61, 0x0c, 0x81, + 0xf2, 0x94, 0x39, 0x7a, 0x23, 0xb0, 0xb6, 0xda, 0x12, 0x2d, 0x61, 0xb0, 0x46, 0x76, 0xb2, 0x1d, + 0xcf, 0x7f, 0xcc, 0x93, 0xb9, 0x73, 0x63, 0xe1, 0x6c, 0x93, 0x8a, 0xc4, 0xaf, 0x20, 0x23, 0x45, + 0x19, 0xd7, 0x28, 0xbb, 0x10, 0xbb, 0xe5, 0xcd, 0xf2, 0xd6, 0x8c, 0xbf, 0x3c, 0xd4, 0x4f, 0x87, + 0xb2, 0xb3, 0x43, 0xaa, 0x11, 0xc6, 0xd8, 0x02, 0x8d, 0x63, 0x76, 0xce, 0xb0, 0x95, 0x51, 0x21, + 0x87, 0xb7, 0x49, 0x25, 0xc2, 0x54, 0x28, 0xa6, 0xc7, 0xec, 0x94, 0xf5, 0x1d, 0xea, 0x39, 0xba, + 0x47, 0x5c, 0x89, 0x11, 0x26, 0xa9, 0x66, 0x82, 0x53, 0x59, 0xb0, 0x9f, 0x36, 0x2d, 0x4f, 0xc7, + 0x75, 0xff, 0xfe, 0x9f, 0xec, 0x90, 0xaa, 0xbd, 0x30, 0x0d, 0x45, 0x92, 0x30, 0xa5, 0x98, 0xe0, + 0xee, 0x8c, 0x9d, 0xc8, 0x16, 0x8e, 0x73, 0xdd, 0xf9, 0x42, 0x2a, 0x03, 0xc1, 0x0d, 0x4a, 0x21, + 0x8a, 0x24, 0x2a, 0xe5, 0xce, 0x6e, 0x4e, 0x6f, 0x2d, 0xee, 0xbe, 0xf5, 0x1e, 0x4e, 0xd0, 0xb3, + 0x39, 0x79, 0x57, 0x82, 0x67, 0x66, 0x87, 0xb6, 0xf1, 0x84, 0x6b, 0xd9, 0xf7, 0x97, 0x06, 0x05, + 0x31, 0x1b, 0x47, 0x22, 0xe3, 0x5d, 0x54, 0xf7, 0x2e, 0xfd, 0xc8, 0x8e, 0x33, 0x2a, 0xe4, 0xb3, + 0xbf, 0x27, 0x1b, 0x5d, 0x88, 0x59, 0x04, 0x5a, 0x48, 0x2a, 0x31, 0x80, 0x18, 0x78, 0xc8, 0x78, + 0x8b, 0xea, 0xb6, 0x44, 0xd5, 0x16, 0x71, 0xe4, 0xce, 0x9b, 0xd6, 0xf5, 0x1c, 0xf3, 0xc7, 0xd4, + 0xe5, 0x08, 0x72, 0x5e, 0x92, 0x2a, 0x0b, 0x81, 0x6a, 0x96, 0xa0, 0xe8, 0x68, 0xca, 0x81, 0x0b, + 0xe5, 0x2e, 0xd8, 0xa4, 0x59, 0x08, 0x97, 0x56, 0x3f, 0xcb, 0x64, 0x67, 0x83, 0x2c, 0x06, 0x9d, + 0x66, 0x13, 0x25, 0x55, 0x6c, 0x80, 0x2e, 0x31, 0x14, 0xb1, 0xd2, 0x05, 0x1b, 0xa0, 0xf3, 0x8a, + 0x38, 0x2c, 0x08, 0x73, 0xb3, 0x20, 0x16, 0xe1, 0xb5, 0x72, 0x17, 0xed, 0x15, 0x58, 0x10, 0x0e, + 0xdd, 0x8e, 0x8c, 0xee, 0x1c, 0x90, 0x5a, 0x13, 0x91, 0x6a, 0x09, 0x5c, 0x65, 0xa6, 0xc5, 0x19, + 0x1e, 0x9b, 0xae, 0x67, 0x4d, 0xc4, 0xcb, 0x21, 0x50, 0x98, 0xe5, 0x1d, 0x59, 0x4f, 0xa0, 0x47, + 0x4d, 0xce, 0x34, 0xbb, 0x41, 0x08, 0x71, 0xac, 0x68, 0x8a, 0x92, 0x62, 0x2a, 0xc2, 0xb6, 0xfb, + 0xc4, 0xf4, 0xbb, 0x09, 0xf4, 0x2e, 0x32, 0xe6, 0x34, 0x84, 0xe3, 0x8c, 0x38, 0x47, 0x79, 0x92, + 0xd5, 0x9d, 0x33, 0xf2, 0x42, 0x41, 0x13, 0x75, 0x9f, 0x26, 0x8c, 0xd3, 0x7f, 0x5f, 0xd0, 0x38, + 0xc5, 0x25, 0xe3, 0xb3, 0x69, 0xd9, 0x4f, 0x8c, 0xfb, 0x85, 0xb7, 0x34, 0x0e, 0xf2, 0x9e, 0x1f, + 0xf4, 0xfe, 0xe3, 0xb7, 0x5c, 0xf0, 0x83, 0xde, 0x43, 0x7e, 0x07, 0xa4, 0x66, 0xb2, 0x9c, 0x9c, + 0x4e, 0xc5, 0xa6, 0x93, 0x65, 0x3a, 0x29, 0x9d, 0x5d, 0xb2, 0x36, 0x1c, 0x86, 0x77, 0x12, 0x9a, + 0xbf, 0x00, 0xe5, 0x56, 0x4d, 0xdf, 0x8a, 0x2d, 0x9e, 0x75, 0x92, 0xcf, 0x79, 0xa9, 0x76, 0x48, + 0x56, 0x26, 0xbc, 0x52, 0xa7, 0x42, 0xa6, 0xaf, 0xb1, 0x6f, 0x96, 0x7a, 0xc1, 0xcf, 0x8e, 0xce, + 0x2a, 0x99, 0xed, 0x42, 0xdc, 0x41, 0xb3, 0x90, 0x0b, 0xbe, 0xfd, 0xb1, 0x3f, 0xb5, 0x57, 0xde, + 0x9f, 0xf9, 0xfe, 0x73, 0xa3, 0x74, 0xf4, 0xe1, 0xd7, 0x6d, 0xbd, 0x7c, 0x73, 0x5b, 0x2f, 0xff, + 0xb9, 0xad, 0x97, 0xbf, 0xdd, 0xd5, 0x4b, 0x37, 0x77, 0xf5, 0xd2, 0xef, 0xbb, 0x7a, 0xe9, 0xca, + 0x6b, 0x31, 0xdd, 0xee, 0x04, 0x5e, 0x28, 0x92, 0x86, 0xdd, 0x99, 0xd7, 0x1f, 0x21, 0x50, 0x0d, + 0xbb, 0x34, 0x8d, 0x5e, 0x23, 0xff, 0x42, 0xe9, 0x7e, 0x8a, 0x2a, 0x98, 0x33, 0xdf, 0x9b, 0x37, + 0x7f, 0x03, 0x00, 0x00, 0xff, 0xff, 0x04, 0xcc, 0xfd, 0xae, 0xba, 0x04, 0x00, 0x00, } func (m *Params) Marshal() (dAtA []byte, err error) { @@ -263,6 +272,13 @@ func (m *Params) MarshalToSizedBuffer(dAtA []byte) (int, error) { _ = i var l int _ = l + if m.SafetyNumValidators != 0 { + i = encodeVarintParams(dAtA, i, uint64(m.SafetyNumValidators)) + i-- + dAtA[i] = 0x1 + i-- + dAtA[i] = 0x88 + } if m.IbcTransferTimeoutNanos != 0 { i = encodeVarintParams(dAtA, i, uint64(m.IbcTransferTimeoutNanos)) i-- @@ -432,6 +448,9 @@ func (m *Params) Size() (n int) { if m.IbcTransferTimeoutNanos != 0 { n += 2 + sovParams(uint64(m.IbcTransferTimeoutNanos)) } + if m.SafetyNumValidators != 0 { + n += 2 + sovParams(uint64(m.SafetyNumValidators)) + } return n } @@ -882,6 +901,25 @@ func (m *Params) Unmarshal(dAtA []byte) error { break } } + case 17: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field SafetyNumValidators", wireType) + } + m.SafetyNumValidators = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowParams + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.SafetyNumValidators |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } default: iNdEx = preIndex skippy, err := skipParams(dAtA[iNdEx:])