From 5e9656f363a0b8e1e00a58aaeee3c0a8c1e1561b Mon Sep 17 00:00:00 2001 From: Marko Date: Tue, 22 Mar 2022 01:24:28 +0100 Subject: [PATCH] feat: staking config (#10988) ## Description staking config to remove DefaultPowerReduction global. I want to see if this would be accepted as its easier to document and show users how to do this. --- ### Author Checklist *All items are required. Please add a note to the item if the item is not applicable and please add links to any relevant follow up issues.* I have... - [ ] included the correct [type prefix](https://github.com/commitizen/conventional-commit-types/blob/v3.0.0/index.json) in the PR title - [ ] added `!` to the type prefix if API or client breaking change - [ ] targeted the correct branch (see [PR Targeting](https://github.com/cosmos/cosmos-sdk/blob/master/CONTRIBUTING.md#pr-targeting)) - [ ] provided a link to the relevant issue or specification - [ ] followed the guidelines for [building modules](https://github.com/cosmos/cosmos-sdk/blob/master/docs/building-modules) - [ ] included the necessary unit and integration [tests](https://github.com/cosmos/cosmos-sdk/blob/master/CONTRIBUTING.md#testing) - [ ] added a changelog entry to `CHANGELOG.md` - [ ] included comments for [documenting Go code](https://blog.golang.org/godoc) - [ ] updated the relevant documentation or specification - [ ] reviewed "Files changed" and left comments if necessary - [ ] confirmed all CI checks have passed ### Reviewers Checklist *All items are required. Please add a note if the item is not applicable and please add your handle next to the items reviewed if you only reviewed selected items.* I have... - [ ] confirmed the correct [type prefix](https://github.com/commitizen/conventional-commit-types/blob/v3.0.0/index.json) in the PR title - [ ] confirmed `!` in the type prefix if API or client breaking change - [ ] confirmed all author checklist items have been addressed - [ ] reviewed state machine logic - [ ] reviewed API design and naming - [ ] reviewed documentation is accurate - [ ] reviewed tests and test coverage - [ ] manually tested (if applicable) --- CHANGELOG.md | 3 +- doc/proto-docs.md | 99 ------------------------ simapp/app.go | 8 +- simapp/simd/cmd/testnet.go | 6 +- simapp/test_helpers.go | 2 +- testutil/network/network.go | 6 +- testutil/token.go | 28 +++++++ types/{staking.go => globals.go} | 13 ---- types/module/module.go | 2 +- types/staking_test.go | 26 ------- x/auth/client/testutil/suite.go | 4 +- x/auth/migrations/v043/store_test.go | 4 +- x/bank/keeper/grpc_query_test.go | 3 +- x/bank/keeper/keeper_test.go | 4 +- x/bank/types/balance_test.go | 8 +- x/evidence/keeper/keeper_test.go | 6 +- x/feegrant/simulation/operations_test.go | 3 +- x/gov/abci_test.go | 3 +- x/gov/common_test.go | 3 +- x/gov/keeper/common_test.go | 1 + x/group/simulation/operations_test.go | 3 +- x/slashing/abci_test.go | 2 + x/slashing/app_test.go | 5 +- x/slashing/init_test.go | 10 --- x/slashing/keeper/common_test.go | 8 -- x/slashing/keeper/keeper_test.go | 2 + x/staking/app_test.go | 4 +- x/staking/client/cli/tx.go | 2 +- x/staking/common_test.go | 6 +- x/staking/keeper/common_test.go | 8 +- x/staking/keeper/grpc_query_test.go | 1 + x/staking/keeper/keeper.go | 4 +- x/staking/keeper/params.go | 7 +- x/staking/keeper/power_reduction.go | 5 +- x/staking/keeper/power_reduction_test.go | 6 +- x/staking/migrations/v040/keys.go | 2 +- x/staking/migrations/v043/store_test.go | 2 +- x/staking/simulation/common_test.go | 11 --- x/staking/simulation/operations_test.go | 2 +- x/staking/types/config.go | 17 ++++ x/staking/types/historical_info_test.go | 5 +- x/staking/types/keys.go | 2 +- x/staking/types/keys_test.go | 8 +- x/staking/types/power_reduction.go | 26 +++++++ x/staking/types/power_reduction_test.go | 34 ++++++++ x/staking/types/validator.go | 2 +- x/staking/types/validator_test.go | 12 +-- 47 files changed, 190 insertions(+), 238 deletions(-) delete mode 100644 doc/proto-docs.md create mode 100644 testutil/token.go rename types/{staking.go => globals.go} (56%) delete mode 100644 types/staking_test.go delete mode 100644 x/slashing/init_test.go delete mode 100644 x/slashing/keeper/common_test.go delete mode 100644 x/staking/simulation/common_test.go create mode 100644 x/staking/types/config.go create mode 100644 x/staking/types/power_reduction.go create mode 100644 x/staking/types/power_reduction_test.go diff --git a/CHANGELOG.md b/CHANGELOG.md index 56d13262093c..b21174619c22 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -140,9 +140,10 @@ Ref: https://keepachangelog.com/en/1.0.0/ * [\#11124](https://github.com/cosmos/cosmos-sdk/pull/11124) Add `GetAllVersions` to application store * (x/authz) [\#10447](https://github.com/cosmos/cosmos-sdk/pull/10447) authz `NewGrant` takes a new argument: block time, to correctly validate expire time. * [\#10961](https://github.com/cosmos/cosmos-sdk/pull/10961) Support third-party modules to add extension snapshots to state-sync. +* [\#10988](https://github.com/cosmos/cosmos-sdk/pull/10988) Removes sdk.PowerReduction as a global and pass it directly to the staking keeper on creation. + - Deletes `types/staking.go` and moves the functions to `x/staking/types/power_reduction.go` * [\#11274](https://github.com/cosmos/cosmos-sdk/pull/11274) `types/errors.New` now is an alias for `types/errors.Register` and should only be used in initialization code. - ### Client Breaking Changes * [\#11089](https://github.com/cosmos/cosmos-sdk/pull/11089]) interacting with the node through `grpc.Dial` requires clients to pass a codec refer to [doc](docs/run-node/interact-node.md). diff --git a/doc/proto-docs.md b/doc/proto-docs.md deleted file mode 100644 index 32c76e260cb2..000000000000 --- a/doc/proto-docs.md +++ /dev/null @@ -1,99 +0,0 @@ - -# Protobuf Documentation - - - -## Table of Contents - -* [cosmos/base/query/v1beta1/pagination.proto](#cosmosbasequeryv1beta1paginationproto) - * [PageRequest](#pagerequest) - * [PageResponse](#pageresponse) -* [Scalar Value Types](#scalar-value-types) - - -

Top

- -## cosmos/base/query/v1beta1/pagination.proto - - - - - -### PageRequest - -PageRequest is to be embedded in gRPC request messages for efficient -pagination. Ex: - - message SomeRequest { - Foo some_parameter = 1; - PageRequest pagination = 2; - } - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `key` | [bytes](#bytes) | | key is a value returned in PageResponse.next_key to begin querying the next page most efficiently. Only one of offset or key should be set. | -| `offset` | [uint64](#uint64) | | offset is a numeric offset that can be used when key is unavailable. It is less efficient than using key. Only one of offset or key should be set. | -| `limit` | [uint64](#uint64) | | limit is the total number of results to be returned in the result page. If left empty it will default to a value to be set by each app. | -| `count_total` | [bool](#bool) | | count_total is set to true to indicate that the result set should include a count of the total number of items available for pagination in UIs. count_total is only respected when offset is used. It is ignored when key is set. | -| `reverse` | [bool](#bool) | | reverse is set to true if results are to be returned in the descending order. - -Since: cosmos-sdk 0.43 | - - - - - - - - -### PageResponse - -PageResponse is to be embedded in gRPC response messages where the -corresponding request message has used PageRequest. - - message SomeResponse { - repeated Bar results = 1; - PageResponse page = 2; - } - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `next_key` | [bytes](#bytes) | | next_key is the key to be passed to PageRequest.key to query the next page most efficiently | -| `total` | [uint64](#uint64) | | total is total number of results available if PageRequest.count_total was set, its value is undefined otherwise | - - - - - - - - - - - - - - - -## Scalar Value Types - -| .proto Type | Notes | C++ | Java | Python | Go | C# | PHP | Ruby | -| ----------- | ----- | --- | ---- | ------ | -- | -- | --- | ---- | -| double | | double | double | float | float64 | double | float | Float | -| float | | float | float | float | float32 | float | float | Float | -| int32 | Uses variable-length encoding. Inefficient for encoding negative numbers – if your field is likely to have negative values, use sint32 instead. | int32 | int | int | int32 | int | integer | Bignum or Fixnum (as required) | -| int64 | Uses variable-length encoding. Inefficient for encoding negative numbers – if your field is likely to have negative values, use sint64 instead. | int64 | long | int/long | int64 | long | integer/string | Bignum | -| uint32 | Uses variable-length encoding. | uint32 | int | int/long | uint32 | uint | integer | Bignum or Fixnum (as required) | -| uint64 | Uses variable-length encoding. | uint64 | long | int/long | uint64 | ulong | integer/string | Bignum or Fixnum (as required) | -| sint32 | Uses variable-length encoding. Signed int value. These more efficiently encode negative numbers than regular int32s. | int32 | int | int | int32 | int | integer | Bignum or Fixnum (as required) | -| sint64 | Uses variable-length encoding. Signed int value. These more efficiently encode negative numbers than regular int64s. | int64 | long | int/long | int64 | long | integer/string | Bignum | -| fixed32 | Always four bytes. More efficient than uint32 if values are often greater than 2^28. | uint32 | int | int | uint32 | uint | integer | Bignum or Fixnum (as required) | -| fixed64 | Always eight bytes. More efficient than uint64 if values are often greater than 2^56. | uint64 | long | int/long | uint64 | ulong | integer/string | Bignum | -| sfixed32 | Always four bytes. | int32 | int | int | int32 | int | integer | Bignum or Fixnum (as required) | -| sfixed64 | Always eight bytes. | int64 | long | int/long | int64 | long | integer/string | Bignum | -| bool | | bool | boolean | boolean | bool | bool | boolean | TrueClass/FalseClass | -| string | A string must always contain UTF-8 encoded or 7-bit ASCII text. | string | String | str/unicode | string | string | string | String (UTF-8) | -| bytes | May contain any arbitrary sequence of bytes. | string | ByteString | str | []byte | ByteString | string | String (ASCII-8BIT) | - diff --git a/simapp/app.go b/simapp/app.go index 8e9b94075df8..e892839cae86 100644 --- a/simapp/app.go +++ b/simapp/app.go @@ -267,8 +267,14 @@ func NewSimApp( app.BankKeeper = bankkeeper.NewBaseKeeper( appCodec, keys[banktypes.StoreKey], app.AccountKeeper, app.GetSubspace(banktypes.ModuleName), app.ModuleAccountAddrs(), ) + + stakingConfig := stakingtypes.DefaultConfig() + /* + Example of setting staking params: + stakingConfig.PowerReduction = sdk.NewIntFromUint64(10) + */ stakingKeeper := stakingkeeper.NewKeeper( - appCodec, keys[stakingtypes.StoreKey], app.AccountKeeper, app.BankKeeper, app.GetSubspace(stakingtypes.ModuleName), + appCodec, keys[stakingtypes.StoreKey], app.AccountKeeper, app.BankKeeper, app.GetSubspace(stakingtypes.ModuleName), stakingConfig, ) app.MintKeeper = mintkeeper.NewKeeper( appCodec, keys[minttypes.StoreKey], app.GetSubspace(minttypes.ModuleName), &stakingKeeper, diff --git a/simapp/simd/cmd/testnet.go b/simapp/simd/cmd/testnet.go index 20ded76a92e1..3c285c055de3 100644 --- a/simapp/simd/cmd/testnet.go +++ b/simapp/simd/cmd/testnet.go @@ -282,8 +282,8 @@ func initTestnetFiles( return err } - accTokens := sdk.TokensFromConsensusPower(1000, sdk.DefaultPowerReduction) - accStakingTokens := sdk.TokensFromConsensusPower(500, sdk.DefaultPowerReduction) + accTokens := sdk.NewIntFromUint64(1000_000_000) + accStakingTokens := sdk.NewIntFromUint64(500_000_000) coins := sdk.Coins{ sdk.NewCoin("testtoken", accTokens), sdk.NewCoin(sdk.DefaultBondDenom, accStakingTokens), @@ -292,7 +292,7 @@ func initTestnetFiles( genBalances = append(genBalances, banktypes.Balance{Address: addr.String(), Coins: coins.Sort()}) genAccounts = append(genAccounts, authtypes.NewBaseAccount(addr, nil, 0, 0)) - valTokens := sdk.TokensFromConsensusPower(100, sdk.DefaultPowerReduction) + valTokens := sdk.NewIntFromUint64(100_000_000) createValMsg, err := stakingtypes.NewMsgCreateValidator( sdk.ValAddress(addr), valPubKeys[i], diff --git a/simapp/test_helpers.go b/simapp/test_helpers.go index 364891a5f0c9..1be73c4257c4 100644 --- a/simapp/test_helpers.go +++ b/simapp/test_helpers.go @@ -154,7 +154,7 @@ func genesisStateWithValSet(t *testing.T, validators := make([]stakingtypes.Validator, 0, len(valSet.Validators)) delegations := make([]stakingtypes.Delegation, 0, len(valSet.Validators)) - bondAmt := sdk.DefaultPowerReduction + bondAmt := stakingtypes.DefaultConfig().PowerReduction for _, val := range valSet.Validators { pk, err := cryptocodec.FromTmPubKeyInterface(val.PubKey) diff --git a/testutil/network/network.go b/testutil/network/network.go index c21c78d54fd5..77b65b69f5e2 100644 --- a/testutil/network/network.go +++ b/testutil/network/network.go @@ -116,9 +116,9 @@ func DefaultConfig() Config { NumValidators: 4, BondDenom: sdk.DefaultBondDenom, MinGasPrices: fmt.Sprintf("0.000006%s", sdk.DefaultBondDenom), - AccountTokens: sdk.TokensFromConsensusPower(1000, sdk.DefaultPowerReduction), - StakingTokens: sdk.TokensFromConsensusPower(500, sdk.DefaultPowerReduction), - BondedTokens: sdk.TokensFromConsensusPower(100, sdk.DefaultPowerReduction), + AccountTokens: sdk.NewIntFromUint64(1000_000_000), + StakingTokens: sdk.NewIntFromUint64(500_000_000), + BondedTokens: sdk.NewIntFromUint64(100_000_000), PruningStrategy: storetypes.PruningOptionNothing, CleanupDir: true, SigningAlgo: string(hd.Secp256k1Type), diff --git a/testutil/token.go b/testutil/token.go new file mode 100644 index 000000000000..88338a9bf0cb --- /dev/null +++ b/testutil/token.go @@ -0,0 +1,28 @@ +package testutil + +import ( + "math" + + sdk "github.com/cosmos/cosmos-sdk/types" +) + +var DefaultpowerReduction = sdk.NewInt(1_000_000) + +// TokensToConsensusPower - convert input tokens to Power +func TokensToConsensusPower(tokens sdk.Int, powerReduction sdk.Int) int64 { + if tokens.IsNil() || powerReduction.IsNil() || powerReduction.IsZero() { + return 0 + } + + power := tokens.Quo(powerReduction) + + if power.GT(sdk.NewIntFromUint64(math.MaxInt64)) { + return 0 + } + return power.Int64() +} + +// TokensFromConsensusPower - convert input power to tokens +func TokensFromConsensusPower(power int64, powerReduction sdk.Int) sdk.Int { + return sdk.NewInt(power).Mul(powerReduction) +} diff --git a/types/staking.go b/types/globals.go similarity index 56% rename from types/staking.go rename to types/globals.go index 2f17bb1dd85f..9c7d6126144d 100644 --- a/types/staking.go +++ b/types/globals.go @@ -17,16 +17,3 @@ const ( // https://tendermint.com/docs/spec/abci/apps.html#endblock ValidatorUpdateDelay int64 = 1 ) - -// DefaultPowerReduction is the default amount of staking tokens required for 1 unit of consensus-engine power -var DefaultPowerReduction = NewIntFromUint64(1000000) - -// TokensToConsensusPower - convert input tokens to potential consensus-engine power -func TokensToConsensusPower(tokens Int, powerReduction Int) int64 { - return (tokens.Quo(powerReduction)).Int64() -} - -// TokensFromConsensusPower - convert input power to tokens -func TokensFromConsensusPower(power int64, powerReduction Int) Int { - return NewInt(power).Mul(powerReduction) -} diff --git a/types/module/module.go b/types/module/module.go index 4128d781adfc..958a278ddb5a 100644 --- a/types/module/module.go +++ b/types/module/module.go @@ -335,7 +335,7 @@ func (m *Manager) InitGenesis(ctx sdk.Context, cdc codec.JSONCodec, genesisData // a chain must initialize with a non-empty validator set if len(validatorUpdates) == 0 { - panic(fmt.Sprintf("validator set is empty after InitGenesis, please ensure at least one validator is initialized with a delegation greater than or equal to the DefaultPowerReduction (%d)", sdk.DefaultPowerReduction)) + panic(fmt.Sprintf("validator set is empty after InitGenesis, please ensure at least one validator is initialized with a delegation greater than or equal to the DefaultPowerReduction, found in x/staking/types/config.go")) } return abci.ResponseInitChain{ diff --git a/types/staking_test.go b/types/staking_test.go deleted file mode 100644 index fe6c36bd991b..000000000000 --- a/types/staking_test.go +++ /dev/null @@ -1,26 +0,0 @@ -package types_test - -import ( - "testing" - - "github.com/stretchr/testify/suite" - - sdk "github.com/cosmos/cosmos-sdk/types" -) - -type stakingTestSuite struct { - suite.Suite -} - -func TestStakingTestSuite(t *testing.T) { - suite.Run(t, new(stakingTestSuite)) -} - -func (s *stakingTestSuite) SetupSuite() { - s.T().Parallel() -} - -func (s *stakingTestSuite) TestTokensToConsensusPower() { - s.Require().Equal(int64(0), sdk.TokensToConsensusPower(sdk.NewInt(999_999), sdk.DefaultPowerReduction)) - s.Require().Equal(int64(1), sdk.TokensToConsensusPower(sdk.NewInt(1_000_000), sdk.DefaultPowerReduction)) -} diff --git a/x/auth/client/testutil/suite.go b/x/auth/client/testutil/suite.go index 8e5d25d652e7..ac6b8709c0ac 100644 --- a/x/auth/client/testutil/suite.go +++ b/x/auth/client/testutil/suite.go @@ -648,7 +648,7 @@ func (s *IntegrationTestSuite) TestCLISendGenerateSignAndBroadcast() { account, err := val1.ClientCtx.Keyring.Key("newAccount") s.Require().NoError(err) - sendTokens := sdk.NewCoin(s.cfg.BondDenom, sdk.TokensFromConsensusPower(10, sdk.DefaultPowerReduction)) + sendTokens := sdk.NewCoin(s.cfg.BondDenom, testutil.TokensFromConsensusPower(10, testutil.DefaultpowerReduction)) addr, err := account.GetAddress() s.Require().NoError(err) @@ -849,7 +849,7 @@ func (s *IntegrationTestSuite) TestCLIMultisignInsufficientCosigners() { func (s *IntegrationTestSuite) TestCLIEncode() { val1 := s.network.Validators[0] - sendTokens := sdk.NewCoin(s.cfg.BondDenom, sdk.TokensFromConsensusPower(10, sdk.DefaultPowerReduction)) + sendTokens := sdk.NewCoin(s.cfg.BondDenom, testutil.TokensFromConsensusPower(10, testutil.DefaultpowerReduction)) normalGeneratedTx, err := s.createBankMsg( val1, val1.Address, diff --git a/x/auth/migrations/v043/store_test.go b/x/auth/migrations/v043/store_test.go index cae87b96885c..386926eedc46 100644 --- a/x/auth/migrations/v043/store_test.go +++ b/x/auth/migrations/v043/store_test.go @@ -9,6 +9,7 @@ import ( tmproto "github.com/tendermint/tendermint/proto/tendermint/types" "github.com/cosmos/cosmos-sdk/simapp" + "github.com/cosmos/cosmos-sdk/testutil" sdk "github.com/cosmos/cosmos-sdk/types" authkeeper "github.com/cosmos/cosmos-sdk/x/auth/keeper" authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" @@ -657,7 +658,7 @@ func dirtyTrackingFields(ctx sdk.Context, vesting exported.VestingAccount, app * } func createValidator(t *testing.T, ctx sdk.Context, app *simapp.SimApp, powers int64) (sdk.AccAddress, sdk.ValAddress) { - valTokens := sdk.TokensFromConsensusPower(powers, sdk.DefaultPowerReduction) + valTokens := testutil.TokensFromConsensusPower(powers, testutil.DefaultpowerReduction) addrs := simapp.AddTestAddrsIncremental(app, ctx, 1, valTokens) valAddrs := simapp.ConvertAddrsToValAddrs(addrs) pks := simapp.CreateTestPubKeys(1) @@ -669,6 +670,7 @@ func createValidator(t *testing.T, ctx sdk.Context, app *simapp.SimApp, powers i app.AccountKeeper, app.BankKeeper, app.GetSubspace(stakingtypes.ModuleName), + stakingtypes.DefaultConfig(), ) val1, err := stakingtypes.NewValidator(valAddrs[0], pks[0], stakingtypes.Description{}) diff --git a/x/bank/keeper/grpc_query_test.go b/x/bank/keeper/grpc_query_test.go index 1f8a1de5efc4..ed58dcb7f356 100644 --- a/x/bank/keeper/grpc_query_test.go +++ b/x/bank/keeper/grpc_query_test.go @@ -4,6 +4,7 @@ import ( gocontext "context" "fmt" + sdktestutil "github.com/cosmos/cosmos-sdk/testutil" "github.com/cosmos/cosmos-sdk/testutil/testdata" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/types/query" @@ -324,7 +325,7 @@ func (suite *IntegrationTestSuite) TestGRPCDenomOwners() { bal := sdk.NewCoins(sdk.NewCoin( sdk.DefaultBondDenom, - sdk.TokensFromConsensusPower(initialPower/10, sdk.DefaultPowerReduction), + sdktestutil.TokensFromConsensusPower(initialPower/10, sdktestutil.DefaultpowerReduction), )) suite.Require().NoError(keeper.SendCoinsFromModuleToAccount(ctx, minttypes.ModuleName, acc.GetAddress(), bal)) } diff --git a/x/bank/keeper/keeper_test.go b/x/bank/keeper/keeper_test.go index 6c3e55955ed4..760c0289d3e4 100644 --- a/x/bank/keeper/keeper_test.go +++ b/x/bank/keeper/keeper_test.go @@ -12,6 +12,7 @@ import ( "github.com/cosmos/cosmos-sdk/baseapp" "github.com/cosmos/cosmos-sdk/simapp" + sdktestutil "github.com/cosmos/cosmos-sdk/testutil" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/types/query" authkeeper "github.com/cosmos/cosmos-sdk/x/auth/keeper" @@ -40,8 +41,7 @@ var ( randomPermAcc = authtypes.NewEmptyModuleAccount(randomPerm, "random") // The default power validators are initialized to have within tests - initTokens = sdk.TokensFromConsensusPower(initialPower, sdk.DefaultPowerReduction) - initCoins = sdk.NewCoins(sdk.NewCoin(sdk.DefaultBondDenom, initTokens)) + initCoins = sdk.NewCoins(sdk.NewCoin(sdk.DefaultBondDenom, sdktestutil.TokensFromConsensusPower(initialPower, sdktestutil.DefaultpowerReduction))) ) func newFooCoin(amt int64) sdk.Coin { diff --git a/x/bank/types/balance_test.go b/x/bank/types/balance_test.go index 10ee2a74bf6e..e1ecee4a9baa 100644 --- a/x/bank/types/balance_test.go +++ b/x/bank/types/balance_test.go @@ -7,6 +7,7 @@ import ( "github.com/stretchr/testify/require" "github.com/cosmos/cosmos-sdk/crypto/keys/ed25519" + "github.com/cosmos/cosmos-sdk/testutil" sdk "github.com/cosmos/cosmos-sdk/types" bank "github.com/cosmos/cosmos-sdk/x/bank/types" ) @@ -141,8 +142,7 @@ func TestBalance_GetAddress(t *testing.T) { func TestSanitizeBalances(t *testing.T) { // 1. Generate balances - tokens := sdk.TokensFromConsensusPower(81, sdk.DefaultPowerReduction) - coin := sdk.NewCoin("benchcoin", tokens) + coin := sdk.NewCoin("benchcoin", testutil.TokensFromConsensusPower(81, testutil.DefaultpowerReduction)) coins := sdk.Coins{coin} addrs, _ := makeRandomAddressesAndPublicKeys(20) @@ -193,9 +193,7 @@ func BenchmarkSanitizeBalances1000(b *testing.B) { func benchmarkSanitizeBalances(b *testing.B, nAddresses int) { b.ReportAllocs() - tokens := sdk.TokensFromConsensusPower(81, sdk.DefaultPowerReduction) - coin := sdk.NewCoin("benchcoin", tokens) - coins := sdk.Coins{coin} + coins := sdk.NewCoins(sdk.NewCoin("benchcoin", testutil.TokensFromConsensusPower(81, testutil.DefaultpowerReduction))) addrs, _ := makeRandomAddressesAndPublicKeys(nAddresses) b.ResetTimer() diff --git a/x/evidence/keeper/keeper_test.go b/x/evidence/keeper/keeper_test.go index b0b12176efc2..517f129bf0aa 100644 --- a/x/evidence/keeper/keeper_test.go +++ b/x/evidence/keeper/keeper_test.go @@ -5,8 +5,6 @@ import ( "fmt" "time" - minttypes "github.com/cosmos/cosmos-sdk/x/mint/types" - "github.com/stretchr/testify/suite" tmproto "github.com/tendermint/tendermint/proto/tendermint/types" @@ -14,11 +12,13 @@ import ( "github.com/cosmos/cosmos-sdk/crypto/keys/ed25519" cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types" "github.com/cosmos/cosmos-sdk/simapp" + "github.com/cosmos/cosmos-sdk/testutil" sdk "github.com/cosmos/cosmos-sdk/types" authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" "github.com/cosmos/cosmos-sdk/x/evidence/exported" "github.com/cosmos/cosmos-sdk/x/evidence/keeper" "github.com/cosmos/cosmos-sdk/x/evidence/types" + minttypes "github.com/cosmos/cosmos-sdk/x/mint/types" ) var ( @@ -35,7 +35,7 @@ var ( } // The default power validators are initialized to have within tests - initAmt = sdk.TokensFromConsensusPower(200, sdk.DefaultPowerReduction) + initAmt = testutil.TokensFromConsensusPower(200, testutil.DefaultpowerReduction) initCoins = sdk.NewCoins(sdk.NewCoin(sdk.DefaultBondDenom, initAmt)) ) diff --git a/x/feegrant/simulation/operations_test.go b/x/feegrant/simulation/operations_test.go index f958330d9810..0aecf388faa9 100644 --- a/x/feegrant/simulation/operations_test.go +++ b/x/feegrant/simulation/operations_test.go @@ -11,6 +11,7 @@ import ( "github.com/cosmos/cosmos-sdk/simapp" simappparams "github.com/cosmos/cosmos-sdk/simapp/params" + sdktestutil "github.com/cosmos/cosmos-sdk/testutil" sdk "github.com/cosmos/cosmos-sdk/types" simtypes "github.com/cosmos/cosmos-sdk/types/simulation" "github.com/cosmos/cosmos-sdk/x/bank/testutil" @@ -38,7 +39,7 @@ func (suite *SimTestSuite) SetupTest() { func (suite *SimTestSuite) getTestingAccounts(r *rand.Rand, n int) []simtypes.Account { accounts := simtypes.RandomAccounts(r, n) - initAmt := sdk.TokensFromConsensusPower(200, sdk.DefaultPowerReduction) + initAmt := sdktestutil.TokensFromConsensusPower(200, sdktestutil.DefaultpowerReduction) initCoins := sdk.NewCoins(sdk.NewCoin(sdk.DefaultBondDenom, initAmt)) // add coins to the accounts diff --git a/x/gov/abci_test.go b/x/gov/abci_test.go index f0e002f12395..3ed06af3e464 100644 --- a/x/gov/abci_test.go +++ b/x/gov/abci_test.go @@ -9,6 +9,7 @@ import ( tmproto "github.com/tendermint/tendermint/proto/tendermint/types" "github.com/cosmos/cosmos-sdk/simapp" + "github.com/cosmos/cosmos-sdk/testutil" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/x/gov" "github.com/cosmos/cosmos-sdk/x/gov/keeper" @@ -373,7 +374,7 @@ func createValidators(t *testing.T, stakingMsgSvr stakingtypes.MsgServer, ctx sd require.True(t, len(addrs) <= len(pubkeys), "Not enough pubkeys specified at top of file.") for i := 0; i < len(addrs); i++ { - valTokens := sdk.TokensFromConsensusPower(powerAmt[i], sdk.DefaultPowerReduction) + valTokens := testutil.TokensFromConsensusPower(powerAmt[i], testutil.DefaultpowerReduction) valCreateMsg, err := stakingtypes.NewMsgCreateValidator( addrs[i], pubkeys[i], sdk.NewCoin(sdk.DefaultBondDenom, valTokens), TestDescription, TestCommissionRates, sdk.OneInt(), diff --git a/x/gov/common_test.go b/x/gov/common_test.go index ff20ec01cb6b..f5c4660f0f96 100644 --- a/x/gov/common_test.go +++ b/x/gov/common_test.go @@ -8,6 +8,7 @@ import ( "github.com/cosmos/cosmos-sdk/crypto/keys/ed25519" cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types" + "github.com/cosmos/cosmos-sdk/testutil" sdk "github.com/cosmos/cosmos-sdk/types" authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" "github.com/cosmos/cosmos-sdk/x/gov/types" @@ -18,7 +19,7 @@ import ( ) var ( - valTokens = sdk.TokensFromConsensusPower(42, sdk.DefaultPowerReduction) + valTokens = testutil.TokensFromConsensusPower(42, testutil.DefaultpowerReduction) TestProposal = v1beta1.NewTextProposal("Test", "description") TestDescription = stakingtypes.NewDescription("T", "E", "S", "T", "Z") TestCommissionRates = stakingtypes.NewCommissionRates(sdk.ZeroDec(), sdk.ZeroDec(), sdk.ZeroDec()) diff --git a/x/gov/keeper/common_test.go b/x/gov/keeper/common_test.go index e5e5bf183109..89d7097b16e0 100644 --- a/x/gov/keeper/common_test.go +++ b/x/gov/keeper/common_test.go @@ -48,6 +48,7 @@ func createValidators(t *testing.T, ctx sdk.Context, app *simapp.SimApp, powers app.AccountKeeper, app.BankKeeper, app.GetSubspace(stakingtypes.ModuleName), + stakingtypes.DefaultConfig(), ) val1, err := stakingtypes.NewValidator(valAddrs[0], pks[0], stakingtypes.Description{}) diff --git a/x/group/simulation/operations_test.go b/x/group/simulation/operations_test.go index 12f476b88a06..148ce89fba58 100644 --- a/x/group/simulation/operations_test.go +++ b/x/group/simulation/operations_test.go @@ -12,6 +12,7 @@ import ( tmproto "github.com/tendermint/tendermint/proto/tendermint/types" "github.com/cosmos/cosmos-sdk/simapp" + sdktestutil "github.com/cosmos/cosmos-sdk/testutil" sdk "github.com/cosmos/cosmos-sdk/types" simtypes "github.com/cosmos/cosmos-sdk/types/simulation" "github.com/cosmos/cosmos-sdk/x/bank/testutil" @@ -82,7 +83,7 @@ func (suite *SimTestSuite) TestWeightedOperations() { func (suite *SimTestSuite) getTestingAccounts(r *rand.Rand, n int) []simtypes.Account { accounts := simtypes.RandomAccounts(r, n) - initAmt := sdk.TokensFromConsensusPower(200, sdk.DefaultPowerReduction) + initAmt := sdktestutil.TokensFromConsensusPower(200, sdktestutil.DefaultpowerReduction) initCoins := sdk.NewCoins(sdk.NewCoin(sdk.DefaultBondDenom, initAmt)) // add coins to the accounts diff --git a/x/slashing/abci_test.go b/x/slashing/abci_test.go index f2958d4d3b62..ad80e7f4fb12 100644 --- a/x/slashing/abci_test.go +++ b/x/slashing/abci_test.go @@ -25,12 +25,14 @@ func TestBeginBlocker(t *testing.T) { addr, pk := sdk.ValAddress(pks[0].Address()), pks[0] tstaking := teststaking.NewHelper(t, ctx, app.StakingKeeper) + InitTokens := sdk.NewIntFromUint64(200_000_000) // bond the validator power := int64(100) amt := tstaking.CreateValidatorWithValPower(addr, pk, power, true) staking.EndBlocker(ctx, app.StakingKeeper) require.Equal( t, app.BankKeeper.GetAllBalances(ctx, sdk.AccAddress(addr)), + sdk.NewCoins(sdk.NewCoin(app.StakingKeeper.GetParams(ctx).BondDenom, InitTokens.Sub(amt))), ) require.Equal(t, amt, app.StakingKeeper.Validator(ctx, addr).GetBondedTokens()) diff --git a/x/slashing/app_test.go b/x/slashing/app_test.go index e9ece2c690a1..f4802ad24a61 100644 --- a/x/slashing/app_test.go +++ b/x/slashing/app_test.go @@ -11,6 +11,7 @@ import ( "github.com/cosmos/cosmos-sdk/crypto/keys/ed25519" "github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1" "github.com/cosmos/cosmos-sdk/simapp" + "github.com/cosmos/cosmos-sdk/testutil" sdk "github.com/cosmos/cosmos-sdk/types" authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" @@ -41,8 +42,8 @@ func checkValidatorSigningInfo(t *testing.T, app *simapp.SimApp, addr sdk.ConsAd } func TestSlashingMsgs(t *testing.T) { - genTokens := sdk.TokensFromConsensusPower(42, sdk.DefaultPowerReduction) - bondTokens := sdk.TokensFromConsensusPower(10, sdk.DefaultPowerReduction) + genTokens := testutil.TokensFromConsensusPower(42, testutil.DefaultpowerReduction) + bondTokens := testutil.TokensFromConsensusPower(10, testutil.DefaultpowerReduction) genCoin := sdk.NewCoin(sdk.DefaultBondDenom, genTokens) bondCoin := sdk.NewCoin(sdk.DefaultBondDenom, bondTokens) diff --git a/x/slashing/init_test.go b/x/slashing/init_test.go deleted file mode 100644 index a2217cfda7b0..000000000000 --- a/x/slashing/init_test.go +++ /dev/null @@ -1,10 +0,0 @@ -package slashing_test - -import ( - sdk "github.com/cosmos/cosmos-sdk/types" -) - -var ( - // The default power validators are initialized to have within tests - InitTokens = sdk.TokensFromConsensusPower(200, sdk.DefaultPowerReduction) -) diff --git a/x/slashing/keeper/common_test.go b/x/slashing/keeper/common_test.go deleted file mode 100644 index 91a972ed1110..000000000000 --- a/x/slashing/keeper/common_test.go +++ /dev/null @@ -1,8 +0,0 @@ -package keeper_test - -import sdk "github.com/cosmos/cosmos-sdk/types" - -var ( - // The default power validators are initialized to have within tests - InitTokens = sdk.TokensFromConsensusPower(200, sdk.DefaultPowerReduction) -) diff --git a/x/slashing/keeper/keeper_test.go b/x/slashing/keeper/keeper_test.go index 7385c1f4d7e2..ad877bddd132 100644 --- a/x/slashing/keeper/keeper_test.go +++ b/x/slashing/keeper/keeper_test.go @@ -94,10 +94,12 @@ func TestHandleNewValidator(t *testing.T) { // Validator created amt := tstaking.CreateValidatorWithValPower(addr, val, 100, true) + InitTokens := sdk.NewIntFromUint64(200_000_000) staking.EndBlocker(ctx, app.StakingKeeper) require.Equal( t, app.BankKeeper.GetAllBalances(ctx, sdk.AccAddress(addr)), + sdk.NewCoins(sdk.NewCoin(app.StakingKeeper.GetParams(ctx).BondDenom, InitTokens.Sub(amt))), ) require.Equal(t, amt, app.StakingKeeper.Validator(ctx, addr).GetBondedTokens()) diff --git a/x/staking/app_test.go b/x/staking/app_test.go index a97954254826..4324891f745d 100644 --- a/x/staking/app_test.go +++ b/x/staking/app_test.go @@ -40,8 +40,8 @@ func checkDelegation( } func TestStakingMsgs(t *testing.T) { - genTokens := sdk.TokensFromConsensusPower(42, sdk.DefaultPowerReduction) - bondTokens := sdk.TokensFromConsensusPower(10, sdk.DefaultPowerReduction) + genTokens := types.TokensFromConsensusPower(42, types.DefaultConfig().PowerReduction) + bondTokens := types.TokensFromConsensusPower(10, types.DefaultConfig().PowerReduction) genCoin := sdk.NewCoin(sdk.DefaultBondDenom, genTokens) bondCoin := sdk.NewCoin(sdk.DefaultBondDenom, bondTokens) diff --git a/x/staking/client/cli/tx.go b/x/staking/client/cli/tx.go index 138bfa24930d..f99e3924d8ac 100644 --- a/x/staking/client/cli/tx.go +++ b/x/staking/client/cli/tx.go @@ -20,7 +20,7 @@ import ( // default values var ( - DefaultTokens = sdk.TokensFromConsensusPower(100, sdk.DefaultPowerReduction) + DefaultTokens = types.TokensFromConsensusPower(100, types.DefaultConfig().PowerReduction) defaultAmount = DefaultTokens.String() + sdk.DefaultBondDenom defaultCommissionRate = "0.1" defaultCommissionMaxRate = "0.2" diff --git a/x/staking/common_test.go b/x/staking/common_test.go index 93193e459ca1..4ed51e5d116a 100644 --- a/x/staking/common_test.go +++ b/x/staking/common_test.go @@ -1,7 +1,6 @@ package staking_test import ( - "math/big" "testing" tmproto "github.com/tendermint/tendermint/proto/tendermint/types" @@ -15,10 +14,6 @@ import ( "github.com/cosmos/cosmos-sdk/x/staking/types" ) -func init() { - sdk.DefaultPowerReduction = sdk.NewIntFromBigInt(new(big.Int).Exp(big.NewInt(10), big.NewInt(18), nil)) -} - // nolint:deadcode,unused,varcheck var ( priv1 = secp256k1.GenPrivKey() @@ -48,6 +43,7 @@ func getBaseSimappWithCustomKeeper(t *testing.T) (*codec.LegacyAmino, *simapp.Si app.AccountKeeper, app.BankKeeper, app.GetSubspace(types.ModuleName), + types.DefaultConfig(), ) app.StakingKeeper.SetParams(ctx, types.DefaultParams()) diff --git a/x/staking/keeper/common_test.go b/x/staking/keeper/common_test.go index 6833ea4c0baf..8251f95afa1f 100644 --- a/x/staking/keeper/common_test.go +++ b/x/staking/keeper/common_test.go @@ -17,22 +17,22 @@ var ( PKs = simapp.CreateTestPubKeys(500) ) -func init() { - sdk.DefaultPowerReduction = sdk.NewIntFromBigInt(new(big.Int).Exp(big.NewInt(10), big.NewInt(18), nil)) -} - // createTestInput Returns a simapp with custom StakingKeeper // to avoid messing with the hooks. func createTestInput(t *testing.T) (*codec.LegacyAmino, *simapp.SimApp, sdk.Context) { app := simapp.Setup(t, false) ctx := app.BaseApp.NewContext(false, tmproto.Header{}) + stakingConfig := types.DefaultConfig() + stakingConfig.PowerReduction = sdk.NewIntFromBigInt(new(big.Int).Exp(big.NewInt(10), big.NewInt(18), nil)) + app.StakingKeeper = keeper.NewKeeper( app.AppCodec(), app.GetKey(types.StoreKey), app.AccountKeeper, app.BankKeeper, app.GetSubspace(types.ModuleName), + stakingConfig, ) return app.LegacyAmino(), app, ctx } diff --git a/x/staking/keeper/grpc_query_test.go b/x/staking/keeper/grpc_query_test.go index 8bb355571cd2..eb698e7aebc3 100644 --- a/x/staking/keeper/grpc_query_test.go +++ b/x/staking/keeper/grpc_query_test.go @@ -780,6 +780,7 @@ func createValidators(t *testing.T, ctx sdk.Context, app *simapp.SimApp, powers app.AccountKeeper, app.BankKeeper, app.GetSubspace(types.ModuleName), + types.DefaultConfig(), ) val1 := teststaking.NewValidator(t, valAddrs[0], pks[0]) diff --git a/x/staking/keeper/keeper.go b/x/staking/keeper/keeper.go index 5dde8f1bb92a..893dd4116081 100644 --- a/x/staking/keeper/keeper.go +++ b/x/staking/keeper/keeper.go @@ -26,12 +26,13 @@ type Keeper struct { bankKeeper types.BankKeeper hooks types.StakingHooks paramstore paramtypes.Subspace + Config types.Config } // NewKeeper creates a new staking Keeper instance func NewKeeper( cdc codec.BinaryCodec, key storetypes.StoreKey, ak types.AccountKeeper, bk types.BankKeeper, - ps paramtypes.Subspace, + ps paramtypes.Subspace, cfg types.Config, ) Keeper { // set KeyTable if it has not already been set if !ps.HasKeyTable() { @@ -54,6 +55,7 @@ func NewKeeper( bankKeeper: bk, paramstore: ps, hooks: nil, + Config: cfg, } } diff --git a/x/staking/keeper/params.go b/x/staking/keeper/params.go index 498576fea53f..daf36ee42f1b 100644 --- a/x/staking/keeper/params.go +++ b/x/staking/keeper/params.go @@ -40,11 +40,8 @@ func (k Keeper) BondDenom(ctx sdk.Context) (res string) { } // PowerReduction - is the amount of staking tokens required for 1 unit of consensus-engine power. -// Currently, this returns a global variable that the app developer can tweak. -// TODO: we might turn this into an on-chain param: -// https://github.com/cosmos/cosmos-sdk/issues/8365 -func (k Keeper) PowerReduction(ctx sdk.Context) sdk.Int { - return sdk.DefaultPowerReduction +func (k Keeper) PowerReduction(_ sdk.Context) sdk.Int { + return k.Config.PowerReduction } // MinCommissionRate - Minimum validator commission rate diff --git a/x/staking/keeper/power_reduction.go b/x/staking/keeper/power_reduction.go index d979228b36fa..5a64cbead97f 100644 --- a/x/staking/keeper/power_reduction.go +++ b/x/staking/keeper/power_reduction.go @@ -2,14 +2,15 @@ package keeper import ( sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/x/staking/types" ) // TokensToConsensusPower - convert input tokens to potential consensus-engine power func (k Keeper) TokensToConsensusPower(ctx sdk.Context, tokens sdk.Int) int64 { - return sdk.TokensToConsensusPower(tokens, k.PowerReduction(ctx)) + return types.TokensToConsensusPower(tokens, k.PowerReduction(ctx)) } // TokensFromConsensusPower - convert input power to tokens func (k Keeper) TokensFromConsensusPower(ctx sdk.Context, power int64) sdk.Int { - return sdk.TokensFromConsensusPower(power, k.PowerReduction(ctx)) + return types.TokensFromConsensusPower(power, k.PowerReduction(ctx)) } diff --git a/x/staking/keeper/power_reduction_test.go b/x/staking/keeper/power_reduction_test.go index e18230d854b2..cca2f326b690 100644 --- a/x/staking/keeper/power_reduction_test.go +++ b/x/staking/keeper/power_reduction_test.go @@ -5,11 +5,11 @@ import ( ) func (suite *KeeperTestSuite) TestTokensToConsensusPower() { - suite.Require().Equal(int64(0), suite.app.StakingKeeper.TokensToConsensusPower(suite.ctx, sdk.DefaultPowerReduction.Sub(sdk.NewInt(1)))) - suite.Require().Equal(int64(1), suite.app.StakingKeeper.TokensToConsensusPower(suite.ctx, sdk.DefaultPowerReduction)) + suite.Require().Equal(int64(0), suite.app.StakingKeeper.TokensToConsensusPower(suite.ctx, suite.app.StakingKeeper.Config.PowerReduction.Sub(sdk.NewInt(1)))) + suite.Require().Equal(int64(1), suite.app.StakingKeeper.TokensToConsensusPower(suite.ctx, suite.app.StakingKeeper.Config.PowerReduction)) } func (suite *KeeperTestSuite) TestTokensFromConsensusPower() { suite.Require().Equal(sdk.NewInt(0), suite.app.StakingKeeper.TokensFromConsensusPower(suite.ctx, 0)) - suite.Require().Equal(sdk.DefaultPowerReduction, suite.app.StakingKeeper.TokensFromConsensusPower(suite.ctx, 1)) + suite.Require().Equal(suite.app.StakingKeeper.Config.PowerReduction, suite.app.StakingKeeper.TokensFromConsensusPower(suite.ctx, 1)) } diff --git a/x/staking/migrations/v040/keys.go b/x/staking/migrations/v040/keys.go index 27e2f9eae02b..0384915bfac7 100644 --- a/x/staking/migrations/v040/keys.go +++ b/x/staking/migrations/v040/keys.go @@ -79,7 +79,7 @@ func GetValidatorsByPowerIndexKey(validator types.Validator) []byte { // NOTE the address doesn't need to be stored because counter bytes must always be different // NOTE the larger values are of higher value - consensusPower := sdk.TokensToConsensusPower(validator.Tokens, sdk.DefaultPowerReduction) + consensusPower := types.TokensToConsensusPower(validator.Tokens, types.DefaultConfig().PowerReduction) consensusPowerBytes := make([]byte, 8) binary.BigEndian.PutUint64(consensusPowerBytes, uint64(consensusPower)) diff --git a/x/staking/migrations/v043/store_test.go b/x/staking/migrations/v043/store_test.go index 756590a5dc19..15d451f3aaf0 100644 --- a/x/staking/migrations/v043/store_test.go +++ b/x/staking/migrations/v043/store_test.go @@ -62,7 +62,7 @@ func TestStoreMigration(t *testing.T) { { "ValidatorsByPowerIndexKey", v040staking.GetValidatorsByPowerIndexKey(val), - types.GetValidatorsByPowerIndexKey(val, sdk.DefaultPowerReduction), + types.GetValidatorsByPowerIndexKey(val, types.DefaultConfig().PowerReduction), }, { "DelegationKey", diff --git a/x/staking/simulation/common_test.go b/x/staking/simulation/common_test.go deleted file mode 100644 index e22ecd15aa2c..000000000000 --- a/x/staking/simulation/common_test.go +++ /dev/null @@ -1,11 +0,0 @@ -package simulation_test - -import ( - "math/big" - - sdk "github.com/cosmos/cosmos-sdk/types" -) - -func init() { - sdk.DefaultPowerReduction = sdk.NewIntFromBigInt(new(big.Int).Exp(big.NewInt(10), big.NewInt(18), nil)) -} diff --git a/x/staking/simulation/operations_test.go b/x/staking/simulation/operations_test.go index ae93cf79008a..8ff8540778d6 100644 --- a/x/staking/simulation/operations_test.go +++ b/x/staking/simulation/operations_test.go @@ -256,7 +256,6 @@ func TestSimulateMsgBeginRedelegate(t *testing.T) { // returns context and an app with updated mint keeper func createTestApp(t *testing.T, isCheckTx bool, r *rand.Rand, n int) (*simapp.SimApp, sdk.Context, []simtypes.Account) { - sdk.DefaultPowerReduction = sdk.NewIntFromBigInt(new(big.Int).Exp(big.NewInt(10), big.NewInt(18), nil)) accounts := simtypes.RandomAccounts(r, n) // create validator set with single validator @@ -281,6 +280,7 @@ func createTestApp(t *testing.T, isCheckTx bool, r *rand.Rand, n int) (*simapp.S app.MintKeeper.SetParams(ctx, minttypes.DefaultParams()) app.MintKeeper.SetMinter(ctx, minttypes.DefaultInitialMinter()) + app.StakingKeeper.Config.PowerReduction = sdk.NewIntFromBigInt(new(big.Int).Exp(big.NewInt(10), big.NewInt(18), nil)) initAmt := app.StakingKeeper.TokensFromConsensusPower(ctx, 200) initCoins := sdk.NewCoins(sdk.NewCoin(sdk.DefaultBondDenom, initAmt)) diff --git a/x/staking/types/config.go b/x/staking/types/config.go new file mode 100644 index 000000000000..481f69401e6c --- /dev/null +++ b/x/staking/types/config.go @@ -0,0 +1,17 @@ +package types + +import ( + sdk "github.com/cosmos/cosmos-sdk/types" +) + +// Config is a config struct used for intialising the staking module to avoid using globals. +type Config struct { + // PowerReduction is the amount of staking tokens required for 1 unit of consensus-engine power + PowerReduction sdk.Int +} + +func DefaultConfig() Config { + return Config{ + PowerReduction: sdk.NewIntFromUint64(1000000), + } +} diff --git a/x/staking/types/historical_info_test.go b/x/staking/types/historical_info_test.go index 66d3105897e1..b8872ef766d1 100644 --- a/x/staking/types/historical_info_test.go +++ b/x/staking/types/historical_info_test.go @@ -10,7 +10,6 @@ import ( "github.com/stretchr/testify/require" tmproto "github.com/tendermint/tendermint/proto/tendermint/types" - sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/x/staking/types" ) @@ -29,7 +28,7 @@ func createValidators(t *testing.T) []types.Validator { func TestHistoricalInfo(t *testing.T) { validators := createValidators(t) - hi := types.NewHistoricalInfo(header, validators, sdk.DefaultPowerReduction) + hi := types.NewHistoricalInfo(header, validators, types.DefaultConfig().PowerReduction) require.True(t, sort.IsSorted(types.Validators(hi.Valset)), "Validators are not sorted") var value []byte @@ -70,7 +69,7 @@ func TestValidateBasic(t *testing.T) { err = types.ValidateBasic(hi) require.Error(t, err, "ValidateBasic passed on unsorted ValSet") - hi = types.NewHistoricalInfo(header, validators, sdk.DefaultPowerReduction) + hi = types.NewHistoricalInfo(header, validators, types.DefaultConfig().PowerReduction) err = types.ValidateBasic(hi) require.NoError(t, err, "ValidateBasic failed on valid HistoricalInfo") } diff --git a/x/staking/types/keys.go b/x/staking/types/keys.go index 74d73bf19c7e..0877680564f7 100644 --- a/x/staking/types/keys.go +++ b/x/staking/types/keys.go @@ -82,7 +82,7 @@ func GetValidatorsByPowerIndexKey(validator Validator, powerReduction sdk.Int) [ // NOTE the address doesn't need to be stored because counter bytes must always be different // NOTE the larger values are of higher value - consensusPower := sdk.TokensToConsensusPower(validator.Tokens, powerReduction) + consensusPower := TokensToConsensusPower(validator.Tokens, powerReduction) consensusPowerBytes := make([]byte, 8) binary.BigEndian.PutUint64(consensusPowerBytes, uint64(consensusPower)) diff --git a/x/staking/types/keys_test.go b/x/staking/types/keys_test.go index 35667f949da5..e4f36af1ef94 100644 --- a/x/staking/types/keys_test.go +++ b/x/staking/types/keys_test.go @@ -28,10 +28,10 @@ func TestGetValidatorPowerRank(t *testing.T) { val1 := newValidator(t, valAddr1, keysPK1) val1.Tokens = sdk.ZeroInt() val2, val3, val4 := val1, val1, val1 - val2.Tokens = sdk.TokensFromConsensusPower(1, sdk.DefaultPowerReduction) - val3.Tokens = sdk.TokensFromConsensusPower(10, sdk.DefaultPowerReduction) + val2.Tokens = sdk.NewIntFromUint64(1_000_000) + val3.Tokens = sdk.NewIntFromUint64(10_000_000) x := new(big.Int).Exp(big.NewInt(2), big.NewInt(40), big.NewInt(0)) - val4.Tokens = sdk.TokensFromConsensusPower(x.Int64(), sdk.DefaultPowerReduction) + val4.Tokens = sdk.NewInt(x.Int64()).Mul(sdk.NewIntFromUint64(1_000_000)) tests := []struct { validator types.Validator @@ -43,7 +43,7 @@ func TestGetValidatorPowerRank(t *testing.T) { {val4, "230000010000000000149c288ede7df62742fc3b7d0962045a8cef0f79f6"}, } for i, tt := range tests { - got := hex.EncodeToString(types.GetValidatorsByPowerIndexKey(tt.validator, sdk.DefaultPowerReduction)) + got := hex.EncodeToString(types.GetValidatorsByPowerIndexKey(tt.validator, types.DefaultConfig().PowerReduction)) require.Equal(t, tt.wantHex, got, "Keys did not match on test case %d", i) } diff --git a/x/staking/types/power_reduction.go b/x/staking/types/power_reduction.go new file mode 100644 index 000000000000..8f61dd518b07 --- /dev/null +++ b/x/staking/types/power_reduction.go @@ -0,0 +1,26 @@ +package types + +import ( + "math" + + sdk "github.com/cosmos/cosmos-sdk/types" +) + +// TokensToConsensusPower - convert input tokens to Power +func TokensToConsensusPower(tokens sdk.Int, powerReduction sdk.Int) int64 { + if tokens.IsNil() || powerReduction.IsNil() || powerReduction.IsZero() { + return 0 + } + + power := tokens.Quo(powerReduction) + + if power.GT(sdk.NewIntFromUint64(math.MaxInt64)) { + return 0 + } + return power.Int64() +} + +// TokensFromConsensusPower - convert input power to tokens +func TokensFromConsensusPower(power int64, powerReduction sdk.Int) sdk.Int { + return sdk.NewInt(power).Mul(powerReduction) +} diff --git a/x/staking/types/power_reduction_test.go b/x/staking/types/power_reduction_test.go new file mode 100644 index 000000000000..448063574ba1 --- /dev/null +++ b/x/staking/types/power_reduction_test.go @@ -0,0 +1,34 @@ +package types_test + +import ( + "math" + "math/big" + "testing" + + "github.com/stretchr/testify/suite" + + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/x/staking/types" +) + +var powerReduction = sdk.NewIntFromUint64(1000000) + +type stakingTestSuite struct { + suite.Suite +} + +func TestStakingTestSuite(t *testing.T) { + suite.Run(t, new(stakingTestSuite)) +} + +func (s *stakingTestSuite) SetupSuite() { + s.T().Parallel() +} + +func (s *stakingTestSuite) TestTokensToConsensusPower() { + + s.Require().Equal(int64(0), types.TokensToConsensusPower(sdk.NewInt(999_999), powerReduction)) + s.Require().Equal(int64(1), types.TokensToConsensusPower(sdk.NewInt(1_000_000), powerReduction)) + s.Require().Equal(int64(0), types.TokensToConsensusPower(sdk.NewIntFromBigInt(big.NewInt(math.MaxInt64).Add(big.NewInt(math.MaxInt64), big.NewInt(1))), sdk.NewIntFromUint64(1))) + s.Require().Equal(int64(0), types.TokensToConsensusPower(sdk.NewInt(1_000_000), sdk.NewIntFromUint64(0))) +} diff --git a/x/staking/types/validator.go b/x/staking/types/validator.go index 79bd2a4f55b1..2d5b434eb4fc 100644 --- a/x/staking/types/validator.go +++ b/x/staking/types/validator.go @@ -366,7 +366,7 @@ func (v Validator) ConsensusPower(r sdk.Int) int64 { // PotentialConsensusPower returns the potential consensus-engine power. func (v Validator) PotentialConsensusPower(r sdk.Int) int64 { - return sdk.TokensToConsensusPower(v.Tokens, r) + return TokensToConsensusPower(v.Tokens, r) } // UpdateStatus updates the location of the shares within a validator diff --git a/x/staking/types/validator_test.go b/x/staking/types/validator_test.go index 8601fbeec723..26b45e1c8586 100644 --- a/x/staking/types/validator_test.go +++ b/x/staking/types/validator_test.go @@ -58,7 +58,7 @@ func TestUpdateDescription(t *testing.T) { func TestABCIValidatorUpdate(t *testing.T) { validator := newValidator(t, valAddr1, pk1) - abciVal := validator.ABCIValidatorUpdate(sdk.DefaultPowerReduction) + abciVal := validator.ABCIValidatorUpdate(types.DefaultConfig().PowerReduction) pk, err := validator.TmConsPublicKey() require.NoError(t, err) require.Equal(t, pk, abciVal.PubKey) @@ -290,15 +290,15 @@ func TestValidatorsSortTendermint(t *testing.T) { valz := types.Validators(vals) // create expected tendermint validators by converting to tendermint then sorting - expectedVals, err := teststaking.ToTmValidators(valz, sdk.DefaultPowerReduction) + expectedVals, err := teststaking.ToTmValidators(valz, types.DefaultConfig().PowerReduction) require.NoError(t, err) sort.Sort(tmtypes.ValidatorsByVotingPower(expectedVals)) // sort in SDK and then convert to tendermint sort.SliceStable(valz, func(i, j int) bool { - return types.ValidatorsByVotingPower(valz).Less(i, j, sdk.DefaultPowerReduction) + return types.ValidatorsByVotingPower(valz).Less(i, j, types.DefaultConfig().PowerReduction) }) - actualVals, err := teststaking.ToTmValidators(valz, sdk.DefaultPowerReduction) + actualVals, err := teststaking.ToTmValidators(valz, types.DefaultConfig().PowerReduction) require.NoError(t, err) require.Equal(t, expectedVals, actualVals, "sorting in SDK is not the same as sorting in Tendermint") @@ -316,9 +316,9 @@ func TestValidatorToTm(t *testing.T) { vals[i] = val tmPk, err := cryptocodec.ToTmPubKeyInterface(pk) require.NoError(t, err) - expected[i] = tmtypes.NewValidator(tmPk, val.ConsensusPower(sdk.DefaultPowerReduction)) + expected[i] = tmtypes.NewValidator(tmPk, val.ConsensusPower(types.DefaultConfig().PowerReduction)) } - vs, err := teststaking.ToTmValidators(vals, sdk.DefaultPowerReduction) + vs, err := teststaking.ToTmValidators(vals, types.DefaultConfig().PowerReduction) require.NoError(t, err) require.Equal(t, expected, vs) }