diff --git a/.gitignore b/.gitignore index 2bf18165980a..83d56ddf8e75 100644 --- a/.gitignore +++ b/.gitignore @@ -26,7 +26,7 @@ artifacts # Data - ideally these don't exist baseapp/data/* client/lcd/keys/* -mytestnet +.testnets # Testing coverage.txt diff --git a/.mergify.yml b/.mergify.yml index 28ec751ea159..bcc4c6da1b9a 100644 --- a/.mergify.yml +++ b/.mergify.yml @@ -9,6 +9,14 @@ pull_request_rules: method: squash strict: true commit_message: title+body + - name: backport patches to v0.43.x branch + conditions: + - base=master + - label=backport/0.43.x + actions: + backport: + branches: + - release/v0.43.x - name: backport patches to v0.42.x branch conditions: - base=master diff --git a/CHANGELOG.md b/CHANGELOG.md index ec66d9159602..9611cd353110 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -37,11 +37,27 @@ Ref: https://keepachangelog.com/en/1.0.0/ ## [Unreleased] +### Features + +* [\#9533](https://github.com/cosmos/cosmos-sdk/pull/9533) Added a new gRPC method, `DenomOwners`, in `x/bank` to query for all account holders of a specific denomination. + ### API Breaking Changes +* [\#9571](https://github.com/cosmos/cosmos-sdk/pull/9571) Implemented error handling for staking hooks, which now return an error on failure. +* [\#9427](https://github.com/cosmos/cosmos-sdk/pull/9427) Move simapp `FundAccount` and `FundModuleAccount` to `x/bank/testutil` +* (client/tx) [\#9421](https://github.com/cosmos/cosmos-sdk/pull/9421/) `BuildUnsignedTx`, `BuildSimTx`, `PrintUnsignedStdTx` functions are moved to + the Tx Factory as methods. +* [\#9246](https://github.com/cosmos/cosmos-sdk/pull/9246) The `New` method for the network package now returns an error. * (codec) [\#9521](https://github.com/cosmos/cosmos-sdk/pull/9521) Removed deprecated `clientCtx.JSONCodec` from `client.Context`. * (codec) [\#9521](https://github.com/cosmos/cosmos-sdk/pull/9521) Rename `EncodingConfig.Marshaler` to `Codec`. +### CLI Breaking Changes + +* [\#9246](https://github.com/cosmos/cosmos-sdk/pull/9246) Removed the CLI flag `--setup-config-only` from the `testnet` command and added the subcommand `init-files`. + +### Improvements +* (cli) [\#9593](https://github.com/cosmos/cosmos-sdk/pull/9593) Check if chain-id is blank before verifying signatures in multisign and error. + ## [v0.43.0-rc0](https://github.com/cosmos/cosmos-sdk/releases/tag/v0.43.0-rc0) - 2021-06-25 ### Features @@ -116,7 +132,6 @@ Ref: https://keepachangelog.com/en/1.0.0/ * (codec) [\#9251](https://github.com/cosmos/cosmos-sdk/pull/9251) Rename `clientCtx.JSONMarshaler` to `clientCtx.JSONCodec` as per #9226. * (x/bank) [\#9271](https://github.com/cosmos/cosmos-sdk/pull/9271) SendEnabledCoin(s) renamed to IsSendEnabledCoin(s) to better reflect its functionality. - ### State Machine Breaking * (x/{bank,distrib,gov,slashing,staking}) [\#8363](https://github.com/cosmos/cosmos-sdk/issues/8363) Store keys have been modified to allow for variable-length addresses. diff --git a/Makefile b/Makefile index 12fbae141aee..9d4d589becc1 100644 --- a/Makefile +++ b/Makefile @@ -475,16 +475,16 @@ proto-update-deps: ### Localnet ### ############################################################################### -# Run a 4-node testnet locally +# Run a 4-node testnet locally via docker compose localnet-start: build-linux localnet-stop $(if $(shell $(DOCKER) inspect -f '{{ .Id }}' cosmossdk/simd-env 2>/dev/null),$(info found image cosmossdk/simd-env),$(MAKE) -C contrib/images simd-env) - if ! [ -f build/node0/simd/config/genesis.json ]; then $(DOCKER) run --rm \ + if ! test -f build/node0/simd/config/genesis.json; then $(DOCKER) run --rm \ --user $(shell id -u):$(shell id -g) \ -v $(BUILDDIR):/simd:Z \ -v /etc/group:/etc/group:ro \ -v /etc/passwd:/etc/passwd:ro \ -v /etc/shadow:/etc/shadow:ro \ - cosmossdk/simd-env testnet --v 4 -o . --starting-ip-address 192.168.10.2 --keyring-backend=test ; fi + cosmossdk/simd-env testnet init-files --v 4 -o . --starting-ip-address 192.168.10.2 --keyring-backend=test ; fi docker-compose up -d localnet-stop: diff --git a/client/context_test.go b/client/context_test.go index 9c2e8d4ab19e..d500bc97783b 100644 --- a/client/context_test.go +++ b/client/context_test.go @@ -105,7 +105,8 @@ func TestCLIQueryConn(t *testing.T) { cfg := network.DefaultConfig() cfg.NumValidators = 1 - n := network.New(t, cfg) + n, err := network.New(t, t.TempDir(), cfg) + require.NoError(t, err) defer n.Cleanup() testClient := testdata.NewQueryClient(n.Validators[0].ClientCtx) diff --git a/client/grpc/tmservice/service_test.go b/client/grpc/tmservice/service_test.go index 3de92411c9f7..abdc6145ad6f 100644 --- a/client/grpc/tmservice/service_test.go +++ b/client/grpc/tmservice/service_test.go @@ -32,11 +32,12 @@ func (s *IntegrationTestSuite) SetupSuite() { cfg.NumValidators = 1 s.cfg = cfg - s.network = network.New(s.T(), cfg) - s.Require().NotNil(s.network) + var err error + s.network, err = network.New(s.T(), s.T().TempDir(), s.cfg) + s.Require().NoError(err) - _, err := s.network.WaitForHeight(1) + _, err = s.network.WaitForHeight(1) s.Require().NoError(err) s.queryClient = tmservice.NewServiceClient(s.network.Validators[0].ClientCtx) diff --git a/client/grpc_query_test.go b/client/grpc_query_test.go index c4d2f024a07b..b63937ac2337 100644 --- a/client/grpc_query_test.go +++ b/client/grpc_query_test.go @@ -27,10 +27,11 @@ type IntegrationTestSuite struct { func (s *IntegrationTestSuite) SetupSuite() { s.T().Log("setting up integration test suite") - s.network = network.New(s.T(), network.DefaultConfig()) - s.Require().NotNil(s.network) + var err error + s.network, err = network.New(s.T(), s.T().TempDir(), network.DefaultConfig()) + s.Require().NoError(err) - _, err := s.network.WaitForHeight(2) + _, err = s.network.WaitForHeight(2) s.Require().NoError(err) } diff --git a/client/rpc/rpc_test.go b/client/rpc/rpc_test.go index adb7dac82d21..c2c18a0d1c6a 100644 --- a/client/rpc/rpc_test.go +++ b/client/rpc/rpc_test.go @@ -23,8 +23,9 @@ type IntegrationTestSuite struct { func (s *IntegrationTestSuite) SetupSuite() { s.T().Log("setting up integration test suite") - s.network = network.New(s.T(), network.DefaultConfig()) - s.Require().NotNil(s.network) + var err error + s.network, err = network.New(s.T(), s.T().TempDir(), network.DefaultConfig()) + s.Require().NoError(err) s.Require().NoError(s.network.WaitForNextBlock()) } diff --git a/client/tx/factory.go b/client/tx/factory.go index 2cb951922d0a..3dc994b3917d 100644 --- a/client/tx/factory.go +++ b/client/tx/factory.go @@ -1,11 +1,16 @@ package tx import ( + "errors" + "fmt" + "os" + "github.com/spf13/pflag" "github.com/cosmos/cosmos-sdk/client" "github.com/cosmos/cosmos-sdk/client/flags" "github.com/cosmos/cosmos-sdk/crypto/keyring" + "github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/types/tx/signing" ) @@ -189,3 +194,132 @@ func (f Factory) WithTimeoutHeight(height uint64) Factory { f.timeoutHeight = height return f } + +// BuildUnsignedTx builds a transaction to be signed given a set of messages. +// Once created, the fee, memo, and messages are set. +func (f Factory) BuildUnsignedTx(msgs ...sdk.Msg) (client.TxBuilder, error) { + if f.chainID == "" { + return nil, fmt.Errorf("chain ID required but not specified") + } + + fees := f.fees + + if !f.gasPrices.IsZero() { + if !fees.IsZero() { + return nil, errors.New("cannot provide both fees and gas prices") + } + + glDec := sdk.NewDec(int64(f.gas)) + + // Derive the fees based on the provided gas prices, where + // fee = ceil(gasPrice * gasLimit). + fees = make(sdk.Coins, len(f.gasPrices)) + + for i, gp := range f.gasPrices { + fee := gp.Amount.Mul(glDec) + fees[i] = sdk.NewCoin(gp.Denom, fee.Ceil().RoundInt()) + } + } + + tx := f.txConfig.NewTxBuilder() + + if err := tx.SetMsgs(msgs...); err != nil { + return nil, err + } + + tx.SetMemo(f.memo) + tx.SetFeeAmount(fees) + tx.SetGasLimit(f.gas) + tx.SetTimeoutHeight(f.TimeoutHeight()) + + return tx, nil +} + +// PrintUnsignedTx will generate an unsigned transaction and print it to the writer +// specified by ctx.Output. If simulation was requested, the gas will be +// simulated and also printed to the same writer before the transaction is +// printed. +func (f Factory) PrintUnsignedTx(clientCtx client.Context, msgs ...sdk.Msg) error { + if f.SimulateAndExecute() { + if clientCtx.Offline { + return errors.New("cannot estimate gas in offline mode") + } + + _, adjusted, err := CalculateGas(clientCtx, f, msgs...) + if err != nil { + return err + } + + f = f.WithGas(adjusted) + _, _ = fmt.Fprintf(os.Stderr, "%s\n", GasEstimateResponse{GasEstimate: f.Gas()}) + } + + tx, err := f.BuildUnsignedTx(msgs...) + if err != nil { + return err + } + + json, err := clientCtx.TxConfig.TxJSONEncoder()(tx.GetTx()) + if err != nil { + return err + } + + return clientCtx.PrintString(fmt.Sprintf("%s\n", json)) +} + +// BuildSimTx creates an unsigned tx with an empty single signature and returns +// the encoded transaction or an error if the unsigned transaction cannot be +// built. +func (f Factory) BuildSimTx(msgs ...sdk.Msg) ([]byte, error) { + txb, err := f.BuildUnsignedTx(msgs...) + if err != nil { + return nil, err + } + + // Create an empty signature literal as the ante handler will populate with a + // sentinel pubkey. + sig := signing.SignatureV2{ + PubKey: &secp256k1.PubKey{}, + Data: &signing.SingleSignatureData{ + SignMode: f.signMode, + }, + Sequence: f.Sequence(), + } + if err := txb.SetSignatures(sig); err != nil { + return nil, err + } + + return f.txConfig.TxEncoder()(txb.GetTx()) +} + +// Prepare ensures the account defined by ctx.GetFromAddress() exists and +// if the account number and/or the account sequence number are zero (not set), +// they will be queried for and set on the provided Factory. A new Factory with +// the updated fields will be returned. +func (f Factory) Prepare(clientCtx client.Context) (Factory, error) { + fc := f + + from := clientCtx.GetFromAddress() + + if err := fc.accountRetriever.EnsureExists(clientCtx, from); err != nil { + return fc, err + } + + initNum, initSeq := fc.accountNumber, fc.sequence + if initNum == 0 || initSeq == 0 { + num, seq, err := fc.accountRetriever.GetAccountNumberSequence(clientCtx, from) + if err != nil { + return fc, err + } + + if initNum == 0 { + fc = fc.WithAccountNumber(num) + } + + if initSeq == 0 { + fc = fc.WithSequence(seq) + } + } + + return fc, nil +} diff --git a/client/tx/tx.go b/client/tx/tx.go index 8e20be369bfd..ee0c7553de83 100644 --- a/client/tx/tx.go +++ b/client/tx/tx.go @@ -14,7 +14,6 @@ import ( "github.com/cosmos/cosmos-sdk/client" "github.com/cosmos/cosmos-sdk/client/flags" "github.com/cosmos/cosmos-sdk/client/input" - "github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1" cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types" sdk "github.com/cosmos/cosmos-sdk/types" sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" @@ -45,49 +44,17 @@ func GenerateOrBroadcastTxWithFactory(clientCtx client.Context, txf Factory, msg } if clientCtx.GenerateOnly { - return GenerateTx(clientCtx, txf, msgs...) + return txf.PrintUnsignedTx(clientCtx, msgs...) } return BroadcastTx(clientCtx, txf, msgs...) } -// GenerateTx will generate an unsigned transaction and print it to the writer -// specified by ctx.Output. If simulation was requested, the gas will be -// simulated and also printed to the same writer before the transaction is -// printed. -func GenerateTx(clientCtx client.Context, txf Factory, msgs ...sdk.Msg) error { - if txf.SimulateAndExecute() { - if clientCtx.Offline { - return errors.New("cannot estimate gas in offline mode") - } - - _, adjusted, err := CalculateGas(clientCtx, txf, msgs...) - if err != nil { - return err - } - - txf = txf.WithGas(adjusted) - _, _ = fmt.Fprintf(os.Stderr, "%s\n", GasEstimateResponse{GasEstimate: txf.Gas()}) - } - - tx, err := BuildUnsignedTx(txf, msgs...) - if err != nil { - return err - } - - json, err := clientCtx.TxConfig.TxJSONEncoder()(tx.GetTx()) - if err != nil { - return err - } - - return clientCtx.PrintString(fmt.Sprintf("%s\n", json)) -} - // BroadcastTx attempts to generate, sign and broadcast a transaction with the // given set of messages. It will also simulate gas requirements if necessary. // It will return an error upon failure. func BroadcastTx(clientCtx client.Context, txf Factory, msgs ...sdk.Msg) error { - txf, err := prepareFactory(clientCtx, txf) + txf, err := txf.Prepare(clientCtx) if err != nil { return err } @@ -106,7 +73,7 @@ func BroadcastTx(clientCtx client.Context, txf Factory, msgs ...sdk.Msg) error { return nil } - tx, err := BuildUnsignedTx(txf, msgs...) + tx, err := txf.BuildUnsignedTx(msgs...) if err != nil { return err } @@ -197,7 +164,7 @@ func WriteGeneratedTxResponse( } } - tx, err := BuildUnsignedTx(txf, msgs...) + tx, err := txf.BuildUnsignedTx(msgs...) if rest.CheckBadRequestError(w, err) { return } @@ -217,78 +184,12 @@ func WriteGeneratedTxResponse( _, _ = w.Write(output) } -// BuildUnsignedTx builds a transaction to be signed given a set of messages. The -// transaction is initially created via the provided factory's generator. Once -// created, the fee, memo, and messages are set. -func BuildUnsignedTx(txf Factory, msgs ...sdk.Msg) (client.TxBuilder, error) { - if txf.chainID == "" { - return nil, fmt.Errorf("chain ID required but not specified") - } - - fees := txf.fees - - if !txf.gasPrices.IsZero() { - if !fees.IsZero() { - return nil, errors.New("cannot provide both fees and gas prices") - } - - glDec := sdk.NewDec(int64(txf.gas)) - - // Derive the fees based on the provided gas prices, where - // fee = ceil(gasPrice * gasLimit). - fees = make(sdk.Coins, len(txf.gasPrices)) - - for i, gp := range txf.gasPrices { - fee := gp.Amount.Mul(glDec) - fees[i] = sdk.NewCoin(gp.Denom, fee.Ceil().RoundInt()) - } - } - - tx := txf.txConfig.NewTxBuilder() - - if err := tx.SetMsgs(msgs...); err != nil { - return nil, err - } - - tx.SetMemo(txf.memo) - tx.SetFeeAmount(fees) - tx.SetGasLimit(txf.gas) - tx.SetTimeoutHeight(txf.TimeoutHeight()) - - return tx, nil -} - -// BuildSimTx creates an unsigned tx with an empty single signature and returns -// the encoded transaction or an error if the unsigned transaction cannot be -// built. -func BuildSimTx(txf Factory, msgs ...sdk.Msg) ([]byte, error) { - txb, err := BuildUnsignedTx(txf, msgs...) - if err != nil { - return nil, err - } - - // Create an empty signature literal as the ante handler will populate with a - // sentinel pubkey. - sig := signing.SignatureV2{ - PubKey: &secp256k1.PubKey{}, - Data: &signing.SingleSignatureData{ - SignMode: txf.signMode, - }, - Sequence: txf.Sequence(), - } - if err := txb.SetSignatures(sig); err != nil { - return nil, err - } - - return txf.txConfig.TxEncoder()(txb.GetTx()) -} - // CalculateGas simulates the execution of a transaction and returns the // simulation response obtained by the query and the adjusted gas amount. func CalculateGas( clientCtx gogogrpc.ClientConn, txf Factory, msgs ...sdk.Msg, ) (*tx.SimulateResponse, uint64, error) { - txBytes, err := BuildSimTx(txf, msgs...) + txBytes, err := txf.BuildSimTx(msgs...) if err != nil { return nil, 0, err } @@ -304,36 +205,6 @@ func CalculateGas( return simRes, uint64(txf.GasAdjustment() * float64(simRes.GasInfo.GasUsed)), nil } -// prepareFactory ensures the account defined by ctx.GetFromAddress() exists and -// if the account number and/or the account sequence number are zero (not set), -// they will be queried for and set on the provided Factory. A new Factory with -// the updated fields will be returned. -func prepareFactory(clientCtx client.Context, txf Factory) (Factory, error) { - from := clientCtx.GetFromAddress() - - if err := txf.accountRetriever.EnsureExists(clientCtx, from); err != nil { - return txf, err - } - - initNum, initSeq := txf.accountNumber, txf.sequence - if initNum == 0 || initSeq == 0 { - num, seq, err := txf.accountRetriever.GetAccountNumberSequence(clientCtx, from) - if err != nil { - return txf, err - } - - if initNum == 0 { - txf = txf.WithAccountNumber(num) - } - - if initSeq == 0 { - txf = txf.WithSequence(seq) - } - } - - return txf, nil -} - // SignWithPrivKey signs a given tx with the given private key, and returns the // corresponding SignatureV2 if the signing is successful. func SignWithPrivKey( diff --git a/client/tx/tx_test.go b/client/tx/tx_test.go index b095d05b9e5d..54bcc7ade649 100644 --- a/client/tx/tx_test.go +++ b/client/tx/tx_test.go @@ -107,7 +107,7 @@ func TestBuildSimTx(t *testing.T) { WithSignMode(txCfg.SignModeHandler().DefaultMode()) msg := banktypes.NewMsgSend(sdk.AccAddress("from"), sdk.AccAddress("to"), nil) - bz, err := tx.BuildSimTx(txf, msg) + bz, err := txf.BuildSimTx(msg) require.NoError(t, err) require.NotNil(t, bz) } @@ -122,7 +122,7 @@ func TestBuildUnsignedTx(t *testing.T) { WithChainID("test-chain") msg := banktypes.NewMsgSend(sdk.AccAddress("from"), sdk.AccAddress("to"), nil) - tx, err := tx.BuildUnsignedTx(txf, msg) + tx, err := txf.BuildUnsignedTx(msg) require.NoError(t, err) require.NotNil(t, tx) @@ -169,11 +169,11 @@ func TestSign(t *testing.T) { WithSignMode(signingtypes.SignMode_SIGN_MODE_LEGACY_AMINO_JSON) msg1 := banktypes.NewMsgSend(info1.GetAddress(), sdk.AccAddress("to"), nil) msg2 := banktypes.NewMsgSend(info2.GetAddress(), sdk.AccAddress("to"), nil) - txb, err := tx.BuildUnsignedTx(txfNoKeybase, msg1, msg2) + txb, err := txfNoKeybase.BuildUnsignedTx(msg1, msg2) requireT.NoError(err) - txb2, err := tx.BuildUnsignedTx(txfNoKeybase, msg1, msg2) + txb2, err := txfNoKeybase.BuildUnsignedTx(msg1, msg2) requireT.NoError(err) - txbSimple, err := tx.BuildUnsignedTx(txfNoKeybase, msg2) + txbSimple, err := txfNoKeybase.BuildUnsignedTx(msg2) requireT.NoError(err) testCases := []struct { diff --git a/docs/.vuepress/config.js b/docs/.vuepress/config.js index 01ae958a804e..7721100094a9 100644 --- a/docs/.vuepress/config.js +++ b/docs/.vuepress/config.js @@ -46,6 +46,10 @@ module.exports = { "label": "v0.42", "key": "v0.42" }, + { + "label": "v0.43", + "key": "v0.43" + }, { "label": "master", "key": "master" diff --git a/docs/core/proto-docs.md b/docs/core/proto-docs.md index 6b2ddbe1e46c..87e6a2e623bd 100644 --- a/docs/core/proto-docs.md +++ b/docs/core/proto-docs.md @@ -89,12 +89,15 @@ - [GenesisState](#cosmos.bank.v1beta1.GenesisState) - [cosmos/bank/v1beta1/query.proto](#cosmos/bank/v1beta1/query.proto) + - [DenomOwner](#cosmos.bank.v1beta1.DenomOwner) - [QueryAllBalancesRequest](#cosmos.bank.v1beta1.QueryAllBalancesRequest) - [QueryAllBalancesResponse](#cosmos.bank.v1beta1.QueryAllBalancesResponse) - [QueryBalanceRequest](#cosmos.bank.v1beta1.QueryBalanceRequest) - [QueryBalanceResponse](#cosmos.bank.v1beta1.QueryBalanceResponse) - [QueryDenomMetadataRequest](#cosmos.bank.v1beta1.QueryDenomMetadataRequest) - [QueryDenomMetadataResponse](#cosmos.bank.v1beta1.QueryDenomMetadataResponse) + - [QueryDenomOwnersRequest](#cosmos.bank.v1beta1.QueryDenomOwnersRequest) + - [QueryDenomOwnersResponse](#cosmos.bank.v1beta1.QueryDenomOwnersResponse) - [QueryDenomsMetadataRequest](#cosmos.bank.v1beta1.QueryDenomsMetadataRequest) - [QueryDenomsMetadataResponse](#cosmos.bank.v1beta1.QueryDenomsMetadataResponse) - [QueryParamsRequest](#cosmos.bank.v1beta1.QueryParamsRequest) @@ -1703,6 +1706,19 @@ GenesisState defines the bank module's genesis state. + + +### DenomOwner + +DenomOwner defines structure representing an account that owns or holds a +particular denominated token. It contains the account address and account +balance of the denominated token. + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `address` | [string](#string) | | address defines the address that owns a particular denomination. | +| `balance` | [cosmos.base.v1beta1.Coin](#cosmos.base.v1beta1.Coin) | | balance is the balance of the denominated coin for an account. | + ### QueryAllBalancesRequest @@ -1798,6 +1814,40 @@ method. + + +### QueryDenomOwnersRequest +QueryDenomOwnersRequest defines the request type for the DenomOwners RPC query, +which queries for a paginated set of all account holders of a particular +denomination. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `denom` | [string](#string) | | denom defines the coin denomination to query all account holders for. | +| `pagination` | [cosmos.base.query.v1beta1.PageRequest](#cosmos.base.query.v1beta1.PageRequest) | | pagination defines an optional pagination for the request. | + + + + + + + + +### QueryDenomOwnersResponse +QueryDenomOwnersResponse defines the RPC response of a DenomOwners RPC query. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `denom_owners` | [DenomOwner](#cosmos.bank.v1beta1.DenomOwner) | repeated | | +| `pagination` | [cosmos.base.query.v1beta1.PageResponse](#cosmos.base.query.v1beta1.PageResponse) | | pagination defines the pagination in the response. | + + + + + + ### QueryDenomsMetadataRequest @@ -1938,6 +1988,7 @@ Query defines the gRPC querier service. | `Params` | [QueryParamsRequest](#cosmos.bank.v1beta1.QueryParamsRequest) | [QueryParamsResponse](#cosmos.bank.v1beta1.QueryParamsResponse) | Params queries the parameters of x/bank module. | GET|/cosmos/bank/v1beta1/params| | `DenomMetadata` | [QueryDenomMetadataRequest](#cosmos.bank.v1beta1.QueryDenomMetadataRequest) | [QueryDenomMetadataResponse](#cosmos.bank.v1beta1.QueryDenomMetadataResponse) | DenomsMetadata queries the client metadata of a given coin denomination. | GET|/cosmos/bank/v1beta1/denoms_metadata/{denom}| | `DenomsMetadata` | [QueryDenomsMetadataRequest](#cosmos.bank.v1beta1.QueryDenomsMetadataRequest) | [QueryDenomsMetadataResponse](#cosmos.bank.v1beta1.QueryDenomsMetadataResponse) | DenomsMetadata queries the client metadata for all registered coin denominations. | GET|/cosmos/bank/v1beta1/denoms_metadata| +| `DenomOwners` | [QueryDenomOwnersRequest](#cosmos.bank.v1beta1.QueryDenomOwnersRequest) | [QueryDenomOwnersResponse](#cosmos.bank.v1beta1.QueryDenomOwnersResponse) | DenomOwners queries for all account addresses that own a particular token denomination. | GET|/cosmos/bank/v1beta1/denom_owners/{denom}| @@ -8259,4 +8310,3 @@ still be used for delegating and for governance votes even while locked. | 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/docs/versions b/docs/versions index 0fc449e86f44..d01230080817 100644 --- a/docs/versions +++ b/docs/versions @@ -1,3 +1,4 @@ master master launchpad/backports v0.39 release/v0.42.x v0.42 +release/v0.43.x v0.43 diff --git a/proto/cosmos/bank/v1beta1/query.proto b/proto/cosmos/bank/v1beta1/query.proto index e3a464f8baac..9ffa9d86fd65 100644 --- a/proto/cosmos/bank/v1beta1/query.proto +++ b/proto/cosmos/bank/v1beta1/query.proto @@ -41,10 +41,17 @@ service Query { option (google.api.http).get = "/cosmos/bank/v1beta1/denoms_metadata/{denom}"; } - // DenomsMetadata queries the client metadata for all registered coin denominations. + // DenomsMetadata queries the client metadata for all registered coin + // denominations. rpc DenomsMetadata(QueryDenomsMetadataRequest) returns (QueryDenomsMetadataResponse) { option (google.api.http).get = "/cosmos/bank/v1beta1/denoms_metadata"; } + + // DenomOwners queries for all account addresses that own a particular token + // denomination. + rpc DenomOwners(QueryDenomOwnersRequest) returns (QueryDenomOwnersResponse) { + option (google.api.http).get = "/cosmos/bank/v1beta1/denom_owners/{denom}"; + } } // QueryBalanceRequest is the request type for the Query/Balance RPC method. @@ -157,3 +164,33 @@ message QueryDenomMetadataResponse { // metadata describes and provides all the client information for the requested token. Metadata metadata = 1 [(gogoproto.nullable) = false]; } + +// QueryDenomOwnersRequest defines the request type for the DenomOwners RPC query, +// which queries for a paginated set of all account holders of a particular +// denomination. +message QueryDenomOwnersRequest { + // denom defines the coin denomination to query all account holders for. + string denom = 1; + + // pagination defines an optional pagination for the request. + cosmos.base.query.v1beta1.PageRequest pagination = 2; +} + +// DenomOwner defines structure representing an account that owns or holds a +// particular denominated token. It contains the account address and account +// balance of the denominated token. +message DenomOwner { + // address defines the address that owns a particular denomination. + string address = 1; + + // balance is the balance of the denominated coin for an account. + cosmos.base.v1beta1.Coin balance = 2 [(gogoproto.nullable) = false]; +} + +// QueryDenomOwnersResponse defines the RPC response of a DenomOwners RPC query. +message QueryDenomOwnersResponse { + repeated DenomOwner denom_owners = 1; + + // pagination defines the pagination in the response. + cosmos.base.query.v1beta1.PageResponse pagination = 2; +} diff --git a/server/grpc/grpc_web_test.go b/server/grpc/grpc_web_test.go index fa657ae941ad..8fcdd216be7d 100644 --- a/server/grpc/grpc_web_test.go +++ b/server/grpc/grpc_web_test.go @@ -45,10 +45,12 @@ func (s *GRPCWebTestSuite) SetupSuite() { cfg := network.DefaultConfig() cfg.NumValidators = 1 s.cfg = cfg - s.network = network.New(s.T(), s.cfg) - s.Require().NotNil(s.network) - _, err := s.network.WaitForHeight(2) + var err error + s.network, err = network.New(s.T(), s.T().TempDir(), s.cfg) + s.Require().NoError(err) + + _, err = s.network.WaitForHeight(2) s.Require().NoError(err) s.protoCdc = codec.NewProtoCodec(s.cfg.InterfaceRegistry) diff --git a/server/grpc/server_test.go b/server/grpc/server_test.go index 7f3c7a742cb4..9867f9d08817 100644 --- a/server/grpc/server_test.go +++ b/server/grpc/server_test.go @@ -48,10 +48,12 @@ func (s *IntegrationTestSuite) SetupSuite() { s.app = simapp.Setup(false) s.cfg = network.DefaultConfig() s.cfg.NumValidators = 1 - s.network = network.New(s.T(), s.cfg) - s.Require().NotNil(s.network) - _, err := s.network.WaitForHeight(2) + var err error + s.network, err = network.New(s.T(), s.T().TempDir(), s.cfg) + s.Require().NoError(err) + + _, err = s.network.WaitForHeight(2) s.Require().NoError(err) val0 := s.network.Validators[0] diff --git a/simapp/export.go b/simapp/export.go index 8d09e333a2e1..7c59ffc69c0a 100644 --- a/simapp/export.go +++ b/simapp/export.go @@ -109,7 +109,9 @@ func (app *SimApp) prepForZeroHeightGenesis(ctx sdk.Context, jailAllowedAddrs [] feePool.CommunityPool = feePool.CommunityPool.Add(scraps...) app.DistrKeeper.SetFeePool(ctx, feePool) - app.DistrKeeper.Hooks().AfterValidatorCreated(ctx, val.GetOperator()) + if err := app.DistrKeeper.Hooks().AfterValidatorCreated(ctx, val.GetOperator()); err != nil { + panic(err) + } return false }) diff --git a/simapp/simd/cmd/root.go b/simapp/simd/cmd/root.go index 8cae91722ad4..a5bdbced5956 100644 --- a/simapp/simd/cmd/root.go +++ b/simapp/simd/cmd/root.go @@ -146,7 +146,7 @@ func initRootCmd(rootCmd *cobra.Command, encodingConfig params.EncodingConfig) { genutilcli.ValidateGenesisCmd(simapp.ModuleBasics), AddGenesisAccountCmd(simapp.DefaultNodeHome), tmcli.NewCompletionCmd(rootCmd, true), - testnetCmd(simapp.ModuleBasics, banktypes.GenesisBalancesIterator{}), + NewTestnetCmd(simapp.ModuleBasics, banktypes.GenesisBalancesIterator{}), debug.Cmd(), config.Cmd(), ) diff --git a/simapp/simd/cmd/testnet.go b/simapp/simd/cmd/testnet.go index 071d9364d0e2..d5c60f0522ea 100644 --- a/simapp/simd/cmd/testnet.go +++ b/simapp/simd/cmd/testnet.go @@ -25,6 +25,7 @@ import ( cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types" "github.com/cosmos/cosmos-sdk/server" srvconfig "github.com/cosmos/cosmos-sdk/server/config" + "github.com/cosmos/cosmos-sdk/testutil/network" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/types/module" authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" @@ -40,20 +41,78 @@ var ( flagOutputDir = "output-dir" flagNodeDaemonHome = "node-daemon-home" flagStartingIPAddress = "starting-ip-address" + flagEnableLogging = "enable-logging" + flagGRPCAddress = "grpc.address" + flagRPCAddress = "rpc.address" + flagAPIAddress = "api.address" + flagPrintMnemonic = "print-mnemonic" ) +type initArgs struct { + algo string + chainID string + keyringBackend string + minGasPrices string + nodeDaemonHome string + nodeDirPrefix string + numValidators int + outputDir string + startingIPAddress string +} + +type startArgs struct { + algo string + apiAddress string + chainID string + enableLogging bool + grpcAddress string + minGasPrices string + numValidators int + outputDir string + printMnemonic bool + rpcAddress string +} + +func addTestnetFlagsToCmd(cmd *cobra.Command) { + cmd.Flags().Int(flagNumValidators, 4, "Number of validators to initialize the testnet with") + cmd.Flags().StringP(flagOutputDir, "o", "./.testnets", "Directory to store initialization data for the testnet") + cmd.Flags().String(flags.FlagChainID, "", "genesis file chain-id, if left blank will be randomly created") + cmd.Flags().String(server.FlagMinGasPrices, fmt.Sprintf("0.000006%s", sdk.DefaultBondDenom), "Minimum gas prices to accept for transactions; All fees in a tx must meet this minimum (e.g. 0.01photino,0.001stake)") + cmd.Flags().String(flags.FlagKeyAlgorithm, string(hd.Secp256k1Type), "Key signing algorithm to generate keys for") +} + +// NewTestnetCmd creates a root testnet command with subcommands to run an in-process testnet or initialize +// validator configuration files for running a multi-validator testnet in a separate process +func NewTestnetCmd(mbm module.BasicManager, genBalIterator banktypes.GenesisBalancesIterator) *cobra.Command { + testnetCmd := &cobra.Command{ + Use: "testnet", + Short: "subcommands for starting or configuring local testnets", + DisableFlagParsing: true, + SuggestionsMinimumDistance: 2, + RunE: client.ValidateCmd, + } + + testnetCmd.AddCommand(testnetStartCmd()) + testnetCmd.AddCommand(testnetInitFilesCmd(mbm, genBalIterator)) + + return testnetCmd +} + // get cmd to initialize all files for tendermint testnet and application -func testnetCmd(mbm module.BasicManager, genBalIterator banktypes.GenesisBalancesIterator) *cobra.Command { +func testnetInitFilesCmd(mbm module.BasicManager, genBalIterator banktypes.GenesisBalancesIterator) *cobra.Command { cmd := &cobra.Command{ - Use: "testnet", - Short: "Initialize files for a simapp testnet", - Long: `testnet will create "v" number of directories and populate each with -necessary files (private validator, genesis, config, etc.). + Use: "init-files", + Short: "Initialize config directories & files for a multi-validator testnet running locally via separate processes (e.g. Docker Compose or similar)", + Long: `init-files will setup "v" number of directories and populate each with +necessary files (private validator, genesis, config, etc.) for running "v" validator nodes. + +Booting up a network with these validator folders is intended to be used with Docker Compose, +or a similar setup where each node has a manually configurable IP address. Note, strict routability for addresses is turned off in the config file. Example: - simd testnet --v 4 --output-dir ./output --starting-ip-address 192.168.10.2 + simd testnet init-files --v 4 --output-dir ./.testnets --starting-ip-address 192.168.10.2 `, RunE: func(cmd *cobra.Command, _ []string) error { clientCtx, err := client.GetClientQueryContext(cmd) @@ -64,70 +123,97 @@ Example: serverCtx := server.GetServerContextFromCmd(cmd) config := serverCtx.Config - outputDir, _ := cmd.Flags().GetString(flagOutputDir) - keyringBackend, _ := cmd.Flags().GetString(flags.FlagKeyringBackend) - chainID, _ := cmd.Flags().GetString(flags.FlagChainID) - minGasPrices, _ := cmd.Flags().GetString(server.FlagMinGasPrices) - nodeDirPrefix, _ := cmd.Flags().GetString(flagNodeDirPrefix) - nodeDaemonHome, _ := cmd.Flags().GetString(flagNodeDaemonHome) - startingIPAddress, _ := cmd.Flags().GetString(flagStartingIPAddress) - numValidators, _ := cmd.Flags().GetInt(flagNumValidators) - algo, _ := cmd.Flags().GetString(flags.FlagKeyAlgorithm) - - return InitTestnet( - clientCtx, cmd, config, mbm, genBalIterator, outputDir, chainID, minGasPrices, - nodeDirPrefix, nodeDaemonHome, startingIPAddress, keyringBackend, algo, numValidators, - ) + args := initArgs{} + args.outputDir, _ = cmd.Flags().GetString(flagOutputDir) + args.keyringBackend, _ = cmd.Flags().GetString(flags.FlagKeyringBackend) + args.chainID, _ = cmd.Flags().GetString(flags.FlagChainID) + args.minGasPrices, _ = cmd.Flags().GetString(server.FlagMinGasPrices) + args.nodeDirPrefix, _ = cmd.Flags().GetString(flagNodeDirPrefix) + args.nodeDaemonHome, _ = cmd.Flags().GetString(flagNodeDaemonHome) + args.startingIPAddress, _ = cmd.Flags().GetString(flagStartingIPAddress) + args.numValidators, _ = cmd.Flags().GetInt(flagNumValidators) + args.algo, _ = cmd.Flags().GetString(flags.FlagKeyAlgorithm) + + return initTestnetFiles(clientCtx, cmd, config, mbm, genBalIterator, args) + }, } - cmd.Flags().Int(flagNumValidators, 4, "Number of validators to initialize the testnet with") - cmd.Flags().StringP(flagOutputDir, "o", "./mytestnet", "Directory to store initialization data for the testnet") + addTestnetFlagsToCmd(cmd) cmd.Flags().String(flagNodeDirPrefix, "node", "Prefix the directory name for each node with (node results in node0, node1, ...)") cmd.Flags().String(flagNodeDaemonHome, "simd", "Home directory of the node's daemon configuration") cmd.Flags().String(flagStartingIPAddress, "192.168.0.1", "Starting IP address (192.168.0.1 results in persistent peers list ID0@192.168.0.1:46656, ID1@192.168.0.2:46656, ...)") - cmd.Flags().String(flags.FlagChainID, "", "genesis file chain-id, if left blank will be randomly created") - cmd.Flags().String(server.FlagMinGasPrices, fmt.Sprintf("0.000006%s", sdk.DefaultBondDenom), "Minimum gas prices to accept for transactions; All fees in a tx must meet this minimum (e.g. 0.01photino,0.001stake)") cmd.Flags().String(flags.FlagKeyringBackend, flags.DefaultKeyringBackend, "Select keyring's backend (os|file|test)") - cmd.Flags().String(flags.FlagKeyAlgorithm, string(hd.Secp256k1Type), "Key signing algorithm to generate keys for") return cmd } +// get cmd to start multi validator in-process testnet +func testnetStartCmd() *cobra.Command { + cmd := &cobra.Command{ + Use: "start", + Short: "Launch an in-process multi-validator testnet", + Long: `testnet will launch an in-process multi-validator testnet, +and generate "v" directories, populated with necessary validator configuration files +(private validator, genesis, config, etc.). + +Example: + simd testnet --v 4 --output-dir ./.testnets + `, + RunE: func(cmd *cobra.Command, _ []string) error { + + args := startArgs{} + args.outputDir, _ = cmd.Flags().GetString(flagOutputDir) + args.chainID, _ = cmd.Flags().GetString(flags.FlagChainID) + args.minGasPrices, _ = cmd.Flags().GetString(server.FlagMinGasPrices) + args.numValidators, _ = cmd.Flags().GetInt(flagNumValidators) + args.algo, _ = cmd.Flags().GetString(flags.FlagKeyAlgorithm) + args.enableLogging, _ = cmd.Flags().GetBool(flagEnableLogging) + args.rpcAddress, _ = cmd.Flags().GetString(flagRPCAddress) + args.apiAddress, _ = cmd.Flags().GetString(flagAPIAddress) + args.grpcAddress, _ = cmd.Flags().GetString(flagGRPCAddress) + args.printMnemonic, _ = cmd.Flags().GetBool(flagPrintMnemonic) + + return startTestnet(cmd, args) + + }, + } + + addTestnetFlagsToCmd(cmd) + cmd.Flags().Bool(flagEnableLogging, false, "Enable INFO logging of tendermint validator nodes") + cmd.Flags().String(flagRPCAddress, "tcp://0.0.0.0:26657", "the RPC address to listen on") + cmd.Flags().String(flagAPIAddress, "tcp://0.0.0.0:1317", "the address to listen on for REST API") + cmd.Flags().String(flagGRPCAddress, "0.0.0.0:9090", "the gRPC server address to listen on") + cmd.Flags().Bool(flagPrintMnemonic, true, "print mnemonic of first validator to stdout for manual testing") + return cmd +} + const nodeDirPerm = 0755 -// Initialize the testnet -func InitTestnet( +// initTestnetFiles initializes testnet files for a testnet to be run in a separate process +func initTestnetFiles( clientCtx client.Context, cmd *cobra.Command, nodeConfig *tmconfig.Config, mbm module.BasicManager, genBalIterator banktypes.GenesisBalancesIterator, - outputDir, - chainID, - minGasPrices, - nodeDirPrefix, - nodeDaemonHome, - startingIPAddress, - keyringBackend, - algoStr string, - numValidators int, + args initArgs, ) error { - if chainID == "" { - chainID = "chain-" + tmrand.NewRand().Str(6) + if args.chainID == "" { + args.chainID = "chain-" + tmrand.NewRand().Str(6) } - nodeIDs := make([]string, numValidators) - valPubKeys := make([]cryptotypes.PubKey, numValidators) + nodeIDs := make([]string, args.numValidators) + valPubKeys := make([]cryptotypes.PubKey, args.numValidators) simappConfig := srvconfig.DefaultConfig() - simappConfig.MinGasPrices = minGasPrices + simappConfig.MinGasPrices = args.minGasPrices simappConfig.API.Enable = true simappConfig.Telemetry.Enabled = true simappConfig.Telemetry.PrometheusRetentionTime = 60 simappConfig.Telemetry.EnableHostnameLabel = false - simappConfig.Telemetry.GlobalLabels = [][]string{{"chain_id", chainID}} + simappConfig.Telemetry.GlobalLabels = [][]string{{"chain_id", args.chainID}} var ( genAccounts []authtypes.GenesisAccount @@ -137,50 +223,50 @@ func InitTestnet( inBuf := bufio.NewReader(cmd.InOrStdin()) // generate private keys, node IDs, and initial transactions - for i := 0; i < numValidators; i++ { - nodeDirName := fmt.Sprintf("%s%d", nodeDirPrefix, i) - nodeDir := filepath.Join(outputDir, nodeDirName, nodeDaemonHome) - gentxsDir := filepath.Join(outputDir, "gentxs") + for i := 0; i < args.numValidators; i++ { + nodeDirName := fmt.Sprintf("%s%d", args.nodeDirPrefix, i) + nodeDir := filepath.Join(args.outputDir, nodeDirName, args.nodeDaemonHome) + gentxsDir := filepath.Join(args.outputDir, "gentxs") nodeConfig.SetRoot(nodeDir) nodeConfig.RPC.ListenAddress = "tcp://0.0.0.0:26657" if err := os.MkdirAll(filepath.Join(nodeDir, "config"), nodeDirPerm); err != nil { - _ = os.RemoveAll(outputDir) + _ = os.RemoveAll(args.outputDir) return err } nodeConfig.Moniker = nodeDirName - ip, err := getIP(i, startingIPAddress) + ip, err := getIP(i, args.startingIPAddress) if err != nil { - _ = os.RemoveAll(outputDir) + _ = os.RemoveAll(args.outputDir) return err } nodeIDs[i], valPubKeys[i], err = genutil.InitializeNodeValidatorFiles(nodeConfig) if err != nil { - _ = os.RemoveAll(outputDir) + _ = os.RemoveAll(args.outputDir) return err } memo := fmt.Sprintf("%s@%s:26656", nodeIDs[i], ip) genFiles = append(genFiles, nodeConfig.GenesisFile()) - kb, err := keyring.New(sdk.KeyringServiceName(), keyringBackend, nodeDir, inBuf) + kb, err := keyring.New(sdk.KeyringServiceName(), args.keyringBackend, nodeDir, inBuf) if err != nil { return err } keyringAlgos, _ := kb.SupportedAlgorithms() - algo, err := keyring.NewSigningAlgoFromString(algoStr, keyringAlgos) + algo, err := keyring.NewSigningAlgoFromString(args.algo, keyringAlgos) if err != nil { return err } addr, secret, err := server.GenerateSaveCoinKey(kb, nodeDirName, true, algo) if err != nil { - _ = os.RemoveAll(outputDir) + _ = os.RemoveAll(args.outputDir) return err } @@ -228,7 +314,7 @@ func InitTestnet( txFactory := tx.Factory{} txFactory = txFactory. - WithChainID(chainID). + WithChainID(args.chainID). WithMemo(memo). WithKeybase(kb). WithTxConfig(clientCtx.TxConfig) @@ -249,19 +335,19 @@ func InitTestnet( srvconfig.WriteConfigFile(filepath.Join(nodeDir, "config/app.toml"), simappConfig) } - if err := initGenFiles(clientCtx, mbm, chainID, genAccounts, genBalances, genFiles, numValidators); err != nil { + if err := initGenFiles(clientCtx, mbm, args.chainID, genAccounts, genBalances, genFiles, args.numValidators); err != nil { return err } err := collectGenFiles( - clientCtx, nodeConfig, chainID, nodeIDs, valPubKeys, numValidators, - outputDir, nodeDirPrefix, nodeDaemonHome, genBalIterator, + clientCtx, nodeConfig, args.chainID, nodeIDs, valPubKeys, args.numValidators, + args.outputDir, args.nodeDirPrefix, args.nodeDaemonHome, genBalIterator, ) if err != nil { return err } - cmd.PrintErrf("Successfully initialized %d node directories\n", numValidators) + cmd.PrintErrf("Successfully initialized %d node directories\n", args.numValidators) return nil } @@ -401,3 +487,42 @@ func writeFile(name string, dir string, contents []byte) error { return nil } + +// startTestnet starts an in-process testnet +func startTestnet(cmd *cobra.Command, args startArgs) error { + networkConfig := network.DefaultConfig() + + // Default networkConfig.ChainID is random, and we should only override it if chainID provided + // is non-empty + if args.chainID != "" { + networkConfig.ChainID = args.chainID + } + networkConfig.SigningAlgo = args.algo + networkConfig.MinGasPrices = args.minGasPrices + networkConfig.NumValidators = args.numValidators + networkConfig.EnableTMLogging = args.enableLogging + networkConfig.RPCAddress = args.rpcAddress + networkConfig.APIAddress = args.apiAddress + networkConfig.GRPCAddress = args.grpcAddress + networkConfig.PrintMnemonic = args.printMnemonic + networkLogger := network.NewCLILogger(cmd) + + baseDir := fmt.Sprintf("%s/%s", args.outputDir, networkConfig.ChainID) + if _, err := os.Stat(baseDir); !os.IsNotExist(err) { + return fmt.Errorf( + "testnests directory already exists for chain-id '%s': %s, please remove or select a new --chain-id", + networkConfig.ChainID, baseDir) + } + + testnet, err := network.New(networkLogger, baseDir, networkConfig) + if err != nil { + return err + } + + testnet.WaitForHeight(1) + cmd.Println("press the Enter Key to terminate") + fmt.Scanln() // wait for Enter Key + testnet.Cleanup() + + return nil +} diff --git a/simapp/simd/cmd/testnet_test.go b/simapp/simd/cmd/testnet_test.go index 01b25a464124..eafc3d4cdd5c 100644 --- a/simapp/simd/cmd/testnet_test.go +++ b/simapp/simd/cmd/testnet_test.go @@ -36,7 +36,7 @@ func Test_TestnetCmd(t *testing.T) { ctx := context.Background() ctx = context.WithValue(ctx, server.ServerContextKey, serverCtx) ctx = context.WithValue(ctx, client.ClientContextKey, &clientCtx) - cmd := testnetCmd(simapp.ModuleBasics, banktypes.GenesisBalancesIterator{}) + cmd := testnetInitFilesCmd(simapp.ModuleBasics, banktypes.GenesisBalancesIterator{}) cmd.SetArgs([]string{fmt.Sprintf("--%s=test", flags.FlagKeyringBackend), fmt.Sprintf("--output-dir=%s", home)}) err = cmd.ExecuteContext(ctx) require.NoError(t, err) diff --git a/simapp/test_helpers.go b/simapp/test_helpers.go index 2a8b60016168..8d7548e1026a 100644 --- a/simapp/test_helpers.go +++ b/simapp/test_helpers.go @@ -26,7 +26,6 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/types/errors" authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" - bankkeeper "github.com/cosmos/cosmos-sdk/x/bank/keeper" banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" minttypes "github.com/cosmos/cosmos-sdk/x/mint/types" stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" @@ -437,31 +436,3 @@ type EmptyAppOptions struct{} func (ao EmptyAppOptions) Get(o string) interface{} { return nil } - -// FundAccount is a utility function that funds an account by minting and -// sending the coins to the address. This should be used for testing purposes -// only! -// -// TODO: Instead of using the mint module account, which has the -// permission of minting, create a "faucet" account. (@fdymylja) -func FundAccount(bankKeeper bankkeeper.Keeper, ctx sdk.Context, addr sdk.AccAddress, amounts sdk.Coins) error { - if err := bankKeeper.MintCoins(ctx, minttypes.ModuleName, amounts); err != nil { - return err - } - - return bankKeeper.SendCoinsFromModuleToAccount(ctx, minttypes.ModuleName, addr, amounts) -} - -// FundModuleAccount is a utility function that funds a module account by -// minting and sending the coins to the address. This should be used for testing -// purposes only! -// -// TODO: Instead of using the mint module account, which has the -// permission of minting, create a "faucet" account. (@fdymylja) -func FundModuleAccount(bankKeeper bankkeeper.Keeper, ctx sdk.Context, recipientMod string, amounts sdk.Coins) error { - if err := bankKeeper.MintCoins(ctx, minttypes.ModuleName, amounts); err != nil { - return err - } - - return bankKeeper.SendCoinsFromModuleToModule(ctx, minttypes.ModuleName, recipientMod, amounts) -} diff --git a/testutil/network/network.go b/testutil/network/network.go index 28466d5facdd..738f0afd9682 100644 --- a/testutil/network/network.go +++ b/testutil/network/network.go @@ -6,16 +6,16 @@ import ( "encoding/json" "errors" "fmt" - "io/ioutil" "net/http" "net/url" "os" "path/filepath" + "strings" "sync" "testing" "time" - "github.com/stretchr/testify/require" + "github.com/spf13/cobra" tmcfg "github.com/tendermint/tendermint/config" tmflags "github.com/tendermint/tendermint/libs/cli/flags" "github.com/tendermint/tendermint/libs/log" @@ -87,10 +87,14 @@ type Config struct { StakingTokens sdk.Int // the amount of tokens each validator has available to stake BondedTokens sdk.Int // the amount of tokens each validator stakes PruningStrategy string // the pruning strategy each validator will have - EnableLogging bool // enable Tendermint logging to STDOUT + EnableTMLogging bool // enable Tendermint logging to STDOUT CleanupDir bool // remove base temporary directory during cleanup SigningAlgo string // signing algorithm for keys - KeyringOptions []keyring.Option + KeyringOptions []keyring.Option // keyring configuration options + RPCAddress string // RPC listen address (including port) + APIAddress string // REST API listen address (including port) + GRPCAddress string // GRPC server listen address (including port) + PrintMnemonic bool // print the mnemonic of first validator as log output for testing } // DefaultConfig returns a sane default configuration suitable for nearly all @@ -118,6 +122,7 @@ func DefaultConfig() Config { CleanupDir: true, SigningAlgo: string(hd.Secp256k1Type), KeyringOptions: []keyring.Option{}, + PrintMnemonic: false, } } @@ -133,7 +138,7 @@ type ( // to create networks. In addition, only the first validator will have a valid // RPC and API server/client. Network struct { - T *testing.T + Logger Logger BaseDir string Validators []*Validator @@ -165,24 +170,46 @@ type ( } ) -// New creates a new Network for integration tests. -func New(t *testing.T, cfg Config) *Network { +// Logger is a network logger interface that exposes testnet-level Log() methods for an in-process testing network +// This is not to be confused with logging that may happen at an individual node or validator level +type Logger interface { + Log(args ...interface{}) + Logf(format string, args ...interface{}) +} + +var _ Logger = (*testing.T)(nil) +var _ Logger = (*CLILogger)(nil) + +type CLILogger struct { + cmd *cobra.Command +} + +func (s CLILogger) Log(args ...interface{}) { + s.cmd.Println(args...) +} + +func (s CLILogger) Logf(format string, args ...interface{}) { + s.cmd.Printf(format, args...) +} + +func NewCLILogger(cmd *cobra.Command) CLILogger { + return CLILogger{cmd} +} + +// New creates a new Network for integration tests or in-process testnets run via the CLI +func New(l Logger, baseDir string, cfg Config) (*Network, error) { // only one caller/test can create and use a network at a time - t.Log("acquiring test network lock") + l.Log("acquiring test network lock") lock.Lock() - baseDir, err := ioutil.TempDir(t.TempDir(), cfg.ChainID) - require.NoError(t, err) - t.Logf("created temporary directory: %s", baseDir) - network := &Network{ - T: t, + Logger: l, BaseDir: baseDir, Validators: make([]*Validator, cfg.NumValidators), Config: cfg, } - t.Log("preparing test network...") + l.Logf("preparing test network with chain-id \"%s\"\n", cfg.ChainID) monikers := make([]string, cfg.NumValidators) nodeIDs := make([]string, cfg.NumValidators) @@ -215,32 +242,56 @@ func New(t *testing.T, cfg Config) *Network { tmCfg.RPC.ListenAddress = "" appCfg.GRPC.Enable = false appCfg.GRPCWeb.Enable = false + apiListenAddr := "" if i == 0 { - apiListenAddr, _, err := server.FreeTCPAddr() - require.NoError(t, err) - appCfg.API.Address = apiListenAddr + if cfg.APIAddress != "" { + apiListenAddr = cfg.APIAddress + } else { + var err error + apiListenAddr, _, err = server.FreeTCPAddr() + if err != nil { + return nil, err + } + } + appCfg.API.Address = apiListenAddr apiURL, err := url.Parse(apiListenAddr) - require.NoError(t, err) + if err != nil { + return nil, err + } apiAddr = fmt.Sprintf("http://%s:%s", apiURL.Hostname(), apiURL.Port()) - rpcAddr, _, err := server.FreeTCPAddr() - require.NoError(t, err) - tmCfg.RPC.ListenAddress = rpcAddr + if cfg.RPCAddress != "" { + tmCfg.RPC.ListenAddress = cfg.RPCAddress + } else { + rpcAddr, _, err := server.FreeTCPAddr() + if err != nil { + return nil, err + } + tmCfg.RPC.ListenAddress = rpcAddr + } - _, grpcPort, err := server.FreeTCPAddr() - require.NoError(t, err) - appCfg.GRPC.Address = fmt.Sprintf("0.0.0.0:%s", grpcPort) + if cfg.GRPCAddress != "" { + appCfg.GRPC.Address = cfg.GRPCAddress + } else { + _, grpcPort, err := server.FreeTCPAddr() + if err != nil { + return nil, err + } + appCfg.GRPC.Address = fmt.Sprintf("0.0.0.0:%s", grpcPort) + } appCfg.GRPC.Enable = true _, grpcWebPort, err := server.FreeTCPAddr() - require.NoError(t, err) + if err != nil { + return nil, err + } appCfg.GRPCWeb.Address = fmt.Sprintf("0.0.0.0:%s", grpcWebPort) appCfg.GRPCWeb.Enable = true } logger := log.NewNopLogger() - if cfg.EnableLogging { + if cfg.EnableTMLogging { logger = log.NewTMLogger(log.NewSyncWriter(os.Stdout)) logger, _ = tmflags.ParseLogLevel("info", logger, tmcfg.DefaultLogLevel) } @@ -252,44 +303,74 @@ func New(t *testing.T, cfg Config) *Network { clientDir := filepath.Join(network.BaseDir, nodeDirName, "simcli") gentxsDir := filepath.Join(network.BaseDir, "gentxs") - require.NoError(t, os.MkdirAll(filepath.Join(nodeDir, "config"), 0755)) - require.NoError(t, os.MkdirAll(clientDir, 0755)) + err := os.MkdirAll(filepath.Join(nodeDir, "config"), 0755) + if err != nil { + return nil, err + } + + err = os.MkdirAll(clientDir, 0755) + if err != nil { + return nil, err + } tmCfg.SetRoot(nodeDir) tmCfg.Moniker = nodeDirName monikers[i] = nodeDirName proxyAddr, _, err := server.FreeTCPAddr() - require.NoError(t, err) + if err != nil { + return nil, err + } tmCfg.ProxyApp = proxyAddr p2pAddr, _, err := server.FreeTCPAddr() - require.NoError(t, err) + if err != nil { + return nil, err + } tmCfg.P2P.ListenAddress = p2pAddr tmCfg.P2P.AddrBookStrict = false tmCfg.P2P.AllowDuplicateIP = true nodeID, pubKey, err := genutil.InitializeNodeValidatorFiles(tmCfg) - require.NoError(t, err) + if err != nil { + return nil, err + } nodeIDs[i] = nodeID valPubKeys[i] = pubKey kb, err := keyring.New(sdk.KeyringServiceName(), keyring.BackendTest, clientDir, buf, cfg.KeyringOptions...) - require.NoError(t, err) + if err != nil { + return nil, err + } keyringAlgos, _ := kb.SupportedAlgorithms() algo, err := keyring.NewSigningAlgoFromString(cfg.SigningAlgo, keyringAlgos) - require.NoError(t, err) + if err != nil { + return nil, err + } addr, secret, err := server.GenerateSaveCoinKey(kb, nodeDirName, true, algo) - require.NoError(t, err) + if err != nil { + return nil, err + } + + // if PrintMnemonic is set to true, we print the first validator node's secret to the network's logger + // for debugging and manual testing + if cfg.PrintMnemonic && i == 0 { + printMnemonic(l, secret) + } info := map[string]string{"secret": secret} infoBz, err := json.Marshal(info) - require.NoError(t, err) + if err != nil { + return nil, err + } // save private key seed words - require.NoError(t, writeFile(fmt.Sprintf("%v.json", "key_seed"), clientDir, infoBz)) + err = writeFile(fmt.Sprintf("%v.json", "key_seed"), clientDir, infoBz) + if err != nil { + return nil, err + } balances := sdk.NewCoins( sdk.NewCoin(fmt.Sprintf("%stoken", nodeDirName), cfg.AccountTokens), @@ -301,7 +382,9 @@ func New(t *testing.T, cfg Config) *Network { genAccounts = append(genAccounts, authtypes.NewBaseAccount(addr, nil, 0, 0)) commission, err := sdk.NewDecFromStr("0.5") - require.NoError(t, err) + if err != nil { + return nil, err + } createValMsg, err := stakingtypes.NewMsgCreateValidator( sdk.ValAddress(addr), @@ -311,15 +394,22 @@ func New(t *testing.T, cfg Config) *Network { stakingtypes.NewCommissionRates(commission, sdk.OneDec(), sdk.OneDec()), sdk.OneInt(), ) - require.NoError(t, err) + if err != nil { + return nil, err + } p2pURL, err := url.Parse(p2pAddr) - require.NoError(t, err) + if err != nil { + return nil, err + } memo := fmt.Sprintf("%s@%s:%s", nodeIDs[i], p2pURL.Hostname(), p2pURL.Port()) fee := sdk.NewCoins(sdk.NewCoin(fmt.Sprintf("%stoken", nodeDirName), sdk.NewInt(0))) txBuilder := cfg.TxConfig.NewTxBuilder() - require.NoError(t, txBuilder.SetMsgs(createValMsg)) + err = txBuilder.SetMsgs(createValMsg) + if err != nil { + return nil, err + } txBuilder.SetFeeAmount(fee) // Arbitrary fee txBuilder.SetGasLimit(1000000) // Need at least 100386 txBuilder.SetMemo(memo) @@ -332,11 +422,18 @@ func New(t *testing.T, cfg Config) *Network { WithTxConfig(cfg.TxConfig) err = tx.Sign(txFactory, nodeDirName, txBuilder, true) - require.NoError(t, err) + if err != nil { + return nil, err + } txBz, err := cfg.TxConfig.TxJSONEncoder()(txBuilder.GetTx()) - require.NoError(t, err) - require.NoError(t, writeFile(fmt.Sprintf("%v.json", nodeDirName), gentxsDir, txBz)) + if err != nil { + return nil, err + } + err = writeFile(fmt.Sprintf("%v.json", nodeDirName), gentxsDir, txBz) + if err != nil { + return nil, err + } srvconfig.WriteConfigFile(filepath.Join(nodeDir, "config/app.toml"), appCfg) @@ -367,21 +464,30 @@ func New(t *testing.T, cfg Config) *Network { } } - require.NoError(t, initGenFiles(cfg, genAccounts, genBalances, genFiles)) - require.NoError(t, collectGenFiles(cfg, network.Validators, network.BaseDir)) + err := initGenFiles(cfg, genAccounts, genBalances, genFiles) + if err != nil { + return nil, err + } + err = collectGenFiles(cfg, network.Validators, network.BaseDir) + if err != nil { + return nil, err + } - t.Log("starting test network...") + l.Log("starting test network...") for _, v := range network.Validators { - require.NoError(t, startInProcess(cfg, v)) + err := startInProcess(cfg, v) + if err != nil { + return nil, err + } } - t.Log("started test network") + l.Log("started test network") // Ensure we cleanup incase any test was abruptly halted (e.g. SIGINT) as any // defer in a test would not be called. server.TrapSignal(network.Cleanup) - return network + return network, nil } // LatestHeight returns the latest height of the network or an error if the @@ -459,10 +565,10 @@ func (n *Network) WaitForNextBlock() error { func (n *Network) Cleanup() { defer func() { lock.Unlock() - n.T.Log("released test network lock") + n.Logger.Log("released test network lock") }() - n.T.Log("cleaning up test network...") + n.Logger.Log("cleaning up test network...") for _, v := range n.Validators { if v.tmNode != nil && v.tmNode.IsRunning() { @@ -485,5 +591,47 @@ func (n *Network) Cleanup() { _ = os.RemoveAll(n.BaseDir) } - n.T.Log("finished cleaning up test network") + n.Logger.Log("finished cleaning up test network") +} + +// printMnemonic prints a provided mnemonic seed phrase on a network logger +// for debugging and manual testing +func printMnemonic(l Logger, secret string) { + lines := []string{ + "THIS MNEMONIC IS FOR TESTING PURPOSES ONLY", + "DO NOT USE IN PRODUCTION", + "", + strings.Join(strings.Fields(secret)[0:8], " "), + strings.Join(strings.Fields(secret)[8:16], " "), + strings.Join(strings.Fields(secret)[16:24], " "), + } + + lineLengths := make([]int, len(lines)) + for i, line := range lines { + lineLengths[i] = len(line) + } + + maxLineLength := 0 + for _, lineLen := range lineLengths { + if lineLen > maxLineLength { + maxLineLength = lineLen + } + } + + l.Log("\n") + l.Log(strings.Repeat("+", maxLineLength+8)) + for _, line := range lines { + l.Logf("++ %s ++\n", centerText(line, maxLineLength)) + } + l.Log(strings.Repeat("+", maxLineLength+8)) + l.Log("\n") +} + +// centerText centers text across a fixed width, filling either side with whitespace buffers +func centerText(text string, width int) string { + textLen := len(text) + leftBuffer := strings.Repeat(" ", (width-textLen)/2) + rightBuffer := strings.Repeat(" ", (width-textLen)/2+(width-textLen)%2) + + return fmt.Sprintf("%s%s%s", leftBuffer, text, rightBuffer) } diff --git a/testutil/network/network_test.go b/testutil/network/network_test.go index 3e45309f2f12..e13c8c454d28 100644 --- a/testutil/network/network_test.go +++ b/testutil/network/network_test.go @@ -20,10 +20,11 @@ type IntegrationTestSuite struct { func (s *IntegrationTestSuite) SetupSuite() { s.T().Log("setting up integration test suite") - s.network = network.New(s.T(), network.DefaultConfig()) - s.Require().NotNil(s.network) + var err error + s.network, err = network.New(s.T(), s.T().TempDir(), network.DefaultConfig()) + s.Require().NoError(err) - _, err := s.network.WaitForHeight(1) + _, err = s.network.WaitForHeight(1) s.Require().NoError(err) } diff --git a/types/query/filtered_pagination_test.go b/types/query/filtered_pagination_test.go index 913211b28472..7f462a603947 100644 --- a/types/query/filtered_pagination_test.go +++ b/types/query/filtered_pagination_test.go @@ -4,11 +4,11 @@ import ( "fmt" "github.com/cosmos/cosmos-sdk/codec" - "github.com/cosmos/cosmos-sdk/simapp" "github.com/cosmos/cosmos-sdk/store/prefix" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/types/address" "github.com/cosmos/cosmos-sdk/types/query" + "github.com/cosmos/cosmos-sdk/x/bank/testutil" "github.com/cosmos/cosmos-sdk/x/bank/types" ) @@ -32,7 +32,7 @@ func (s *paginationTestSuite) TestFilteredPaginations() { addr1 := sdk.AccAddress([]byte("addr1")) acc1 := app.AccountKeeper.NewAccountWithAddress(ctx, addr1) app.AccountKeeper.SetAccount(ctx, acc1) - s.Require().NoError(simapp.FundAccount(app.BankKeeper, ctx, addr1, balances)) + s.Require().NoError(testutil.FundAccount(app.BankKeeper, ctx, addr1, balances)) store := ctx.KVStore(app.GetKey(types.StoreKey)) // verify pagination with limit > total values @@ -107,7 +107,7 @@ func (s *paginationTestSuite) TestReverseFilteredPaginations() { addr1 := sdk.AccAddress([]byte("addr1")) acc1 := app.AccountKeeper.NewAccountWithAddress(ctx, addr1) app.AccountKeeper.SetAccount(ctx, acc1) - s.Require().NoError(simapp.FundAccount(app.BankKeeper, ctx, addr1, balances)) + s.Require().NoError(testutil.FundAccount(app.BankKeeper, ctx, addr1, balances)) store := ctx.KVStore(app.GetKey(types.StoreKey)) // verify pagination with limit > total values @@ -188,7 +188,7 @@ func ExampleFilteredPaginate() { addr1 := sdk.AccAddress([]byte("addr1")) acc1 := app.AccountKeeper.NewAccountWithAddress(ctx, addr1) app.AccountKeeper.SetAccount(ctx, acc1) - err := simapp.FundAccount(app.BankKeeper, ctx, addr1, balances) + err := testutil.FundAccount(app.BankKeeper, ctx, addr1, balances) if err != nil { // should return no error fmt.Println(err) } diff --git a/types/query/pagination_test.go b/types/query/pagination_test.go index da07a5e1b093..98097642a1a4 100644 --- a/types/query/pagination_test.go +++ b/types/query/pagination_test.go @@ -18,6 +18,7 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/types/address" "github.com/cosmos/cosmos-sdk/types/query" + "github.com/cosmos/cosmos-sdk/x/bank/testutil" "github.com/cosmos/cosmos-sdk/x/bank/types" ) @@ -76,7 +77,7 @@ func (s *paginationTestSuite) TestPagination() { addr1 := sdk.AccAddress(secp256k1.GenPrivKey().PubKey().Address()) acc1 := app.AccountKeeper.NewAccountWithAddress(ctx, addr1) app.AccountKeeper.SetAccount(ctx, acc1) - s.Require().NoError(simapp.FundAccount(app.BankKeeper, ctx, addr1, balances)) + s.Require().NoError(testutil.FundAccount(app.BankKeeper, ctx, addr1, balances)) s.T().Log("verify empty page request results a max of defaultLimit records and counts total records") pageReq := &query.PageRequest{} @@ -185,7 +186,7 @@ func (s *paginationTestSuite) TestReversePagination() { addr1 := sdk.AccAddress(secp256k1.GenPrivKey().PubKey().Address()) acc1 := app.AccountKeeper.NewAccountWithAddress(ctx, addr1) app.AccountKeeper.SetAccount(ctx, acc1) - s.Require().NoError(simapp.FundAccount(app.BankKeeper, ctx, addr1, balances)) + s.Require().NoError(testutil.FundAccount(app.BankKeeper, ctx, addr1, balances)) s.T().Log("verify paginate with custom limit and countTotal, Reverse false") pageReq := &query.PageRequest{Limit: 2, CountTotal: true, Reverse: true, Key: nil} @@ -306,7 +307,7 @@ func ExamplePaginate() { addr1 := sdk.AccAddress([]byte("addr1")) acc1 := app.AccountKeeper.NewAccountWithAddress(ctx, addr1) app.AccountKeeper.SetAccount(ctx, acc1) - err := simapp.FundAccount(app.BankKeeper, ctx, addr1, balances) + err := testutil.FundAccount(app.BankKeeper, ctx, addr1, balances) if err != nil { // should return no error fmt.Println(err) } diff --git a/x/auth/ante/ante_test.go b/x/auth/ante/ante_test.go index d2af80904476..3ce43a5a17e3 100644 --- a/x/auth/ante/ante_test.go +++ b/x/auth/ante/ante_test.go @@ -7,10 +7,6 @@ import ( "strings" "testing" - "github.com/cosmos/cosmos-sdk/simapp" - - minttypes "github.com/cosmos/cosmos-sdk/x/mint/types" - "github.com/stretchr/testify/require" "github.com/cosmos/cosmos-sdk/crypto/keys/ed25519" @@ -23,6 +19,8 @@ import ( "github.com/cosmos/cosmos-sdk/types/tx/signing" "github.com/cosmos/cosmos-sdk/x/auth/ante" "github.com/cosmos/cosmos-sdk/x/auth/types" + "github.com/cosmos/cosmos-sdk/x/bank/testutil" + minttypes "github.com/cosmos/cosmos-sdk/x/mint/types" ) // Test that simulate transaction accurately estimates gas cost @@ -472,7 +470,7 @@ func (suite *AnteTestSuite) TestAnteHandlerFees() { { "signer does not have enough funds to pay the fee", func() { - err := simapp.FundAccount(suite.app.BankKeeper, suite.ctx, addr0, sdk.NewCoins(sdk.NewInt64Coin("atom", 149))) + err := testutil.FundAccount(suite.app.BankKeeper, suite.ctx, addr0, sdk.NewCoins(sdk.NewInt64Coin("atom", 149))) suite.Require().NoError(err) }, false, @@ -489,7 +487,7 @@ func (suite *AnteTestSuite) TestAnteHandlerFees() { suite.Require().True(suite.app.BankKeeper.GetAllBalances(suite.ctx, modAcc.GetAddress()).Empty()) require.True(sdk.IntEq(suite.T(), suite.app.BankKeeper.GetAllBalances(suite.ctx, addr0).AmountOf("atom"), sdk.NewInt(149))) - err := simapp.FundAccount(suite.app.BankKeeper, suite.ctx, addr0, sdk.NewCoins(sdk.NewInt64Coin("atom", 1))) + err := testutil.FundAccount(suite.app.BankKeeper, suite.ctx, addr0, sdk.NewCoins(sdk.NewInt64Coin("atom", 1))) suite.Require().NoError(err) }, false, diff --git a/x/auth/ante/fee_test.go b/x/auth/ante/fee_test.go index 7edd8fad9257..06ccb4d3948f 100644 --- a/x/auth/ante/fee_test.go +++ b/x/auth/ante/fee_test.go @@ -2,10 +2,10 @@ package ante_test import ( cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types" - "github.com/cosmos/cosmos-sdk/simapp" "github.com/cosmos/cosmos-sdk/testutil/testdata" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/x/auth/ante" + "github.com/cosmos/cosmos-sdk/x/bank/testutil" ) func (suite *AnteTestSuite) TestEnsureMempoolFees() { @@ -83,7 +83,7 @@ func (suite *AnteTestSuite) TestDeductFees() { acc := suite.app.AccountKeeper.NewAccountWithAddress(suite.ctx, addr1) suite.app.AccountKeeper.SetAccount(suite.ctx, acc) coins := sdk.NewCoins(sdk.NewCoin("atom", sdk.NewInt(10))) - err = simapp.FundAccount(suite.app.BankKeeper, suite.ctx, addr1, coins) + err = testutil.FundAccount(suite.app.BankKeeper, suite.ctx, addr1, coins) suite.Require().NoError(err) dfd := ante.NewDeductFeeDecorator(suite.app.AccountKeeper, suite.app.BankKeeper, nil) @@ -95,7 +95,7 @@ func (suite *AnteTestSuite) TestDeductFees() { // Set account with sufficient funds suite.app.AccountKeeper.SetAccount(suite.ctx, acc) - err = simapp.FundAccount(suite.app.BankKeeper, suite.ctx, addr1, sdk.NewCoins(sdk.NewCoin("atom", sdk.NewInt(200)))) + err = testutil.FundAccount(suite.app.BankKeeper, suite.ctx, addr1, sdk.NewCoins(sdk.NewCoin("atom", sdk.NewInt(200)))) suite.Require().NoError(err) _, err = antehandler(suite.ctx, tx, false) diff --git a/x/auth/ante/feegrant_test.go b/x/auth/ante/feegrant_test.go index b23c2cec619d..7c03e3dbefd6 100644 --- a/x/auth/ante/feegrant_test.go +++ b/x/auth/ante/feegrant_test.go @@ -10,8 +10,6 @@ import ( "github.com/cosmos/cosmos-sdk/client" "github.com/cosmos/cosmos-sdk/codec" cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types" - - "github.com/cosmos/cosmos-sdk/simapp" "github.com/cosmos/cosmos-sdk/simapp/helpers" "github.com/cosmos/cosmos-sdk/testutil/testdata" sdk "github.com/cosmos/cosmos-sdk/types" @@ -21,6 +19,7 @@ import ( authsign "github.com/cosmos/cosmos-sdk/x/auth/signing" "github.com/cosmos/cosmos-sdk/x/auth/tx" authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" + "github.com/cosmos/cosmos-sdk/x/bank/testutil" "github.com/cosmos/cosmos-sdk/x/feegrant" ) @@ -46,11 +45,11 @@ func (suite *AnteTestSuite) TestDeductFeesNoDelegation() { priv5, _, addr5 := testdata.KeyTestPubAddr() // Set addr1 with insufficient funds - err := simapp.FundAccount(suite.app.BankKeeper, suite.ctx, addr1, []sdk.Coin{sdk.NewCoin("atom", sdk.NewInt(10))}) + err := testutil.FundAccount(suite.app.BankKeeper, suite.ctx, addr1, []sdk.Coin{sdk.NewCoin("atom", sdk.NewInt(10))}) suite.Require().NoError(err) // Set addr2 with more funds - err = simapp.FundAccount(suite.app.BankKeeper, suite.ctx, addr2, []sdk.Coin{sdk.NewCoin("atom", sdk.NewInt(99999))}) + err = testutil.FundAccount(suite.app.BankKeeper, suite.ctx, addr2, []sdk.Coin{sdk.NewCoin("atom", sdk.NewInt(99999))}) suite.Require().NoError(err) // grant fee allowance from `addr2` to `addr3` (plenty to pay) diff --git a/x/auth/client/cli/tx_multisign.go b/x/auth/client/cli/tx_multisign.go index 7fdcace968f5..5beeba3a12f4 100644 --- a/x/auth/client/cli/tx_multisign.go +++ b/x/auth/client/cli/tx_multisign.go @@ -109,6 +109,10 @@ func makeMultiSignCmd() func(cmd *cobra.Command, args []string) (err error) { return err } + if txFactory.ChainID() == "" { + return fmt.Errorf("set the chain id with either the --chain-id flag or config file") + } + signingData := signing.SignerData{ ChainID: txFactory.ChainID(), AccountNumber: txFactory.AccountNumber(), diff --git a/x/auth/client/rest/rest_test.go b/x/auth/client/rest/rest_test.go index 4d7ebf92687a..a382306e3228 100644 --- a/x/auth/client/rest/rest_test.go +++ b/x/auth/client/rest/rest_test.go @@ -48,12 +48,14 @@ func (s *IntegrationTestSuite) SetupSuite() { cfg := network.DefaultConfig() cfg.NumValidators = 2 - s.cfg = cfg - s.network = network.New(s.T(), cfg) + + var err error + s.network, err = network.New(s.T(), s.T().TempDir(), cfg) + s.Require().NoError(err) kb := s.network.Validators[0].ClientCtx.Keyring - _, _, err := kb.NewMnemonic("newAccount", keyring.English, sdk.FullFundraiserPath, keyring.DefaultBIP39Passphrase, hd.Secp256k1) + _, _, err = kb.NewMnemonic("newAccount", keyring.English, sdk.FullFundraiserPath, keyring.DefaultBIP39Passphrase, hd.Secp256k1) s.Require().NoError(err) account1, _, err := kb.NewMnemonic("newAccount1", keyring.English, sdk.FullFundraiserPath, keyring.DefaultBIP39Passphrase, hd.Secp256k1) diff --git a/x/auth/client/testutil/suite.go b/x/auth/client/testutil/suite.go index 773f8dba1ae9..c285a0841b15 100644 --- a/x/auth/client/testutil/suite.go +++ b/x/auth/client/testutil/suite.go @@ -48,10 +48,12 @@ func NewIntegrationTestSuite(cfg network.Config) *IntegrationTestSuite { func (s *IntegrationTestSuite) SetupSuite() { s.T().Log("setting up integration test suite") - s.network = network.New(s.T(), s.cfg) + var err error + s.network, err = network.New(s.T(), s.T().TempDir(), s.cfg) + s.Require().NoError(err) kb := s.network.Validators[0].ClientCtx.Keyring - _, _, err := kb.NewMnemonic("newAccount", keyring.English, sdk.FullFundraiserPath, keyring.DefaultBIP39Passphrase, hd.Secp256k1) + _, _, err = kb.NewMnemonic("newAccount", keyring.English, sdk.FullFundraiserPath, keyring.DefaultBIP39Passphrase, hd.Secp256k1) s.Require().NoError(err) account1, _, err := kb.NewMnemonic("newAccount1", keyring.English, sdk.FullFundraiserPath, keyring.DefaultBIP39Passphrase, hd.Secp256k1) diff --git a/x/auth/client/tx.go b/x/auth/client/tx.go index 80debcc1dedf..47268e643902 100644 --- a/x/auth/client/tx.go +++ b/x/auth/client/tx.go @@ -30,12 +30,6 @@ func (gr GasEstimateResponse) String() string { return fmt.Sprintf("gas estimate: %d", gr.GasEstimate) } -// PrintUnsignedStdTx builds an unsigned StdTx and prints it to os.Stdout. -func PrintUnsignedStdTx(txBldr tx.Factory, clientCtx client.Context, msgs []sdk.Msg) error { - err := tx.GenerateTx(clientCtx, txBldr, msgs...) - return err -} - // SignTx signs a transaction managed by the TxBuilder using a `name` key stored in Keybase. // The new signature is appended to the TxBuilder when overwrite=false or overwritten otherwise. // Don't perform online validation or lookups if offline is true. diff --git a/x/auth/signing/verify_test.go b/x/auth/signing/verify_test.go index 56df1811c2ab..d3f2194c141d 100644 --- a/x/auth/signing/verify_test.go +++ b/x/auth/signing/verify_test.go @@ -17,6 +17,7 @@ import ( "github.com/cosmos/cosmos-sdk/x/auth/legacy/legacytx" "github.com/cosmos/cosmos-sdk/x/auth/signing" "github.com/cosmos/cosmos-sdk/x/auth/types" + "github.com/cosmos/cosmos-sdk/x/bank/testutil" ) func TestVerifySignature(t *testing.T) { @@ -40,9 +41,9 @@ func TestVerifySignature(t *testing.T) { _ = app.AccountKeeper.NewAccountWithAddress(ctx, addr1) app.AccountKeeper.SetAccount(ctx, acc1) balances := sdk.NewCoins(sdk.NewInt64Coin("atom", 200)) - require.NoError(t, simapp.FundAccount(app.BankKeeper, ctx, addr, balances)) + require.NoError(t, testutil.FundAccount(app.BankKeeper, ctx, addr, balances)) acc, err := ante.GetSignerAcc(ctx, app.AccountKeeper, addr) - require.NoError(t, simapp.FundAccount(app.BankKeeper, ctx, addr, balances)) + require.NoError(t, testutil.FundAccount(app.BankKeeper, ctx, addr, balances)) msgs := []sdk.Msg{testdata.NewTestMsg(addr)} fee := legacytx.NewStdFee(50000, sdk.Coins{sdk.NewInt64Coin("atom", 150)}) diff --git a/x/auth/tx/service_test.go b/x/auth/tx/service_test.go index 9a4bc1d40d4b..266c81439f3d 100644 --- a/x/auth/tx/service_test.go +++ b/x/auth/tx/service_test.go @@ -49,14 +49,15 @@ func (s *IntegrationTestSuite) SetupSuite() { cfg := network.DefaultConfig() cfg.NumValidators = 1 - s.cfg = cfg - s.network = network.New(s.T(), cfg) - s.Require().NotNil(s.network) + + var err error + s.network, err = network.New(s.T(), s.T().TempDir(), s.cfg) + s.Require().NoError(err) val := s.network.Validators[0] - _, err := s.network.WaitForHeight(1) + _, err = s.network.WaitForHeight(1) s.Require().NoError(err) s.queryClient = tx.NewServiceClient(val.ClientCtx) diff --git a/x/auth/types/account_retriever_test.go b/x/auth/types/account_retriever_test.go index 1053ffdcbdf6..e756a802daff 100644 --- a/x/auth/types/account_retriever_test.go +++ b/x/auth/types/account_retriever_test.go @@ -13,10 +13,11 @@ func TestAccountRetriever(t *testing.T) { cfg := network.DefaultConfig() cfg.NumValidators = 1 - network := network.New(t, cfg) + network, err := network.New(t, t.TempDir(), cfg) + require.NoError(t, err) defer network.Cleanup() - _, err := network.WaitForHeight(3) + _, err = network.WaitForHeight(3) require.NoError(t, err) val := network.Validators[0] diff --git a/x/auth/vesting/client/testutil/suite.go b/x/auth/vesting/client/testutil/suite.go index f619f31165c8..d76090f3089c 100644 --- a/x/auth/vesting/client/testutil/suite.go +++ b/x/auth/vesting/client/testutil/suite.go @@ -27,9 +27,11 @@ func NewIntegrationTestSuite(cfg network.Config) *IntegrationTestSuite { func (s *IntegrationTestSuite) SetupSuite() { s.T().Log("setting up integration test suite") - s.network = network.New(s.T(), s.cfg) + var err error + s.network, err = network.New(s.T(), s.T().TempDir(), s.cfg) + s.Require().NoError(err) - _, err := s.network.WaitForHeight(1) + _, err = s.network.WaitForHeight(1) s.Require().NoError(err) } diff --git a/x/auth/vesting/handler_test.go b/x/auth/vesting/handler_test.go index f78a337044db..8af58073e90d 100644 --- a/x/auth/vesting/handler_test.go +++ b/x/auth/vesting/handler_test.go @@ -10,6 +10,7 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/x/auth/vesting" "github.com/cosmos/cosmos-sdk/x/auth/vesting/types" + "github.com/cosmos/cosmos-sdk/x/bank/testutil" ) type HandlerTestSuite struct { @@ -37,7 +38,7 @@ func (suite *HandlerTestSuite) TestMsgCreateVestingAccount() { acc1 := suite.app.AccountKeeper.NewAccountWithAddress(ctx, addr1) suite.app.AccountKeeper.SetAccount(ctx, acc1) - suite.Require().NoError(simapp.FundAccount(suite.app.BankKeeper, ctx, addr1, balances)) + suite.Require().NoError(testutil.FundAccount(suite.app.BankKeeper, ctx, addr1, balances)) testCases := []struct { name string diff --git a/x/authz/client/rest/grpc_query_test.go b/x/authz/client/rest/grpc_query_test.go index 3f29323815ab..2de1e713bbca 100644 --- a/x/authz/client/rest/grpc_query_test.go +++ b/x/authz/client/rest/grpc_query_test.go @@ -37,10 +37,12 @@ func (s *IntegrationTestSuite) SetupSuite() { s.T().Log("setting up integration test suite") cfg := network.DefaultConfig() - cfg.NumValidators = 1 s.cfg = cfg - s.network = network.New(s.T(), cfg) + + var err error + s.network, err = network.New(s.T(), s.T().TempDir(), cfg) + s.Require().NoError(err) val := s.network.Validators[0] // Create new account in the keyring. diff --git a/x/authz/client/testutil/tx.go b/x/authz/client/testutil/tx.go index 10932d9bda23..119edec998f0 100644 --- a/x/authz/client/testutil/tx.go +++ b/x/authz/client/testutil/tx.go @@ -38,7 +38,9 @@ func NewIntegrationTestSuite(cfg network.Config) *IntegrationTestSuite { func (s *IntegrationTestSuite) SetupSuite() { s.T().Log("setting up integration test suite") - s.network = network.New(s.T(), s.cfg) + var err error + s.network, err = network.New(s.T(), s.T().TempDir(), s.cfg) + s.Require().NoError(err) val := s.network.Validators[0] diff --git a/x/authz/keeper/keeper_test.go b/x/authz/keeper/keeper_test.go index 8dfebac95a3b..2500f7a87dcf 100644 --- a/x/authz/keeper/keeper_test.go +++ b/x/authz/keeper/keeper_test.go @@ -12,6 +12,7 @@ import ( "github.com/cosmos/cosmos-sdk/simapp" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/x/authz" + "github.com/cosmos/cosmos-sdk/x/bank/testutil" banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" ) @@ -129,7 +130,7 @@ func (s *TestSuite) TestKeeperFees() { granterAddr := addrs[0] granteeAddr := addrs[1] recipientAddr := addrs[2] - s.Require().NoError(simapp.FundAccount(app.BankKeeper, s.ctx, granterAddr, sdk.NewCoins(sdk.NewInt64Coin("steak", 10000)))) + s.Require().NoError(testutil.FundAccount(app.BankKeeper, s.ctx, granterAddr, sdk.NewCoins(sdk.NewInt64Coin("steak", 10000)))) now := s.ctx.BlockHeader().Time s.Require().NotNil(now) @@ -204,7 +205,7 @@ func (s *TestSuite) TestDispatchedEvents() { granterAddr := addrs[0] granteeAddr := addrs[1] recipientAddr := addrs[2] - require.NoError(simapp.FundAccount(app.BankKeeper, s.ctx, granterAddr, sdk.NewCoins(sdk.NewInt64Coin("steak", 10000)))) + require.NoError(testutil.FundAccount(app.BankKeeper, s.ctx, granterAddr, sdk.NewCoins(sdk.NewInt64Coin("steak", 10000)))) now := s.ctx.BlockHeader().Time require.NotNil(now) diff --git a/x/authz/simulation/operations_test.go b/x/authz/simulation/operations_test.go index bdb7f98f82db..4202eed73044 100644 --- a/x/authz/simulation/operations_test.go +++ b/x/authz/simulation/operations_test.go @@ -6,7 +6,6 @@ import ( "time" "github.com/stretchr/testify/suite" - abci "github.com/tendermint/tendermint/abci/types" tmproto "github.com/tendermint/tendermint/proto/tendermint/types" @@ -15,6 +14,7 @@ import ( simtypes "github.com/cosmos/cosmos-sdk/types/simulation" "github.com/cosmos/cosmos-sdk/x/authz" "github.com/cosmos/cosmos-sdk/x/authz/simulation" + "github.com/cosmos/cosmos-sdk/x/bank/testutil" banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" ) @@ -76,7 +76,7 @@ func (suite *SimTestSuite) getTestingAccounts(r *rand.Rand, n int) []simtypes.Ac for _, account := range accounts { acc := suite.app.AccountKeeper.NewAccountWithAddress(suite.ctx, account.Address) suite.app.AccountKeeper.SetAccount(suite.ctx, acc) - suite.Require().NoError(simapp.FundAccount(suite.app.BankKeeper, suite.ctx, account.Address, initCoins)) + suite.Require().NoError(testutil.FundAccount(suite.app.BankKeeper, suite.ctx, account.Address, initCoins)) } return accounts diff --git a/x/bank/app_test.go b/x/bank/app_test.go index ba8085026a5c..5e134010e483 100644 --- a/x/bank/app_test.go +++ b/x/bank/app_test.go @@ -11,6 +11,7 @@ import ( "github.com/cosmos/cosmos-sdk/simapp" sdk "github.com/cosmos/cosmos-sdk/types" authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" + "github.com/cosmos/cosmos-sdk/x/bank/testutil" "github.com/cosmos/cosmos-sdk/x/bank/types" ) @@ -94,7 +95,7 @@ func TestSendNotEnoughBalance(t *testing.T) { app := simapp.SetupWithGenesisAccounts(genAccs) ctx := app.BaseApp.NewContext(false, tmproto.Header{}) - require.NoError(t, simapp.FundAccount(app.BankKeeper, ctx, addr1, sdk.NewCoins(sdk.NewInt64Coin("foocoin", 67)))) + require.NoError(t, testutil.FundAccount(app.BankKeeper, ctx, addr1, sdk.NewCoins(sdk.NewInt64Coin("foocoin", 67)))) app.Commit() @@ -129,7 +130,7 @@ func TestMsgMultiSendWithAccounts(t *testing.T) { app := simapp.SetupWithGenesisAccounts(genAccs) ctx := app.BaseApp.NewContext(false, tmproto.Header{}) - require.NoError(t, simapp.FundAccount(app.BankKeeper, ctx, addr1, sdk.NewCoins(sdk.NewInt64Coin("foocoin", 67)))) + require.NoError(t, testutil.FundAccount(app.BankKeeper, ctx, addr1, sdk.NewCoins(sdk.NewInt64Coin("foocoin", 67)))) app.Commit() @@ -199,9 +200,9 @@ func TestMsgMultiSendMultipleOut(t *testing.T) { app := simapp.SetupWithGenesisAccounts(genAccs) ctx := app.BaseApp.NewContext(false, tmproto.Header{}) - require.NoError(t, simapp.FundAccount(app.BankKeeper, ctx, addr1, sdk.NewCoins(sdk.NewInt64Coin("foocoin", 42)))) + require.NoError(t, testutil.FundAccount(app.BankKeeper, ctx, addr1, sdk.NewCoins(sdk.NewInt64Coin("foocoin", 42)))) - require.NoError(t, simapp.FundAccount(app.BankKeeper, ctx, addr2, sdk.NewCoins(sdk.NewInt64Coin("foocoin", 42)))) + require.NoError(t, testutil.FundAccount(app.BankKeeper, ctx, addr2, sdk.NewCoins(sdk.NewInt64Coin("foocoin", 42)))) app.Commit() @@ -248,11 +249,11 @@ func TestMsgMultiSendMultipleInOut(t *testing.T) { app := simapp.SetupWithGenesisAccounts(genAccs) ctx := app.BaseApp.NewContext(false, tmproto.Header{}) - require.NoError(t, simapp.FundAccount(app.BankKeeper, ctx, addr1, sdk.NewCoins(sdk.NewInt64Coin("foocoin", 42)))) + require.NoError(t, testutil.FundAccount(app.BankKeeper, ctx, addr1, sdk.NewCoins(sdk.NewInt64Coin("foocoin", 42)))) - require.NoError(t, simapp.FundAccount(app.BankKeeper, ctx, addr2, sdk.NewCoins(sdk.NewInt64Coin("foocoin", 42)))) + require.NoError(t, testutil.FundAccount(app.BankKeeper, ctx, addr2, sdk.NewCoins(sdk.NewInt64Coin("foocoin", 42)))) - require.NoError(t, simapp.FundAccount(app.BankKeeper, ctx, addr4, sdk.NewCoins(sdk.NewInt64Coin("foocoin", 42)))) + require.NoError(t, testutil.FundAccount(app.BankKeeper, ctx, addr4, sdk.NewCoins(sdk.NewInt64Coin("foocoin", 42)))) app.Commit() @@ -295,7 +296,7 @@ func TestMsgMultiSendDependent(t *testing.T) { app := simapp.SetupWithGenesisAccounts(genAccs) ctx := app.BaseApp.NewContext(false, tmproto.Header{}) - require.NoError(t, simapp.FundAccount(app.BankKeeper, ctx, addr1, sdk.NewCoins(sdk.NewInt64Coin("foocoin", 42)))) + require.NoError(t, testutil.FundAccount(app.BankKeeper, ctx, addr1, sdk.NewCoins(sdk.NewInt64Coin("foocoin", 42)))) app.Commit() diff --git a/x/bank/bench_test.go b/x/bank/bench_test.go index 4ba2624b7627..3550f44f7b2a 100644 --- a/x/bank/bench_test.go +++ b/x/bank/bench_test.go @@ -12,6 +12,7 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/x/auth/types" authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" + "github.com/cosmos/cosmos-sdk/x/bank/testutil" stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" ) @@ -30,7 +31,7 @@ func BenchmarkOneBankSendTxPerBlock(b *testing.B) { ctx := benchmarkApp.BaseApp.NewContext(false, tmproto.Header{}) // some value conceivably higher than the benchmarks would ever go - require.NoError(b, simapp.FundAccount(benchmarkApp.BankKeeper, ctx, addr1, sdk.NewCoins(sdk.NewInt64Coin("foocoin", 100000000000)))) + require.NoError(b, testutil.FundAccount(benchmarkApp.BankKeeper, ctx, addr1, sdk.NewCoins(sdk.NewInt64Coin("foocoin", 100000000000)))) benchmarkApp.Commit() txGen := simappparams.MakeTestEncodingConfig().TxConfig @@ -72,7 +73,7 @@ func BenchmarkOneBankMultiSendTxPerBlock(b *testing.B) { ctx := benchmarkApp.BaseApp.NewContext(false, tmproto.Header{}) // some value conceivably higher than the benchmarks would ever go - require.NoError(b, simapp.FundAccount(benchmarkApp.BankKeeper, ctx, addr1, sdk.NewCoins(sdk.NewInt64Coin("foocoin", 100000000000)))) + require.NoError(b, testutil.FundAccount(benchmarkApp.BankKeeper, ctx, addr1, sdk.NewCoins(sdk.NewInt64Coin("foocoin", 100000000000)))) benchmarkApp.Commit() txGen := simappparams.MakeTestEncodingConfig().TxConfig diff --git a/x/bank/client/rest/query_test.go b/x/bank/client/rest/query_test.go index a9e43a53db86..ef9e26d5072a 100644 --- a/x/bank/client/rest/query_test.go +++ b/x/bank/client/rest/query_test.go @@ -58,9 +58,10 @@ func (s *IntegrationTestSuite) SetupSuite() { s.Require().NoError(err) genesisState[types.ModuleName] = bankGenesisBz cfg.GenesisState = genesisState - s.cfg = cfg - s.network = network.New(s.T(), cfg) + + s.network, err = network.New(s.T(), s.T().TempDir(), cfg) + s.Require().NoError(err) _, err = s.network.WaitForHeight(2) s.Require().NoError(err) diff --git a/x/bank/client/testutil/suite.go b/x/bank/client/testutil/suite.go index 19be5401c672..da09851701c1 100644 --- a/x/bank/client/testutil/suite.go +++ b/x/bank/client/testutil/suite.go @@ -80,7 +80,8 @@ func (s *IntegrationTestSuite) SetupSuite() { genesisState[types.ModuleName] = bankGenesisBz s.cfg.GenesisState = genesisState - s.network = network.New(s.T(), s.cfg) + s.network, err = network.New(s.T(), s.T().TempDir(), s.cfg) + s.Require().NoError(err) _, err = s.network.WaitForHeight(1) s.Require().NoError(err) diff --git a/x/bank/keeper/grpc_query.go b/x/bank/keeper/grpc_query.go index 02655aa2f595..53c192954f6a 100644 --- a/x/bank/keeper/grpc_query.go +++ b/x/bank/keeper/grpc_query.go @@ -164,3 +164,61 @@ func (k BaseKeeper) DenomMetadata(c context.Context, req *types.QueryDenomMetada Metadata: metadata, }, nil } + +func (k BaseKeeper) DenomOwners( + goCtx context.Context, + req *types.QueryDenomOwnersRequest, +) (*types.QueryDenomOwnersResponse, error) { + + if req == nil { + return nil, status.Errorf(codes.InvalidArgument, "empty request") + } + + if req.Denom == "" { + return nil, status.Error(codes.InvalidArgument, "empty denom") + } + + ctx := sdk.UnwrapSDKContext(goCtx) + + store := ctx.KVStore(k.storeKey) + balancesStore := prefix.NewStore(store, types.BalancesPrefix) + + var denomOwners []*types.DenomOwner + pageRes, err := query.FilteredPaginate( + balancesStore, + req.Pagination, + func(key []byte, value []byte, accumulate bool) (bool, error) { + var balance sdk.Coin + if err := k.cdc.Unmarshal(value, &balance); err != nil { + return false, err + } + + if req.Denom != balance.Denom { + return false, nil + } + + if accumulate { + address, err := types.AddressFromBalancesStore(key) + if err != nil { + return false, err + } + + denomOwners = append( + denomOwners, + &types.DenomOwner{ + Address: address.String(), + Balance: balance, + }, + ) + } + + return true, nil + }, + ) + + if err != nil { + return nil, status.Error(codes.Internal, err.Error()) + } + + return &types.QueryDenomOwnersResponse{DenomOwners: denomOwners, Pagination: pageRes}, nil +} diff --git a/x/bank/keeper/grpc_query_test.go b/x/bank/keeper/grpc_query_test.go index 181506a6d7fb..50be8cea940e 100644 --- a/x/bank/keeper/grpc_query_test.go +++ b/x/bank/keeper/grpc_query_test.go @@ -4,14 +4,13 @@ import ( gocontext "context" "fmt" - "github.com/cosmos/cosmos-sdk/simapp" - - minttypes "github.com/cosmos/cosmos-sdk/x/mint/types" - "github.com/cosmos/cosmos-sdk/testutil/testdata" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/types/query" + authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" + "github.com/cosmos/cosmos-sdk/x/bank/testutil" "github.com/cosmos/cosmos-sdk/x/bank/types" + minttypes "github.com/cosmos/cosmos-sdk/x/mint/types" ) func (suite *IntegrationTestSuite) TestQueryBalance() { @@ -34,7 +33,7 @@ func (suite *IntegrationTestSuite) TestQueryBalance() { acc := app.AccountKeeper.NewAccountWithAddress(ctx, addr) app.AccountKeeper.SetAccount(ctx, acc) - suite.Require().NoError(simapp.FundAccount(app.BankKeeper, ctx, acc.GetAddress(), origCoins)) + suite.Require().NoError(testutil.FundAccount(app.BankKeeper, ctx, acc.GetAddress(), origCoins)) res, err = queryClient.Balance(gocontext.Background(), req) suite.Require().NoError(err) @@ -66,7 +65,7 @@ func (suite *IntegrationTestSuite) TestQueryAllBalances() { acc := app.AccountKeeper.NewAccountWithAddress(ctx, addr) app.AccountKeeper.SetAccount(ctx, acc) - suite.Require().NoError(simapp.FundAccount(app.BankKeeper, ctx, acc.GetAddress(), origCoins)) + suite.Require().NoError(testutil.FundAccount(app.BankKeeper, ctx, acc.GetAddress(), origCoins)) res, err = queryClient.AllBalances(gocontext.Background(), req) suite.Require().NoError(err) @@ -305,3 +304,92 @@ func (suite *IntegrationTestSuite) QueryDenomMetadataRequest() { }) } } + +func (suite *IntegrationTestSuite) TestGRPCDenomOwners() { + ctx := suite.ctx + + authKeeper, keeper := suite.initKeepersWithmAccPerms(make(map[string]bool)) + suite.Require().NoError(keeper.MintCoins(ctx, minttypes.ModuleName, initCoins)) + + for i := 0; i < 10; i++ { + acc := authKeeper.NewAccountWithAddress(ctx, authtypes.NewModuleAddress(fmt.Sprintf("account-%d", i))) + authKeeper.SetAccount(ctx, acc) + + bal := sdk.NewCoins(sdk.NewCoin( + sdk.DefaultBondDenom, + sdk.TokensFromConsensusPower(initialPower/10, sdk.DefaultPowerReduction), + )) + suite.Require().NoError(keeper.SendCoinsFromModuleToAccount(ctx, minttypes.ModuleName, acc.GetAddress(), bal)) + } + + testCases := map[string]struct { + req *types.QueryDenomOwnersRequest + expPass bool + numAddrs int + hasNext bool + total uint64 + }{ + "empty request": { + req: &types.QueryDenomOwnersRequest{}, + expPass: false, + }, + "invalid denom": { + req: &types.QueryDenomOwnersRequest{ + Denom: "foo", + }, + expPass: true, + numAddrs: 0, + hasNext: false, + total: 0, + }, + "valid request - page 1": { + req: &types.QueryDenomOwnersRequest{ + Denom: sdk.DefaultBondDenom, + Pagination: &query.PageRequest{ + Limit: 6, + CountTotal: true, + }, + }, + expPass: true, + numAddrs: 6, + hasNext: true, + total: 10, + }, + "valid request - page 2": { + req: &types.QueryDenomOwnersRequest{ + Denom: sdk.DefaultBondDenom, + Pagination: &query.PageRequest{ + Offset: 6, + Limit: 10, + CountTotal: true, + }, + }, + expPass: true, + numAddrs: 4, + hasNext: false, + total: 10, + }, + } + + for name, tc := range testCases { + suite.Run(name, func() { + resp, err := suite.queryClient.DenomOwners(gocontext.Background(), tc.req) + if tc.expPass { + suite.NoError(err) + suite.NotNil(resp) + suite.Len(resp.DenomOwners, tc.numAddrs) + suite.Equal(tc.total, resp.Pagination.Total) + + if tc.hasNext { + suite.NotNil(resp.Pagination.NextKey) + } else { + suite.Nil(resp.Pagination.NextKey) + } + } else { + suite.Require().Error(err) + } + }) + } + + suite.Require().True(true) +} diff --git a/x/bank/keeper/keeper_test.go b/x/bank/keeper/keeper_test.go index 576968fd3275..d7f840f9e1f8 100644 --- a/x/bank/keeper/keeper_test.go +++ b/x/bank/keeper/keeper_test.go @@ -4,11 +4,6 @@ import ( "testing" "time" - "github.com/cosmos/cosmos-sdk/types/query" - - "github.com/cosmos/cosmos-sdk/x/auth/vesting/exported" - minttypes "github.com/cosmos/cosmos-sdk/x/mint/types" - "github.com/stretchr/testify/suite" abci "github.com/tendermint/tendermint/abci/types" tmproto "github.com/tendermint/tendermint/proto/tendermint/types" @@ -17,11 +12,15 @@ import ( "github.com/cosmos/cosmos-sdk/baseapp" "github.com/cosmos/cosmos-sdk/simapp" sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/types/query" authkeeper "github.com/cosmos/cosmos-sdk/x/auth/keeper" authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" + "github.com/cosmos/cosmos-sdk/x/auth/vesting/exported" vesting "github.com/cosmos/cosmos-sdk/x/auth/vesting/types" "github.com/cosmos/cosmos-sdk/x/bank/keeper" + "github.com/cosmos/cosmos-sdk/x/bank/testutil" "github.com/cosmos/cosmos-sdk/x/bank/types" + minttypes "github.com/cosmos/cosmos-sdk/x/mint/types" ) const ( @@ -310,7 +309,7 @@ func (suite *IntegrationTestSuite) TestSendCoinsNewAccount() { addr1 := sdk.AccAddress([]byte("addr1_______________")) acc1 := app.AccountKeeper.NewAccountWithAddress(ctx, addr1) app.AccountKeeper.SetAccount(ctx, acc1) - suite.Require().NoError(simapp.FundAccount(app.BankKeeper, ctx, addr1, balances)) + suite.Require().NoError(testutil.FundAccount(app.BankKeeper, ctx, addr1, balances)) acc1Balances := app.BankKeeper.GetAllBalances(ctx, addr1) suite.Require().Equal(balances, acc1Balances) @@ -340,7 +339,7 @@ func (suite *IntegrationTestSuite) TestInputOutputNewAccount() { addr1 := sdk.AccAddress([]byte("addr1_______________")) acc1 := app.AccountKeeper.NewAccountWithAddress(ctx, addr1) app.AccountKeeper.SetAccount(ctx, acc1) - suite.Require().NoError(simapp.FundAccount(app.BankKeeper, ctx, addr1, balances)) + suite.Require().NoError(testutil.FundAccount(app.BankKeeper, ctx, addr1, balances)) acc1Balances := app.BankKeeper.GetAllBalances(ctx, addr1) suite.Require().Equal(balances, acc1Balances) @@ -393,7 +392,7 @@ func (suite *IntegrationTestSuite) TestInputOutputCoins() { suite.Require().Error(app.BankKeeper.InputOutputCoins(ctx, inputs, []types.Output{})) suite.Require().Error(app.BankKeeper.InputOutputCoins(ctx, inputs, outputs)) - suite.Require().NoError(simapp.FundAccount(app.BankKeeper, ctx, addr1, balances)) + suite.Require().NoError(testutil.FundAccount(app.BankKeeper, ctx, addr1, balances)) insufficientInputs := []types.Input{ {Address: addr1.String(), Coins: sdk.NewCoins(newFooCoin(300), newBarCoin(100))}, @@ -428,12 +427,12 @@ func (suite *IntegrationTestSuite) TestSendCoins() { addr2 := sdk.AccAddress("addr2_______________") acc2 := app.AccountKeeper.NewAccountWithAddress(ctx, addr2) app.AccountKeeper.SetAccount(ctx, acc2) - suite.Require().NoError(simapp.FundAccount(app.BankKeeper, ctx, addr2, balances)) + suite.Require().NoError(testutil.FundAccount(app.BankKeeper, ctx, addr2, balances)) sendAmt := sdk.NewCoins(newFooCoin(50), newBarCoin(25)) suite.Require().Error(app.BankKeeper.SendCoins(ctx, addr1, addr2, sendAmt)) - suite.Require().NoError(simapp.FundAccount(app.BankKeeper, ctx, addr1, balances)) + suite.Require().NoError(testutil.FundAccount(app.BankKeeper, ctx, addr1, balances)) suite.Require().NoError(app.BankKeeper.SendCoins(ctx, addr1, addr2, sendAmt)) acc1Balances := app.BankKeeper.GetAllBalances(ctx, addr1) @@ -469,14 +468,14 @@ func (suite *IntegrationTestSuite) TestValidateBalance() { app.AccountKeeper.SetAccount(ctx, acc) balances := sdk.NewCoins(newFooCoin(100)) - suite.Require().NoError(simapp.FundAccount(app.BankKeeper, ctx, addr1, balances)) + suite.Require().NoError(testutil.FundAccount(app.BankKeeper, ctx, addr1, balances)) suite.Require().NoError(app.BankKeeper.ValidateBalance(ctx, addr1)) bacc := authtypes.NewBaseAccountWithAddress(addr2) vacc := vesting.NewContinuousVestingAccount(bacc, balances.Add(balances...), now.Unix(), endTime.Unix()) app.AccountKeeper.SetAccount(ctx, vacc) - suite.Require().NoError(simapp.FundAccount(app.BankKeeper, ctx, addr2, balances)) + suite.Require().NoError(testutil.FundAccount(app.BankKeeper, ctx, addr2, balances)) suite.Require().Error(app.BankKeeper.ValidateBalance(ctx, addr2)) } @@ -533,7 +532,7 @@ func (suite *IntegrationTestSuite) TestHasBalance() { balances := sdk.NewCoins(newFooCoin(100)) suite.Require().False(app.BankKeeper.HasBalance(ctx, addr, newFooCoin(99))) - suite.Require().NoError(simapp.FundAccount(app.BankKeeper, ctx, addr, balances)) + suite.Require().NoError(testutil.FundAccount(app.BankKeeper, ctx, addr, balances)) suite.Require().False(app.BankKeeper.HasBalance(ctx, addr, newFooCoin(101))) suite.Require().True(app.BankKeeper.HasBalance(ctx, addr, newFooCoin(100))) suite.Require().True(app.BankKeeper.HasBalance(ctx, addr, newFooCoin(1))) @@ -547,7 +546,7 @@ func (suite *IntegrationTestSuite) TestMsgSendEvents() { app.AccountKeeper.SetAccount(ctx, acc) newCoins := sdk.NewCoins(sdk.NewInt64Coin(fooDenom, 50)) - suite.Require().NoError(simapp.FundAccount(app.BankKeeper, ctx, addr, newCoins)) + suite.Require().NoError(testutil.FundAccount(app.BankKeeper, ctx, addr, newCoins)) suite.Require().NoError(app.BankKeeper.SendCoins(ctx, addr, addr2, newCoins)) event1 := sdk.Event{ @@ -615,7 +614,7 @@ func (suite *IntegrationTestSuite) TestMsgMultiSendEvents() { suite.Require().Equal(0, len(events)) // Set addr's coins but not addr2's coins - suite.Require().NoError(simapp.FundAccount(app.BankKeeper, ctx, addr, sdk.NewCoins(sdk.NewInt64Coin(fooDenom, 50)))) + suite.Require().NoError(testutil.FundAccount(app.BankKeeper, ctx, addr, sdk.NewCoins(sdk.NewInt64Coin(fooDenom, 50)))) suite.Require().Error(app.BankKeeper.InputOutputCoins(ctx, inputs, outputs)) events = ctx.EventManager().ABCIEvents() @@ -632,10 +631,10 @@ func (suite *IntegrationTestSuite) TestMsgMultiSendEvents() { suite.Require().Equal(abci.Event(event1), events[7]) // Set addr's coins and addr2's coins - suite.Require().NoError(simapp.FundAccount(app.BankKeeper, ctx, addr, sdk.NewCoins(sdk.NewInt64Coin(fooDenom, 50)))) + suite.Require().NoError(testutil.FundAccount(app.BankKeeper, ctx, addr, sdk.NewCoins(sdk.NewInt64Coin(fooDenom, 50)))) newCoins = sdk.NewCoins(sdk.NewInt64Coin(fooDenom, 50)) - suite.Require().NoError(simapp.FundAccount(app.BankKeeper, ctx, addr2, sdk.NewCoins(sdk.NewInt64Coin(barDenom, 100)))) + suite.Require().NoError(testutil.FundAccount(app.BankKeeper, ctx, addr2, sdk.NewCoins(sdk.NewInt64Coin(barDenom, 100)))) newCoins2 = sdk.NewCoins(sdk.NewInt64Coin(barDenom, 100)) suite.Require().NoError(app.BankKeeper.InputOutputCoins(ctx, inputs, outputs)) @@ -702,8 +701,8 @@ func (suite *IntegrationTestSuite) TestSpendableCoins() { app.AccountKeeper.SetAccount(ctx, macc) app.AccountKeeper.SetAccount(ctx, vacc) app.AccountKeeper.SetAccount(ctx, acc) - suite.Require().NoError(simapp.FundAccount(app.BankKeeper, ctx, addr1, origCoins)) - suite.Require().NoError(simapp.FundAccount(app.BankKeeper, ctx, addr2, origCoins)) + suite.Require().NoError(testutil.FundAccount(app.BankKeeper, ctx, addr1, origCoins)) + suite.Require().NoError(testutil.FundAccount(app.BankKeeper, ctx, addr2, origCoins)) suite.Require().Equal(origCoins, app.BankKeeper.SpendableCoins(ctx, addr2)) @@ -728,13 +727,13 @@ func (suite *IntegrationTestSuite) TestVestingAccountSend() { vacc := vesting.NewContinuousVestingAccount(bacc, origCoins, now.Unix(), endTime.Unix()) app.AccountKeeper.SetAccount(ctx, vacc) - suite.Require().NoError(simapp.FundAccount(app.BankKeeper, ctx, addr1, origCoins)) + suite.Require().NoError(testutil.FundAccount(app.BankKeeper, ctx, addr1, origCoins)) // require that no coins be sendable at the beginning of the vesting schedule suite.Require().Error(app.BankKeeper.SendCoins(ctx, addr1, addr2, sendCoins)) // receive some coins - suite.Require().NoError(simapp.FundAccount(app.BankKeeper, ctx, addr1, sendCoins)) + suite.Require().NoError(testutil.FundAccount(app.BankKeeper, ctx, addr1, sendCoins)) // require that all vested coins are spendable plus any received ctx = ctx.WithBlockTime(now.Add(12 * time.Hour)) suite.Require().NoError(app.BankKeeper.SendCoins(ctx, addr1, addr2, sendCoins)) @@ -760,13 +759,13 @@ func (suite *IntegrationTestSuite) TestPeriodicVestingAccountSend() { vacc := vesting.NewPeriodicVestingAccount(bacc, origCoins, ctx.BlockHeader().Time.Unix(), periods) app.AccountKeeper.SetAccount(ctx, vacc) - suite.Require().NoError(simapp.FundAccount(app.BankKeeper, ctx, addr1, origCoins)) + suite.Require().NoError(testutil.FundAccount(app.BankKeeper, ctx, addr1, origCoins)) // require that no coins be sendable at the beginning of the vesting schedule suite.Require().Error(app.BankKeeper.SendCoins(ctx, addr1, addr2, sendCoins)) // receive some coins - suite.Require().NoError(simapp.FundAccount(app.BankKeeper, ctx, addr1, sendCoins)) + suite.Require().NoError(testutil.FundAccount(app.BankKeeper, ctx, addr1, sendCoins)) // require that all vested coins are spendable plus any received ctx = ctx.WithBlockTime(now.Add(12 * time.Hour)) @@ -792,8 +791,8 @@ func (suite *IntegrationTestSuite) TestVestingAccountReceive() { app.AccountKeeper.SetAccount(ctx, vacc) app.AccountKeeper.SetAccount(ctx, acc) - suite.Require().NoError(simapp.FundAccount(app.BankKeeper, ctx, addr1, origCoins)) - suite.Require().NoError(simapp.FundAccount(app.BankKeeper, ctx, addr2, origCoins)) + suite.Require().NoError(testutil.FundAccount(app.BankKeeper, ctx, addr1, origCoins)) + suite.Require().NoError(testutil.FundAccount(app.BankKeeper, ctx, addr2, origCoins)) // send some coins to the vesting account suite.Require().NoError(app.BankKeeper.SendCoins(ctx, addr2, addr1, sendCoins)) @@ -831,8 +830,8 @@ func (suite *IntegrationTestSuite) TestPeriodicVestingAccountReceive() { app.AccountKeeper.SetAccount(ctx, vacc) app.AccountKeeper.SetAccount(ctx, acc) - suite.Require().NoError(simapp.FundAccount(app.BankKeeper, ctx, addr1, origCoins)) - suite.Require().NoError(simapp.FundAccount(app.BankKeeper, ctx, addr2, origCoins)) + suite.Require().NoError(testutil.FundAccount(app.BankKeeper, ctx, addr1, origCoins)) + suite.Require().NoError(testutil.FundAccount(app.BankKeeper, ctx, addr2, origCoins)) // send some coins to the vesting account suite.Require().NoError(app.BankKeeper.SendCoins(ctx, addr2, addr1, sendCoins)) @@ -868,8 +867,8 @@ func (suite *IntegrationTestSuite) TestDelegateCoins() { app.AccountKeeper.SetAccount(ctx, vacc) app.AccountKeeper.SetAccount(ctx, acc) app.AccountKeeper.SetAccount(ctx, macc) - suite.Require().NoError(simapp.FundAccount(app.BankKeeper, ctx, addr1, origCoins)) - suite.Require().NoError(simapp.FundAccount(app.BankKeeper, ctx, addr2, origCoins)) + suite.Require().NoError(testutil.FundAccount(app.BankKeeper, ctx, addr1, origCoins)) + suite.Require().NoError(testutil.FundAccount(app.BankKeeper, ctx, addr2, origCoins)) ctx = ctx.WithBlockTime(now.Add(12 * time.Hour)) @@ -932,8 +931,8 @@ func (suite *IntegrationTestSuite) TestUndelegateCoins() { app.AccountKeeper.SetAccount(ctx, vacc) app.AccountKeeper.SetAccount(ctx, acc) app.AccountKeeper.SetAccount(ctx, macc) - suite.Require().NoError(simapp.FundAccount(app.BankKeeper, ctx, addr1, origCoins)) - suite.Require().NoError(simapp.FundAccount(app.BankKeeper, ctx, addr2, origCoins)) + suite.Require().NoError(testutil.FundAccount(app.BankKeeper, ctx, addr1, origCoins)) + suite.Require().NoError(testutil.FundAccount(app.BankKeeper, ctx, addr2, origCoins)) ctx = ctx.WithBlockTime(now.Add(12 * time.Hour)) @@ -983,7 +982,7 @@ func (suite *IntegrationTestSuite) TestUndelegateCoins_Invalid() { suite.Require().Error(app.BankKeeper.UndelegateCoins(ctx, addrModule, addr1, delCoins)) app.AccountKeeper.SetAccount(ctx, macc) - suite.Require().NoError(simapp.FundAccount(app.BankKeeper, ctx, addr1, origCoins)) + suite.Require().NoError(testutil.FundAccount(app.BankKeeper, ctx, addr1, origCoins)) suite.Require().Error(app.BankKeeper.UndelegateCoins(ctx, addrModule, addr1, delCoins)) app.AccountKeeper.SetAccount(ctx, acc) diff --git a/x/bank/keeper/querier_test.go b/x/bank/keeper/querier_test.go index 66f98fdd17f8..8404ed360f2f 100644 --- a/x/bank/keeper/querier_test.go +++ b/x/bank/keeper/querier_test.go @@ -5,11 +5,11 @@ import ( abci "github.com/tendermint/tendermint/abci/types" - "github.com/cosmos/cosmos-sdk/simapp" "github.com/cosmos/cosmos-sdk/testutil/testdata" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/types/query" "github.com/cosmos/cosmos-sdk/x/bank/keeper" + "github.com/cosmos/cosmos-sdk/x/bank/testutil" "github.com/cosmos/cosmos-sdk/x/bank/types" minttypes "github.com/cosmos/cosmos-sdk/x/mint/types" ) @@ -42,7 +42,7 @@ func (suite *IntegrationTestSuite) TestQuerier_QueryBalance() { acc := app.AccountKeeper.NewAccountWithAddress(ctx, addr) app.AccountKeeper.SetAccount(ctx, acc) - suite.Require().NoError(simapp.FundAccount(app.BankKeeper, ctx, acc.GetAddress(), origCoins)) + suite.Require().NoError(testutil.FundAccount(app.BankKeeper, ctx, acc.GetAddress(), origCoins)) res, err = querier(ctx, []string{types.QueryBalance}, req) suite.Require().NoError(err) @@ -79,7 +79,7 @@ func (suite *IntegrationTestSuite) TestQuerier_QueryAllBalances() { acc := app.AccountKeeper.NewAccountWithAddress(ctx, addr) app.AccountKeeper.SetAccount(ctx, acc) - suite.Require().NoError(simapp.FundAccount(app.BankKeeper, ctx, acc.GetAddress(), origCoins)) + suite.Require().NoError(testutil.FundAccount(app.BankKeeper, ctx, acc.GetAddress(), origCoins)) res, err = querier(ctx, []string{types.QueryAllBalances}, req) suite.Require().NoError(err) suite.Require().NotNil(res) diff --git a/x/bank/simulation/operations_test.go b/x/bank/simulation/operations_test.go index aeaa9f938905..b00716d27d9f 100644 --- a/x/bank/simulation/operations_test.go +++ b/x/bank/simulation/operations_test.go @@ -13,6 +13,7 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" simtypes "github.com/cosmos/cosmos-sdk/types/simulation" "github.com/cosmos/cosmos-sdk/x/bank/simulation" + "github.com/cosmos/cosmos-sdk/x/bank/testutil" "github.com/cosmos/cosmos-sdk/x/bank/types" ) @@ -193,7 +194,7 @@ func (suite *SimTestSuite) getTestingAccounts(r *rand.Rand, n int) []simtypes.Ac for _, account := range accounts { acc := suite.app.AccountKeeper.NewAccountWithAddress(suite.ctx, account.Address) suite.app.AccountKeeper.SetAccount(suite.ctx, acc) - suite.Require().NoError(simapp.FundAccount(suite.app.BankKeeper, suite.ctx, account.Address, initCoins)) + suite.Require().NoError(testutil.FundAccount(suite.app.BankKeeper, suite.ctx, account.Address, initCoins)) } return accounts diff --git a/x/bank/testutil/test_helpers.go b/x/bank/testutil/test_helpers.go new file mode 100644 index 000000000000..e8805ed7b348 --- /dev/null +++ b/x/bank/testutil/test_helpers.go @@ -0,0 +1,35 @@ +package testutil + +import ( + sdk "github.com/cosmos/cosmos-sdk/types" + bankkeeper "github.com/cosmos/cosmos-sdk/x/bank/keeper" + minttypes "github.com/cosmos/cosmos-sdk/x/mint/types" +) + +// FundAccount is a utility function that funds an account by minting and +// sending the coins to the address. This should be used for testing purposes +// only! +// +// TODO: Instead of using the mint module account, which has the +// permission of minting, create a "faucet" account. (@fdymylja) +func FundAccount(bankKeeper bankkeeper.Keeper, ctx sdk.Context, addr sdk.AccAddress, amounts sdk.Coins) error { + if err := bankKeeper.MintCoins(ctx, minttypes.ModuleName, amounts); err != nil { + return err + } + + return bankKeeper.SendCoinsFromModuleToAccount(ctx, minttypes.ModuleName, addr, amounts) +} + +// FundModuleAccount is a utility function that funds a module account by +// minting and sending the coins to the address. This should be used for testing +// purposes only! +// +// TODO: Instead of using the mint module account, which has the +// permission of minting, create a "faucet" account. (@fdymylja) +func FundModuleAccount(bankKeeper bankkeeper.Keeper, ctx sdk.Context, recipientMod string, amounts sdk.Coins) error { + if err := bankKeeper.MintCoins(ctx, minttypes.ModuleName, amounts); err != nil { + return err + } + + return bankKeeper.SendCoinsFromModuleToModule(ctx, minttypes.ModuleName, recipientMod, amounts) +} diff --git a/x/bank/types/query.pb.go b/x/bank/types/query.pb.go index 5ad95812ba8c..3b4fd4654756 100644 --- a/x/bank/types/query.pb.go +++ b/x/bank/types/query.pb.go @@ -681,6 +681,174 @@ func (m *QueryDenomMetadataResponse) GetMetadata() Metadata { return Metadata{} } +// QueryDenomOwnersRequest defines the request type for the DenomOwners RPC query, +// which queries for a paginated set of all account holders of a particular +// denomination. +type QueryDenomOwnersRequest struct { + // denom defines the coin denomination to query all account holders for. + Denom string `protobuf:"bytes,1,opt,name=denom,proto3" json:"denom,omitempty"` + // pagination defines an optional pagination for the request. + Pagination *query.PageRequest `protobuf:"bytes,2,opt,name=pagination,proto3" json:"pagination,omitempty"` +} + +func (m *QueryDenomOwnersRequest) Reset() { *m = QueryDenomOwnersRequest{} } +func (m *QueryDenomOwnersRequest) String() string { return proto.CompactTextString(m) } +func (*QueryDenomOwnersRequest) ProtoMessage() {} +func (*QueryDenomOwnersRequest) Descriptor() ([]byte, []int) { + return fileDescriptor_9c6fc1939682df13, []int{14} +} +func (m *QueryDenomOwnersRequest) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *QueryDenomOwnersRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_QueryDenomOwnersRequest.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 *QueryDenomOwnersRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_QueryDenomOwnersRequest.Merge(m, src) +} +func (m *QueryDenomOwnersRequest) XXX_Size() int { + return m.Size() +} +func (m *QueryDenomOwnersRequest) XXX_DiscardUnknown() { + xxx_messageInfo_QueryDenomOwnersRequest.DiscardUnknown(m) +} + +var xxx_messageInfo_QueryDenomOwnersRequest proto.InternalMessageInfo + +func (m *QueryDenomOwnersRequest) GetDenom() string { + if m != nil { + return m.Denom + } + return "" +} + +func (m *QueryDenomOwnersRequest) GetPagination() *query.PageRequest { + if m != nil { + return m.Pagination + } + return nil +} + +// DenomOwner defines structure representing an account that owns or holds a +// particular denominated token. It contains the account address and account +// balance of the denominated token. +type DenomOwner struct { + // address defines the address that owns a particular denomination. + Address string `protobuf:"bytes,1,opt,name=address,proto3" json:"address,omitempty"` + // balance is the balance of the denominated coin for an account. + Balance types.Coin `protobuf:"bytes,2,opt,name=balance,proto3" json:"balance"` +} + +func (m *DenomOwner) Reset() { *m = DenomOwner{} } +func (m *DenomOwner) String() string { return proto.CompactTextString(m) } +func (*DenomOwner) ProtoMessage() {} +func (*DenomOwner) Descriptor() ([]byte, []int) { + return fileDescriptor_9c6fc1939682df13, []int{15} +} +func (m *DenomOwner) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *DenomOwner) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_DenomOwner.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 *DenomOwner) XXX_Merge(src proto.Message) { + xxx_messageInfo_DenomOwner.Merge(m, src) +} +func (m *DenomOwner) XXX_Size() int { + return m.Size() +} +func (m *DenomOwner) XXX_DiscardUnknown() { + xxx_messageInfo_DenomOwner.DiscardUnknown(m) +} + +var xxx_messageInfo_DenomOwner proto.InternalMessageInfo + +func (m *DenomOwner) GetAddress() string { + if m != nil { + return m.Address + } + return "" +} + +func (m *DenomOwner) GetBalance() types.Coin { + if m != nil { + return m.Balance + } + return types.Coin{} +} + +// QueryDenomOwnersResponse defines the RPC response of a DenomOwners RPC query. +type QueryDenomOwnersResponse struct { + DenomOwners []*DenomOwner `protobuf:"bytes,1,rep,name=denom_owners,json=denomOwners,proto3" json:"denom_owners,omitempty"` + // pagination defines the pagination in the response. + Pagination *query.PageResponse `protobuf:"bytes,2,opt,name=pagination,proto3" json:"pagination,omitempty"` +} + +func (m *QueryDenomOwnersResponse) Reset() { *m = QueryDenomOwnersResponse{} } +func (m *QueryDenomOwnersResponse) String() string { return proto.CompactTextString(m) } +func (*QueryDenomOwnersResponse) ProtoMessage() {} +func (*QueryDenomOwnersResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_9c6fc1939682df13, []int{16} +} +func (m *QueryDenomOwnersResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *QueryDenomOwnersResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_QueryDenomOwnersResponse.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 *QueryDenomOwnersResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_QueryDenomOwnersResponse.Merge(m, src) +} +func (m *QueryDenomOwnersResponse) XXX_Size() int { + return m.Size() +} +func (m *QueryDenomOwnersResponse) XXX_DiscardUnknown() { + xxx_messageInfo_QueryDenomOwnersResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_QueryDenomOwnersResponse proto.InternalMessageInfo + +func (m *QueryDenomOwnersResponse) GetDenomOwners() []*DenomOwner { + if m != nil { + return m.DenomOwners + } + return nil +} + +func (m *QueryDenomOwnersResponse) GetPagination() *query.PageResponse { + if m != nil { + return m.Pagination + } + return nil +} + func init() { proto.RegisterType((*QueryBalanceRequest)(nil), "cosmos.bank.v1beta1.QueryBalanceRequest") proto.RegisterType((*QueryBalanceResponse)(nil), "cosmos.bank.v1beta1.QueryBalanceResponse") @@ -696,64 +864,73 @@ func init() { proto.RegisterType((*QueryDenomsMetadataResponse)(nil), "cosmos.bank.v1beta1.QueryDenomsMetadataResponse") proto.RegisterType((*QueryDenomMetadataRequest)(nil), "cosmos.bank.v1beta1.QueryDenomMetadataRequest") proto.RegisterType((*QueryDenomMetadataResponse)(nil), "cosmos.bank.v1beta1.QueryDenomMetadataResponse") + proto.RegisterType((*QueryDenomOwnersRequest)(nil), "cosmos.bank.v1beta1.QueryDenomOwnersRequest") + proto.RegisterType((*DenomOwner)(nil), "cosmos.bank.v1beta1.DenomOwner") + proto.RegisterType((*QueryDenomOwnersResponse)(nil), "cosmos.bank.v1beta1.QueryDenomOwnersResponse") } func init() { proto.RegisterFile("cosmos/bank/v1beta1/query.proto", fileDescriptor_9c6fc1939682df13) } var fileDescriptor_9c6fc1939682df13 = []byte{ - // 825 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xb4, 0x56, 0x4d, 0x6f, 0xd3, 0x58, - 0x14, 0xcd, 0xeb, 0x4c, 0xd3, 0xf4, 0x46, 0x33, 0x8b, 0xd7, 0x8c, 0x26, 0x75, 0xa7, 0xc9, 0xc8, - 0x9d, 0x69, 0xd3, 0x92, 0xda, 0x4d, 0x8b, 0x54, 0xc1, 0x06, 0x35, 0x45, 0xb0, 0x40, 0xa8, 0x21, - 0xb0, 0x42, 0x42, 0xe8, 0x25, 0x31, 0x26, 0x6a, 0xe2, 0xe7, 0xe6, 0x39, 0x88, 0xaa, 0xaa, 0x84, - 0x90, 0x90, 0x58, 0x01, 0x12, 0x0b, 0x16, 0x6c, 0xca, 0x06, 0x09, 0x96, 0xfc, 0x8a, 0x2e, 0x58, - 0x54, 0x62, 0xc3, 0x0a, 0x50, 0xcb, 0x82, 0x9f, 0x81, 0xf2, 0x3e, 0x5c, 0x27, 0x71, 0x13, 0x2f, - 0xc2, 0x2a, 0xf6, 0xf5, 0xfd, 0x38, 0xe7, 0x3c, 0xdf, 0xe3, 0x40, 0xb6, 0x4a, 0x59, 0x93, 0x32, - 0xb3, 0x42, 0x9c, 0x6d, 0xf3, 0x41, 0xa1, 0x62, 0x79, 0xa4, 0x60, 0xee, 0xb4, 0xad, 0xd6, 0xae, - 0xe1, 0xb6, 0xa8, 0x47, 0xf1, 0x94, 0x48, 0x30, 0x3a, 0x09, 0x86, 0x4c, 0xd0, 0x96, 0xfc, 0x2a, - 0x66, 0x89, 0x6c, 0xbf, 0xd6, 0x25, 0x76, 0xdd, 0x21, 0x5e, 0x9d, 0x3a, 0xa2, 0x81, 0x96, 0xb2, - 0xa9, 0x4d, 0xf9, 0xa5, 0xd9, 0xb9, 0x92, 0xd1, 0x7f, 0x6c, 0x4a, 0xed, 0x86, 0x65, 0x12, 0xb7, - 0x6e, 0x12, 0xc7, 0xa1, 0x1e, 0x2f, 0x61, 0xf2, 0x69, 0x26, 0xd8, 0x5f, 0x75, 0xae, 0xd2, 0xba, - 0xd3, 0xf7, 0x3c, 0x80, 0x9a, 0x23, 0xe4, 0xcf, 0xf5, 0x2d, 0x98, 0xba, 0xd1, 0x41, 0x55, 0x24, - 0x0d, 0xe2, 0x54, 0xad, 0xb2, 0xb5, 0xd3, 0xb6, 0x98, 0x87, 0xd3, 0x30, 0x41, 0x6a, 0xb5, 0x96, - 0xc5, 0x58, 0x1a, 0xfd, 0x8b, 0x72, 0x93, 0x65, 0x75, 0x8b, 0x53, 0x30, 0x5e, 0xb3, 0x1c, 0xda, - 0x4c, 0x8f, 0xf1, 0xb8, 0xb8, 0xb9, 0x98, 0x78, 0x7a, 0x90, 0x8d, 0xfd, 0x38, 0xc8, 0xc6, 0xf4, - 0x6b, 0x90, 0xea, 0x6e, 0xc8, 0x5c, 0xea, 0x30, 0x0b, 0xaf, 0xc1, 0x44, 0x45, 0x84, 0x78, 0xc7, - 0xe4, 0xea, 0xb4, 0xe1, 0xeb, 0xc5, 0x2c, 0xa5, 0x97, 0xb1, 0x49, 0xeb, 0x4e, 0x59, 0x65, 0xea, - 0x4f, 0x10, 0xfc, 0xcd, 0xbb, 0x6d, 0x34, 0x1a, 0xb2, 0x21, 0x1b, 0x0e, 0xf1, 0x0a, 0xc0, 0xa9, - 0xb6, 0x1c, 0x67, 0x72, 0x75, 0xbe, 0x6b, 0x9a, 0x38, 0x36, 0x35, 0xb3, 0x44, 0x6c, 0x45, 0xbc, - 0x1c, 0xa8, 0x0c, 0x90, 0xfa, 0x88, 0x20, 0xdd, 0x8f, 0x43, 0x32, 0xb3, 0x21, 0x21, 0xf1, 0x76, - 0x90, 0xfc, 0x36, 0x90, 0x5a, 0x71, 0xe5, 0xf0, 0x4b, 0x36, 0xf6, 0xfe, 0x6b, 0x36, 0x67, 0xd7, - 0xbd, 0xfb, 0xed, 0x8a, 0x51, 0xa5, 0x4d, 0x53, 0x1e, 0x91, 0xf8, 0x59, 0x66, 0xb5, 0x6d, 0xd3, - 0xdb, 0x75, 0x2d, 0xc6, 0x0b, 0x58, 0xd9, 0x6f, 0x8e, 0xaf, 0x86, 0xf0, 0x5a, 0x18, 0xca, 0x4b, - 0xa0, 0x0c, 0x12, 0xd3, 0xb7, 0xa5, 0xaa, 0xb7, 0xa8, 0x47, 0x1a, 0x37, 0xdb, 0xae, 0xdb, 0xd8, - 0x55, 0xaa, 0x76, 0x6b, 0x87, 0x46, 0xa0, 0xdd, 0xa1, 0xd2, 0xae, 0x6b, 0x9a, 0xd4, 0xae, 0x0a, - 0x71, 0xc6, 0x23, 0xbf, 0x42, 0x39, 0xd9, 0x7a, 0x74, 0xba, 0xe5, 0xe5, 0xbb, 0x2d, 0x48, 0x6c, - 0xdd, 0x53, 0xa2, 0xf9, 0x3b, 0x81, 0x02, 0x3b, 0xa1, 0x97, 0xe0, 0xaf, 0x9e, 0x6c, 0x49, 0x7a, - 0x1d, 0xe2, 0xa4, 0x49, 0xdb, 0x8e, 0x37, 0x74, 0x13, 0x8a, 0xbf, 0x77, 0x48, 0x97, 0x65, 0xba, - 0x9e, 0x02, 0xcc, 0x3b, 0x96, 0x48, 0x8b, 0x34, 0xd5, 0x22, 0xe8, 0x25, 0xb9, 0xc2, 0x2a, 0x2a, - 0xa7, 0x5c, 0x80, 0xb8, 0xcb, 0x23, 0x72, 0xca, 0x8c, 0x11, 0xe2, 0x4f, 0x86, 0x28, 0x52, 0x73, - 0x44, 0x81, 0x5e, 0x03, 0x8d, 0x77, 0xbc, 0xdc, 0xe1, 0xc1, 0xae, 0x5b, 0x1e, 0xa9, 0x11, 0x8f, - 0x8c, 0xf8, 0x15, 0xd1, 0xdf, 0x21, 0x98, 0x09, 0x1d, 0x23, 0x09, 0x6c, 0xc0, 0x64, 0x53, 0xc6, - 0xd4, 0x62, 0xcd, 0x86, 0x72, 0x50, 0x95, 0x92, 0xc5, 0x69, 0xd5, 0xe8, 0x4e, 0xbe, 0x00, 0xd3, - 0xa7, 0x50, 0x7b, 0x05, 0x09, 0x3f, 0xfe, 0x3b, 0x41, 0x11, 0xfb, 0xc8, 0x5d, 0x82, 0x84, 0x82, - 0x29, 0x25, 0x8c, 0xc4, 0xcd, 0x2f, 0x5a, 0xfd, 0x90, 0x80, 0x71, 0xde, 0x1f, 0xbf, 0x42, 0x30, - 0x21, 0x4d, 0x09, 0xe7, 0x42, 0x9b, 0x84, 0x38, 0xbc, 0xb6, 0x18, 0x21, 0x53, 0x60, 0xd5, 0xd7, - 0x1f, 0x7f, 0xfa, 0xfe, 0x72, 0xac, 0x80, 0x4d, 0x33, 0xfc, 0x63, 0x22, 0xec, 0xc9, 0xdc, 0x93, - 0xfe, 0xbb, 0x6f, 0xee, 0x71, 0x05, 0xf6, 0xf1, 0x6b, 0x04, 0xc9, 0x80, 0x63, 0xe2, 0xfc, 0xd9, - 0x33, 0xfb, 0x0d, 0x5e, 0x5b, 0x8e, 0x98, 0x2d, 0x51, 0x9a, 0x1c, 0xe5, 0x22, 0x5e, 0x88, 0x88, - 0x12, 0x3f, 0x47, 0x90, 0x0c, 0x78, 0xd2, 0x20, 0x74, 0xfd, 0x46, 0x39, 0x08, 0x5d, 0x88, 0xd1, - 0xe9, 0x73, 0x1c, 0xdd, 0x2c, 0x9e, 0x09, 0x45, 0x27, 0x8d, 0xea, 0x19, 0x82, 0x84, 0x72, 0x0b, - 0x3c, 0xe0, 0x80, 0x7a, 0xfc, 0x47, 0x5b, 0x8a, 0x92, 0x2a, 0x81, 0x9c, 0xe3, 0x40, 0xfe, 0xc7, - 0x73, 0x03, 0x80, 0xf8, 0x07, 0xf8, 0x08, 0x41, 0x5c, 0x38, 0x04, 0x5e, 0x38, 0x7b, 0x46, 0x97, - 0x1d, 0x69, 0xb9, 0xe1, 0x89, 0x91, 0x34, 0x11, 0x5e, 0x84, 0xdf, 0x22, 0xf8, 0xa3, 0x6b, 0x85, - 0xb0, 0x71, 0xf6, 0x80, 0xb0, 0xf5, 0xd4, 0xcc, 0xc8, 0xf9, 0x12, 0xd7, 0x79, 0x8e, 0xcb, 0xc0, - 0xf9, 0x50, 0x5c, 0x5c, 0x1a, 0x76, 0x57, 0x2d, 0xa2, 0xaf, 0xd5, 0x1b, 0x04, 0x7f, 0x76, 0x3b, - 0x19, 0x1e, 0x36, 0xb9, 0xd7, 0x5a, 0xb5, 0x95, 0xe8, 0x05, 0x12, 0x6b, 0x9e, 0x63, 0x9d, 0xc7, - 0xff, 0x45, 0xc1, 0x5a, 0xdc, 0x3c, 0x3c, 0xce, 0xa0, 0xa3, 0xe3, 0x0c, 0xfa, 0x76, 0x9c, 0x41, - 0x2f, 0x4e, 0x32, 0xb1, 0xa3, 0x93, 0x4c, 0xec, 0xf3, 0x49, 0x26, 0x76, 0x7b, 0x71, 0xe0, 0x57, - 0xf5, 0xa1, 0x68, 0xcb, 0x3f, 0xae, 0x95, 0x38, 0xff, 0xe7, 0xb8, 0xf6, 0x33, 0x00, 0x00, 0xff, - 0xff, 0xa0, 0xfe, 0xe2, 0x92, 0x11, 0x0b, 0x00, 0x00, + // 917 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xb4, 0x57, 0x4f, 0x4f, 0x3b, 0x45, + 0x18, 0xee, 0xa0, 0x94, 0xf2, 0x56, 0x3d, 0x0c, 0x35, 0x96, 0x45, 0x5a, 0xb3, 0x28, 0xb4, 0x50, + 0x76, 0x29, 0x98, 0x10, 0xbc, 0x18, 0x8a, 0xd1, 0x83, 0x31, 0xd4, 0xea, 0xc9, 0xc4, 0x90, 0x69, + 0xbb, 0xae, 0x0d, 0xed, 0xce, 0xd2, 0xd9, 0x8a, 0x84, 0x90, 0x18, 0x13, 0x13, 0x4f, 0x6a, 0xe2, + 0xc1, 0x83, 0x31, 0xc1, 0x8b, 0x46, 0x3f, 0x09, 0x07, 0x0f, 0x44, 0x2f, 0x9e, 0xd4, 0x80, 0x07, + 0x3f, 0x86, 0xe9, 0xfc, 0xd9, 0xee, 0xb6, 0xdb, 0xed, 0x1e, 0xfa, 0x3b, 0xd1, 0x9d, 0x7d, 0xff, + 0x3c, 0xcf, 0x33, 0x33, 0xef, 0xb3, 0x40, 0xb1, 0x45, 0x59, 0x8f, 0x32, 0xb3, 0x49, 0x9c, 0x73, + 0xf3, 0x93, 0x6a, 0xd3, 0xf2, 0x48, 0xd5, 0xbc, 0x18, 0x58, 0xfd, 0x2b, 0xc3, 0xed, 0x53, 0x8f, + 0xe2, 0x15, 0x11, 0x60, 0x0c, 0x03, 0x0c, 0x19, 0xa0, 0x6d, 0xfb, 0x59, 0xcc, 0x12, 0xd1, 0x7e, + 0xae, 0x4b, 0xec, 0x8e, 0x43, 0xbc, 0x0e, 0x75, 0x44, 0x01, 0x2d, 0x67, 0x53, 0x9b, 0xf2, 0x9f, + 0xe6, 0xf0, 0x97, 0x5c, 0x7d, 0xd1, 0xa6, 0xd4, 0xee, 0x5a, 0x26, 0x71, 0x3b, 0x26, 0x71, 0x1c, + 0xea, 0xf1, 0x14, 0x26, 0xdf, 0x16, 0x82, 0xf5, 0x55, 0xe5, 0x16, 0xed, 0x38, 0x13, 0xef, 0x03, + 0xa8, 0x39, 0x42, 0xfe, 0x5e, 0x3f, 0x85, 0x95, 0x77, 0x87, 0xa8, 0x6a, 0xa4, 0x4b, 0x9c, 0x96, + 0xd5, 0xb0, 0x2e, 0x06, 0x16, 0xf3, 0x70, 0x1e, 0x96, 0x48, 0xbb, 0xdd, 0xb7, 0x18, 0xcb, 0xa3, + 0x97, 0x50, 0x69, 0xb9, 0xa1, 0x1e, 0x71, 0x0e, 0x16, 0xdb, 0x96, 0x43, 0x7b, 0xf9, 0x05, 0xbe, + 0x2e, 0x1e, 0x5e, 0xcb, 0x7c, 0x79, 0x5b, 0x4c, 0xfd, 0x77, 0x5b, 0x4c, 0xe9, 0x6f, 0x43, 0x2e, + 0x5c, 0x90, 0xb9, 0xd4, 0x61, 0x16, 0x3e, 0x80, 0xa5, 0xa6, 0x58, 0xe2, 0x15, 0xb3, 0xfb, 0xab, + 0x86, 0xaf, 0x17, 0xb3, 0x94, 0x5e, 0xc6, 0x09, 0xed, 0x38, 0x0d, 0x15, 0xa9, 0x7f, 0x81, 0xe0, + 0x05, 0x5e, 0xed, 0xb8, 0xdb, 0x95, 0x05, 0xd9, 0x6c, 0x88, 0x6f, 0x02, 0x8c, 0xb4, 0xe5, 0x38, + 0xb3, 0xfb, 0x9b, 0xa1, 0x6e, 0x62, 0xdb, 0x54, 0xcf, 0x3a, 0xb1, 0x15, 0xf1, 0x46, 0x20, 0x33, + 0x40, 0xea, 0x37, 0x04, 0xf9, 0x49, 0x1c, 0x92, 0x99, 0x0d, 0x19, 0x89, 0x77, 0x88, 0xe4, 0xa9, + 0x58, 0x6a, 0xb5, 0xbd, 0xbb, 0xbf, 0x8a, 0xa9, 0x5f, 0xff, 0x2e, 0x96, 0xec, 0x8e, 0xf7, 0xf1, + 0xa0, 0x69, 0xb4, 0x68, 0xcf, 0x94, 0x5b, 0x24, 0xfe, 0xec, 0xb2, 0xf6, 0xb9, 0xe9, 0x5d, 0xb9, + 0x16, 0xe3, 0x09, 0xac, 0xe1, 0x17, 0xc7, 0x6f, 0x45, 0xf0, 0xda, 0x9a, 0xc9, 0x4b, 0xa0, 0x0c, + 0x12, 0xd3, 0xcf, 0xa5, 0xaa, 0xef, 0x53, 0x8f, 0x74, 0xdf, 0x1b, 0xb8, 0x6e, 0xf7, 0x4a, 0xa9, + 0x1a, 0xd6, 0x0e, 0xcd, 0x41, 0xbb, 0x3b, 0xa5, 0x5d, 0xa8, 0x9b, 0xd4, 0xae, 0x05, 0x69, 0xc6, + 0x57, 0x9e, 0x84, 0x72, 0xb2, 0xf4, 0xfc, 0x74, 0xab, 0xc8, 0xb3, 0x2d, 0x48, 0x9c, 0x7e, 0xa4, + 0x44, 0xf3, 0xef, 0x04, 0x0a, 0xdc, 0x09, 0xbd, 0x0e, 0xcf, 0x8f, 0x45, 0x4b, 0xd2, 0x87, 0x90, + 0x26, 0x3d, 0x3a, 0x70, 0xbc, 0x99, 0x37, 0xa1, 0xf6, 0xf4, 0x90, 0x74, 0x43, 0x86, 0xeb, 0x39, + 0xc0, 0xbc, 0x62, 0x9d, 0xf4, 0x49, 0x4f, 0x5d, 0x04, 0xbd, 0x2e, 0xaf, 0xb0, 0x5a, 0x95, 0x5d, + 0x8e, 0x20, 0xed, 0xf2, 0x15, 0xd9, 0x65, 0xcd, 0x88, 0x98, 0x4f, 0x86, 0x48, 0x52, 0x7d, 0x44, + 0x82, 0xde, 0x06, 0x8d, 0x57, 0x7c, 0x63, 0xc8, 0x83, 0xbd, 0x63, 0x79, 0xa4, 0x4d, 0x3c, 0x32, + 0xe7, 0x23, 0xa2, 0xff, 0x82, 0x60, 0x2d, 0xb2, 0x8d, 0x24, 0x70, 0x0c, 0xcb, 0x3d, 0xb9, 0xa6, + 0x2e, 0xd6, 0x7a, 0x24, 0x07, 0x95, 0x29, 0x59, 0x8c, 0xb2, 0xe6, 0xb7, 0xf3, 0x55, 0x58, 0x1d, + 0x41, 0x1d, 0x17, 0x24, 0x7a, 0xfb, 0x3f, 0x0c, 0x8a, 0x38, 0x41, 0xee, 0x75, 0xc8, 0x28, 0x98, + 0x52, 0xc2, 0x44, 0xdc, 0xfc, 0x24, 0xfd, 0x52, 0xde, 0x61, 0x5e, 0xfe, 0xf4, 0xd2, 0xb1, 0xfa, + 0x2c, 0x16, 0xcf, 0xbc, 0xa6, 0xa2, 0x4e, 0x00, 0x46, 0x3d, 0x63, 0xa6, 0xf0, 0xd1, 0x68, 0xe0, + 0x2f, 0x24, 0x3b, 0xe6, 0xfe, 0xd8, 0xff, 0x59, 0x8d, 0x8c, 0x10, 0x39, 0xa9, 0x5c, 0x0d, 0x9e, + 0xe1, 0x84, 0xce, 0x28, 0x5f, 0x97, 0x27, 0xa3, 0x18, 0xa9, 0xde, 0x28, 0xbf, 0x91, 0x6d, 0x8f, + 0x6a, 0xcd, 0xed, 0x5c, 0xec, 0xff, 0xbe, 0x0c, 0x8b, 0x1c, 0x29, 0xfe, 0x0e, 0xc1, 0x92, 0xb4, + 0x06, 0x5c, 0x8a, 0x04, 0x13, 0xe1, 0xb3, 0x5a, 0x39, 0x41, 0xa4, 0x68, 0xab, 0x1f, 0x7e, 0xfe, + 0xc7, 0xbf, 0xdf, 0x2e, 0x54, 0xb1, 0x69, 0x46, 0x5b, 0xba, 0x30, 0x09, 0xf3, 0x5a, 0xea, 0x7f, + 0x63, 0x5e, 0x73, 0xc6, 0x37, 0xf8, 0x7b, 0x04, 0xd9, 0x80, 0x6f, 0xe1, 0xca, 0xf4, 0x9e, 0x93, + 0x36, 0xab, 0xed, 0x26, 0x8c, 0x96, 0x28, 0x4d, 0x8e, 0xb2, 0x8c, 0xb7, 0x12, 0xa2, 0xc4, 0x5f, + 0x23, 0xc8, 0x06, 0x9c, 0x21, 0x0e, 0xdd, 0xa4, 0x5d, 0xc5, 0xa1, 0x8b, 0xb0, 0x1b, 0x7d, 0x83, + 0xa3, 0x5b, 0xc7, 0x6b, 0x91, 0xe8, 0xa4, 0x5d, 0x7c, 0x85, 0x20, 0xa3, 0x66, 0x36, 0x8e, 0xd9, + 0xa0, 0x31, 0x17, 0xd0, 0xb6, 0x93, 0x84, 0x4a, 0x20, 0x3b, 0x1c, 0xc8, 0x2b, 0x78, 0x23, 0x06, + 0x88, 0xbf, 0x81, 0x9f, 0x21, 0x48, 0x8b, 0x39, 0x8d, 0xb7, 0xa6, 0xf7, 0x08, 0x99, 0x82, 0x56, + 0x9a, 0x1d, 0x98, 0x48, 0x13, 0xe1, 0x08, 0xf8, 0x27, 0x04, 0xcf, 0x86, 0x06, 0x19, 0x36, 0xa6, + 0x37, 0x88, 0x1a, 0x92, 0x9a, 0x99, 0x38, 0x5e, 0xe2, 0x7a, 0x95, 0xe3, 0x32, 0x70, 0x25, 0x12, + 0x17, 0x97, 0x86, 0x9d, 0xa9, 0x71, 0xe8, 0x6b, 0xf5, 0x23, 0x82, 0xe7, 0xc2, 0x7e, 0x82, 0x67, + 0x75, 0x1e, 0x37, 0x38, 0x6d, 0x2f, 0x79, 0x82, 0xc4, 0x5a, 0xe1, 0x58, 0x37, 0xf1, 0xcb, 0x49, + 0xb0, 0xe2, 0x1f, 0x10, 0x64, 0x03, 0x93, 0x2d, 0xee, 0xc8, 0x4f, 0x4e, 0xf7, 0xb8, 0x23, 0x1f, + 0x31, 0x2e, 0xf5, 0x2a, 0x87, 0xb6, 0x83, 0xcb, 0xd3, 0xa1, 0xc9, 0x49, 0xaa, 0x34, 0xac, 0x9d, + 0xdc, 0x3d, 0x14, 0xd0, 0xfd, 0x43, 0x01, 0xfd, 0xf3, 0x50, 0x40, 0xdf, 0x3c, 0x16, 0x52, 0xf7, + 0x8f, 0x85, 0xd4, 0x9f, 0x8f, 0x85, 0xd4, 0x07, 0xe5, 0xd8, 0x6f, 0xaf, 0x4f, 0x45, 0x6d, 0xfe, + 0x09, 0xd6, 0x4c, 0xf3, 0xff, 0x2f, 0x0e, 0xfe, 0x0f, 0x00, 0x00, 0xff, 0xff, 0x75, 0x2d, 0x5e, + 0xd9, 0x37, 0x0d, 0x00, 0x00, } // Reference imports to suppress errors if they are not otherwise used. @@ -780,8 +957,12 @@ type QueryClient interface { Params(ctx context.Context, in *QueryParamsRequest, opts ...grpc.CallOption) (*QueryParamsResponse, error) // DenomsMetadata queries the client metadata of a given coin denomination. DenomMetadata(ctx context.Context, in *QueryDenomMetadataRequest, opts ...grpc.CallOption) (*QueryDenomMetadataResponse, error) - // DenomsMetadata queries the client metadata for all registered coin denominations. + // DenomsMetadata queries the client metadata for all registered coin + // denominations. DenomsMetadata(ctx context.Context, in *QueryDenomsMetadataRequest, opts ...grpc.CallOption) (*QueryDenomsMetadataResponse, error) + // DenomOwners queries for all account addresses that own a particular token + // denomination. + DenomOwners(ctx context.Context, in *QueryDenomOwnersRequest, opts ...grpc.CallOption) (*QueryDenomOwnersResponse, error) } type queryClient struct { @@ -855,6 +1036,15 @@ func (c *queryClient) DenomsMetadata(ctx context.Context, in *QueryDenomsMetadat return out, nil } +func (c *queryClient) DenomOwners(ctx context.Context, in *QueryDenomOwnersRequest, opts ...grpc.CallOption) (*QueryDenomOwnersResponse, error) { + out := new(QueryDenomOwnersResponse) + err := c.cc.Invoke(ctx, "/cosmos.bank.v1beta1.Query/DenomOwners", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + // QueryServer is the server API for Query service. type QueryServer interface { // Balance queries the balance of a single coin for a single account. @@ -869,8 +1059,12 @@ type QueryServer interface { Params(context.Context, *QueryParamsRequest) (*QueryParamsResponse, error) // DenomsMetadata queries the client metadata of a given coin denomination. DenomMetadata(context.Context, *QueryDenomMetadataRequest) (*QueryDenomMetadataResponse, error) - // DenomsMetadata queries the client metadata for all registered coin denominations. + // DenomsMetadata queries the client metadata for all registered coin + // denominations. DenomsMetadata(context.Context, *QueryDenomsMetadataRequest) (*QueryDenomsMetadataResponse, error) + // DenomOwners queries for all account addresses that own a particular token + // denomination. + DenomOwners(context.Context, *QueryDenomOwnersRequest) (*QueryDenomOwnersResponse, error) } // UnimplementedQueryServer can be embedded to have forward compatible implementations. @@ -898,6 +1092,9 @@ func (*UnimplementedQueryServer) DenomMetadata(ctx context.Context, req *QueryDe func (*UnimplementedQueryServer) DenomsMetadata(ctx context.Context, req *QueryDenomsMetadataRequest) (*QueryDenomsMetadataResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method DenomsMetadata not implemented") } +func (*UnimplementedQueryServer) DenomOwners(ctx context.Context, req *QueryDenomOwnersRequest) (*QueryDenomOwnersResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method DenomOwners not implemented") +} func RegisterQueryServer(s grpc1.Server, srv QueryServer) { s.RegisterService(&_Query_serviceDesc, srv) @@ -1029,6 +1226,24 @@ func _Query_DenomsMetadata_Handler(srv interface{}, ctx context.Context, dec fun return interceptor(ctx, in, info, handler) } +func _Query_DenomOwners_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(QueryDenomOwnersRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(QueryServer).DenomOwners(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/cosmos.bank.v1beta1.Query/DenomOwners", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(QueryServer).DenomOwners(ctx, req.(*QueryDenomOwnersRequest)) + } + return interceptor(ctx, in, info, handler) +} + var _Query_serviceDesc = grpc.ServiceDesc{ ServiceName: "cosmos.bank.v1beta1.Query", HandlerType: (*QueryServer)(nil), @@ -1061,6 +1276,10 @@ var _Query_serviceDesc = grpc.ServiceDesc{ MethodName: "DenomsMetadata", Handler: _Query_DenomsMetadata_Handler, }, + { + MethodName: "DenomOwners", + Handler: _Query_DenomOwners_Handler, + }, }, Streams: []grpc.StreamDesc{}, Metadata: "cosmos/bank/v1beta1/query.proto", @@ -1579,6 +1798,137 @@ func (m *QueryDenomMetadataResponse) MarshalToSizedBuffer(dAtA []byte) (int, err return len(dAtA) - i, nil } +func (m *QueryDenomOwnersRequest) 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 *QueryDenomOwnersRequest) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *QueryDenomOwnersRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.Pagination != nil { + { + size, err := m.Pagination.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintQuery(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x12 + } + if len(m.Denom) > 0 { + i -= len(m.Denom) + copy(dAtA[i:], m.Denom) + i = encodeVarintQuery(dAtA, i, uint64(len(m.Denom))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *DenomOwner) 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 *DenomOwner) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *DenomOwner) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + { + size, err := m.Balance.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintQuery(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x12 + if len(m.Address) > 0 { + i -= len(m.Address) + copy(dAtA[i:], m.Address) + i = encodeVarintQuery(dAtA, i, uint64(len(m.Address))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *QueryDenomOwnersResponse) 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 *QueryDenomOwnersResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *QueryDenomOwnersResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.Pagination != nil { + { + size, err := m.Pagination.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintQuery(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x12 + } + if len(m.DenomOwners) > 0 { + for iNdEx := len(m.DenomOwners) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.DenomOwners[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintQuery(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + } + } + return len(dAtA) - i, nil +} + func encodeVarintQuery(dAtA []byte, offset int, v uint64) int { offset -= sovQuery(v) base := offset @@ -1788,20 +2138,71 @@ func (m *QueryDenomMetadataResponse) Size() (n int) { return n } -func sovQuery(x uint64) (n int) { - return (math_bits.Len64(x|1) + 6) / 7 -} -func sozQuery(x uint64) (n int) { - return sovQuery(uint64((x << 1) ^ uint64((int64(x) >> 63)))) -} -func (m *QueryBalanceRequest) 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 { +func (m *QueryDenomOwnersRequest) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Denom) + if l > 0 { + n += 1 + l + sovQuery(uint64(l)) + } + if m.Pagination != nil { + l = m.Pagination.Size() + n += 1 + l + sovQuery(uint64(l)) + } + return n +} + +func (m *DenomOwner) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Address) + if l > 0 { + n += 1 + l + sovQuery(uint64(l)) + } + l = m.Balance.Size() + n += 1 + l + sovQuery(uint64(l)) + return n +} + +func (m *QueryDenomOwnersResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if len(m.DenomOwners) > 0 { + for _, e := range m.DenomOwners { + l = e.Size() + n += 1 + l + sovQuery(uint64(l)) + } + } + if m.Pagination != nil { + l = m.Pagination.Size() + n += 1 + l + sovQuery(uint64(l)) + } + return n +} + +func sovQuery(x uint64) (n int) { + return (math_bits.Len64(x|1) + 6) / 7 +} +func sozQuery(x uint64) (n int) { + return sovQuery(uint64((x << 1) ^ uint64((int64(x) >> 63)))) +} +func (m *QueryBalanceRequest) 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 ErrIntOverflowQuery } if iNdEx >= l { @@ -3107,6 +3508,359 @@ func (m *QueryDenomMetadataResponse) Unmarshal(dAtA []byte) error { } return nil } +func (m *QueryDenomOwnersRequest) 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 ErrIntOverflowQuery + } + 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: QueryDenomOwnersRequest: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: QueryDenomOwnersRequest: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Denom", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + 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 ErrInvalidLengthQuery + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthQuery + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Denom = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Pagination", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthQuery + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthQuery + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.Pagination == nil { + m.Pagination = &query.PageRequest{} + } + if err := m.Pagination.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipQuery(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthQuery + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *DenomOwner) 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 ErrIntOverflowQuery + } + 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: DenomOwner: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: DenomOwner: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Address", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + 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 ErrInvalidLengthQuery + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthQuery + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Address = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Balance", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthQuery + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthQuery + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.Balance.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipQuery(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthQuery + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *QueryDenomOwnersResponse) 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 ErrIntOverflowQuery + } + 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: QueryDenomOwnersResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: QueryDenomOwnersResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field DenomOwners", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthQuery + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthQuery + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.DenomOwners = append(m.DenomOwners, &DenomOwner{}) + if err := m.DenomOwners[len(m.DenomOwners)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Pagination", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthQuery + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthQuery + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.Pagination == nil { + m.Pagination = &query.PageResponse{} + } + if err := m.Pagination.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipQuery(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthQuery + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} func skipQuery(dAtA []byte) (n int, err error) { l := len(dAtA) iNdEx := 0 diff --git a/x/bank/types/query.pb.gw.go b/x/bank/types/query.pb.gw.go index 8b8ed9a52607..60ebdb975662 100644 --- a/x/bank/types/query.pb.gw.go +++ b/x/bank/types/query.pb.gw.go @@ -377,6 +377,78 @@ func local_request_Query_DenomsMetadata_0(ctx context.Context, marshaler runtime } +var ( + filter_Query_DenomOwners_0 = &utilities.DoubleArray{Encoding: map[string]int{"denom": 0}, Base: []int{1, 1, 0}, Check: []int{0, 1, 2}} +) + +func request_Query_DenomOwners_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryDenomOwnersRequest + var metadata runtime.ServerMetadata + + var ( + val string + ok bool + err error + _ = err + ) + + val, ok = pathParams["denom"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "denom") + } + + protoReq.Denom, err = runtime.String(val) + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "denom", err) + } + + if err := req.ParseForm(); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_Query_DenomOwners_0); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + + msg, err := client.DenomOwners(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + return msg, metadata, err + +} + +func local_request_Query_DenomOwners_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryDenomOwnersRequest + var metadata runtime.ServerMetadata + + var ( + val string + ok bool + err error + _ = err + ) + + val, ok = pathParams["denom"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "denom") + } + + protoReq.Denom, err = runtime.String(val) + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "denom", err) + } + + if err := req.ParseForm(); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_Query_DenomOwners_0); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + + msg, err := server.DenomOwners(ctx, &protoReq) + return msg, metadata, err + +} + // RegisterQueryHandlerServer registers the http handlers for service Query to "mux". // UnaryRPC :call QueryServer directly. // StreamingRPC :currently unsupported pending https://github.com/grpc/grpc-go/issues/906. @@ -523,6 +595,26 @@ func RegisterQueryHandlerServer(ctx context.Context, mux *runtime.ServeMux, serv }) + mux.Handle("GET", pattern_Query_DenomOwners_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := local_request_Query_DenomOwners_0(rctx, inboundMarshaler, server, req, pathParams) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Query_DenomOwners_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + return nil } @@ -704,6 +796,26 @@ func RegisterQueryHandlerClient(ctx context.Context, mux *runtime.ServeMux, clie }) + mux.Handle("GET", pattern_Query_DenomOwners_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + rctx, err := runtime.AnnotateContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := request_Query_DenomOwners_0(rctx, inboundMarshaler, client, req, pathParams) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Query_DenomOwners_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + return nil } @@ -721,6 +833,8 @@ var ( pattern_Query_DenomMetadata_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 1, 0, 4, 1, 5, 4}, []string{"cosmos", "bank", "v1beta1", "denoms_metadata", "denom"}, "", runtime.AssumeColonVerbOpt(false))) pattern_Query_DenomsMetadata_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"cosmos", "bank", "v1beta1", "denoms_metadata"}, "", runtime.AssumeColonVerbOpt(false))) + + pattern_Query_DenomOwners_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 1, 0, 4, 1, 5, 4}, []string{"cosmos", "bank", "v1beta1", "denom_owners", "denom"}, "", runtime.AssumeColonVerbOpt(false))) ) var ( @@ -737,4 +851,6 @@ var ( forward_Query_DenomMetadata_0 = runtime.ForwardResponseMessage forward_Query_DenomsMetadata_0 = runtime.ForwardResponseMessage + + forward_Query_DenomOwners_0 = runtime.ForwardResponseMessage ) diff --git a/x/crisis/client/testsuite/suite.go b/x/crisis/client/testsuite/suite.go index d0d82f62120b..c80679a2d4e6 100644 --- a/x/crisis/client/testsuite/suite.go +++ b/x/crisis/client/testsuite/suite.go @@ -27,8 +27,11 @@ func NewIntegrationTestSuite(cfg network.Config) *IntegrationTestSuite { func (s *IntegrationTestSuite) SetupSuite() { s.T().Log("setting up integration test suite") - s.network = network.New(s.T(), s.cfg) - _, err := s.network.WaitForHeight(1) + var err error + s.network, err = network.New(s.T(), s.T().TempDir(), s.cfg) + s.Require().NoError(err) + + _, err = s.network.WaitForHeight(1) s.Require().NoError(err) } diff --git a/x/distribution/client/rest/grpc_query_test.go b/x/distribution/client/rest/grpc_query_test.go index ec8e2a7666dd..d458d4a5a2d8 100644 --- a/x/distribution/client/rest/grpc_query_test.go +++ b/x/distribution/client/rest/grpc_query_test.go @@ -28,11 +28,13 @@ func (s *IntegrationTestSuite) SetupSuite() { cfg := network.DefaultConfig() cfg.NumValidators = 1 - s.cfg = cfg - s.network = network.New(s.T(), cfg) - _, err := s.network.WaitForHeight(1) + var err error + s.network, err = network.New(s.T(), s.T().TempDir(), cfg) + s.Require().NoError(err) + + _, err = s.network.WaitForHeight(1) s.Require().NoError(err) } diff --git a/x/distribution/client/testutil/suite.go b/x/distribution/client/testutil/suite.go index 3dcfca70aa68..3be8d5410aac 100644 --- a/x/distribution/client/testutil/suite.go +++ b/x/distribution/client/testutil/suite.go @@ -50,7 +50,8 @@ func (s *IntegrationTestSuite) SetupTest() { genesisState[minttypes.ModuleName] = mintDataBz s.cfg.GenesisState = genesisState - s.network = network.New(s.T(), s.cfg) + s.network, err = network.New(s.T(), s.T().TempDir(), s.cfg) + s.Require().NoError(err) _, err = s.network.WaitForHeight(1) s.Require().NoError(err) diff --git a/x/distribution/keeper/allocation_test.go b/x/distribution/keeper/allocation_test.go index 5bcb8c1cff49..bc7058d6f798 100644 --- a/x/distribution/keeper/allocation_test.go +++ b/x/distribution/keeper/allocation_test.go @@ -10,6 +10,7 @@ import ( "github.com/cosmos/cosmos-sdk/simapp" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/x/auth/types" + "github.com/cosmos/cosmos-sdk/x/bank/testutil" "github.com/cosmos/cosmos-sdk/x/staking/teststaking" stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" ) @@ -83,7 +84,7 @@ func TestAllocateTokensToManyValidators(t *testing.T) { require.NotNil(t, feeCollector) // fund fee collector - require.NoError(t, simapp.FundModuleAccount(app.BankKeeper, ctx, feeCollector.GetName(), fees)) + require.NoError(t, testutil.FundModuleAccount(app.BankKeeper, ctx, feeCollector.GetName(), fees)) app.AccountKeeper.SetAccount(ctx, feeCollector) @@ -163,7 +164,7 @@ func TestAllocateTokensTruncation(t *testing.T) { feeCollector := app.AccountKeeper.GetModuleAccount(ctx, types.FeeCollectorName) require.NotNil(t, feeCollector) - require.NoError(t, simapp.FundModuleAccount(app.BankKeeper, ctx, feeCollector.GetName(), fees)) + require.NoError(t, testutil.FundModuleAccount(app.BankKeeper, ctx, feeCollector.GetName(), fees)) app.AccountKeeper.SetAccount(ctx, feeCollector) diff --git a/x/distribution/keeper/delegation_test.go b/x/distribution/keeper/delegation_test.go index 8b4219e28028..7da5fc029684 100644 --- a/x/distribution/keeper/delegation_test.go +++ b/x/distribution/keeper/delegation_test.go @@ -8,6 +8,7 @@ import ( "github.com/cosmos/cosmos-sdk/simapp" sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/x/bank/testutil" "github.com/cosmos/cosmos-sdk/x/staking" "github.com/cosmos/cosmos-sdk/x/staking/teststaking" stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" @@ -280,7 +281,7 @@ func TestWithdrawDelegationRewardsBasic(t *testing.T) { // set module account coins distrAcc := app.DistrKeeper.GetDistributionAccount(ctx) - require.NoError(t, simapp.FundModuleAccount(app.BankKeeper, ctx, distrAcc.GetName(), sdk.NewCoins(sdk.NewCoin(sdk.DefaultBondDenom, balanceTokens)))) + require.NoError(t, testutil.FundModuleAccount(app.BankKeeper, ctx, distrAcc.GetName(), sdk.NewCoins(sdk.NewCoin(sdk.DefaultBondDenom, balanceTokens)))) app.AccountKeeper.SetModuleAccount(ctx, distrAcc) // create validator with 50% commission @@ -492,7 +493,7 @@ func TestCalculateRewardsMultiDelegatorMultWithdraw(t *testing.T) { // set module account coins distrAcc := app.DistrKeeper.GetDistributionAccount(ctx) - require.NoError(t, simapp.FundModuleAccount(app.BankKeeper, ctx, distrAcc.GetName(), sdk.NewCoins(sdk.NewCoin(sdk.DefaultBondDenom, sdk.NewInt(1000))))) + require.NoError(t, testutil.FundModuleAccount(app.BankKeeper, ctx, distrAcc.GetName(), sdk.NewCoins(sdk.NewCoin(sdk.DefaultBondDenom, sdk.NewInt(1000))))) app.AccountKeeper.SetModuleAccount(ctx, distrAcc) tokens := sdk.DecCoins{sdk.NewDecCoinFromDec(sdk.DefaultBondDenom, sdk.NewDec(initial))} diff --git a/x/distribution/keeper/grpc_query_test.go b/x/distribution/keeper/grpc_query_test.go index b8b716ddbc06..33f2722304b2 100644 --- a/x/distribution/keeper/grpc_query_test.go +++ b/x/distribution/keeper/grpc_query_test.go @@ -12,6 +12,7 @@ import ( "github.com/cosmos/cosmos-sdk/simapp" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/types/query" + "github.com/cosmos/cosmos-sdk/x/bank/testutil" "github.com/cosmos/cosmos-sdk/x/distribution/types" "github.com/cosmos/cosmos-sdk/x/staking" "github.com/cosmos/cosmos-sdk/x/staking/teststaking" @@ -623,7 +624,7 @@ func (suite *KeeperTestSuite) TestGRPCCommunityPool() { "valid request", func() { amount := sdk.NewCoins(sdk.NewInt64Coin("stake", 100)) - suite.Require().NoError(simapp.FundAccount(app.BankKeeper, ctx, addrs[0], amount)) + suite.Require().NoError(testutil.FundAccount(app.BankKeeper, ctx, addrs[0], amount)) err := app.DistrKeeper.FundCommunityPool(ctx, amount, addrs[0]) suite.Require().Nil(err) diff --git a/x/distribution/keeper/hooks.go b/x/distribution/keeper/hooks.go index 1d12fcc55513..0c66d44e33e7 100644 --- a/x/distribution/keeper/hooks.go +++ b/x/distribution/keeper/hooks.go @@ -17,13 +17,14 @@ var _ stakingtypes.StakingHooks = Hooks{} func (k Keeper) Hooks() Hooks { return Hooks{k} } // initialize validator distribution record -func (h Hooks) AfterValidatorCreated(ctx sdk.Context, valAddr sdk.ValAddress) { +func (h Hooks) AfterValidatorCreated(ctx sdk.Context, valAddr sdk.ValAddress) error { val := h.k.stakingKeeper.Validator(ctx, valAddr) h.k.initializeValidator(ctx, val) + return nil } // AfterValidatorRemoved performs clean up after a validator is removed -func (h Hooks) AfterValidatorRemoved(ctx sdk.Context, _ sdk.ConsAddress, valAddr sdk.ValAddress) { +func (h Hooks) AfterValidatorRemoved(ctx sdk.Context, _ sdk.ConsAddress, valAddr sdk.ValAddress) error { // fetch outstanding outstanding := h.k.GetValidatorOutstandingRewardsCoins(ctx, valAddr) @@ -47,7 +48,7 @@ func (h Hooks) AfterValidatorRemoved(ctx sdk.Context, _ sdk.ConsAddress, valAddr withdrawAddr := h.k.GetDelegatorWithdrawAddr(ctx, accAddr) if err := h.k.bankKeeper.SendCoinsFromModuleToAccount(ctx, types.ModuleName, withdrawAddr, coins); err != nil { - panic(err) + return err } } } @@ -73,35 +74,48 @@ func (h Hooks) AfterValidatorRemoved(ctx sdk.Context, _ sdk.ConsAddress, valAddr // clear current rewards h.k.DeleteValidatorCurrentRewards(ctx, valAddr) + + return nil } // increment period -func (h Hooks) BeforeDelegationCreated(ctx sdk.Context, delAddr sdk.AccAddress, valAddr sdk.ValAddress) { +func (h Hooks) BeforeDelegationCreated(ctx sdk.Context, delAddr sdk.AccAddress, valAddr sdk.ValAddress) error { val := h.k.stakingKeeper.Validator(ctx, valAddr) - h.k.IncrementValidatorPeriod(ctx, val) + _ = h.k.IncrementValidatorPeriod(ctx, val) + return nil } // withdraw delegation rewards (which also increments period) -func (h Hooks) BeforeDelegationSharesModified(ctx sdk.Context, delAddr sdk.AccAddress, valAddr sdk.ValAddress) { +func (h Hooks) BeforeDelegationSharesModified(ctx sdk.Context, delAddr sdk.AccAddress, valAddr sdk.ValAddress) error { val := h.k.stakingKeeper.Validator(ctx, valAddr) del := h.k.stakingKeeper.Delegation(ctx, delAddr, valAddr) if _, err := h.k.withdrawDelegationRewards(ctx, val, del); err != nil { - panic(err) + return err } + + return nil } // create new delegation period record -func (h Hooks) AfterDelegationModified(ctx sdk.Context, delAddr sdk.AccAddress, valAddr sdk.ValAddress) { +func (h Hooks) AfterDelegationModified(ctx sdk.Context, delAddr sdk.AccAddress, valAddr sdk.ValAddress) error { h.k.initializeDelegation(ctx, valAddr, delAddr) + return nil } // record the slash event -func (h Hooks) BeforeValidatorSlashed(ctx sdk.Context, valAddr sdk.ValAddress, fraction sdk.Dec) { +func (h Hooks) BeforeValidatorSlashed(ctx sdk.Context, valAddr sdk.ValAddress, fraction sdk.Dec) error { h.k.updateValidatorSlashFraction(ctx, valAddr, fraction) + return nil } -func (h Hooks) BeforeValidatorModified(_ sdk.Context, _ sdk.ValAddress) {} -func (h Hooks) AfterValidatorBonded(_ sdk.Context, _ sdk.ConsAddress, _ sdk.ValAddress) {} -func (h Hooks) AfterValidatorBeginUnbonding(_ sdk.Context, _ sdk.ConsAddress, _ sdk.ValAddress) {} -func (h Hooks) BeforeDelegationRemoved(_ sdk.Context, _ sdk.AccAddress, _ sdk.ValAddress) {} +func (h Hooks) BeforeValidatorModified(_ sdk.Context, _ sdk.ValAddress) error { return nil } +func (h Hooks) AfterValidatorBonded(_ sdk.Context, _ sdk.ConsAddress, _ sdk.ValAddress) error { + return nil +} +func (h Hooks) AfterValidatorBeginUnbonding(_ sdk.Context, _ sdk.ConsAddress, _ sdk.ValAddress) error { + return nil +} +func (h Hooks) BeforeDelegationRemoved(_ sdk.Context, _ sdk.AccAddress, _ sdk.ValAddress) error { + return nil +} diff --git a/x/distribution/keeper/keeper_test.go b/x/distribution/keeper/keeper_test.go index 40d6dcd7364c..bdb241051e24 100644 --- a/x/distribution/keeper/keeper_test.go +++ b/x/distribution/keeper/keeper_test.go @@ -9,6 +9,7 @@ import ( "github.com/cosmos/cosmos-sdk/simapp" sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/x/bank/testutil" "github.com/cosmos/cosmos-sdk/x/distribution/types" ) @@ -49,7 +50,7 @@ func TestWithdrawValidatorCommission(t *testing.T) { // set module account coins distrAcc := app.DistrKeeper.GetDistributionAccount(ctx) coins := sdk.NewCoins(sdk.NewCoin("mytoken", sdk.NewInt(2)), sdk.NewCoin("stake", sdk.NewInt(2))) - require.NoError(t, simapp.FundModuleAccount(app.BankKeeper, ctx, distrAcc.GetName(), coins)) + require.NoError(t, testutil.FundModuleAccount(app.BankKeeper, ctx, distrAcc.GetName(), coins)) app.AccountKeeper.SetModuleAccount(ctx, distrAcc) @@ -114,7 +115,7 @@ func TestFundCommunityPool(t *testing.T) { addr := simapp.AddTestAddrs(app, ctx, 2, sdk.ZeroInt()) amount := sdk.NewCoins(sdk.NewInt64Coin("stake", 100)) - require.NoError(t, simapp.FundAccount(app.BankKeeper, ctx, addr[0], amount)) + require.NoError(t, testutil.FundAccount(app.BankKeeper, ctx, addr[0], amount)) initPool := app.DistrKeeper.GetFeePool(ctx) assert.Empty(t, initPool.CommunityPool) diff --git a/x/distribution/proposal_handler_test.go b/x/distribution/proposal_handler_test.go index a9b11b321df3..08e9268215bf 100644 --- a/x/distribution/proposal_handler_test.go +++ b/x/distribution/proposal_handler_test.go @@ -9,6 +9,7 @@ import ( "github.com/cosmos/cosmos-sdk/crypto/keys/ed25519" "github.com/cosmos/cosmos-sdk/simapp" sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/x/bank/testutil" "github.com/cosmos/cosmos-sdk/x/distribution" "github.com/cosmos/cosmos-sdk/x/distribution/types" ) @@ -33,7 +34,7 @@ func TestProposalHandlerPassed(t *testing.T) { // add coins to the module account macc := app.DistrKeeper.GetDistributionAccount(ctx) balances := app.BankKeeper.GetAllBalances(ctx, macc.GetAddress()) - require.NoError(t, simapp.FundModuleAccount(app.BankKeeper, ctx, macc.GetName(), amount)) + require.NoError(t, testutil.FundModuleAccount(app.BankKeeper, ctx, macc.GetName(), amount)) app.AccountKeeper.SetModuleAccount(ctx, macc) diff --git a/x/distribution/simulation/operations_test.go b/x/distribution/simulation/operations_test.go index 33b59a53cca9..8129c5b8bc51 100644 --- a/x/distribution/simulation/operations_test.go +++ b/x/distribution/simulation/operations_test.go @@ -12,6 +12,7 @@ import ( simappparams "github.com/cosmos/cosmos-sdk/simapp/params" sdk "github.com/cosmos/cosmos-sdk/types" simtypes "github.com/cosmos/cosmos-sdk/types/simulation" + "github.com/cosmos/cosmos-sdk/x/bank/testutil" "github.com/cosmos/cosmos-sdk/x/distribution/simulation" "github.com/cosmos/cosmos-sdk/x/distribution/types" distrtypes "github.com/cosmos/cosmos-sdk/x/distribution/types" @@ -143,7 +144,7 @@ func (suite *SimTestSuite) testSimulateMsgWithdrawValidatorCommission(tokenName // set module account coins distrAcc := suite.app.DistrKeeper.GetDistributionAccount(suite.ctx) - suite.Require().NoError(simapp.FundModuleAccount(suite.app.BankKeeper, suite.ctx, distrAcc.GetName(), sdk.NewCoins( + suite.Require().NoError(testutil.FundModuleAccount(suite.app.BankKeeper, suite.ctx, distrAcc.GetName(), sdk.NewCoins( sdk.NewCoin(tokenName, sdk.NewInt(10)), sdk.NewCoin("stake", sdk.NewInt(5)), ))) @@ -229,7 +230,7 @@ func (suite *SimTestSuite) getTestingAccounts(r *rand.Rand, n int) []simtypes.Ac for _, account := range accounts { acc := suite.app.AccountKeeper.NewAccountWithAddress(suite.ctx, account.Address) suite.app.AccountKeeper.SetAccount(suite.ctx, acc) - suite.Require().NoError(simapp.FundAccount(suite.app.BankKeeper, suite.ctx, account.Address, initCoins)) + suite.Require().NoError(testutil.FundAccount(suite.app.BankKeeper, suite.ctx, account.Address, initCoins)) } return accounts diff --git a/x/evidence/client/testutil/suite.go b/x/evidence/client/testutil/suite.go index d12083b64789..32eae04fd5d1 100644 --- a/x/evidence/client/testutil/suite.go +++ b/x/evidence/client/testutil/suite.go @@ -24,9 +24,11 @@ func NewIntegrationTestSuite(cfg network.Config) *IntegrationTestSuite { func (s *IntegrationTestSuite) SetupSuite() { s.T().Log("setting up integration test suite") - s.network = network.New(s.T(), s.cfg) + var err error + s.network, err = network.New(s.T(), s.T().TempDir(), s.cfg) + s.Require().NoError(err) - _, err := s.network.WaitForHeight(1) + _, err = s.network.WaitForHeight(1) s.Require().NoError(err) } diff --git a/x/feegrant/client/testutil/suite.go b/x/feegrant/client/testutil/suite.go index c539cf84766f..74fe155e66ea 100644 --- a/x/feegrant/client/testutil/suite.go +++ b/x/feegrant/client/testutil/suite.go @@ -50,9 +50,11 @@ func (s *IntegrationTestSuite) SetupSuite() { s.T().Skip("skipping test in unit-tests mode.") } - s.network = network.New(s.T(), s.cfg) + var err error + s.network, err = network.New(s.T(), s.T().TempDir(), s.cfg) + s.Require().NoError(err) - _, err := s.network.WaitForHeight(1) + _, err = s.network.WaitForHeight(1) s.Require().NoError(err) val := s.network.Validators[0] diff --git a/x/feegrant/simulation/operations_test.go b/x/feegrant/simulation/operations_test.go index 4d7671f77287..2a7427c6d27b 100644 --- a/x/feegrant/simulation/operations_test.go +++ b/x/feegrant/simulation/operations_test.go @@ -6,7 +6,6 @@ import ( "time" "github.com/stretchr/testify/suite" - abci "github.com/tendermint/tendermint/abci/types" tmproto "github.com/tendermint/tendermint/proto/tendermint/types" @@ -14,6 +13,7 @@ import ( simappparams "github.com/cosmos/cosmos-sdk/simapp/params" sdk "github.com/cosmos/cosmos-sdk/types" simtypes "github.com/cosmos/cosmos-sdk/types/simulation" + "github.com/cosmos/cosmos-sdk/x/bank/testutil" "github.com/cosmos/cosmos-sdk/x/feegrant" "github.com/cosmos/cosmos-sdk/x/feegrant/simulation" ) @@ -43,7 +43,7 @@ func (suite *SimTestSuite) getTestingAccounts(r *rand.Rand, n int) []simtypes.Ac // add coins to the accounts for _, account := range accounts { - err := simapp.FundAccount(suite.app.BankKeeper, suite.ctx, account.Address, initCoins) + err := testutil.FundAccount(suite.app.BankKeeper, suite.ctx, account.Address, initCoins) suite.Require().NoError(err) } diff --git a/x/genutil/client/cli/gentx.go b/x/genutil/client/cli/gentx.go index e6433b2f46f6..3b1aaceb0207 100644 --- a/x/genutil/client/cli/gentx.go +++ b/x/genutil/client/cli/gentx.go @@ -156,14 +156,14 @@ $ %s gentx my-key-name 1000000stake --home=/path/to/home/dir --keyring-backend=o if key.GetType() == keyring.TypeOffline || key.GetType() == keyring.TypeMulti { cmd.PrintErrln("Offline key passed in. Use `tx sign` command to sign.") - return authclient.PrintUnsignedStdTx(txBldr, clientCtx, []sdk.Msg{msg}) + return txBldr.PrintUnsignedTx(clientCtx, msg) } // write the unsigned transaction to the buffer w := bytes.NewBuffer([]byte{}) clientCtx = clientCtx.WithOutput(w) - if err = authclient.PrintUnsignedStdTx(txBldr, clientCtx, []sdk.Msg{msg}); err != nil { + if err = txBldr.PrintUnsignedTx(clientCtx, msg); err != nil { return errors.Wrap(err, "failed to print unsigned std tx") } diff --git a/x/genutil/client/testutil/suite.go b/x/genutil/client/testutil/suite.go index 4c5c38918506..bc226a2ab100 100644 --- a/x/genutil/client/testutil/suite.go +++ b/x/genutil/client/testutil/suite.go @@ -34,9 +34,11 @@ func NewIntegrationTestSuite(cfg network.Config) *IntegrationTestSuite { func (s *IntegrationTestSuite) SetupSuite() { s.T().Log("setting up integration test suite") - s.network = network.New(s.T(), s.cfg) + var err error + s.network, err = network.New(s.T(), s.T().TempDir(), s.cfg) + s.Require().NoError(err) - _, err := s.network.WaitForHeight(1) + _, err = s.network.WaitForHeight(1) s.Require().NoError(err) } diff --git a/x/genutil/gentx_test.go b/x/genutil/gentx_test.go index 5fe7658a34b6..65fd5194d96e 100644 --- a/x/genutil/gentx_test.go +++ b/x/genutil/gentx_test.go @@ -13,6 +13,7 @@ import ( "github.com/cosmos/cosmos-sdk/simapp/helpers" simappparams "github.com/cosmos/cosmos-sdk/simapp/params" sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/x/bank/testutil" banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" "github.com/cosmos/cosmos-sdk/x/genutil" "github.com/cosmos/cosmos-sdk/x/genutil/types" @@ -64,7 +65,7 @@ func (suite *GenTxTestSuite) setAccountBalance(addr sdk.AccAddress, amount int64 acc := suite.app.AccountKeeper.NewAccountWithAddress(suite.ctx, addr) suite.app.AccountKeeper.SetAccount(suite.ctx, acc) - err := simapp.FundAccount(suite.app.BankKeeper, suite.ctx, addr, sdk.Coins{sdk.NewInt64Coin(sdk.DefaultBondDenom, 25)}) + err := testutil.FundAccount(suite.app.BankKeeper, suite.ctx, addr, sdk.Coins{sdk.NewInt64Coin(sdk.DefaultBondDenom, 25)}) suite.Require().NoError(err) bankGenesisState := suite.app.BankKeeper.ExportGenesis(suite.ctx) diff --git a/x/gov/client/rest/grpc_query_test.go b/x/gov/client/rest/grpc_query_test.go index 12247aeb9a91..a7806bde2e62 100644 --- a/x/gov/client/rest/grpc_query_test.go +++ b/x/gov/client/rest/grpc_query_test.go @@ -32,9 +32,11 @@ func (s *IntegrationTestSuite) SetupSuite() { s.cfg = network.DefaultConfig() s.cfg.NumValidators = 1 - s.network = network.New(s.T(), s.cfg) + var err error + s.network, err = network.New(s.T(), s.T().TempDir(), s.cfg) + s.Require().NoError(err) - _, err := s.network.WaitForHeight(1) + _, err = s.network.WaitForHeight(1) s.Require().NoError(err) val := s.network.Validators[0] diff --git a/x/gov/client/testutil/deposits.go b/x/gov/client/testutil/deposits.go index 57c3c9363330..a6096eb33ab4 100644 --- a/x/gov/client/testutil/deposits.go +++ b/x/gov/client/testutil/deposits.go @@ -28,9 +28,11 @@ func NewDepositTestSuite(cfg network.Config) *DepositTestSuite { func (s *DepositTestSuite) SetupSuite() { s.T().Log("setting up test suite") - s.network = network.New(s.T(), s.cfg) + var err error + s.network, err = network.New(s.T(), s.T().TempDir(), s.cfg) + s.Require().NoError(err) - _, err := s.network.WaitForHeight(1) + _, err = s.network.WaitForHeight(1) s.Require().NoError(err) s.fees = sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(20))).String() diff --git a/x/gov/client/testutil/suite.go b/x/gov/client/testutil/suite.go index ee2634e3d188..ba1db3ff6272 100644 --- a/x/gov/client/testutil/suite.go +++ b/x/gov/client/testutil/suite.go @@ -33,9 +33,11 @@ func NewIntegrationTestSuite(cfg network.Config) *IntegrationTestSuite { func (s *IntegrationTestSuite) SetupSuite() { s.T().Log("setting up integration test suite") - s.network = network.New(s.T(), s.cfg) + var err error + s.network, err = network.New(s.T(), s.T().TempDir(), s.cfg) + s.Require().NoError(err) - _, err := s.network.WaitForHeight(1) + _, err = s.network.WaitForHeight(1) s.Require().NoError(err) val := s.network.Validators[0] diff --git a/x/gov/simulation/operations_test.go b/x/gov/simulation/operations_test.go index 6a5252dc3785..83f612a8358d 100644 --- a/x/gov/simulation/operations_test.go +++ b/x/gov/simulation/operations_test.go @@ -14,6 +14,7 @@ import ( simappparams "github.com/cosmos/cosmos-sdk/simapp/params" sdk "github.com/cosmos/cosmos-sdk/types" simtypes "github.com/cosmos/cosmos-sdk/types/simulation" + "github.com/cosmos/cosmos-sdk/x/bank/testutil" "github.com/cosmos/cosmos-sdk/x/gov/simulation" "github.com/cosmos/cosmos-sdk/x/gov/types" minttypes "github.com/cosmos/cosmos-sdk/x/mint/types" @@ -271,7 +272,7 @@ func getTestingAccounts(t *testing.T, r *rand.Rand, app *simapp.SimApp, ctx sdk. for _, account := range accounts { acc := app.AccountKeeper.NewAccountWithAddress(ctx, account.Address) app.AccountKeeper.SetAccount(ctx, acc) - require.NoError(t, simapp.FundAccount(app.BankKeeper, ctx, account.Address, initCoins)) + require.NoError(t, testutil.FundAccount(app.BankKeeper, ctx, account.Address, initCoins)) } return accounts diff --git a/x/mint/client/rest/grpc_query_test.go b/x/mint/client/rest/grpc_query_test.go index fdbb4ff75998..d813d6467b91 100644 --- a/x/mint/client/rest/grpc_query_test.go +++ b/x/mint/client/rest/grpc_query_test.go @@ -45,7 +45,8 @@ func (s *IntegrationTestSuite) SetupSuite() { cfg.GenesisState = genesisState s.cfg = cfg - s.network = network.New(s.T(), cfg) + s.network, err = network.New(s.T(), s.T().TempDir(), cfg) + s.Require().NoError(err) _, err = s.network.WaitForHeight(1) s.Require().NoError(err) diff --git a/x/mint/client/testutil/suite.go b/x/mint/client/testutil/suite.go index 24e74267608c..dd90d2d54333 100644 --- a/x/mint/client/testutil/suite.go +++ b/x/mint/client/testutil/suite.go @@ -44,7 +44,8 @@ func (s *IntegrationTestSuite) SetupSuite() { genesisState[minttypes.ModuleName] = mintDataBz s.cfg.GenesisState = genesisState - s.network = network.New(s.T(), s.cfg) + s.network, err = network.New(s.T(), s.T().TempDir(), s.cfg) + s.Require().NoError(err) _, err = s.network.WaitForHeight(1) s.Require().NoError(err) diff --git a/x/params/client/rest/grpc_query_test.go b/x/params/client/rest/grpc_query_test.go index f2c4440e29d5..8de3f2cbd878 100644 --- a/x/params/client/rest/grpc_query_test.go +++ b/x/params/client/rest/grpc_query_test.go @@ -24,11 +24,13 @@ func (s *IntegrationTestSuite) SetupSuite() { cfg := network.DefaultConfig() cfg.NumValidators = 1 - s.cfg = cfg - s.network = network.New(s.T(), cfg) - _, err := s.network.WaitForHeight(1) + var err error + s.network, err = network.New(s.T(), s.T().TempDir(), cfg) + s.Require().NoError(err) + + _, err = s.network.WaitForHeight(1) s.Require().NoError(err) } diff --git a/x/params/client/testutil/suite.go b/x/params/client/testutil/suite.go index e539b8791df6..c38d93b9b66e 100644 --- a/x/params/client/testutil/suite.go +++ b/x/params/client/testutil/suite.go @@ -26,9 +26,11 @@ func NewIntegrationTestSuite(cfg network.Config) *IntegrationTestSuite { func (s *IntegrationTestSuite) SetupSuite() { s.T().Log("setting up integration test suite") - s.network = network.New(s.T(), s.cfg) + var err error + s.network, err = network.New(s.T(), s.T().TempDir(), s.cfg) + s.Require().NoError(err) - _, err := s.network.WaitForHeight(1) + _, err = s.network.WaitForHeight(1) s.Require().NoError(err) } diff --git a/x/slashing/client/rest/grpc_query_test.go b/x/slashing/client/rest/grpc_query_test.go index 39daf06f69c5..0531d1e98ebf 100644 --- a/x/slashing/client/rest/grpc_query_test.go +++ b/x/slashing/client/rest/grpc_query_test.go @@ -28,11 +28,13 @@ func (s *IntegrationTestSuite) SetupSuite() { cfg := network.DefaultConfig() cfg.NumValidators = 1 - s.cfg = cfg - s.network = network.New(s.T(), cfg) - _, err := s.network.WaitForHeight(1) + var err error + s.network, err = network.New(s.T(), s.T().TempDir(), cfg) + s.Require().NoError(err) + + _, err = s.network.WaitForHeight(1) s.Require().NoError(err) } diff --git a/x/slashing/client/testutil/suite.go b/x/slashing/client/testutil/suite.go index cf5cf997b6c3..06bcdca70110 100644 --- a/x/slashing/client/testutil/suite.go +++ b/x/slashing/client/testutil/suite.go @@ -31,9 +31,11 @@ func NewIntegrationTestSuite(cfg network.Config) *IntegrationTestSuite { func (s *IntegrationTestSuite) SetupSuite() { s.T().Log("setting up integration test suite") - s.network = network.New(s.T(), s.cfg) + var err error + s.network, err = network.New(s.T(), s.T().TempDir(), s.cfg) + s.Require().NoError(err) - _, err := s.network.WaitForHeight(1) + _, err = s.network.WaitForHeight(1) s.Require().NoError(err) } diff --git a/x/slashing/keeper/hooks.go b/x/slashing/keeper/hooks.go index e3a00e9f5556..09d1afe02fac 100644 --- a/x/slashing/keeper/hooks.go +++ b/x/slashing/keeper/hooks.go @@ -9,7 +9,7 @@ import ( "github.com/cosmos/cosmos-sdk/x/slashing/types" ) -func (k Keeper) AfterValidatorBonded(ctx sdk.Context, address sdk.ConsAddress, _ sdk.ValAddress) { +func (k Keeper) AfterValidatorBonded(ctx sdk.Context, address sdk.ConsAddress, _ sdk.ValAddress) error { // Update the signing info start height or create a new signing info _, found := k.GetValidatorSigningInfo(ctx, address) if !found { @@ -23,6 +23,8 @@ func (k Keeper) AfterValidatorBonded(ctx sdk.Context, address sdk.ConsAddress, _ ) k.SetValidatorSigningInfo(ctx, address, signingInfo) } + + return nil } // AfterValidatorCreated adds the address-pubkey relation when a validator is created. @@ -32,14 +34,14 @@ func (k Keeper) AfterValidatorCreated(ctx sdk.Context, valAddr sdk.ValAddress) e if err != nil { return err } - k.AddPubkey(ctx, consPk) - return nil + return k.AddPubkey(ctx, consPk) } // AfterValidatorRemoved deletes the address-pubkey relation when a validator is removed, -func (k Keeper) AfterValidatorRemoved(ctx sdk.Context, address sdk.ConsAddress) { +func (k Keeper) AfterValidatorRemoved(ctx sdk.Context, address sdk.ConsAddress) error { k.deleteAddrPubkeyRelation(ctx, crypto.Address(address)) + return nil } // Hooks wrapper struct for slashing keeper @@ -55,24 +57,34 @@ func (k Keeper) Hooks() Hooks { } // Implements sdk.ValidatorHooks -func (h Hooks) AfterValidatorBonded(ctx sdk.Context, consAddr sdk.ConsAddress, valAddr sdk.ValAddress) { - h.k.AfterValidatorBonded(ctx, consAddr, valAddr) +func (h Hooks) AfterValidatorBonded(ctx sdk.Context, consAddr sdk.ConsAddress, valAddr sdk.ValAddress) error { + return h.k.AfterValidatorBonded(ctx, consAddr, valAddr) } // Implements sdk.ValidatorHooks -func (h Hooks) AfterValidatorRemoved(ctx sdk.Context, consAddr sdk.ConsAddress, _ sdk.ValAddress) { - h.k.AfterValidatorRemoved(ctx, consAddr) +func (h Hooks) AfterValidatorRemoved(ctx sdk.Context, consAddr sdk.ConsAddress, _ sdk.ValAddress) error { + return h.k.AfterValidatorRemoved(ctx, consAddr) } // Implements sdk.ValidatorHooks -func (h Hooks) AfterValidatorCreated(ctx sdk.Context, valAddr sdk.ValAddress) { - h.k.AfterValidatorCreated(ctx, valAddr) +func (h Hooks) AfterValidatorCreated(ctx sdk.Context, valAddr sdk.ValAddress) error { + return h.k.AfterValidatorCreated(ctx, valAddr) } -func (h Hooks) AfterValidatorBeginUnbonding(_ sdk.Context, _ sdk.ConsAddress, _ sdk.ValAddress) {} -func (h Hooks) BeforeValidatorModified(_ sdk.Context, _ sdk.ValAddress) {} -func (h Hooks) BeforeDelegationCreated(_ sdk.Context, _ sdk.AccAddress, _ sdk.ValAddress) {} -func (h Hooks) BeforeDelegationSharesModified(_ sdk.Context, _ sdk.AccAddress, _ sdk.ValAddress) {} -func (h Hooks) BeforeDelegationRemoved(_ sdk.Context, _ sdk.AccAddress, _ sdk.ValAddress) {} -func (h Hooks) AfterDelegationModified(_ sdk.Context, _ sdk.AccAddress, _ sdk.ValAddress) {} -func (h Hooks) BeforeValidatorSlashed(_ sdk.Context, _ sdk.ValAddress, _ sdk.Dec) {} +func (h Hooks) AfterValidatorBeginUnbonding(_ sdk.Context, _ sdk.ConsAddress, _ sdk.ValAddress) error { + return nil +} +func (h Hooks) BeforeValidatorModified(_ sdk.Context, _ sdk.ValAddress) error { return nil } +func (h Hooks) BeforeDelegationCreated(_ sdk.Context, _ sdk.AccAddress, _ sdk.ValAddress) error { + return nil +} +func (h Hooks) BeforeDelegationSharesModified(_ sdk.Context, _ sdk.AccAddress, _ sdk.ValAddress) error { + return nil +} +func (h Hooks) BeforeDelegationRemoved(_ sdk.Context, _ sdk.AccAddress, _ sdk.ValAddress) error { + return nil +} +func (h Hooks) AfterDelegationModified(_ sdk.Context, _ sdk.AccAddress, _ sdk.ValAddress) error { + return nil +} +func (h Hooks) BeforeValidatorSlashed(_ sdk.Context, _ sdk.ValAddress, _ sdk.Dec) error { return nil } diff --git a/x/slashing/simulation/operations_test.go b/x/slashing/simulation/operations_test.go index ea58a6e67c86..8b25711bdaec 100644 --- a/x/slashing/simulation/operations_test.go +++ b/x/slashing/simulation/operations_test.go @@ -13,6 +13,7 @@ import ( simappparams "github.com/cosmos/cosmos-sdk/simapp/params" sdk "github.com/cosmos/cosmos-sdk/types" simtypes "github.com/cosmos/cosmos-sdk/types/simulation" + "github.com/cosmos/cosmos-sdk/x/bank/testutil" distrtypes "github.com/cosmos/cosmos-sdk/x/distribution/types" minttypes "github.com/cosmos/cosmos-sdk/x/mint/types" "github.com/cosmos/cosmos-sdk/x/slashing/simulation" @@ -123,7 +124,7 @@ func getTestingAccounts(t *testing.T, r *rand.Rand, app *simapp.SimApp, ctx sdk. for _, account := range accounts { acc := app.AccountKeeper.NewAccountWithAddress(ctx, account.Address) app.AccountKeeper.SetAccount(ctx, acc) - require.NoError(t, simapp.FundAccount(app.BankKeeper, ctx, account.Address, initCoins)) + require.NoError(t, testutil.FundAccount(app.BankKeeper, ctx, account.Address, initCoins)) } return accounts diff --git a/x/slashing/types/expected_keepers.go b/x/slashing/types/expected_keepers.go index 9710ad1786e7..7bddb6cebc61 100644 --- a/x/slashing/types/expected_keepers.go +++ b/x/slashing/types/expected_keepers.go @@ -56,8 +56,8 @@ type StakingKeeper interface { // StakingHooks event hooks for staking validator object (noalias) type StakingHooks interface { - AfterValidatorCreated(ctx sdk.Context, valAddr sdk.ValAddress) // Must be called when a validator is created - AfterValidatorRemoved(ctx sdk.Context, consAddr sdk.ConsAddress, valAddr sdk.ValAddress) // Must be called when a validator is deleted + AfterValidatorCreated(ctx sdk.Context, valAddr sdk.ValAddress) error // Must be called when a validator is created + AfterValidatorRemoved(ctx sdk.Context, consAddr sdk.ConsAddress, valAddr sdk.ValAddress) error // Must be called when a validator is deleted - AfterValidatorBonded(ctx sdk.Context, consAddr sdk.ConsAddress, valAddr sdk.ValAddress) // Must be called when a validator is bonded + AfterValidatorBonded(ctx sdk.Context, consAddr sdk.ConsAddress, valAddr sdk.ValAddress) error // Must be called when a validator is bonded } diff --git a/x/staking/client/rest/grpc_query_test.go b/x/staking/client/rest/grpc_query_test.go index 55a10194f603..29e95775e29f 100644 --- a/x/staking/client/rest/grpc_query_test.go +++ b/x/staking/client/rest/grpc_query_test.go @@ -35,11 +35,13 @@ func (s *IntegrationTestSuite) SetupSuite() { cfg := network.DefaultConfig() cfg.NumValidators = 2 - s.cfg = cfg - s.network = network.New(s.T(), cfg) - _, err := s.network.WaitForHeight(1) + var err error + s.network, err = network.New(s.T(), s.T().TempDir(), cfg) + s.Require().NoError(err) + + _, err = s.network.WaitForHeight(1) s.Require().NoError(err) unbond, err := sdk.ParseCoinNormalized("10stake") diff --git a/x/staking/client/testutil/suite.go b/x/staking/client/testutil/suite.go index f24a1ad5a234..fc6229ecca43 100644 --- a/x/staking/client/testutil/suite.go +++ b/x/staking/client/testutil/suite.go @@ -43,9 +43,11 @@ func (s *IntegrationTestSuite) SetupSuite() { s.T().Skip("skipping test in unit-tests mode.") } - s.network = network.New(s.T(), s.cfg) + var err error + s.network, err = network.New(s.T(), s.T().TempDir(), s.cfg) + s.Require().NoError(err) - _, err := s.network.WaitForHeight(1) + _, err = s.network.WaitForHeight(1) s.Require().NoError(err) unbond, err := sdk.ParseCoinNormalized("10stake") diff --git a/x/staking/genesis.go b/x/staking/genesis.go index 34a5be852a02..55daae2ce9f8 100644 --- a/x/staking/genesis.go +++ b/x/staking/genesis.go @@ -2,7 +2,6 @@ package staking import ( "fmt" - "log" abci "github.com/tendermint/tendermint/abci/types" tmtypes "github.com/tendermint/tendermint/types" @@ -44,7 +43,9 @@ func InitGenesis( // Call the creation hook if not exported if !data.Exported { - keeper.AfterValidatorCreated(ctx, validator.GetOperator()) + if err := keeper.AfterValidatorCreated(ctx, validator.GetOperator()); err != nil { + panic(err) + } } // update timeslice if necessary @@ -70,13 +71,17 @@ func InitGenesis( // Call the before-creation hook if not exported if !data.Exported { - keeper.BeforeDelegationCreated(ctx, delegatorAddress, delegation.GetValidatorAddr()) + if err := keeper.BeforeDelegationCreated(ctx, delegatorAddress, delegation.GetValidatorAddr()); err != nil { + panic(err) + } } keeper.SetDelegation(ctx, delegation) // Call the after-modification hook if not exported if !data.Exported { - keeper.AfterDelegationModified(ctx, delegatorAddress, delegation.GetValidatorAddr()) + if err := keeper.AfterDelegationModified(ctx, delegatorAddress, delegation.GetValidatorAddr()); err != nil { + panic(err) + } } } @@ -149,7 +154,7 @@ func InitGenesis( var err error res, err = keeper.ApplyAndReturnValidatorSetUpdates(ctx) if err != nil { - log.Fatal(err) + panic(err) } } diff --git a/x/staking/genesis_test.go b/x/staking/genesis_test.go index 0c686e2d998e..93fea369e9b3 100644 --- a/x/staking/genesis_test.go +++ b/x/staking/genesis_test.go @@ -14,6 +14,7 @@ import ( "github.com/cosmos/cosmos-sdk/crypto/keys/ed25519" "github.com/cosmos/cosmos-sdk/simapp" sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/x/bank/testutil" "github.com/cosmos/cosmos-sdk/x/staking" "github.com/cosmos/cosmos-sdk/x/staking/teststaking" "github.com/cosmos/cosmos-sdk/x/staking/types" @@ -64,7 +65,7 @@ func TestInitGenesis(t *testing.T) { log.Printf("%#v", len(validators)) // mint coins in the bonded pool representing the validators coins require.NoError(t, - simapp.FundModuleAccount( + testutil.FundModuleAccount( app.BankKeeper, ctx, types.BondedPoolName, @@ -182,7 +183,7 @@ func TestInitGenesisLargeValidatorSet(t *testing.T) { // mint coins in the bonded pool representing the validators coins require.NoError(t, - simapp.FundModuleAccount( + testutil.FundModuleAccount( app.BankKeeper, ctx, types.BondedPoolName, diff --git a/x/staking/handler_test.go b/x/staking/handler_test.go index 12dea7d7267a..240ddfee6a5a 100644 --- a/x/staking/handler_test.go +++ b/x/staking/handler_test.go @@ -5,14 +5,13 @@ import ( "testing" "time" + "github.com/golang/protobuf/proto" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" abci "github.com/tendermint/tendermint/abci/types" tmproto "github.com/tendermint/tendermint/proto/tendermint/types" tmtypes "github.com/tendermint/tendermint/types" - "github.com/golang/protobuf/proto" - cryptocodec "github.com/cosmos/cosmos-sdk/crypto/codec" "github.com/cosmos/cosmos-sdk/crypto/keys/ed25519" "github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1" @@ -20,6 +19,7 @@ import ( "github.com/cosmos/cosmos-sdk/simapp" "github.com/cosmos/cosmos-sdk/testutil/testdata" sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/x/bank/testutil" "github.com/cosmos/cosmos-sdk/x/staking" "github.com/cosmos/cosmos-sdk/x/staking/keeper" "github.com/cosmos/cosmos-sdk/x/staking/teststaking" @@ -38,7 +38,7 @@ func bootstrapHandlerGenesisTest(t *testing.T, power int64, numAddrs int, accAmo // set non bonded pool balance app.AccountKeeper.SetModuleAccount(ctx, notBondedPool) - require.NoError(t, simapp.FundModuleAccount(app.BankKeeper, ctx, notBondedPool.GetName(), totalSupply)) + require.NoError(t, testutil.FundModuleAccount(app.BankKeeper, ctx, notBondedPool.GetName(), totalSupply)) return app, ctx, addrDels, addrVals } diff --git a/x/staking/keeper/delegation.go b/x/staking/keeper/delegation.go index 6ed92e37aab9..ca4ab27658fe 100644 --- a/x/staking/keeper/delegation.go +++ b/x/staking/keeper/delegation.go @@ -101,15 +101,19 @@ func (k Keeper) SetDelegation(ctx sdk.Context, delegation types.Delegation) { } // remove a delegation -func (k Keeper) RemoveDelegation(ctx sdk.Context, delegation types.Delegation) { +func (k Keeper) RemoveDelegation(ctx sdk.Context, delegation types.Delegation) error { delegatorAddress, err := sdk.AccAddressFromBech32(delegation.DelegatorAddress) if err != nil { panic(err) } // TODO: Consider calling hooks outside of the store wrapper functions, it's unobvious. - k.BeforeDelegationRemoved(ctx, delegatorAddress, delegation.GetValidatorAddr()) + if err := k.BeforeDelegationRemoved(ctx, delegatorAddress, delegation.GetValidatorAddr()); err != nil { + return err + } + store := ctx.KVStore(k.storeKey) store.Delete(types.GetDelegationKey(delegatorAddress, delegation.GetValidatorAddr())) + return nil } // return a given amount of all the delegator unbonding-delegations @@ -563,9 +567,13 @@ func (k Keeper) Delegate( // call the appropriate hook if present if found { - k.BeforeDelegationSharesModified(ctx, delAddr, validator.GetOperator()) + err = k.BeforeDelegationSharesModified(ctx, delAddr, validator.GetOperator()) } else { - k.BeforeDelegationCreated(ctx, delAddr, validator.GetOperator()) + err = k.BeforeDelegationCreated(ctx, delAddr, validator.GetOperator()) + } + + if err != nil { + return sdk.ZeroDec(), err } delegatorAddress, err := sdk.AccAddressFromBech32(delegation.DelegatorAddress) @@ -621,7 +629,9 @@ func (k Keeper) Delegate( k.SetDelegation(ctx, delegation) // Call the after-modification hook - k.AfterDelegationModified(ctx, delegatorAddress, delegation.GetValidatorAddr()) + if err := k.AfterDelegationModified(ctx, delegatorAddress, delegation.GetValidatorAddr()); err != nil { + return newShares, err + } return newShares, nil } @@ -637,7 +647,9 @@ func (k Keeper) Unbond( } // call the before-delegation-modified hook - k.BeforeDelegationSharesModified(ctx, delAddr, valAddr) + if err := k.BeforeDelegationSharesModified(ctx, delAddr, valAddr); err != nil { + return amount, err + } // ensure that we have enough shares to remove if delegation.Shares.LT(shares) { @@ -670,11 +682,15 @@ func (k Keeper) Unbond( // remove the delegation if delegation.Shares.IsZero() { - k.RemoveDelegation(ctx, delegation) + err = k.RemoveDelegation(ctx, delegation) } else { k.SetDelegation(ctx, delegation) // call the after delegation modification hook - k.AfterDelegationModified(ctx, delegatorAddress, delegation.GetValidatorAddr()) + err = k.AfterDelegationModified(ctx, delegatorAddress, delegation.GetValidatorAddr()) + } + + if err != nil { + return amount, err } // remove the shares and coins from the validator diff --git a/x/staking/keeper/delegation_test.go b/x/staking/keeper/delegation_test.go index cac61af1fbe2..9a6699eb8b93 100644 --- a/x/staking/keeper/delegation_test.go +++ b/x/staking/keeper/delegation_test.go @@ -9,6 +9,7 @@ import ( "github.com/cosmos/cosmos-sdk/simapp" sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/x/bank/testutil" "github.com/cosmos/cosmos-sdk/x/staking/keeper" "github.com/cosmos/cosmos-sdk/x/staking/teststaking" "github.com/cosmos/cosmos-sdk/x/staking/types" @@ -186,7 +187,7 @@ func TestUnbondDelegation(t *testing.T) { startTokens := app.StakingKeeper.TokensFromConsensusPower(ctx, 10) notBondedPool := app.StakingKeeper.GetNotBondedPool(ctx) - require.NoError(t, simapp.FundModuleAccount(app.BankKeeper, ctx, notBondedPool.GetName(), sdk.NewCoins(sdk.NewCoin(app.StakingKeeper.BondDenom(ctx), startTokens)))) + require.NoError(t, testutil.FundModuleAccount(app.BankKeeper, ctx, notBondedPool.GetName(), sdk.NewCoins(sdk.NewCoin(app.StakingKeeper.BondDenom(ctx), startTokens)))) app.AccountKeeper.SetModuleAccount(ctx, notBondedPool) // create a validator and a delegator to that validator @@ -227,7 +228,7 @@ func TestUnbondingDelegationsMaxEntries(t *testing.T) { bondDenom := app.StakingKeeper.BondDenom(ctx) notBondedPool := app.StakingKeeper.GetNotBondedPool(ctx) - require.NoError(t, simapp.FundModuleAccount(app.BankKeeper, ctx, notBondedPool.GetName(), sdk.NewCoins(sdk.NewCoin(bondDenom, startTokens)))) + require.NoError(t, testutil.FundModuleAccount(app.BankKeeper, ctx, notBondedPool.GetName(), sdk.NewCoins(sdk.NewCoin(bondDenom, startTokens)))) app.AccountKeeper.SetModuleAccount(ctx, notBondedPool) // create a validator and a delegator to that validator @@ -315,7 +316,7 @@ func TestUndelegateSelfDelegationBelowMinSelfDelegation(t *testing.T) { // add bonded tokens to pool for delegations notBondedPool := app.StakingKeeper.GetNotBondedPool(ctx) - require.NoError(t, simapp.FundModuleAccount(app.BankKeeper, ctx, notBondedPool.GetName(), delCoins)) + require.NoError(t, testutil.FundModuleAccount(app.BankKeeper, ctx, notBondedPool.GetName(), delCoins)) app.AccountKeeper.SetModuleAccount(ctx, notBondedPool) validator = keeper.TestingUpdateValidator(app.StakingKeeper, ctx, validator, true) @@ -327,7 +328,7 @@ func TestUndelegateSelfDelegationBelowMinSelfDelegation(t *testing.T) { // add bonded tokens to pool for delegations bondedPool := app.StakingKeeper.GetBondedPool(ctx) - require.NoError(t, simapp.FundModuleAccount(app.BankKeeper, ctx, bondedPool.GetName(), delCoins)) + require.NoError(t, testutil.FundModuleAccount(app.BankKeeper, ctx, bondedPool.GetName(), delCoins)) app.AccountKeeper.SetModuleAccount(ctx, bondedPool) // create a second delegation to this validator @@ -337,7 +338,7 @@ func TestUndelegateSelfDelegationBelowMinSelfDelegation(t *testing.T) { require.Equal(t, delTokens, issuedShares.RoundInt()) // add bonded tokens to pool for delegations - require.NoError(t, simapp.FundModuleAccount(app.BankKeeper, ctx, bondedPool.GetName(), delCoins)) + require.NoError(t, testutil.FundModuleAccount(app.BankKeeper, ctx, bondedPool.GetName(), delCoins)) app.AccountKeeper.SetModuleAccount(ctx, bondedPool) validator = keeper.TestingUpdateValidator(app.StakingKeeper, ctx, validator, true) @@ -375,7 +376,7 @@ func TestUndelegateFromUnbondingValidator(t *testing.T) { // add bonded tokens to pool for delegations notBondedPool := app.StakingKeeper.GetNotBondedPool(ctx) - require.NoError(t, simapp.FundModuleAccount(app.BankKeeper, ctx, notBondedPool.GetName(), delCoins)) + require.NoError(t, testutil.FundModuleAccount(app.BankKeeper, ctx, notBondedPool.GetName(), delCoins)) app.AccountKeeper.SetModuleAccount(ctx, notBondedPool) validator = keeper.TestingUpdateValidator(app.StakingKeeper, ctx, validator, true) @@ -386,7 +387,7 @@ func TestUndelegateFromUnbondingValidator(t *testing.T) { // add bonded tokens to pool for delegations bondedPool := app.StakingKeeper.GetBondedPool(ctx) - require.NoError(t, simapp.FundModuleAccount(app.BankKeeper, ctx, bondedPool.GetName(), delCoins)) + require.NoError(t, testutil.FundModuleAccount(app.BankKeeper, ctx, bondedPool.GetName(), delCoins)) app.AccountKeeper.SetModuleAccount(ctx, bondedPool) // create a second delegation to this validator @@ -395,14 +396,14 @@ func TestUndelegateFromUnbondingValidator(t *testing.T) { validator, issuedShares = validator.AddTokensFromDel(delTokens) require.Equal(t, delTokens, issuedShares.RoundInt()) - require.NoError(t, simapp.FundModuleAccount(app.BankKeeper, ctx, bondedPool.GetName(), delCoins)) + require.NoError(t, testutil.FundModuleAccount(app.BankKeeper, ctx, bondedPool.GetName(), delCoins)) app.AccountKeeper.SetModuleAccount(ctx, bondedPool) validator = keeper.TestingUpdateValidator(app.StakingKeeper, ctx, validator, true) delegation := types.NewDelegation(addrDels[1], addrVals[0], issuedShares) app.StakingKeeper.SetDelegation(ctx, delegation) - require.NoError(t, simapp.FundModuleAccount(app.BankKeeper, ctx, bondedPool.GetName(), delCoins)) + require.NoError(t, testutil.FundModuleAccount(app.BankKeeper, ctx, bondedPool.GetName(), delCoins)) app.AccountKeeper.SetModuleAccount(ctx, bondedPool) header := ctx.BlockHeader() @@ -454,7 +455,7 @@ func TestUndelegateFromUnbondedValidator(t *testing.T) { // add bonded tokens to pool for delegations notBondedPool := app.StakingKeeper.GetNotBondedPool(ctx) - require.NoError(t, simapp.FundModuleAccount(app.BankKeeper, ctx, notBondedPool.GetName(), delCoins)) + require.NoError(t, testutil.FundModuleAccount(app.BankKeeper, ctx, notBondedPool.GetName(), delCoins)) app.AccountKeeper.SetModuleAccount(ctx, notBondedPool) // create a validator with a self-delegation @@ -473,7 +474,7 @@ func TestUndelegateFromUnbondedValidator(t *testing.T) { // add bonded tokens to pool for delegations bondedPool := app.StakingKeeper.GetBondedPool(ctx) - require.NoError(t, simapp.FundModuleAccount(app.BankKeeper, ctx, bondedPool.GetName(), delCoins)) + require.NoError(t, testutil.FundModuleAccount(app.BankKeeper, ctx, bondedPool.GetName(), delCoins)) app.AccountKeeper.SetModuleAccount(ctx, bondedPool) // create a second delegation to this validator @@ -535,7 +536,7 @@ func TestUnbondingAllDelegationFromValidator(t *testing.T) { // add bonded tokens to pool for delegations notBondedPool := app.StakingKeeper.GetNotBondedPool(ctx) - require.NoError(t, simapp.FundModuleAccount(app.BankKeeper, ctx, notBondedPool.GetName(), delCoins)) + require.NoError(t, testutil.FundModuleAccount(app.BankKeeper, ctx, notBondedPool.GetName(), delCoins)) app.AccountKeeper.SetModuleAccount(ctx, notBondedPool) //create a validator with a self-delegation @@ -560,7 +561,7 @@ func TestUnbondingAllDelegationFromValidator(t *testing.T) { // add bonded tokens to pool for delegations bondedPool := app.StakingKeeper.GetBondedPool(ctx) - require.NoError(t, simapp.FundModuleAccount(app.BankKeeper, ctx, bondedPool.GetName(), delCoins)) + require.NoError(t, testutil.FundModuleAccount(app.BankKeeper, ctx, bondedPool.GetName(), delCoins)) app.AccountKeeper.SetModuleAccount(ctx, bondedPool) validator = keeper.TestingUpdateValidator(app.StakingKeeper, ctx, validator, true) @@ -699,7 +700,7 @@ func TestRedelegateToSameValidator(t *testing.T) { // add bonded tokens to pool for delegations notBondedPool := app.StakingKeeper.GetNotBondedPool(ctx) - require.NoError(t, simapp.FundModuleAccount(app.BankKeeper, ctx, notBondedPool.GetName(), startCoins)) + require.NoError(t, testutil.FundModuleAccount(app.BankKeeper, ctx, notBondedPool.GetName(), startCoins)) app.AccountKeeper.SetModuleAccount(ctx, notBondedPool) // create a validator with a self-delegation @@ -728,7 +729,7 @@ func TestRedelegationMaxEntries(t *testing.T) { // add bonded tokens to pool for delegations notBondedPool := app.StakingKeeper.GetNotBondedPool(ctx) - require.NoError(t, simapp.FundModuleAccount(app.BankKeeper, ctx, notBondedPool.GetName(), startCoins)) + require.NoError(t, testutil.FundModuleAccount(app.BankKeeper, ctx, notBondedPool.GetName(), startCoins)) app.AccountKeeper.SetModuleAccount(ctx, notBondedPool) // create a validator with a self-delegation @@ -784,7 +785,7 @@ func TestRedelegateSelfDelegation(t *testing.T) { // add bonded tokens to pool for delegations notBondedPool := app.StakingKeeper.GetNotBondedPool(ctx) - require.NoError(t, simapp.FundModuleAccount(app.BankKeeper, ctx, notBondedPool.GetName(), startCoins)) + require.NoError(t, testutil.FundModuleAccount(app.BankKeeper, ctx, notBondedPool.GetName(), startCoins)) app.AccountKeeper.SetModuleAccount(ctx, notBondedPool) //create a validator with a self-delegation @@ -840,7 +841,7 @@ func TestRedelegateFromUnbondingValidator(t *testing.T) { // add bonded tokens to pool for delegations notBondedPool := app.StakingKeeper.GetNotBondedPool(ctx) - require.NoError(t, simapp.FundModuleAccount(app.BankKeeper, ctx, notBondedPool.GetName(), startCoins)) + require.NoError(t, testutil.FundModuleAccount(app.BankKeeper, ctx, notBondedPool.GetName(), startCoins)) app.AccountKeeper.SetModuleAccount(ctx, notBondedPool) //create a validator with a self-delegation @@ -922,7 +923,7 @@ func TestRedelegateFromUnbondedValidator(t *testing.T) { // add bonded tokens to pool for delegations notBondedPool := app.StakingKeeper.GetNotBondedPool(ctx) - require.NoError(t, simapp.FundModuleAccount(app.BankKeeper, ctx, notBondedPool.GetName(), startCoins)) + require.NoError(t, testutil.FundModuleAccount(app.BankKeeper, ctx, notBondedPool.GetName(), startCoins)) app.AccountKeeper.SetModuleAccount(ctx, notBondedPool) //create a validator with a self-delegation diff --git a/x/staking/keeper/hooks.go b/x/staking/keeper/hooks.go index b8f25908babd..91375c9e3881 100644 --- a/x/staking/keeper/hooks.go +++ b/x/staking/keeper/hooks.go @@ -9,71 +9,81 @@ import ( var _ types.StakingHooks = Keeper{} // AfterValidatorCreated - call hook if registered -func (k Keeper) AfterValidatorCreated(ctx sdk.Context, valAddr sdk.ValAddress) { +func (k Keeper) AfterValidatorCreated(ctx sdk.Context, valAddr sdk.ValAddress) error { if k.hooks != nil { - k.hooks.AfterValidatorCreated(ctx, valAddr) + return k.hooks.AfterValidatorCreated(ctx, valAddr) } + return nil } // BeforeValidatorModified - call hook if registered -func (k Keeper) BeforeValidatorModified(ctx sdk.Context, valAddr sdk.ValAddress) { +func (k Keeper) BeforeValidatorModified(ctx sdk.Context, valAddr sdk.ValAddress) error { if k.hooks != nil { - k.hooks.BeforeValidatorModified(ctx, valAddr) + return k.hooks.BeforeValidatorModified(ctx, valAddr) } + return nil } // AfterValidatorRemoved - call hook if registered -func (k Keeper) AfterValidatorRemoved(ctx sdk.Context, consAddr sdk.ConsAddress, valAddr sdk.ValAddress) { +func (k Keeper) AfterValidatorRemoved(ctx sdk.Context, consAddr sdk.ConsAddress, valAddr sdk.ValAddress) error { if k.hooks != nil { - k.hooks.AfterValidatorRemoved(ctx, consAddr, valAddr) + return k.hooks.AfterValidatorRemoved(ctx, consAddr, valAddr) } + return nil } // AfterValidatorBonded - call hook if registered -func (k Keeper) AfterValidatorBonded(ctx sdk.Context, consAddr sdk.ConsAddress, valAddr sdk.ValAddress) { +func (k Keeper) AfterValidatorBonded(ctx sdk.Context, consAddr sdk.ConsAddress, valAddr sdk.ValAddress) error { if k.hooks != nil { - k.hooks.AfterValidatorBonded(ctx, consAddr, valAddr) + return k.hooks.AfterValidatorBonded(ctx, consAddr, valAddr) } + return nil } // AfterValidatorBeginUnbonding - call hook if registered -func (k Keeper) AfterValidatorBeginUnbonding(ctx sdk.Context, consAddr sdk.ConsAddress, valAddr sdk.ValAddress) { +func (k Keeper) AfterValidatorBeginUnbonding(ctx sdk.Context, consAddr sdk.ConsAddress, valAddr sdk.ValAddress) error { if k.hooks != nil { - k.hooks.AfterValidatorBeginUnbonding(ctx, consAddr, valAddr) + return k.hooks.AfterValidatorBeginUnbonding(ctx, consAddr, valAddr) } + return nil } // BeforeDelegationCreated - call hook if registered -func (k Keeper) BeforeDelegationCreated(ctx sdk.Context, delAddr sdk.AccAddress, valAddr sdk.ValAddress) { +func (k Keeper) BeforeDelegationCreated(ctx sdk.Context, delAddr sdk.AccAddress, valAddr sdk.ValAddress) error { if k.hooks != nil { - k.hooks.BeforeDelegationCreated(ctx, delAddr, valAddr) + return k.hooks.BeforeDelegationCreated(ctx, delAddr, valAddr) } + return nil } // BeforeDelegationSharesModified - call hook if registered -func (k Keeper) BeforeDelegationSharesModified(ctx sdk.Context, delAddr sdk.AccAddress, valAddr sdk.ValAddress) { +func (k Keeper) BeforeDelegationSharesModified(ctx sdk.Context, delAddr sdk.AccAddress, valAddr sdk.ValAddress) error { if k.hooks != nil { - k.hooks.BeforeDelegationSharesModified(ctx, delAddr, valAddr) + return k.hooks.BeforeDelegationSharesModified(ctx, delAddr, valAddr) } + return nil } // BeforeDelegationRemoved - call hook if registered -func (k Keeper) BeforeDelegationRemoved(ctx sdk.Context, delAddr sdk.AccAddress, valAddr sdk.ValAddress) { +func (k Keeper) BeforeDelegationRemoved(ctx sdk.Context, delAddr sdk.AccAddress, valAddr sdk.ValAddress) error { if k.hooks != nil { k.hooks.BeforeDelegationRemoved(ctx, delAddr, valAddr) } + return nil } // AfterDelegationModified - call hook if registered -func (k Keeper) AfterDelegationModified(ctx sdk.Context, delAddr sdk.AccAddress, valAddr sdk.ValAddress) { +func (k Keeper) AfterDelegationModified(ctx sdk.Context, delAddr sdk.AccAddress, valAddr sdk.ValAddress) error { if k.hooks != nil { - k.hooks.AfterDelegationModified(ctx, delAddr, valAddr) + return k.hooks.AfterDelegationModified(ctx, delAddr, valAddr) } + return nil } // BeforeValidatorSlashed - call hook if registered -func (k Keeper) BeforeValidatorSlashed(ctx sdk.Context, valAddr sdk.ValAddress, fraction sdk.Dec) { +func (k Keeper) BeforeValidatorSlashed(ctx sdk.Context, valAddr sdk.ValAddress, fraction sdk.Dec) error { if k.hooks != nil { - k.hooks.BeforeValidatorSlashed(ctx, valAddr, fraction) + return k.hooks.BeforeValidatorSlashed(ctx, valAddr, fraction) } + return nil } diff --git a/x/staking/keeper/msg_server.go b/x/staking/keeper/msg_server.go index 30857c3a0163..db084531ca65 100644 --- a/x/staking/keeper/msg_server.go +++ b/x/staking/keeper/msg_server.go @@ -96,7 +96,9 @@ func (k msgServer) CreateValidator(goCtx context.Context, msg *types.MsgCreateVa k.SetNewValidatorByPowerIndex(ctx, validator) // call the after-creation hook - k.AfterValidatorCreated(ctx, validator.GetOperator()) + if err := k.AfterValidatorCreated(ctx, validator.GetOperator()); err != nil { + return nil, err + } // move coins from the msg.Address account to a (self-delegation) delegator account // the validator account and global shares are updated within here @@ -150,7 +152,9 @@ func (k msgServer) EditValidator(goCtx context.Context, msg *types.MsgEditValida } // call the before-modification hook since we're about to update the commission - k.BeforeValidatorModified(ctx, valAddr) + if err := k.BeforeValidatorModified(ctx, valAddr); err != nil { + return nil, err + } validator.Commission = commission } diff --git a/x/staking/keeper/slash_test.go b/x/staking/keeper/slash_test.go index 64bdb0177d57..81e5c8afb095 100644 --- a/x/staking/keeper/slash_test.go +++ b/x/staking/keeper/slash_test.go @@ -10,6 +10,7 @@ import ( "github.com/cosmos/cosmos-sdk/simapp" sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/x/bank/testutil" "github.com/cosmos/cosmos-sdk/x/staking/keeper" "github.com/cosmos/cosmos-sdk/x/staking/teststaking" "github.com/cosmos/cosmos-sdk/x/staking/types" @@ -25,7 +26,7 @@ func bootstrapSlashTest(t *testing.T, power int64) (*simapp.SimApp, sdk.Context, totalSupply := sdk.NewCoins(sdk.NewCoin(app.StakingKeeper.BondDenom(ctx), amt.MulRaw(int64(len(addrDels))))) notBondedPool := app.StakingKeeper.GetNotBondedPool(ctx) - require.NoError(t, simapp.FundModuleAccount(app.BankKeeper, ctx, notBondedPool.GetName(), totalSupply)) + require.NoError(t, testutil.FundModuleAccount(app.BankKeeper, ctx, notBondedPool.GetName(), totalSupply)) app.AccountKeeper.SetModuleAccount(ctx, notBondedPool) @@ -35,7 +36,7 @@ func bootstrapSlashTest(t *testing.T, power int64) (*simapp.SimApp, sdk.Context, // set bonded pool balance app.AccountKeeper.SetModuleAccount(ctx, bondedPool) - require.NoError(t, simapp.FundModuleAccount(app.BankKeeper, ctx, bondedPool.GetName(), bondedCoins)) + require.NoError(t, testutil.FundModuleAccount(app.BankKeeper, ctx, bondedPool.GetName(), bondedCoins)) for i := int64(0); i < numVals; i++ { validator := teststaking.NewValidator(t, addrVals[i], PKs[i]) @@ -125,7 +126,7 @@ func TestSlashRedelegation(t *testing.T) { bondedPool := app.StakingKeeper.GetBondedPool(ctx) balances := app.BankKeeper.GetAllBalances(ctx, bondedPool.GetAddress()) - require.NoError(t, simapp.FundModuleAccount(app.BankKeeper, ctx, bondedPool.GetName(), startCoins)) + require.NoError(t, testutil.FundModuleAccount(app.BankKeeper, ctx, bondedPool.GetName(), startCoins)) app.AccountKeeper.SetModuleAccount(ctx, bondedPool) // set a redelegation with an expiration timestamp beyond which the @@ -402,7 +403,7 @@ func TestSlashWithRedelegation(t *testing.T) { notBondedPool := app.StakingKeeper.GetNotBondedPool(ctx) rdCoins := sdk.NewCoins(sdk.NewCoin(bondDenom, rdTokens.MulRaw(2))) - require.NoError(t, simapp.FundModuleAccount(app.BankKeeper, ctx, bondedPool.GetName(), rdCoins)) + require.NoError(t, testutil.FundModuleAccount(app.BankKeeper, ctx, bondedPool.GetName(), rdCoins)) app.AccountKeeper.SetModuleAccount(ctx, bondedPool) @@ -565,8 +566,8 @@ func TestSlashBoth(t *testing.T) { bondedPool := app.StakingKeeper.GetBondedPool(ctx) notBondedPool := app.StakingKeeper.GetNotBondedPool(ctx) - require.NoError(t, simapp.FundModuleAccount(app.BankKeeper, ctx, bondedPool.GetName(), bondedCoins)) - require.NoError(t, simapp.FundModuleAccount(app.BankKeeper, ctx, notBondedPool.GetName(), notBondedCoins)) + require.NoError(t, testutil.FundModuleAccount(app.BankKeeper, ctx, bondedPool.GetName(), bondedCoins)) + require.NoError(t, testutil.FundModuleAccount(app.BankKeeper, ctx, notBondedPool.GetName(), notBondedCoins)) app.AccountKeeper.SetModuleAccount(ctx, bondedPool) app.AccountKeeper.SetModuleAccount(ctx, notBondedPool) diff --git a/x/staking/keeper/validator_test.go b/x/staking/keeper/validator_test.go index 31da70eab6a8..3017ffb92fdd 100644 --- a/x/staking/keeper/validator_test.go +++ b/x/staking/keeper/validator_test.go @@ -13,6 +13,7 @@ import ( cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types" "github.com/cosmos/cosmos-sdk/simapp" sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/x/bank/testutil" "github.com/cosmos/cosmos-sdk/x/staking/keeper" "github.com/cosmos/cosmos-sdk/x/staking/teststaking" "github.com/cosmos/cosmos-sdk/x/staking/types" @@ -36,7 +37,7 @@ func bootstrapValidatorTest(t testing.TB, power int64, numAddrs int) (*simapp.Si // set bonded pool supply app.AccountKeeper.SetModuleAccount(ctx, notBondedPool) - require.NoError(t, simapp.FundModuleAccount(app.BankKeeper, ctx, notBondedPool.GetName(), totalSupply)) + require.NoError(t, testutil.FundModuleAccount(app.BankKeeper, ctx, notBondedPool.GetName(), totalSupply)) return app, ctx, addrDels, addrVals } @@ -113,8 +114,8 @@ func TestUpdateValidatorByPowerIndex(t *testing.T) { bondedPool := app.StakingKeeper.GetBondedPool(ctx) notBondedPool := app.StakingKeeper.GetNotBondedPool(ctx) - require.NoError(t, simapp.FundModuleAccount(app.BankKeeper, ctx, bondedPool.GetName(), sdk.NewCoins(sdk.NewCoin(app.StakingKeeper.BondDenom(ctx), app.StakingKeeper.TokensFromConsensusPower(ctx, 1234))))) - require.NoError(t, simapp.FundModuleAccount(app.BankKeeper, ctx, notBondedPool.GetName(), sdk.NewCoins(sdk.NewCoin(app.StakingKeeper.BondDenom(ctx), app.StakingKeeper.TokensFromConsensusPower(ctx, 10000))))) + require.NoError(t, testutil.FundModuleAccount(app.BankKeeper, ctx, bondedPool.GetName(), sdk.NewCoins(sdk.NewCoin(app.StakingKeeper.BondDenom(ctx), app.StakingKeeper.TokensFromConsensusPower(ctx, 1234))))) + require.NoError(t, testutil.FundModuleAccount(app.BankKeeper, ctx, notBondedPool.GetName(), sdk.NewCoins(sdk.NewCoin(app.StakingKeeper.BondDenom(ctx), app.StakingKeeper.TokensFromConsensusPower(ctx, 10000))))) app.AccountKeeper.SetModuleAccount(ctx, bondedPool) app.AccountKeeper.SetModuleAccount(ctx, notBondedPool) @@ -162,8 +163,8 @@ func TestUpdateBondedValidatorsDecreaseCliff(t *testing.T) { app.StakingKeeper.SetParams(ctx, params) // create a random pool - require.NoError(t, simapp.FundModuleAccount(app.BankKeeper, ctx, bondedPool.GetName(), sdk.NewCoins(sdk.NewCoin(app.StakingKeeper.BondDenom(ctx), app.StakingKeeper.TokensFromConsensusPower(ctx, 1234))))) - require.NoError(t, simapp.FundModuleAccount(app.BankKeeper, ctx, notBondedPool.GetName(), sdk.NewCoins(sdk.NewCoin(app.StakingKeeper.BondDenom(ctx), app.StakingKeeper.TokensFromConsensusPower(ctx, 10000))))) + require.NoError(t, testutil.FundModuleAccount(app.BankKeeper, ctx, bondedPool.GetName(), sdk.NewCoins(sdk.NewCoin(app.StakingKeeper.BondDenom(ctx), app.StakingKeeper.TokensFromConsensusPower(ctx, 1234))))) + require.NoError(t, testutil.FundModuleAccount(app.BankKeeper, ctx, notBondedPool.GetName(), sdk.NewCoins(sdk.NewCoin(app.StakingKeeper.BondDenom(ctx), app.StakingKeeper.TokensFromConsensusPower(ctx, 10000))))) app.AccountKeeper.SetModuleAccount(ctx, bondedPool) app.AccountKeeper.SetModuleAccount(ctx, notBondedPool) @@ -217,7 +218,7 @@ func TestSlashToZeroPowerRemoved(t *testing.T) { bondedPool := app.StakingKeeper.GetBondedPool(ctx) - require.NoError(t, simapp.FundModuleAccount(app.BankKeeper, ctx, bondedPool.GetName(), sdk.NewCoins(sdk.NewCoin(app.StakingKeeper.BondDenom(ctx), valTokens)))) + require.NoError(t, testutil.FundModuleAccount(app.BankKeeper, ctx, bondedPool.GetName(), sdk.NewCoins(sdk.NewCoin(app.StakingKeeper.BondDenom(ctx), valTokens)))) app.AccountKeeper.SetModuleAccount(ctx, bondedPool) @@ -422,8 +423,8 @@ func TestGetValidatorSortingMixed(t *testing.T) { bondedPool := app.StakingKeeper.GetBondedPool(ctx) notBondedPool := app.StakingKeeper.GetNotBondedPool(ctx) - require.NoError(t, simapp.FundModuleAccount(app.BankKeeper, ctx, bondedPool.GetName(), sdk.NewCoins(sdk.NewCoin(app.StakingKeeper.BondDenom(ctx), app.StakingKeeper.TokensFromConsensusPower(ctx, 501))))) - require.NoError(t, simapp.FundModuleAccount(app.BankKeeper, ctx, notBondedPool.GetName(), sdk.NewCoins(sdk.NewCoin(app.StakingKeeper.BondDenom(ctx), app.StakingKeeper.TokensFromConsensusPower(ctx, 0))))) + require.NoError(t, testutil.FundModuleAccount(app.BankKeeper, ctx, bondedPool.GetName(), sdk.NewCoins(sdk.NewCoin(app.StakingKeeper.BondDenom(ctx), app.StakingKeeper.TokensFromConsensusPower(ctx, 501))))) + require.NoError(t, testutil.FundModuleAccount(app.BankKeeper, ctx, notBondedPool.GetName(), sdk.NewCoins(sdk.NewCoin(app.StakingKeeper.BondDenom(ctx), app.StakingKeeper.TokensFromConsensusPower(ctx, 0))))) app.AccountKeeper.SetModuleAccount(ctx, notBondedPool) app.AccountKeeper.SetModuleAccount(ctx, bondedPool) @@ -497,7 +498,7 @@ func TestGetValidatorsEdgeCases(t *testing.T) { validators[i], _ = validators[i].AddTokensFromDel(tokens) notBondedPool := app.StakingKeeper.GetNotBondedPool(ctx) - require.NoError(t, simapp.FundModuleAccount(app.BankKeeper, ctx, notBondedPool.GetName(), sdk.NewCoins(sdk.NewCoin(params.BondDenom, tokens)))) + require.NoError(t, testutil.FundModuleAccount(app.BankKeeper, ctx, notBondedPool.GetName(), sdk.NewCoins(sdk.NewCoin(params.BondDenom, tokens)))) app.AccountKeeper.SetModuleAccount(ctx, notBondedPool) validators[i] = keeper.TestingUpdateValidator(app.StakingKeeper, ctx, validators[i], true) } @@ -516,7 +517,7 @@ func TestGetValidatorsEdgeCases(t *testing.T) { newTokens := sdk.NewCoins() - require.NoError(t, simapp.FundModuleAccount(app.BankKeeper, ctx, notBondedPool.GetName(), newTokens)) + require.NoError(t, testutil.FundModuleAccount(app.BankKeeper, ctx, notBondedPool.GetName(), newTokens)) app.AccountKeeper.SetModuleAccount(ctx, notBondedPool) // test that the two largest validators are @@ -548,7 +549,7 @@ func TestGetValidatorsEdgeCases(t *testing.T) { notBondedPool = app.StakingKeeper.GetNotBondedPool(ctx) newTokens = sdk.NewCoins(sdk.NewCoin(params.BondDenom, app.StakingKeeper.TokensFromConsensusPower(ctx, 1))) - require.NoError(t, simapp.FundModuleAccount(app.BankKeeper, ctx, notBondedPool.GetName(), newTokens)) + require.NoError(t, testutil.FundModuleAccount(app.BankKeeper, ctx, notBondedPool.GetName(), newTokens)) app.AccountKeeper.SetModuleAccount(ctx, notBondedPool) validators[3] = keeper.TestingUpdateValidator(app.StakingKeeper, ctx, validators[3], true) @@ -563,7 +564,7 @@ func TestGetValidatorsEdgeCases(t *testing.T) { validators[3], _ = validators[3].RemoveDelShares(sdk.NewDec(201)) bondedPool := app.StakingKeeper.GetBondedPool(ctx) - require.NoError(t, simapp.FundModuleAccount(app.BankKeeper, ctx, bondedPool.GetName(), sdk.NewCoins(sdk.NewCoin(params.BondDenom, rmTokens)))) + require.NoError(t, testutil.FundModuleAccount(app.BankKeeper, ctx, bondedPool.GetName(), sdk.NewCoins(sdk.NewCoin(params.BondDenom, rmTokens)))) app.AccountKeeper.SetModuleAccount(ctx, bondedPool) validators[3] = keeper.TestingUpdateValidator(app.StakingKeeper, ctx, validators[3], true) @@ -577,7 +578,7 @@ func TestGetValidatorsEdgeCases(t *testing.T) { validators[3], _ = validators[3].AddTokensFromDel(sdk.NewInt(200)) notBondedPool = app.StakingKeeper.GetNotBondedPool(ctx) - require.NoError(t, simapp.FundModuleAccount(app.BankKeeper, ctx, notBondedPool.GetName(), sdk.NewCoins(sdk.NewCoin(params.BondDenom, sdk.NewInt(200))))) + require.NoError(t, testutil.FundModuleAccount(app.BankKeeper, ctx, notBondedPool.GetName(), sdk.NewCoins(sdk.NewCoin(params.BondDenom, sdk.NewInt(200))))) app.AccountKeeper.SetModuleAccount(ctx, notBondedPool) validators[3] = keeper.TestingUpdateValidator(app.StakingKeeper, ctx, validators[3], true) diff --git a/x/staking/simulation/operations_test.go b/x/staking/simulation/operations_test.go index da15fdd5e489..bfa27d80285f 100644 --- a/x/staking/simulation/operations_test.go +++ b/x/staking/simulation/operations_test.go @@ -13,6 +13,7 @@ import ( simappparams "github.com/cosmos/cosmos-sdk/simapp/params" sdk "github.com/cosmos/cosmos-sdk/types" simtypes "github.com/cosmos/cosmos-sdk/types/simulation" + "github.com/cosmos/cosmos-sdk/x/bank/testutil" distrtypes "github.com/cosmos/cosmos-sdk/x/distribution/types" minttypes "github.com/cosmos/cosmos-sdk/x/mint/types" "github.com/cosmos/cosmos-sdk/x/staking/simulation" @@ -283,7 +284,7 @@ func getTestingAccounts(t *testing.T, r *rand.Rand, app *simapp.SimApp, ctx sdk. for _, account := range accounts { acc := app.AccountKeeper.NewAccountWithAddress(ctx, account.Address) app.AccountKeeper.SetAccount(ctx, acc) - require.NoError(t, simapp.FundAccount(app.BankKeeper, ctx, account.Address, initCoins)) + require.NoError(t, testutil.FundAccount(app.BankKeeper, ctx, account.Address, initCoins)) } return accounts diff --git a/x/staking/spec/06_hooks.md b/x/staking/spec/06_hooks.md index d4c3228eca7a..655431a7e6ea 100644 --- a/x/staking/spec/06_hooks.md +++ b/x/staking/spec/06_hooks.md @@ -9,19 +9,19 @@ occurred within staking. These events can be registered to execute either right `Before` or `After` the staking event (as per the hook name). The following hooks can registered with staking: -- `AfterValidatorCreated(Context, ValAddress)` +- `AfterValidatorCreated(Context, ValAddress) error` - called when a validator is created -- `BeforeValidatorModified(Context, ValAddress)` +- `BeforeValidatorModified(Context, ValAddress) error` - called when a validator's state is changed -- `AfterValidatorRemoved(Context, ConsAddress, ValAddress)` +- `AfterValidatorRemoved(Context, ConsAddress, ValAddress) error` - called when a validator is deleted -- `AfterValidatorBonded(Context, ConsAddress, ValAddress)` +- `AfterValidatorBonded(Context, ConsAddress, ValAddress) error` - called when a validator is bonded -- `AfterValidatorBeginUnbonding(Context, ConsAddress, ValAddress)` +- `AfterValidatorBeginUnbonding(Context, ConsAddress, ValAddress) error` - called when a validator begins unbonding -- `BeforeDelegationCreated(Context, AccAddress, ValAddress)` +- `BeforeDelegationCreated(Context, AccAddress, ValAddress) error` - called when a delegation is created -- `BeforeDelegationSharesModified(Context, AccAddress, ValAddress)` +- `BeforeDelegationSharesModified(Context, AccAddress, ValAddress) error` - called when a delegation's shares are modified -- `BeforeDelegationRemoved(Context, AccAddress, ValAddress)` +- `BeforeDelegationRemoved(Context, AccAddress, ValAddress) error` - called when a delegation is removed diff --git a/x/staking/types/expected_keepers.go b/x/staking/types/expected_keepers.go index 313db78e7b1c..f00971751c17 100644 --- a/x/staking/types/expected_keepers.go +++ b/x/staking/types/expected_keepers.go @@ -89,16 +89,16 @@ type DelegationSet interface { // StakingHooks event hooks for staking validator object (noalias) type StakingHooks interface { - AfterValidatorCreated(ctx sdk.Context, valAddr sdk.ValAddress) // Must be called when a validator is created - BeforeValidatorModified(ctx sdk.Context, valAddr sdk.ValAddress) // Must be called when a validator's state changes - AfterValidatorRemoved(ctx sdk.Context, consAddr sdk.ConsAddress, valAddr sdk.ValAddress) // Must be called when a validator is deleted - - AfterValidatorBonded(ctx sdk.Context, consAddr sdk.ConsAddress, valAddr sdk.ValAddress) // Must be called when a validator is bonded - AfterValidatorBeginUnbonding(ctx sdk.Context, consAddr sdk.ConsAddress, valAddr sdk.ValAddress) // Must be called when a validator begins unbonding - - BeforeDelegationCreated(ctx sdk.Context, delAddr sdk.AccAddress, valAddr sdk.ValAddress) // Must be called when a delegation is created - BeforeDelegationSharesModified(ctx sdk.Context, delAddr sdk.AccAddress, valAddr sdk.ValAddress) // Must be called when a delegation's shares are modified - BeforeDelegationRemoved(ctx sdk.Context, delAddr sdk.AccAddress, valAddr sdk.ValAddress) // Must be called when a delegation is removed - AfterDelegationModified(ctx sdk.Context, delAddr sdk.AccAddress, valAddr sdk.ValAddress) - BeforeValidatorSlashed(ctx sdk.Context, valAddr sdk.ValAddress, fraction sdk.Dec) + AfterValidatorCreated(ctx sdk.Context, valAddr sdk.ValAddress) error // Must be called when a validator is created + BeforeValidatorModified(ctx sdk.Context, valAddr sdk.ValAddress) error // Must be called when a validator's state changes + AfterValidatorRemoved(ctx sdk.Context, consAddr sdk.ConsAddress, valAddr sdk.ValAddress) error // Must be called when a validator is deleted + + AfterValidatorBonded(ctx sdk.Context, consAddr sdk.ConsAddress, valAddr sdk.ValAddress) error // Must be called when a validator is bonded + AfterValidatorBeginUnbonding(ctx sdk.Context, consAddr sdk.ConsAddress, valAddr sdk.ValAddress) error // Must be called when a validator begins unbonding + + BeforeDelegationCreated(ctx sdk.Context, delAddr sdk.AccAddress, valAddr sdk.ValAddress) error // Must be called when a delegation is created + BeforeDelegationSharesModified(ctx sdk.Context, delAddr sdk.AccAddress, valAddr sdk.ValAddress) error // Must be called when a delegation's shares are modified + BeforeDelegationRemoved(ctx sdk.Context, delAddr sdk.AccAddress, valAddr sdk.ValAddress) error // Must be called when a delegation is removed + AfterDelegationModified(ctx sdk.Context, delAddr sdk.AccAddress, valAddr sdk.ValAddress) error + BeforeValidatorSlashed(ctx sdk.Context, valAddr sdk.ValAddress, fraction sdk.Dec) error } diff --git a/x/staking/types/hooks.go b/x/staking/types/hooks.go index 694caca5405a..33838bcaa030 100644 --- a/x/staking/types/hooks.go +++ b/x/staking/types/hooks.go @@ -5,59 +5,92 @@ import ( ) // combine multiple staking hooks, all hook functions are run in array sequence +var _ StakingHooks = &MultiStakingHooks{} + type MultiStakingHooks []StakingHooks func NewMultiStakingHooks(hooks ...StakingHooks) MultiStakingHooks { return hooks } -func (h MultiStakingHooks) AfterValidatorCreated(ctx sdk.Context, valAddr sdk.ValAddress) { +func (h MultiStakingHooks) AfterValidatorCreated(ctx sdk.Context, valAddr sdk.ValAddress) error { for i := range h { - h[i].AfterValidatorCreated(ctx, valAddr) + if err := h[i].AfterValidatorCreated(ctx, valAddr); err != nil { + return err + } } + + return nil } -func (h MultiStakingHooks) BeforeValidatorModified(ctx sdk.Context, valAddr sdk.ValAddress) { +func (h MultiStakingHooks) BeforeValidatorModified(ctx sdk.Context, valAddr sdk.ValAddress) error { for i := range h { - h[i].BeforeValidatorModified(ctx, valAddr) + if err := h[i].BeforeValidatorModified(ctx, valAddr); err != nil { + return err + } } + return nil } -func (h MultiStakingHooks) AfterValidatorRemoved(ctx sdk.Context, consAddr sdk.ConsAddress, valAddr sdk.ValAddress) { +func (h MultiStakingHooks) AfterValidatorRemoved(ctx sdk.Context, consAddr sdk.ConsAddress, valAddr sdk.ValAddress) error { for i := range h { - h[i].AfterValidatorRemoved(ctx, consAddr, valAddr) + if err := h[i].AfterValidatorRemoved(ctx, consAddr, valAddr); err != nil { + return err + } } + return nil } -func (h MultiStakingHooks) AfterValidatorBonded(ctx sdk.Context, consAddr sdk.ConsAddress, valAddr sdk.ValAddress) { +func (h MultiStakingHooks) AfterValidatorBonded(ctx sdk.Context, consAddr sdk.ConsAddress, valAddr sdk.ValAddress) error { for i := range h { - h[i].AfterValidatorBonded(ctx, consAddr, valAddr) + if err := h[i].AfterValidatorBonded(ctx, consAddr, valAddr); err != nil { + return err + } } + return nil } -func (h MultiStakingHooks) AfterValidatorBeginUnbonding(ctx sdk.Context, consAddr sdk.ConsAddress, valAddr sdk.ValAddress) { +func (h MultiStakingHooks) AfterValidatorBeginUnbonding(ctx sdk.Context, consAddr sdk.ConsAddress, valAddr sdk.ValAddress) error { for i := range h { - h[i].AfterValidatorBeginUnbonding(ctx, consAddr, valAddr) + if err := h[i].AfterValidatorBeginUnbonding(ctx, consAddr, valAddr); err != nil { + return err + } } + return nil } -func (h MultiStakingHooks) BeforeDelegationCreated(ctx sdk.Context, delAddr sdk.AccAddress, valAddr sdk.ValAddress) { +func (h MultiStakingHooks) BeforeDelegationCreated(ctx sdk.Context, delAddr sdk.AccAddress, valAddr sdk.ValAddress) error { for i := range h { - h[i].BeforeDelegationCreated(ctx, delAddr, valAddr) + if err := h[i].BeforeDelegationCreated(ctx, delAddr, valAddr); err != nil { + return err + } } + return nil } -func (h MultiStakingHooks) BeforeDelegationSharesModified(ctx sdk.Context, delAddr sdk.AccAddress, valAddr sdk.ValAddress) { +func (h MultiStakingHooks) BeforeDelegationSharesModified(ctx sdk.Context, delAddr sdk.AccAddress, valAddr sdk.ValAddress) error { for i := range h { - h[i].BeforeDelegationSharesModified(ctx, delAddr, valAddr) + if err := h[i].BeforeDelegationSharesModified(ctx, delAddr, valAddr); err != nil { + return err + } } + return nil } -func (h MultiStakingHooks) BeforeDelegationRemoved(ctx sdk.Context, delAddr sdk.AccAddress, valAddr sdk.ValAddress) { +func (h MultiStakingHooks) BeforeDelegationRemoved(ctx sdk.Context, delAddr sdk.AccAddress, valAddr sdk.ValAddress) error { for i := range h { - h[i].BeforeDelegationRemoved(ctx, delAddr, valAddr) + if err := h[i].BeforeDelegationRemoved(ctx, delAddr, valAddr); err != nil { + return err + } } + return nil } -func (h MultiStakingHooks) AfterDelegationModified(ctx sdk.Context, delAddr sdk.AccAddress, valAddr sdk.ValAddress) { +func (h MultiStakingHooks) AfterDelegationModified(ctx sdk.Context, delAddr sdk.AccAddress, valAddr sdk.ValAddress) error { for i := range h { - h[i].AfterDelegationModified(ctx, delAddr, valAddr) + if err := h[i].AfterDelegationModified(ctx, delAddr, valAddr); err != nil { + return err + } } + return nil } -func (h MultiStakingHooks) BeforeValidatorSlashed(ctx sdk.Context, valAddr sdk.ValAddress, fraction sdk.Dec) { +func (h MultiStakingHooks) BeforeValidatorSlashed(ctx sdk.Context, valAddr sdk.ValAddress, fraction sdk.Dec) error { for i := range h { - h[i].BeforeValidatorSlashed(ctx, valAddr, fraction) + if err := h[i].BeforeValidatorSlashed(ctx, valAddr, fraction); err != nil { + return err + } } + return nil } diff --git a/x/upgrade/client/testutil/suite.go b/x/upgrade/client/testutil/suite.go index 6b559e823c77..bfa7859087d2 100644 --- a/x/upgrade/client/testutil/suite.go +++ b/x/upgrade/client/testutil/suite.go @@ -36,7 +36,10 @@ func (s *IntegrationTestSuite) SetupSuite() { cfg.NumValidators = 1 s.cfg = cfg - s.network = network.New(s.T(), cfg) + + var err error + s.network, err = network.New(s.T(), s.T().TempDir(), cfg) + s.Require().NoError(err) } func (s *IntegrationTestSuite) TearDownSuite() {