From 221ce96f5d85907c67ae4a60e03e091c88ae57c7 Mon Sep 17 00:00:00 2001 From: Federico Kunze <31522760+fedekunze@users.noreply.github.com> Date: Thu, 2 Jan 2020 19:58:58 -0300 Subject: [PATCH] Update x/ibc error handling (#5462) * Merge PR #5428: Add mod, exponentiation for uint * Modified examples in distribution module (#5441) * Merge PR #5442: Remove of the client/alias.go * Merge PR #5445: Mock rpcclient in tests for votes pagination * Merge PR #5435: Added iterator that allows to read only requested values * Merge PR #5427: Remove code duplication in x/auth/client/cli * Merge PR #5421: Refactor Error Handling * update x/ibc error handling * update ICS24 and ICS02 errors * ICS03, ICS23 and common errors * updates from master and errors from ICS04 * build * fix ics20 tests * fix tests * golangcibot fixes Co-authored-by: Kevin Davis Co-authored-by: kaustubhkapatral <54210167+kaustubhkapatral@users.noreply.github.com> Co-authored-by: Ferenc Fabian Co-authored-by: Dmitry Shulyak Co-authored-by: Alessio Treglia Co-authored-by: Alexander Bezobchuk --- CHANGELOG.md | 26 +- baseapp/abci.go | 176 ++++--- baseapp/baseapp.go | 161 +++--- baseapp/baseapp_test.go | 203 +++++--- baseapp/helpers.go | 6 +- baseapp/queryrouter_test.go | 2 +- baseapp/router_test.go | 4 +- client/alias.go | 129 ----- client/context/broadcast.go | 7 +- client/context/broadcast_test.go | 11 +- client/flags/flags.go | 4 + client/routes.go | 3 +- .../adr-015-ibc-packet-receiver.md | 2 +- docs/building-modules/handler.md | 13 +- docs/building-modules/querier.md | 6 +- server/mock/app.go | 12 +- server/mock/tx.go | 7 +- simapp/app.go | 18 +- simapp/test_helpers.go | 20 +- store/errors/errors.go | 26 - store/iavl/store.go | 9 +- store/iavl/store_test.go | 21 +- store/rootmulti/store.go | 21 +- store/rootmulti/store_test.go | 20 +- store/types/iterator.go | 61 +++ store/types/iterator_test.go | 119 +++++ types/decimal.go | 24 +- types/errors.go | 361 -------------- types/errors/abci.go | 39 ++ types/errors/abci_test.go | 26 +- types/errors/errors.go | 43 +- types/errors/stacktrace_test.go | 8 +- types/errors_test.go | 138 ------ types/handler.go | 2 +- types/queryable.go | 9 +- types/result.go | 57 +-- types/result_test.go | 14 +- types/store.go | 12 + types/tx_msg.go | 8 +- types/uint.go | 44 ++ types/uint_test.go | 19 + x/auth/ante/ante_test.go | 71 ++- x/auth/client/cli/decode.go | 102 ++-- x/auth/client/rest/query.go | 6 +- x/auth/client/utils/tx.go | 14 +- x/auth/client/utils/tx_test.go | 7 +- x/auth/keeper/keeper.go | 9 +- x/auth/keeper/querier.go | 15 +- x/auth/types/expected_keepers.go | 2 +- x/auth/types/stdtx.go | 26 +- x/auth/types/stdtx_test.go | 13 +- x/bank/alias.go | 29 +- x/bank/bench_test.go | 10 +- x/bank/client/cli/tx.go | 3 +- x/bank/handler.go | 28 +- x/bank/handler_test.go | 13 +- x/bank/internal/keeper/keeper.go | 101 ++-- x/bank/internal/keeper/keeper_test.go | 12 +- x/bank/internal/keeper/querier.go | 13 +- x/bank/internal/types/errors.go | 34 +- x/bank/internal/types/msgs.go | 43 +- x/bank/simulation/operations.go | 13 +- x/crisis/alias.go | 34 +- x/crisis/client/cli/tx.go | 3 +- x/crisis/handler.go | 17 +- x/crisis/handler_test.go | 24 +- x/crisis/internal/keeper/keeper.go | 2 +- x/crisis/internal/types/errors.go | 22 +- x/crisis/internal/types/expected_keepers.go | 2 +- x/crisis/internal/types/msgs.go | 4 +- x/distribution/alias.go | 16 +- x/distribution/client/cli/query.go | 15 +- x/distribution/client/cli/tx.go | 15 +- x/distribution/handler.go | 37 +- x/distribution/keeper/allocation_test.go | 38 +- x/distribution/keeper/delegation.go | 4 +- x/distribution/keeper/delegation_test.go | 64 ++- x/distribution/keeper/fee_pool.go | 5 +- x/distribution/keeper/keeper.go | 29 +- x/distribution/keeper/proposal_handler.go | 5 +- x/distribution/keeper/querier.go | 88 ++-- x/distribution/keeper/querier_test.go | 12 +- x/distribution/keeper/test_common.go | 8 +- x/distribution/simulation/operations.go | 25 +- x/distribution/types/errors.go | 56 +-- x/distribution/types/expected_keepers.go | 6 +- x/distribution/types/msg.go | 24 +- x/distribution/types/proposal.go | 9 +- x/evidence/alias.go | 30 +- x/evidence/client/cli/query.go | 5 +- x/evidence/client/cli/tx.go | 3 +- x/evidence/genesis_test.go | 3 +- x/evidence/handler.go | 15 +- x/evidence/handler_test.go | 13 +- x/evidence/internal/keeper/infraction_test.go | 15 +- x/evidence/internal/keeper/keeper.go | 13 +- x/evidence/internal/keeper/keeper_test.go | 3 +- x/evidence/internal/keeper/querier.go | 8 +- x/evidence/internal/types/errors.go | 56 +-- x/evidence/internal/types/msgs.go | 8 +- x/genutil/client/cli/collect.go | 4 +- x/genutil/client/cli/gentx.go | 26 +- x/genutil/client/cli/init.go | 6 +- x/genutil/client/cli/init_test.go | 4 +- x/genutil/client/cli/migrate_test.go | 4 +- x/genutil/client/rest/query.go | 19 +- x/gov/abci.go | 2 +- x/gov/abci_test.go | 51 +- x/gov/alias.go | 87 ++-- x/gov/client/cli/query.go | 6 +- x/gov/client/cli/tx.go | 5 +- x/gov/client/rest/query.go | 3 +- x/gov/client/utils/query.go | 13 +- x/gov/client/utils/query_test.go | 118 +++-- x/gov/genesis_test.go | 2 +- x/gov/handler.go | 33 +- x/gov/handler_test.go | 7 +- x/gov/keeper/deposit.go | 11 +- x/gov/keeper/deposit_test.go | 6 +- x/gov/keeper/keeper.go | 6 +- x/gov/keeper/proposal.go | 12 +- x/gov/keeper/proposal_test.go | 25 +- x/gov/keeper/querier.go | 76 +-- x/gov/keeper/querier_test.go | 10 +- x/gov/keeper/test_common.go | 8 +- x/gov/keeper/vote.go | 9 +- x/gov/legacy/v0_36/types.go | 30 +- x/gov/simulation/operations.go | 19 +- x/gov/test_common.go | 28 +- x/gov/types/content.go | 16 +- x/gov/types/errors.go | 71 +-- x/gov/types/expected_keepers.go | 18 +- x/gov/types/msgs.go | 27 +- x/gov/types/proposal.go | 8 +- x/ibc/02-client/alias.go | 29 +- x/ibc/02-client/client/cli/cli.go | 6 +- x/ibc/02-client/client/utils/utils.go | 7 +- x/ibc/02-client/handler.go | 26 +- x/ibc/02-client/keeper/client.go | 24 +- x/ibc/02-client/keeper/keeper.go | 14 +- x/ibc/02-client/keeper/querier.go | 13 +- x/ibc/02-client/types/errors/errors.go | 144 +----- x/ibc/02-client/types/msgs.go | 42 +- x/ibc/02-client/types/msgs_test.go | 2 +- .../types/tendermint/consensus_state.go | 6 +- x/ibc/02-client/types/tendermint/evidence.go | 31 +- x/ibc/02-client/types/tendermint/header.go | 6 +- .../types/tendermint/misbehaviour.go | 30 +- x/ibc/03-connection/alias.go | 46 +- x/ibc/03-connection/client/cli/cli.go | 6 +- x/ibc/03-connection/handler.go | 32 +- x/ibc/03-connection/keeper/handshake.go | 32 +- x/ibc/03-connection/keeper/keeper.go | 9 +- x/ibc/03-connection/keeper/querier.go | 8 +- x/ibc/03-connection/types/connection.go | 16 +- x/ibc/03-connection/types/errors.go | 96 +--- x/ibc/03-connection/types/msgs.go | 75 +-- x/ibc/03-connection/types/msgs_test.go | 212 +++++--- x/ibc/04-channel/alias.go | 139 +++--- x/ibc/04-channel/client/cli/cli.go | 6 +- x/ibc/04-channel/client/utils/utils.go | 6 +- x/ibc/04-channel/handler.go | 48 +- x/ibc/04-channel/keeper/handshake.go | 107 ++-- x/ibc/04-channel/keeper/keeper.go | 4 +- x/ibc/04-channel/keeper/packet.go | 152 +++--- x/ibc/04-channel/keeper/querier.go | 2 +- x/ibc/04-channel/keeper/timeout.go | 61 +-- x/ibc/04-channel/types/channel.go | 36 +- x/ibc/04-channel/types/errors.go | 110 +---- x/ibc/04-channel/types/msgs.go | 72 +-- x/ibc/04-channel/types/msgs_test.go | 180 ++++--- x/ibc/04-channel/types/packet.go | 57 ++- x/ibc/05-port/alias.go | 11 +- x/ibc/05-port/keeper/keeper.go | 17 +- x/ibc/05-port/types/errors.go | 42 +- x/ibc/20-transfer/alias.go | 1 - x/ibc/20-transfer/client/cli/cli.go | 6 +- x/ibc/20-transfer/handler.go | 16 +- x/ibc/20-transfer/handler_test.go | 65 ++- x/ibc/20-transfer/keeper/callbacks.go | 32 +- x/ibc/20-transfer/keeper/keeper.go | 8 +- x/ibc/20-transfer/keeper/relay.go | 25 +- x/ibc/20-transfer/types/expected_keepers.go | 10 +- x/ibc/20-transfer/types/keys.go | 3 - x/ibc/20-transfer/types/msgs.go | 33 +- x/ibc/20-transfer/types/packet.go | 11 +- x/ibc/23-commitment/errors.go | 14 + x/ibc/23-commitment/merkle.go | 8 + x/ibc/23-commitment/merkle_test.go | 3 + x/ibc/23-commitment/types.go | 2 + x/ibc/24-host/errors.go | 42 +- x/ibc/24-host/validate.go | 12 +- x/ibc/alias.go | 9 +- x/ibc/client/cli/cli.go | 5 +- x/ibc/handler.go | 8 +- x/ibc/keeper/keeper.go | 12 +- x/ibc/keeper/querier.go | 4 +- x/ibc/types/errors.go | 30 +- x/mint/alias.go | 7 +- x/mint/client/cli/query.go | 3 +- x/mint/internal/keeper/keeper.go | 8 +- x/mint/internal/keeper/querier.go | 19 +- x/mint/internal/types/expected_keepers.go | 6 +- x/mock/app.go | 2 +- x/mock/app_test.go | 16 +- x/mock/test_utils.go | 33 +- x/mock/types.go | 11 +- x/params/alias.go | 18 +- x/params/commmon_test.go | 2 +- x/params/keeper.go | 20 +- x/params/proposal_handler.go | 12 +- x/params/proposal_handler_test.go | 2 +- x/params/types/errors.go | 49 +- x/params/types/proposal.go | 15 +- x/slashing/abci_test.go | 6 +- x/slashing/alias.go | 15 +- x/slashing/app_test.go | 14 +- x/slashing/client/cli/query.go | 3 +- x/slashing/client/cli/tx.go | 3 +- x/slashing/handler.go | 15 +- x/slashing/handler_test.go | 91 ++-- x/slashing/internal/keeper/keeper.go | 7 +- x/slashing/internal/keeper/keeper_test.go | 30 +- x/slashing/internal/keeper/querier.go | 28 +- x/slashing/internal/keeper/test_common.go | 8 +- x/slashing/internal/keeper/unjail.go | 16 +- x/slashing/internal/types/errors.go | 57 +-- x/slashing/internal/types/msg.go | 4 +- x/slashing/simulation/operations.go | 6 +- x/staking/alias.go | 27 +- x/staking/app_test.go | 4 +- x/staking/client/cli/query.go | 3 +- x/staking/client/cli/tx.go | 20 +- x/staking/exported/exported.go | 40 +- x/staking/handler.go | 75 +-- x/staking/handler_test.go | 467 +++++++++++------- x/staking/keeper/delegation.go | 71 +-- x/staking/keeper/keeper.go | 14 +- x/staking/keeper/pool.go | 4 +- x/staking/keeper/querier.go | 134 ++--- x/staking/keeper/query_utils.go | 8 +- x/staking/keeper/test_common.go | 5 +- x/staking/keeper/validator.go | 2 +- x/staking/simulation/operations.go | 31 +- x/staking/types/commission.go | 24 +- x/staking/types/errors.go | 270 ++-------- x/staking/types/expected_keepers.go | 8 +- x/staking/types/historical_info.go | 4 +- x/staking/types/msg.go | 58 ++- x/staking/types/validator.go | 25 +- x/supply/alias.go | 3 +- x/supply/client/cli/query.go | 3 +- x/supply/internal/keeper/bank.go | 85 ++-- x/supply/internal/keeper/bank_test.go | 24 +- x/supply/internal/keeper/key.go | 8 - x/supply/internal/keeper/querier.go | 19 +- x/supply/internal/types/expected_keepers.go | 10 +- x/upgrade/abci_test.go | 12 +- x/upgrade/alias.go | 8 +- x/upgrade/handler.go | 12 +- x/upgrade/internal/keeper/keeper.go | 10 +- x/upgrade/internal/keeper/querier.go | 20 +- x/upgrade/internal/types/plan.go | 12 +- x/upgrade/internal/types/proposal.go | 14 +- x/upgrade/module.go | 6 +- 265 files changed, 3831 insertions(+), 4517 deletions(-) delete mode 100644 client/alias.go delete mode 100644 store/errors/errors.go create mode 100644 store/types/iterator.go create mode 100644 store/types/iterator_test.go delete mode 100644 types/errors.go delete mode 100644 types/errors_test.go create mode 100644 x/ibc/23-commitment/errors.go diff --git a/CHANGELOG.md b/CHANGELOG.md index 8507b6b1f2ec..be6b7cec3274 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -50,6 +50,21 @@ logic has been implemented for v0.38 target version. Applications can migrate vi ### API Breaking Changes +* (baseapp/types) [\#5421](https://github.com/cosmos/cosmos-sdk/pull/5421) The `Error` interface (`types/errors.go`) + has been removed in favor of the concrete type defined in `types/errors/` which implements the standard `error` + interface. As a result, the `Handler` and `Querier` implementations now return a standard `error`. + Within `BaseApp`, `runTx` now returns a `(GasInfo, *Result, error)` tuple and `runMsgs` returns a + `(*Result, error)` tuple. A reference to a `Result` is now used to indicate success whereas an error + signals an invalid message or failed message execution. As a result, the fields `Code`, `Codespace`, + `GasWanted`, and `GasUsed` have been removed the `Result` type. The latter two fields are now found + in the `GasInfo` type which is always returned regardless of execution outcome. + + Note to developers: Since all handlers and queriers must now return a standard `error`, the `types/errors/` + package contains all the relevant and pre-registered errors that you typically work with. A typical + error returned will look like `sdkerrors.Wrap(sdkerrors.ErrUnknownRequest, "...")`. You can retrieve + relevant ABCI information from the error via `ABCIInfo`. +* (client) [\#5442](https://github.com/cosmos/cosmos-sdk/pull/5442) Remove client/alias.go as it's not necessary and +components can be imported directly from the packages. * (store) [\#4748](https://github.com/cosmos/cosmos-sdk/pull/4748) The `CommitMultiStore` interface now requires a `SetInterBlockCache` method. Applications that do not wish to support this can simply have this method perform a no-op. @@ -76,7 +91,7 @@ if the provided arguments are invalid. `StdTx.Signatures` to get back the array of StdSignatures `[]StdSignature`. * (modules) [\#5299](https://github.com/cosmos/cosmos-sdk/pull/5299) `HandleDoubleSign` along with params `MaxEvidenceAge` and `DoubleSignJailEndTime` have moved from the `x/slashing` module to the `x/evidence` module. -* (keys) [\#4941](https://github.com/cosmos/cosmos-sdk/issues/4941) Initializing a new keybase through `NewKeyringFromHomeFlag`, `NewKeyringFromDir`, `NewKeyBaseFromHomeFlag`, `NewKeyBaseFromDir`, or `NewInMemory` functions now accept optional parameters of type `KeybaseOption`. These optional parameters are also added on the keys subcommands functions, which are now public, and allows these options to be set on the commands or ignored to default to previous behavior. +* (keys) [\#4941](https://github.com/cosmos/cosmos-sdk/issues/4941) Initializing a new keybase through `NewKeyringFromHomeFlag`, `NewKeyringFromDir`, `NewKeyBaseFromHomeFlag`, `NewKeyBaseFromDir`, or `NewInMemory` functions now accept optional parameters of type `KeybaseOption`. These optional parameters are also added on the keys subcommands functions, which are now public, and allows these options to be set on the commands or ignored to default to previous behavior. * The option introduced in this PR is `WithKeygenFunc` which allows a custom bytes to key implementation to be defined when keys are created. * (simapp) [\#5419](https://github.com/cosmos/cosmos-sdk/pull/5419) simapp/helpers.GenTx() now accepts a gas argument. @@ -88,9 +103,11 @@ if the provided arguments are invalid. increased significantly due to modular `AnteHandler` support. Increase GasLimit accordingly. * (rest) [\#5336](https://github.com/cosmos/cosmos-sdk/issues/5336) `MsgEditValidator` uses `description` instead of `Description` as a JSON key. * (keys) [\#5097](https://github.com/cosmos/cosmos-sdk/pull/5097) Due to the keybase -> keyring transition, keys need to be migrated. See `keys migrate` command for more info. +* (x/auth) [\#5424](https://github.com/cosmos/cosmos-sdk/issues/5424) Drop `decode-tx` command from x/auth/client/cli, duplicate of the `decode` command. ### Features +* (store) [\#5435](https://github.com/cosmos/cosmos-sdk/pull/5435) New iterator for paginated requests. Iterator limits DB reads to the range of the requested page. * (x/evidence) [\#5240](https://github.com/cosmos/cosmos-sdk/pull/5240) Initial implementation of the `x/evidence` module. * (cli) [\#5212](https://github.com/cosmos/cosmos-sdk/issues/5212) The `q gov proposals` command now supports pagination. * (store) [\#4724](https://github.com/cosmos/cosmos-sdk/issues/4724) Multistore supports substore migrations upon load. New `rootmulti.Store.LoadLatestVersionAndUpgrade` method in @@ -213,11 +230,12 @@ to detail this new feature and how state transitions occur. * (docs/spec) All module specs moved into their respective module dir in x/ (i.e. docs/spec/staking -->> x/staking/spec) * (docs/) [\#5379](https://github.com/cosmos/cosmos-sdk/pull/5379) Major documentation refactor, including: * (docs/intro/) Add and improve introduction material for newcomers. - * (docs/basics/) Add documentation about basic concepts of the cosmos sdk such as the anatomy of an SDK application, the transaction lifecycle or accounts. - * (docs/core/) Add documentation about core conepts of the cosmos sdk such as `baseapp`, `server`, `store`s, `context` and more. + * (docs/basics/) Add documentation about basic concepts of the cosmos sdk such as the anatomy of an SDK application, the transaction lifecycle or accounts. + * (docs/core/) Add documentation about core conepts of the cosmos sdk such as `baseapp`, `server`, `store`s, `context` and more. * (docs/building-modules/) Add reference documentation on concepts relevant for module developers (`keeper`, `handler`, `messages`, `queries`,...). * (docs/interfaces/) Add documentation on building interfaces for the Cosmos SDK. * Redesigned user interface that features new dynamically generated sidebar, build-time code embedding from GitHub, new homepage as well as many other improvements. +* (types) [\#5428](https://github.com/cosmos/cosmos-sdk/pull/5428) Add `Mod` (modulo) method and `RelativePow` (exponentation) function for `Uint`. ### Bug Fixes @@ -2801,3 +2819,5 @@ BUG FIXES: [v0.37.1]: https://github.com/cosmos/cosmos-sdk/releases/tag/v0.37.1 [v0.37.0]: https://github.com/cosmos/cosmos-sdk/releases/tag/v0.37.0 [v0.36.0]: https://github.com/cosmos/cosmos-sdk/releases/tag/v0.36.0 + + diff --git a/baseapp/abci.go b/baseapp/abci.go index e93b7c56c2c9..57bcec661eff 100644 --- a/baseapp/abci.go +++ b/baseapp/abci.go @@ -11,6 +11,7 @@ import ( "github.com/cosmos/cosmos-sdk/codec" sdk "github.com/cosmos/cosmos-sdk/types" + sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" ) // InitChain implements the ABCI interface. It runs the initialization logic @@ -153,54 +154,66 @@ func (app *BaseApp) EndBlock(req abci.RequestEndBlock) (res abci.ResponseEndBloc return } -// CheckTx implements the ABCI interface. It runs the "basic checks" to see -// whether or not a transaction can possibly be executed, first decoding and then -// the ante handler (which checks signatures/fees/ValidateBasic). -// -// NOTE:CheckTx does not run the actual Msg handler function(s). -func (app *BaseApp) CheckTx(req abci.RequestCheckTx) (res abci.ResponseCheckTx) { - var result sdk.Result - +// CheckTx implements the ABCI interface and executes a tx in CheckTx mode. In +// CheckTx mode, messages are not executed. This means messages are only validated +// and only the AnteHandler is executed. State is persisted to the BaseApp's +// internal CheckTx state if the AnteHandler passes. Otherwise, the ResponseCheckTx +// will contain releveant error information. Regardless of tx execution outcome, +// the ResponseCheckTx will contain relevant gas execution context. +func (app *BaseApp) CheckTx(req abci.RequestCheckTx) abci.ResponseCheckTx { tx, err := app.txDecoder(req.Tx) + if err != nil { + return sdkerrors.ResponseCheckTx(err, 0, 0) + } + + var mode runTxMode + switch { - case err != nil: - result = err.Result() case req.Type == abci.CheckTxType_New: - result = app.runTx(runTxModeCheck, req.Tx, tx) + mode = runTxModeCheck + case req.Type == abci.CheckTxType_Recheck: - result = app.runTx(runTxModeReCheck, req.Tx, tx) + mode = runTxModeReCheck + default: - panic(fmt.Sprintf("Unknown RequestCheckTx Type: %v", req.Type)) + panic(fmt.Sprintf("unknown RequestCheckTx type: %s", req.Type)) + } + + gInfo, result, err := app.runTx(mode, req.Tx, tx) + if err != nil { + return sdkerrors.ResponseCheckTx(err, gInfo.GasWanted, gInfo.GasUsed) } return abci.ResponseCheckTx{ - Code: uint32(result.Code), - Data: result.Data, + GasWanted: int64(gInfo.GasWanted), // TODO: Should type accept unsigned ints? + GasUsed: int64(gInfo.GasUsed), // TODO: Should type accept unsigned ints? Log: result.Log, - GasWanted: int64(result.GasWanted), // TODO: Should type accept unsigned ints? - GasUsed: int64(result.GasUsed), // TODO: Should type accept unsigned ints? + Data: result.Data, Events: result.Events.ToABCIEvents(), } } -// DeliverTx implements the ABCI interface. -func (app *BaseApp) DeliverTx(req abci.RequestDeliverTx) (res abci.ResponseDeliverTx) { - var result sdk.Result - +// DeliverTx implements the ABCI interface and executes a tx in DeliverTx mode. +// State only gets persisted if all messages are valid and get executed successfully. +// Otherwise, the ResponseDeliverTx will contain releveant error information. +// Regardless of tx execution outcome, the ResponseDeliverTx will contain relevant +// gas execution context. +func (app *BaseApp) DeliverTx(req abci.RequestDeliverTx) abci.ResponseDeliverTx { tx, err := app.txDecoder(req.Tx) if err != nil { - result = err.Result() - } else { - result = app.runTx(runTxModeDeliver, req.Tx, tx) + return sdkerrors.ResponseDeliverTx(err, 0, 0) + } + + gInfo, result, err := app.runTx(runTxModeDeliver, req.Tx, tx) + if err != nil { + return sdkerrors.ResponseDeliverTx(err, gInfo.GasWanted, gInfo.GasUsed) } return abci.ResponseDeliverTx{ - Code: uint32(result.Code), - Codespace: string(result.Codespace), - Data: result.Data, + GasWanted: int64(gInfo.GasWanted), // TODO: Should type accept unsigned ints? + GasUsed: int64(gInfo.GasUsed), // TODO: Should type accept unsigned ints? Log: result.Log, - GasWanted: int64(result.GasWanted), // TODO: Should type accept unsigned ints? - GasUsed: int64(result.GasUsed), // TODO: Should type accept unsigned ints? + Data: result.Data, Events: result.Events.ToABCIEvents(), } } @@ -278,11 +291,10 @@ func (app *BaseApp) halt() { // Query implements the ABCI interface. It delegates to CommitMultiStore if it // implements Queryable. -func (app *BaseApp) Query(req abci.RequestQuery) (res abci.ResponseQuery) { +func (app *BaseApp) Query(req abci.RequestQuery) abci.ResponseQuery { path := splitPath(req.Path) if len(path) == 0 { - msg := "no query path provided" - return sdk.ErrUnknownRequest(msg).QueryResult() + sdkerrors.QueryResult(sdkerrors.Wrap(sdkerrors.ErrUnknownRequest, "no query path provided")) } switch path[0] { @@ -294,61 +306,59 @@ func (app *BaseApp) Query(req abci.RequestQuery) (res abci.ResponseQuery) { return handleQueryStore(app, path, req) case "p2p": - return handleQueryP2P(app, path, req) + return handleQueryP2P(app, path) case "custom": return handleQueryCustom(app, path, req) } - msg := "unknown query path" - return sdk.ErrUnknownRequest(msg).QueryResult() + return sdkerrors.QueryResult(sdkerrors.Wrap(sdkerrors.ErrUnknownRequest, "unknown query path")) } -func handleQueryApp(app *BaseApp, path []string, req abci.RequestQuery) (res abci.ResponseQuery) { +func handleQueryApp(app *BaseApp, path []string, req abci.RequestQuery) abci.ResponseQuery { if len(path) >= 2 { - var result sdk.Result - switch path[1] { case "simulate": txBytes := req.Data + tx, err := app.txDecoder(txBytes) if err != nil { - result = err.Result() - } else { - result = app.Simulate(txBytes, tx) + return sdkerrors.QueryResult(sdkerrors.Wrap(err, "failed to decode tx")) + } + + gInfo, _, _ := app.Simulate(txBytes, tx) + + return abci.ResponseQuery{ + Codespace: sdkerrors.RootCodespace, + Height: req.Height, + Value: codec.Cdc.MustMarshalBinaryLengthPrefixed(gInfo.GasUsed), } case "version": return abci.ResponseQuery{ - Code: uint32(sdk.CodeOK), - Codespace: string(sdk.CodespaceRoot), + Codespace: sdkerrors.RootCodespace, Height: req.Height, Value: []byte(app.appVersion), } default: - result = sdk.ErrUnknownRequest(fmt.Sprintf("unknown query: %s", path)).Result() - } - - value := codec.Cdc.MustMarshalBinaryLengthPrefixed(result) - return abci.ResponseQuery{ - Code: uint32(sdk.CodeOK), - Codespace: string(sdk.CodespaceRoot), - Height: req.Height, - Value: value, + return sdkerrors.QueryResult(sdkerrors.Wrapf(sdkerrors.ErrUnknownRequest, "unknown query: %s", path)) } } - msg := "expected second parameter to be either 'simulate' or 'version', neither was present" - return sdk.ErrUnknownRequest(msg).QueryResult() + return sdkerrors.QueryResult( + sdkerrors.Wrap( + sdkerrors.ErrUnknownRequest, + "expected second parameter to be either 'simulate' or 'version', neither was present", + ), + ) } func handleQueryStore(app *BaseApp, path []string, req abci.RequestQuery) abci.ResponseQuery { // "/store" prefix for store queries queryable, ok := app.cms.(sdk.Queryable) if !ok { - msg := "multistore doesn't support queries" - return sdk.ErrUnknownRequest(msg).QueryResult() + return sdkerrors.QueryResult(sdkerrors.Wrap(sdkerrors.ErrUnknownRequest, "multistore doesn't support queries")) } req.Path = "/" + strings.Join(path[1:], "/") @@ -359,7 +369,12 @@ func handleQueryStore(app *BaseApp, path []string, req abci.RequestQuery) abci.R } if req.Height <= 1 && req.Prove { - return sdk.ErrInternal("cannot query with proof when height <= 1; please provide a valid height").QueryResult() + return sdkerrors.QueryResult( + sdkerrors.Wrap( + sdkerrors.ErrInvalidRequest, + "cannot query with proof when height <= 1; please provide a valid height", + ), + ) } resp := queryable.Query(req) @@ -368,7 +383,7 @@ func handleQueryStore(app *BaseApp, path []string, req abci.RequestQuery) abci.R return resp } -func handleQueryP2P(app *BaseApp, path []string, _ abci.RequestQuery) (res abci.ResponseQuery) { +func handleQueryP2P(app *BaseApp, path []string) abci.ResponseQuery { // "/p2p" prefix for p2p queries if len(path) >= 4 { cmd, typ, arg := path[1], path[2], path[3] @@ -383,28 +398,30 @@ func handleQueryP2P(app *BaseApp, path []string, _ abci.RequestQuery) (res abci. } default: - msg := "expected second parameter to be 'filter'" - return sdk.ErrUnknownRequest(msg).QueryResult() + return sdkerrors.QueryResult(sdkerrors.Wrap(sdkerrors.ErrUnknownRequest, "expected second parameter to be 'filter'")) } } - msg := "Expected path is p2p filter " - return sdk.ErrUnknownRequest(msg).QueryResult() + return sdkerrors.QueryResult( + sdkerrors.Wrap( + sdkerrors.ErrUnknownRequest, "expected path is p2p filter ", + ), + ) } -func handleQueryCustom(app *BaseApp, path []string, req abci.RequestQuery) (res abci.ResponseQuery) { +func handleQueryCustom(app *BaseApp, path []string, req abci.RequestQuery) abci.ResponseQuery { // path[0] should be "custom" because "/custom" prefix is required for keeper // queries. // // The QueryRouter routes using path[1]. For example, in the path // "custom/gov/proposal", QueryRouter routes using "gov". if len(path) < 2 || path[1] == "" { - return sdk.ErrUnknownRequest("No route for custom query specified").QueryResult() + return sdkerrors.QueryResult(sdkerrors.Wrap(sdkerrors.ErrUnknownRequest, "no route for custom query specified")) } querier := app.queryRouter.Route(path[1]) if querier == nil { - return sdk.ErrUnknownRequest(fmt.Sprintf("no custom querier found for route %s", path[1])).QueryResult() + return sdkerrors.QueryResult(sdkerrors.Wrapf(sdkerrors.ErrUnknownRequest, "no custom querier found for route %s", path[1])) } // when a client did not provide a query height, manually inject the latest @@ -413,17 +430,22 @@ func handleQueryCustom(app *BaseApp, path []string, req abci.RequestQuery) (res } if req.Height <= 1 && req.Prove { - return sdk.ErrInternal("cannot query with proof when height <= 1; please provide a valid height").QueryResult() + return sdkerrors.QueryResult( + sdkerrors.Wrap( + sdkerrors.ErrInvalidRequest, + "cannot query with proof when height <= 1; please provide a valid height", + ), + ) } cacheMS, err := app.cms.CacheMultiStoreWithVersion(req.Height) if err != nil { - return sdk.ErrInternal( - fmt.Sprintf( - "failed to load state at height %d; %s (latest height: %d)", - req.Height, err, app.LastBlockHeight(), + return sdkerrors.QueryResult( + sdkerrors.Wrapf( + sdkerrors.ErrInvalidRequest, + "failed to load state at height %d; %s (latest height: %d)", req.Height, err, app.LastBlockHeight(), ), - ).QueryResult() + ) } // cache wrap the commit-multistore for safety @@ -435,18 +457,18 @@ func handleQueryCustom(app *BaseApp, path []string, req abci.RequestQuery) (res // // For example, in the path "custom/gov/proposal/test", the gov querier gets // []string{"proposal", "test"} as the path. - resBytes, queryErr := querier(ctx, path[2:], req) - if queryErr != nil { + resBytes, err := querier(ctx, path[2:], req) + if err != nil { + space, code, log := sdkerrors.ABCIInfo(err, false) return abci.ResponseQuery{ - Code: uint32(queryErr.Code()), - Codespace: string(queryErr.Codespace()), + Code: code, + Codespace: space, + Log: log, Height: req.Height, - Log: queryErr.ABCILog(), } } return abci.ResponseQuery{ - Code: uint32(sdk.CodeOK), Height: req.Height, Value: resBytes, } diff --git a/baseapp/baseapp.go b/baseapp/baseapp.go index ae1ca19db7f7..46f3e2649907 100644 --- a/baseapp/baseapp.go +++ b/baseapp/baseapp.go @@ -19,6 +19,7 @@ import ( "github.com/cosmos/cosmos-sdk/store" storetypes "github.com/cosmos/cosmos-sdk/store/types" sdk "github.com/cosmos/cosmos-sdk/types" + sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" ) const ( @@ -446,13 +447,12 @@ func (app *BaseApp) validateHeight(req abci.RequestBeginBlock) error { } // validateBasicTxMsgs executes basic validator calls for messages. -func validateBasicTxMsgs(msgs []sdk.Msg) sdk.Error { +func validateBasicTxMsgs(msgs []sdk.Msg) error { if len(msgs) == 0 { - return sdk.ErrUnknownRequest("Tx.GetMsgs() must return at least one message in list") + return sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "must contain at least one message") } for _, msg := range msgs { - // Validate the Msg. err := msg.ValidateBasic() if err != nil { return err @@ -508,11 +508,14 @@ func (app *BaseApp) cacheTxContext(ctx sdk.Context, txBytes []byte) (sdk.Context return ctx.WithMultiStore(msCache), msCache } -// runTx processes a transaction. The transactions is processed via an -// anteHandler. The provided txBytes may be nil in some cases, eg. in tests. For -// further details on transaction execution, reference the BaseApp SDK -// documentation. -func (app *BaseApp) runTx(mode runTxMode, txBytes []byte, tx sdk.Tx) (result sdk.Result) { +// runTx processes a transaction within a given execution mode, encoded transaction +// bytes, and the decoded transaction itself. All state transitions occur through +// a cached Context depending on the mode provided. State only gets persisted +// if all messages get executed successfully and the execution mode is DeliverTx. +// Note, gas execution info is always returned. A reference to a Result is +// returned if the tx does not run out of gas and if all the messages are valid +// and execute successfully. An error is returned otherwise. +func (app *BaseApp) runTx(mode runTxMode, txBytes []byte, tx sdk.Tx) (gInfo sdk.GasInfo, result *sdk.Result, err error) { // NOTE: GasWanted should be returned by the AnteHandler. GasUsed is // determined by the GasMeter. We need access to the context to get the gas // meter so we initialize upfront. @@ -523,7 +526,8 @@ func (app *BaseApp) runTx(mode runTxMode, txBytes []byte, tx sdk.Tx) (result sdk // only run the tx if there is block gas remaining if mode == runTxModeDeliver && ctx.BlockGasMeter().IsOutOfGas() { - return sdk.ErrOutOfGas("no block gas left to run tx").Result() + gInfo = sdk.GasInfo{GasUsed: ctx.BlockGasMeter().GasConsumed()} + return gInfo, nil, sdkerrors.Wrap(sdkerrors.ErrOutOfGas, "no block gas left to run tx") } var startingGas uint64 @@ -534,20 +538,28 @@ func (app *BaseApp) runTx(mode runTxMode, txBytes []byte, tx sdk.Tx) (result sdk defer func() { if r := recover(); r != nil { switch rType := r.(type) { + // TODO: Use ErrOutOfGas instead of ErrorOutOfGas which would allow us + // to keep the stracktrace. case sdk.ErrorOutOfGas: - log := fmt.Sprintf( - "out of gas in location: %v; gasWanted: %d, gasUsed: %d", - rType.Descriptor, gasWanted, ctx.GasMeter().GasConsumed(), + err = sdkerrors.Wrap( + sdkerrors.ErrOutOfGas, fmt.Sprintf( + "out of gas in location: %v; gasWanted: %d, gasUsed: %d", + rType.Descriptor, gasWanted, ctx.GasMeter().GasConsumed(), + ), ) - result = sdk.ErrOutOfGas(log).Result() + default: - log := fmt.Sprintf("recovered: %v\nstack:\n%v", r, string(debug.Stack())) - result = sdk.ErrInternal(log).Result() + err = sdkerrors.Wrap( + sdkerrors.ErrPanic, fmt.Sprintf( + "recovered: %v\nstack:\n%v", r, string(debug.Stack()), + ), + ) } + + result = nil } - result.GasWanted = gasWanted - result.GasUsed = ctx.GasMeter().GasConsumed() + gInfo = sdk.GasInfo{GasWanted: gasWanted, GasUsed: ctx.GasMeter().GasConsumed()} }() // If BlockGasMeter() panics it will be caught by the above recover and will @@ -558,8 +570,7 @@ func (app *BaseApp) runTx(mode runTxMode, txBytes []byte, tx sdk.Tx) (result sdk defer func() { if mode == runTxModeDeliver { ctx.BlockGasMeter().ConsumeGas( - ctx.GasMeter().GasConsumedToLimit(), - "block gas meter", + ctx.GasMeter().GasConsumedToLimit(), "block gas meter", ) if ctx.BlockGasMeter().GasConsumed() < startingGas { @@ -568,20 +579,21 @@ func (app *BaseApp) runTx(mode runTxMode, txBytes []byte, tx sdk.Tx) (result sdk } }() - var msgs = tx.GetMsgs() + msgs := tx.GetMsgs() if err := validateBasicTxMsgs(msgs); err != nil { - return err.Result() + gInfo = sdk.GasInfo{GasUsed: ctx.BlockGasMeter().GasConsumed()} + return gInfo, nil, err } if app.anteHandler != nil { var anteCtx sdk.Context var msCache sdk.CacheMultiStore - // Cache wrap context before anteHandler call in case it aborts. + // Cache wrap context before AnteHandler call in case it aborts. // This is required for both CheckTx and DeliverTx. // Ref: https://github.com/cosmos/cosmos-sdk/issues/2772 // - // NOTE: Alternatively, we could require that anteHandler ensures that + // NOTE: Alternatively, we could require that AnteHandler ensures that // writes do not happen if aborted/failed. This may have some // performance benefits, but it'll be more difficult to get right. anteCtx, msCache = app.cacheTxContext(ctx, txBytes) @@ -589,11 +601,11 @@ func (app *BaseApp) runTx(mode runTxMode, txBytes []byte, tx sdk.Tx) (result sdk newCtx, err := app.anteHandler(anteCtx, tx, mode == runTxModeSimulate) if !newCtx.IsZero() { // At this point, newCtx.MultiStore() is cache-wrapped, or something else - // replaced by the ante handler. We want the original multistore, not one - // which was cache-wrapped for the ante handler. + // replaced by the AnteHandler. We want the original multistore, not one + // which was cache-wrapped for the AnteHandler. // // Also, in the case of the tx aborting, we need to track gas consumed via - // the instantiated gas meter in the ante handler, so we update the context + // the instantiated gas meter in the AnteHandler, so we update the context // prior to returning. ctx = newCtx.WithMultiStore(ms) } @@ -602,10 +614,7 @@ func (app *BaseApp) runTx(mode runTxMode, txBytes []byte, tx sdk.Tx) (result sdk gasWanted = ctx.GasMeter().Limit() if err != nil { - res := sdk.ResultFromError(err) - res.GasWanted = gasWanted - res.GasUsed = ctx.GasMeter().GasConsumed() - return res + return gInfo, nil, err } msCache.Write() @@ -615,83 +624,63 @@ func (app *BaseApp) runTx(mode runTxMode, txBytes []byte, tx sdk.Tx) (result sdk // MultiStore in case message processing fails. At this point, the MultiStore // is doubly cached-wrapped. runMsgCtx, msCache := app.cacheTxContext(ctx, txBytes) - result = app.runMsgs(runMsgCtx, msgs, mode) - result.GasWanted = gasWanted - // Safety check: don't write the cache state unless we're in DeliverTx. - if mode != runTxModeDeliver { - return result - } - - // only update state if all messages pass - if result.IsOK() { + // Attempt to execute all messages and only update state if all messages pass + // and we're in DeliverTx. Note, runMsgs will never return a reference to a + // Result if any single message fails or does not have a registered Handler. + result, err = app.runMsgs(runMsgCtx, msgs, mode) + if err == nil && mode == runTxModeDeliver { msCache.Write() } - return result + return gInfo, result, err } -// runMsgs iterates through all the messages and executes them. -func (app *BaseApp) runMsgs(ctx sdk.Context, msgs []sdk.Msg, mode runTxMode) (result sdk.Result) { +// runMsgs iterates through a list of messages and executes them with the provided +// Context and execution mode. Messages will only be executed during simulation +// and DeliverTx. An error is returned if any single message fails or if a +// Handler does not exist for a given message route. Otherwise, a reference to a +// Result is returned. The caller must not commit state if an error is returned. +func (app *BaseApp) runMsgs(ctx sdk.Context, msgs []sdk.Msg, mode runTxMode) (*sdk.Result, error) { msgLogs := make(sdk.ABCIMessageLogs, 0, len(msgs)) - data := make([]byte, 0, len(msgs)) - var ( - code sdk.CodeType - codespace sdk.CodespaceType - ) - events := sdk.EmptyEvents() - // NOTE: GasWanted is determined by ante handler and GasUsed by the GasMeter. + // NOTE: GasWanted is determined by the AnteHandler and GasUsed by the GasMeter. for i, msg := range msgs { - // match message route + // skip actual execution for (Re)CheckTx mode + if mode == runTxModeCheck || mode == runTxModeReCheck { + break + } + msgRoute := msg.Route() handler := app.router.Route(msgRoute) if handler == nil { - return sdk.ErrUnknownRequest("unrecognized message type: " + msgRoute).Result() + return nil, sdkerrors.Wrapf(sdkerrors.ErrUnknownRequest, "unrecognized message route: %s; message index: %d", msgRoute, i) } - var msgResult sdk.Result - - // skip actual execution for CheckTx and ReCheckTx mode - if mode != runTxModeCheck && mode != runTxModeReCheck { - msgResult = handler(ctx, msg) + msgResult, err := handler(ctx, msg) + if err != nil { + return nil, sdkerrors.Wrapf(err, "failed to execute message; message index: %d", i) } - // Each message result's Data must be length prefixed in order to separate - // each result. - data = append(data, msgResult.Data...) - - msgEvents := msgResult.Events - - // append events from the message's execution and a message action event - msgEvents = msgEvents.AppendEvent( + msgEvents := sdk.Events{ sdk.NewEvent(sdk.EventTypeMessage, sdk.NewAttribute(sdk.AttributeKeyAction, msg.Type())), - ) - - events = events.AppendEvents(msgEvents) - - // stop execution and return on first failed message - if !msgResult.IsOK() { - msgLogs = append(msgLogs, sdk.NewABCIMessageLog(uint16(i), false, msgResult.Log, msgEvents)) - - code = msgResult.Code - codespace = msgResult.Codespace - break } + msgEvents = msgEvents.AppendEvents(msgResult.Events) - msgLogs = append(msgLogs, sdk.NewABCIMessageLog(uint16(i), true, msgResult.Log, msgEvents)) - } - - result = sdk.Result{ - Code: code, - Codespace: codespace, - Data: data, - Log: strings.TrimSpace(msgLogs.String()), - GasUsed: ctx.GasMeter().GasConsumed(), - Events: events, + // append message events, data and logs + // + // Note: Each message result's data must be length-prefixed in order to + // separate each result. + events = events.AppendEvents(msgEvents) + data = append(data, msgResult.Data...) + msgLogs = append(msgLogs, sdk.NewABCIMessageLog(uint16(i), msgResult.Log, msgEvents)) } - return result + return &sdk.Result{ + Data: data, + Log: strings.TrimSpace(msgLogs.String()), + Events: events, + }, nil } diff --git a/baseapp/baseapp_test.go b/baseapp/baseapp_test.go index 52df9bbef0ed..01996e27ef40 100644 --- a/baseapp/baseapp_test.go +++ b/baseapp/baseapp_test.go @@ -514,8 +514,8 @@ func (tx *txTest) setFailOnHandler(fail bool) { } // Implements Tx -func (tx txTest) GetMsgs() []sdk.Msg { return tx.Msgs } -func (tx txTest) ValidateBasic() sdk.Error { return nil } +func (tx txTest) GetMsgs() []sdk.Msg { return tx.Msgs } +func (tx txTest) ValidateBasic() error { return nil } const ( routeMsgCounter = "msgCounter" @@ -534,19 +534,20 @@ func (msg msgCounter) Route() string { return routeMsgCounter } func (msg msgCounter) Type() string { return "counter1" } func (msg msgCounter) GetSignBytes() []byte { return nil } func (msg msgCounter) GetSigners() []sdk.AccAddress { return nil } -func (msg msgCounter) ValidateBasic() sdk.Error { +func (msg msgCounter) ValidateBasic() error { if msg.Counter >= 0 { return nil } - return sdk.ErrInvalidSequence("counter should be a non-negative integer.") + return sdkerrors.Wrap(sdkerrors.ErrInvalidSequence, "counter should be a non-negative integer") } -func newTxCounter(txInt int64, msgInts ...int64) *txTest { - msgs := make([]sdk.Msg, 0, len(msgInts)) - for _, msgInt := range msgInts { - msgs = append(msgs, msgCounter{msgInt, false}) +func newTxCounter(counter int64, msgCounters ...int64) *txTest { + msgs := make([]sdk.Msg, 0, len(msgCounters)) + for _, c := range msgCounters { + msgs = append(msgs, msgCounter{c, false}) } - return &txTest{msgs, txInt, false} + + return &txTest{msgs, counter, false} } // a msg we dont know how to route @@ -573,24 +574,26 @@ func (msg msgCounter2) Route() string { return routeMsgCounter2 } func (msg msgCounter2) Type() string { return "counter2" } func (msg msgCounter2) GetSignBytes() []byte { return nil } func (msg msgCounter2) GetSigners() []sdk.AccAddress { return nil } -func (msg msgCounter2) ValidateBasic() sdk.Error { +func (msg msgCounter2) ValidateBasic() error { if msg.Counter >= 0 { return nil } - return sdk.ErrInvalidSequence("counter should be a non-negative integer.") + return sdkerrors.Wrap(sdkerrors.ErrInvalidSequence, "counter should be a non-negative integer") } // amino decode func testTxDecoder(cdc *codec.Codec) sdk.TxDecoder { - return func(txBytes []byte) (sdk.Tx, sdk.Error) { + return func(txBytes []byte) (sdk.Tx, error) { var tx txTest if len(txBytes) == 0 { - return nil, sdk.ErrTxDecode("txBytes are empty") + return nil, sdkerrors.Wrap(sdkerrors.ErrTxDecode, "tx bytes are empty") } + err := cdc.UnmarshalBinaryLengthPrefixed(txBytes, &tx) if err != nil { - return nil, sdk.ErrTxDecode("").TraceSDK(err.Error()) + return nil, sdkerrors.ErrTxDecode } + return tx, nil } } @@ -604,25 +607,28 @@ func anteHandlerTxTest(t *testing.T, capKey sdk.StoreKey, storeKey []byte) sdk.A return newCtx, sdkerrors.Wrap(sdkerrors.ErrUnauthorized, "ante handler failure") } - res := incrementingCounter(t, store, storeKey, txTest.Counter) - if !res.IsOK() { - err = sdkerrors.ABCIError(string(res.Codespace), uint32(res.Code), res.Log) + _, err = incrementingCounter(t, store, storeKey, txTest.Counter) + if err != nil { + return newCtx, err } - return + + return newCtx, nil } } func handlerMsgCounter(t *testing.T, capKey sdk.StoreKey, deliverKey []byte) sdk.Handler { - return func(ctx sdk.Context, msg sdk.Msg) sdk.Result { + return func(ctx sdk.Context, msg sdk.Msg) (*sdk.Result, error) { store := ctx.KVStore(capKey) var msgCount int64 + switch m := msg.(type) { case *msgCounter: if m.FailOnHandler { - return sdk.ErrInternal("message handler failure").Result() + return nil, sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "message handler failure") } msgCount = m.Counter + case *msgCounter2: msgCount = m.Counter } @@ -651,11 +657,11 @@ func setIntOnStore(store sdk.KVStore, key []byte, i int64) { // check counter matches what's in store. // increment and store -func incrementingCounter(t *testing.T, store sdk.KVStore, counterKey []byte, counter int64) (res sdk.Result) { +func incrementingCounter(t *testing.T, store sdk.KVStore, counterKey []byte, counter int64) (*sdk.Result, error) { storedCounter := getIntFromStore(store, counterKey) require.Equal(t, storedCounter, counter) setIntOnStore(store, counterKey, counter+1) - return + return &sdk.Result{}, nil } //--------------------------------------------------------------------- @@ -675,7 +681,9 @@ func TestCheckTx(t *testing.T) { anteOpt := func(bapp *BaseApp) { bapp.SetAnteHandler(anteHandlerTxTest(t, capKey1, counterKey)) } routerOpt := func(bapp *BaseApp) { // TODO: can remove this once CheckTx doesnt process msgs. - bapp.Router().AddRoute(routeMsgCounter, func(ctx sdk.Context, msg sdk.Msg) sdk.Result { return sdk.Result{} }) + bapp.Router().AddRoute(routeMsgCounter, func(ctx sdk.Context, msg sdk.Msg) (*sdk.Result, error) { + return &sdk.Result{}, nil + }) } app := setupBaseApp(t, anteOpt, routerOpt) @@ -847,9 +855,9 @@ func TestSimulateTx(t *testing.T) { } routerOpt := func(bapp *BaseApp) { - bapp.Router().AddRoute(routeMsgCounter, func(ctx sdk.Context, msg sdk.Msg) sdk.Result { + bapp.Router().AddRoute(routeMsgCounter, func(ctx sdk.Context, msg sdk.Msg) (*sdk.Result, error) { ctx.GasMeter().ConsumeGas(gasConsumed, "test") - return sdk.Result{GasUsed: ctx.GasMeter().GasConsumed()} + return &sdk.Result{}, nil }) } @@ -872,14 +880,16 @@ func TestSimulateTx(t *testing.T) { require.Nil(t, err) // simulate a message, check gas reported - result := app.Simulate(txBytes, tx) - require.True(t, result.IsOK(), result.Log) - require.Equal(t, gasConsumed, result.GasUsed) + gInfo, result, err := app.Simulate(txBytes, tx) + require.NoError(t, err) + require.NotNil(t, result) + require.Equal(t, gasConsumed, gInfo.GasUsed) // simulate again, same result - result = app.Simulate(txBytes, tx) - require.True(t, result.IsOK(), result.Log) - require.Equal(t, gasConsumed, result.GasUsed) + gInfo, result, err = app.Simulate(txBytes, tx) + require.NoError(t, err) + require.NotNil(t, result) + require.Equal(t, gasConsumed, gInfo.GasUsed) // simulate by calling Query with encoded tx query := abci.RequestQuery{ @@ -889,11 +899,10 @@ func TestSimulateTx(t *testing.T) { queryResult := app.Query(query) require.True(t, queryResult.IsOK(), queryResult.Log) - var res sdk.Result - codec.Cdc.MustUnmarshalBinaryLengthPrefixed(queryResult.Value, &res) - require.Nil(t, err, "Result unmarshalling failed") - require.True(t, res.IsOK(), res.Log) - require.Equal(t, gasConsumed, res.GasUsed, res.Log) + var res uint64 + err = codec.Cdc.UnmarshalBinaryLengthPrefixed(queryResult.Value, &res) + require.NoError(t, err) + require.Equal(t, gasConsumed, res) app.EndBlock(abci.RequestEndBlock{}) app.Commit() } @@ -906,7 +915,9 @@ func TestRunInvalidTransaction(t *testing.T) { }) } routerOpt := func(bapp *BaseApp) { - bapp.Router().AddRoute(routeMsgCounter, func(ctx sdk.Context, msg sdk.Msg) (res sdk.Result) { return }) + bapp.Router().AddRoute(routeMsgCounter, func(ctx sdk.Context, msg sdk.Msg) (*sdk.Result, error) { + return &sdk.Result{}, nil + }) } app := setupBaseApp(t, anteOpt, routerOpt) @@ -914,15 +925,19 @@ func TestRunInvalidTransaction(t *testing.T) { header := abci.Header{Height: 1} app.BeginBlock(abci.RequestBeginBlock{Header: header}) - // Transaction with no messages + // transaction with no messages { emptyTx := &txTest{} - err := app.Deliver(emptyTx) - require.EqualValues(t, sdk.CodeUnknownRequest, err.Code) - require.EqualValues(t, sdk.CodespaceRoot, err.Codespace) + _, result, err := app.Deliver(emptyTx) + require.Error(t, err) + require.Nil(t, result) + + space, code, _ := sdkerrors.ABCIInfo(err, false) + require.EqualValues(t, sdkerrors.ErrInvalidRequest.Codespace(), space, err) + require.EqualValues(t, sdkerrors.ErrInvalidRequest.ABCICode(), code, err) } - // Transaction where ValidateBasic fails + // transaction where ValidateBasic fails { testCases := []struct { tx *txTest @@ -940,27 +955,39 @@ func TestRunInvalidTransaction(t *testing.T) { for _, testCase := range testCases { tx := testCase.tx - res := app.Deliver(tx) + _, result, err := app.Deliver(tx) + if testCase.fail { - require.EqualValues(t, sdk.CodeInvalidSequence, res.Code) - require.EqualValues(t, sdk.CodespaceRoot, res.Codespace) + require.Error(t, err) + + space, code, _ := sdkerrors.ABCIInfo(err, false) + require.EqualValues(t, sdkerrors.ErrInvalidSequence.Codespace(), space, err) + require.EqualValues(t, sdkerrors.ErrInvalidSequence.ABCICode(), code, err) } else { - require.True(t, res.IsOK(), fmt.Sprintf("%v", res)) + require.NotNil(t, result) } } } - // Transaction with no known route + // transaction with no known route { unknownRouteTx := txTest{[]sdk.Msg{msgNoRoute{}}, 0, false} - err := app.Deliver(unknownRouteTx) - require.EqualValues(t, sdk.CodeUnknownRequest, err.Code) - require.EqualValues(t, sdk.CodespaceRoot, err.Codespace) + _, result, err := app.Deliver(unknownRouteTx) + require.Error(t, err) + require.Nil(t, result) + + space, code, _ := sdkerrors.ABCIInfo(err, false) + require.EqualValues(t, sdkerrors.ErrUnknownRequest.Codespace(), space, err) + require.EqualValues(t, sdkerrors.ErrUnknownRequest.ABCICode(), code, err) unknownRouteTx = txTest{[]sdk.Msg{msgCounter{}, msgNoRoute{}}, 0, false} - err = app.Deliver(unknownRouteTx) - require.EqualValues(t, sdk.CodeUnknownRequest, err.Code) - require.EqualValues(t, sdk.CodespaceRoot, err.Codespace) + _, result, err = app.Deliver(unknownRouteTx) + require.Error(t, err) + require.Nil(t, result) + + space, code, _ = sdkerrors.ABCIInfo(err, false) + require.EqualValues(t, sdkerrors.ErrUnknownRequest.Codespace(), space, err) + require.EqualValues(t, sdkerrors.ErrUnknownRequest.ABCICode(), code, err) } // Transaction with an unregistered message @@ -975,9 +1002,10 @@ func TestRunInvalidTransaction(t *testing.T) { txBytes, err := newCdc.MarshalBinaryLengthPrefixed(tx) require.NoError(t, err) + res := app.DeliverTx(abci.RequestDeliverTx{Tx: txBytes}) - require.EqualValues(t, sdk.CodeTxDecode, res.Code) - require.EqualValues(t, sdk.CodespaceRoot, res.Codespace) + require.EqualValues(t, sdkerrors.ErrTxDecode.ABCICode(), res.Code) + require.EqualValues(t, sdkerrors.ErrTxDecode.Codespace(), res.Codespace) } } @@ -996,8 +1024,7 @@ func TestTxGasLimits(t *testing.T) { if r := recover(); r != nil { switch rType := r.(type) { case sdk.ErrorOutOfGas: - log := fmt.Sprintf("out of gas in location: %v", rType.Descriptor) - err = sdkerrors.Wrap(sdkerrors.ErrOutOfGas, log) + err = sdkerrors.Wrapf(sdkerrors.ErrOutOfGas, "out of gas in location: %v", rType.Descriptor) default: panic(r) } @@ -1007,16 +1034,16 @@ func TestTxGasLimits(t *testing.T) { count := tx.(*txTest).Counter newCtx.GasMeter().ConsumeGas(uint64(count), "counter-ante") - return + return newCtx, nil }) } routerOpt := func(bapp *BaseApp) { - bapp.Router().AddRoute(routeMsgCounter, func(ctx sdk.Context, msg sdk.Msg) sdk.Result { + bapp.Router().AddRoute(routeMsgCounter, func(ctx sdk.Context, msg sdk.Msg) (*sdk.Result, error) { count := msg.(msgCounter).Counter ctx.GasMeter().ConsumeGas(uint64(count), "counter-handler") - return sdk.Result{} + return &sdk.Result{}, nil }) } @@ -1051,17 +1078,21 @@ func TestTxGasLimits(t *testing.T) { for i, tc := range testCases { tx := tc.tx - res := app.Deliver(tx) + gInfo, result, err := app.Deliver(tx) // check gas used and wanted - require.Equal(t, tc.gasUsed, res.GasUsed, fmt.Sprintf("%d: %v, %v", i, tc, res)) + require.Equal(t, tc.gasUsed, gInfo.GasUsed, fmt.Sprintf("tc #%d; gas: %v, result: %v, err: %s", i, gInfo, result, err)) // check for out of gas if !tc.fail { - require.True(t, res.IsOK(), fmt.Sprintf("%d: %v, %v", i, tc, res)) + require.NotNil(t, result, fmt.Sprintf("%d: %v, %v", i, tc, err)) } else { - require.Equal(t, sdk.CodeOutOfGas, res.Code, fmt.Sprintf("%d: %v, %v", i, tc, res)) - require.Equal(t, sdk.CodespaceRoot, res.Codespace) + require.Error(t, err) + require.Nil(t, result) + + space, code, _ := sdkerrors.ABCIInfo(err, false) + require.EqualValues(t, sdkerrors.ErrOutOfGas.Codespace(), space, err) + require.EqualValues(t, sdkerrors.ErrOutOfGas.ABCICode(), code, err) } } } @@ -1093,10 +1124,10 @@ func TestMaxBlockGasLimits(t *testing.T) { } routerOpt := func(bapp *BaseApp) { - bapp.Router().AddRoute(routeMsgCounter, func(ctx sdk.Context, msg sdk.Msg) sdk.Result { + bapp.Router().AddRoute(routeMsgCounter, func(ctx sdk.Context, msg sdk.Msg) (*sdk.Result, error) { count := msg.(msgCounter).Counter ctx.GasMeter().ConsumeGas(uint64(count), "counter-handler") - return sdk.Result{} + return &sdk.Result{}, nil }) } @@ -1137,23 +1168,29 @@ func TestMaxBlockGasLimits(t *testing.T) { // execute the transaction multiple times for j := 0; j < tc.numDelivers; j++ { - res := app.Deliver(tx) + _, result, err := app.Deliver(tx) ctx := app.getState(runTxModeDeliver).ctx - blockGasUsed := ctx.BlockGasMeter().GasConsumed() // check for failed transactions if tc.fail && (j+1) > tc.failAfterDeliver { - require.Equal(t, res.Code, sdk.CodeOutOfGas, fmt.Sprintf("%d: %v, %v", i, tc, res)) - require.Equal(t, res.Codespace, sdk.CodespaceRoot, fmt.Sprintf("%d: %v, %v", i, tc, res)) + require.Error(t, err, fmt.Sprintf("tc #%d; result: %v, err: %s", i, result, err)) + require.Nil(t, result, fmt.Sprintf("tc #%d; result: %v, err: %s", i, result, err)) + + space, code, _ := sdkerrors.ABCIInfo(err, false) + require.EqualValues(t, sdkerrors.ErrOutOfGas.Codespace(), space, err) + require.EqualValues(t, sdkerrors.ErrOutOfGas.ABCICode(), code, err) require.True(t, ctx.BlockGasMeter().IsOutOfGas()) } else { // check gas used and wanted + blockGasUsed := ctx.BlockGasMeter().GasConsumed() expBlockGasUsed := tc.gasUsedPerDeliver * uint64(j+1) - require.Equal(t, expBlockGasUsed, blockGasUsed, - fmt.Sprintf("%d,%d: %v, %v, %v, %v", i, j, tc, expBlockGasUsed, blockGasUsed, res)) + require.Equal( + t, expBlockGasUsed, blockGasUsed, + fmt.Sprintf("%d,%d: %v, %v, %v, %v", i, j, tc, expBlockGasUsed, blockGasUsed, result), + ) - require.True(t, res.IsOK(), fmt.Sprintf("%d,%d: %v, %v", i, j, tc, res)) + require.NotNil(t, result, fmt.Sprintf("tc #%d; currDeliver: %d, result: %v, err: %s", i, j, result, err)) require.False(t, ctx.BlockGasMeter().IsPastLimit()) } } @@ -1260,10 +1297,10 @@ func TestGasConsumptionBadTx(t *testing.T) { } routerOpt := func(bapp *BaseApp) { - bapp.Router().AddRoute(routeMsgCounter, func(ctx sdk.Context, msg sdk.Msg) sdk.Result { + bapp.Router().AddRoute(routeMsgCounter, func(ctx sdk.Context, msg sdk.Msg) (*sdk.Result, error) { count := msg.(msgCounter).Counter ctx.GasMeter().ConsumeGas(uint64(count), "counter-handler") - return sdk.Result{} + return &sdk.Result{}, nil }) } @@ -1313,10 +1350,10 @@ func TestQuery(t *testing.T) { } routerOpt := func(bapp *BaseApp) { - bapp.Router().AddRoute(routeMsgCounter, func(ctx sdk.Context, msg sdk.Msg) sdk.Result { + bapp.Router().AddRoute(routeMsgCounter, func(ctx sdk.Context, msg sdk.Msg) (*sdk.Result, error) { store := ctx.KVStore(capKey1) store.Set(key, value) - return sdk.Result{} + return &sdk.Result{}, nil }) } @@ -1338,8 +1375,9 @@ func TestQuery(t *testing.T) { require.Equal(t, 0, len(res.Value)) // query is still empty after a CheckTx - resTx := app.Check(tx) - require.True(t, resTx.IsOK(), fmt.Sprintf("%v", resTx)) + _, resTx, err := app.Check(tx) + require.NoError(t, err) + require.NotNil(t, resTx) res = app.Query(query) require.Equal(t, 0, len(res.Value)) @@ -1347,8 +1385,9 @@ func TestQuery(t *testing.T) { header := abci.Header{Height: app.LastBlockHeight() + 1} app.BeginBlock(abci.RequestBeginBlock{Header: header}) - resTx = app.Deliver(tx) - require.True(t, resTx.IsOK(), fmt.Sprintf("%v", resTx)) + _, resTx, err = app.Deliver(tx) + require.NoError(t, err) + require.NotNil(t, resTx) res = app.Query(query) require.Equal(t, 0, len(res.Value)) diff --git a/baseapp/helpers.go b/baseapp/helpers.go index 5ea3cdcd9a77..aa9c10d328d7 100644 --- a/baseapp/helpers.go +++ b/baseapp/helpers.go @@ -10,15 +10,15 @@ import ( var isAlphaNumeric = regexp.MustCompile(`^[a-zA-Z0-9]+$`).MatchString -func (app *BaseApp) Check(tx sdk.Tx) (result sdk.Result) { +func (app *BaseApp) Check(tx sdk.Tx) (sdk.GasInfo, *sdk.Result, error) { return app.runTx(runTxModeCheck, nil, tx) } -func (app *BaseApp) Simulate(txBytes []byte, tx sdk.Tx) (result sdk.Result) { +func (app *BaseApp) Simulate(txBytes []byte, tx sdk.Tx) (sdk.GasInfo, *sdk.Result, error) { return app.runTx(runTxModeSimulate, txBytes, tx) } -func (app *BaseApp) Deliver(tx sdk.Tx) (result sdk.Result) { +func (app *BaseApp) Deliver(tx sdk.Tx) (sdk.GasInfo, *sdk.Result, error) { return app.runTx(runTxModeDeliver, nil, tx) } diff --git a/baseapp/queryrouter_test.go b/baseapp/queryrouter_test.go index 7743028313cc..c7637f17000e 100644 --- a/baseapp/queryrouter_test.go +++ b/baseapp/queryrouter_test.go @@ -10,7 +10,7 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" ) -var testQuerier = func(_ sdk.Context, _ []string, _ abci.RequestQuery) (res []byte, err sdk.Error) { +var testQuerier = func(_ sdk.Context, _ []string, _ abci.RequestQuery) ([]byte, error) { return nil, nil } diff --git a/baseapp/router_test.go b/baseapp/router_test.go index 86e09cf21b79..1a6d999bcce6 100644 --- a/baseapp/router_test.go +++ b/baseapp/router_test.go @@ -8,8 +8,8 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" ) -var testHandler = func(_ sdk.Context, _ sdk.Msg) sdk.Result { - return sdk.Result{} +var testHandler = func(_ sdk.Context, _ sdk.Msg) (*sdk.Result, error) { + return &sdk.Result{}, nil } func TestRouter(t *testing.T) { diff --git a/client/alias.go b/client/alias.go deleted file mode 100644 index eed043c54401..000000000000 --- a/client/alias.go +++ /dev/null @@ -1,129 +0,0 @@ -// nolint -// autogenerated code using github.com/rigelrozanski/multitool -// aliases generated for the following subdirectories: -// ALIASGEN: github.com/cosmos/cosmos-sdk/client/context -// ALIASGEN: github.com/cosmos/cosmos-sdk/client/flags -// ALIASGEN: github.com/cosmos/cosmos-sdk/client/keys -// ALIASGEN: github.com/cosmos/cosmos-sdk/client/lcd -// ALIASGEN: github.com/cosmos/cosmos-sdk/client/rest -// ALIASGEN: github.com/cosmos/cosmos-sdk/client/rpc -// ALIASGEN: github.com/cosmos/cosmos-sdk/client/tx -// ALIASGEN: github.com/cosmos/cosmos-sdk/client/utils -// ALIASGEN: github.com/cosmos/cosmos-sdk/client/input -package client - -import ( - "github.com/cosmos/cosmos-sdk/client/context" - "github.com/cosmos/cosmos-sdk/client/flags" - "github.com/cosmos/cosmos-sdk/client/input" - "github.com/cosmos/cosmos-sdk/client/keys" - "github.com/cosmos/cosmos-sdk/client/lcd" - "github.com/cosmos/cosmos-sdk/client/rpc" -) - -const ( - DefaultGasAdjustment = flags.DefaultGasAdjustment - DefaultGasLimit = flags.DefaultGasLimit - DefaultKeyringBackend = flags.DefaultKeyringBackend - GasFlagAuto = flags.GasFlagAuto - BroadcastBlock = flags.BroadcastBlock - BroadcastSync = flags.BroadcastSync - BroadcastAsync = flags.BroadcastAsync - FlagHome = flags.FlagHome - FlagUseLedger = flags.FlagUseLedger - FlagChainID = flags.FlagChainID - FlagNode = flags.FlagNode - FlagHeight = flags.FlagHeight - FlagGasAdjustment = flags.FlagGasAdjustment - FlagTrustNode = flags.FlagTrustNode - FlagFrom = flags.FlagFrom - FlagName = flags.FlagName - FlagAccountNumber = flags.FlagAccountNumber - FlagSequence = flags.FlagSequence - FlagMemo = flags.FlagMemo - FlagFees = flags.FlagFees - FlagGasPrices = flags.FlagGasPrices - FlagBroadcastMode = flags.FlagBroadcastMode - FlagDryRun = flags.FlagDryRun - FlagGenerateOnly = flags.FlagGenerateOnly - FlagIndentResponse = flags.FlagIndentResponse - FlagKeyringBackend = flags.FlagKeyringBackend - FlagListenAddr = flags.FlagListenAddr - FlagMaxOpenConnections = flags.FlagMaxOpenConnections - FlagRPCReadTimeout = flags.FlagRPCReadTimeout - FlagRPCWriteTimeout = flags.FlagRPCWriteTimeout - FlagOutputDocument = flags.FlagOutputDocument - FlagSkipConfirmation = flags.FlagSkipConfirmation - KeyringBackendFile = flags.KeyringBackendFile - KeyringBackendOS = flags.KeyringBackendOS - KeyringBackendTest = flags.KeyringBackendTest - DefaultKeyPass = keys.DefaultKeyPass - FlagAddress = keys.FlagAddress - FlagPublicKey = keys.FlagPublicKey - FlagBechPrefix = keys.FlagBechPrefix - FlagDevice = keys.FlagDevice - OutputFormatText = keys.OutputFormatText - OutputFormatJSON = keys.OutputFormatJSON - MinPassLength = input.MinPassLength -) - -var ( - // functions aliases - NewCLIContextWithFrom = context.NewCLIContextWithFrom - NewCLIContextWithInput = context.NewCLIContextWithInput - NewCLIContextWithInputAndFrom = context.NewCLIContextWithInputAndFrom - NewCLIContext = context.NewCLIContext - GetFromFields = context.GetFromFields - ErrInvalidAccount = context.ErrInvalidAccount - ErrVerifyCommit = context.ErrVerifyCommit - GetCommands = flags.GetCommands - PostCommands = flags.PostCommands - RegisterRestServerFlags = flags.RegisterRestServerFlags - ParseGas = flags.ParseGas - NewCompletionCmd = flags.NewCompletionCmd - MarshalJSON = keys.MarshalJSON - UnmarshalJSON = keys.UnmarshalJSON - Commands = keys.Commands - NewAddNewKey = keys.NewAddNewKey - NewRecoverKey = keys.NewRecoverKey - NewUpdateKeyReq = keys.NewUpdateKeyReq - NewDeleteKeyReq = keys.NewDeleteKeyReq - NewKeyringFromDir = keys.NewKeyringFromDir - NewKeyringFromHomeFlag = keys.NewKeyringFromHomeFlag - NewInMemoryKeyBase = keys.NewInMemoryKeyBase - NewRestServer = lcd.NewRestServer - ServeCommand = lcd.ServeCommand - BlockCommand = rpc.BlockCommand - GetChainHeight = rpc.GetChainHeight - BlockRequestHandlerFn = rpc.BlockRequestHandlerFn - LatestBlockRequestHandlerFn = rpc.LatestBlockRequestHandlerFn - RegisterRPCRoutes = rpc.RegisterRPCRoutes - StatusCommand = rpc.StatusCommand - NodeInfoRequestHandlerFn = rpc.NodeInfoRequestHandlerFn - NodeSyncingRequestHandlerFn = rpc.NodeSyncingRequestHandlerFn - ValidatorCommand = rpc.ValidatorCommand - GetValidators = rpc.GetValidators - ValidatorSetRequestHandlerFn = rpc.ValidatorSetRequestHandlerFn - LatestValidatorSetRequestHandlerFn = rpc.LatestValidatorSetRequestHandlerFn - GetPassword = input.GetPassword - GetCheckPassword = input.GetCheckPassword - GetConfirmation = input.GetConfirmation - GetString = input.GetString - PrintPrefixed = input.PrintPrefixed - - // variable aliases - LineBreak = flags.LineBreak - GasFlagVar = flags.GasFlagVar -) - -type ( - CLIContext = context.CLIContext - GasSetting = flags.GasSetting - AddNewKey = keys.AddNewKey - RecoverKey = keys.RecoverKey - UpdateKeyReq = keys.UpdateKeyReq - DeleteKeyReq = keys.DeleteKeyReq - RestServer = lcd.RestServer - ValidatorOutput = rpc.ValidatorOutput - ResultValidatorsOutput = rpc.ResultValidatorsOutput -) diff --git a/client/context/broadcast.go b/client/context/broadcast.go index 1996c47d99cb..67251b6da89d 100644 --- a/client/context/broadcast.go +++ b/client/context/broadcast.go @@ -9,6 +9,7 @@ import ( "github.com/cosmos/cosmos-sdk/client/flags" sdk "github.com/cosmos/cosmos-sdk/types" + sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" ) // BroadcastTx broadcasts a transactions either synchronously or asynchronously @@ -52,19 +53,19 @@ func CheckTendermintError(err error, txBytes []byte) *sdk.TxResponse { switch { case strings.Contains(errStr, strings.ToLower(mempool.ErrTxInCache.Error())): return &sdk.TxResponse{ - Code: uint32(sdk.CodeTxInMempoolCache), + Code: sdkerrors.ErrTxInMempoolCache.ABCICode(), TxHash: txHash, } case strings.Contains(errStr, "mempool is full"): return &sdk.TxResponse{ - Code: uint32(sdk.CodeMempoolIsFull), + Code: sdkerrors.ErrMempoolIsFull.ABCICode(), TxHash: txHash, } case strings.Contains(errStr, "tx too large"): return &sdk.TxResponse{ - Code: uint32(sdk.CodeTxTooLarge), + Code: sdkerrors.ErrTxTooLarge.ABCICode(), TxHash: txHash, } diff --git a/client/context/broadcast_test.go b/client/context/broadcast_test.go index 2afddb8f3524..530645b9d187 100644 --- a/client/context/broadcast_test.go +++ b/client/context/broadcast_test.go @@ -4,16 +4,15 @@ import ( "fmt" "testing" - "github.com/tendermint/tendermint/crypto/tmhash" - "github.com/stretchr/testify/require" + "github.com/tendermint/tendermint/crypto/tmhash" "github.com/tendermint/tendermint/mempool" "github.com/tendermint/tendermint/rpc/client/mock" ctypes "github.com/tendermint/tendermint/rpc/core/types" tmtypes "github.com/tendermint/tendermint/types" "github.com/cosmos/cosmos-sdk/client/flags" - "github.com/cosmos/cosmos-sdk/types" + sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" ) type MockClient struct { @@ -43,9 +42,9 @@ func CreateContextWithErrorAndMode(err error, mode string) CLIContext { // Test the correct code is returned when func TestBroadcastError(t *testing.T) { errors := map[error]uint32{ - mempool.ErrTxInCache: uint32(types.CodeTxInMempoolCache), - mempool.ErrTxTooLarge{}: uint32(types.CodeTxTooLarge), - mempool.ErrMempoolIsFull{}: uint32(types.CodeMempoolIsFull), + mempool.ErrTxInCache: sdkerrors.ErrTxInMempoolCache.ABCICode(), + mempool.ErrTxTooLarge{}: sdkerrors.ErrTxTooLarge.ABCICode(), + mempool.ErrMempoolIsFull{}: sdkerrors.ErrMempoolIsFull.ABCICode(), } modes := []string{ diff --git a/client/flags/flags.go b/client/flags/flags.go index 106061d3a78a..d0ac95e45b8d 100644 --- a/client/flags/flags.go +++ b/client/flags/flags.go @@ -94,6 +94,8 @@ func GetCommands(cmds ...*cobra.Command) []*cobra.Command { viper.BindPFlag(FlagNode, c.Flags().Lookup(FlagNode)) c.MarkFlagRequired(FlagChainID) + + c.SetErr(c.ErrOrStderr()) } return cmds } @@ -129,6 +131,8 @@ func PostCommands(cmds ...*cobra.Command) []*cobra.Command { viper.BindPFlag(FlagKeyringBackend, c.Flags().Lookup(FlagKeyringBackend)) c.MarkFlagRequired(FlagChainID) + + c.SetErr(c.ErrOrStderr()) } return cmds } diff --git a/client/routes.go b/client/routes.go index ded91ca897b0..9eac8fa0d828 100644 --- a/client/routes.go +++ b/client/routes.go @@ -4,9 +4,10 @@ import ( "github.com/gorilla/mux" "github.com/cosmos/cosmos-sdk/client/context" + "github.com/cosmos/cosmos-sdk/client/rpc" ) // Register routes func RegisterRoutes(cliCtx context.CLIContext, r *mux.Router) { - RegisterRPCRoutes(cliCtx, r) + rpc.RegisterRPCRoutes(cliCtx, r) } diff --git a/docs/architecture/adr-015-ibc-packet-receiver.md b/docs/architecture/adr-015-ibc-packet-receiver.md index e772c3234c47..2ea26dcb5bae 100644 --- a/docs/architecture/adr-015-ibc-packet-receiver.md +++ b/docs/architecture/adr-015-ibc-packet-receiver.md @@ -204,7 +204,7 @@ type PacketDataI interface { GetCommitment() []byte // Commitment form that will be stored in the state. GetTimeoutHeight() uint64 - ValidateBasic() sdk.Error + ValidateBasic() error Type() string } ``` diff --git a/docs/building-modules/handler.md b/docs/building-modules/handler.md index 3b19bf9603a9..37b46511a09a 100644 --- a/docs/building-modules/handler.md +++ b/docs/building-modules/handler.md @@ -25,19 +25,24 @@ Let us break it down: ## Implementation of a module `handler`s -Module `handler`s are typically implemented in a `./handler.go` file inside the module's folder. The [module manager](./module-manager.md) is used to add the module's `handler`s to the [application's `router`](../core/baseapp.md#message-routing) via the `NewHandler()` method. Typically, the manager's `NewHandler()` method simply calls a `NewHandler()` method defined in `handler.go`, which looks like the following: +Module `handler`s are typically implemented in a `./handler.go` file inside the module's folder. The +[module manager](./module-manager.md) is used to add the module's `handler`s to the +[application's `router`](../core/baseapp.md#message-routing) via the `NewHandler()` method. Typically, +the manager's `NewHandler()` method simply calls a `NewHandler()` method defined in `handler.go`, +which looks like the following: ```go func NewHandler(keeper Keeper) sdk.Handler { - return func(ctx sdk.Context, msg sdk.Msg) sdk.Result { + return func(ctx sdk.Context, msg sdk.Msg) (*sdk.Result, error) { switch msg := msg.(type) { case MsgType1: return handleMsgType1(ctx, keeper, msg) + case MsgType2: return handleMsgType2(ctx, keeper, msg) + default: - errMsg := fmt.Sprintf("Unrecognized nameservice Msg type: %v", msg.Type()) - return sdk.ErrUnknownRequest(errMsg).Result() + return nil, sdkerrors.Wrapf(sdkerrors.ErrUnknownRequest, "unrecognized %s message type: %T", ModuleName, msg) } } } diff --git a/docs/building-modules/querier.md b/docs/building-modules/querier.md index 02c334fc3843..be4750778661 100644 --- a/docs/building-modules/querier.md +++ b/docs/building-modules/querier.md @@ -29,14 +29,16 @@ Module `querier`s are typically implemented in a `./internal/keeper/querier.go` ```go func NewQuerier(keeper Keeper) sdk.Querier { - return func(ctx sdk.Context, path []string, req abci.RequestQuery) (res []byte, err sdk.Error) { + return func(ctx sdk.Context, path []string, req abci.RequestQuery) ([]byte, error) { switch path[0] { case QueryType1: return queryType1(ctx, path[1:], req, keeper) + case QueryType2: return queryType2(ctx, path[1:], req, keeper) + default: - return nil, sdk.ErrUnknownRequest("unknown nameservice query endpoint") + return nil, sdkerrors.Wrapf(sdkerrors.ErrUnknownRequest, "unknown %s query endpoint: %s", types.ModuleName, path[0]) } } } diff --git a/server/mock/app.go b/server/mock/app.go index 9063bb7c5ea1..d1e1146d6a57 100644 --- a/server/mock/app.go +++ b/server/mock/app.go @@ -2,6 +2,7 @@ package mock import ( "encoding/json" + "errors" "fmt" "path/filepath" @@ -49,10 +50,10 @@ func NewApp(rootDir string, logger log.Logger) (abci.Application, error) { // KVStoreHandler is a simple handler that takes kvstoreTx and writes // them to the db func KVStoreHandler(storeKey sdk.StoreKey) sdk.Handler { - return func(ctx sdk.Context, msg sdk.Msg) sdk.Result { + return func(ctx sdk.Context, msg sdk.Msg) (*sdk.Result, error) { dTx, ok := msg.(kvstoreTx) if !ok { - panic("KVStoreHandler should only receive kvstoreTx") + return nil, errors.New("KVStoreHandler should only receive kvstoreTx") } // tx is already unmarshalled @@ -62,10 +63,9 @@ func KVStoreHandler(storeKey sdk.StoreKey) sdk.Handler { store := ctx.KVStore(storeKey) store.Set(key, value) - return sdk.Result{ - Code: 0, - Log: fmt.Sprintf("set %s=%s", key, value), - } + return &sdk.Result{ + Log: fmt.Sprintf("set %s=%s", key, value), + }, nil } } diff --git a/server/mock/tx.go b/server/mock/tx.go index 6774fb28145a..27441051ce8a 100644 --- a/server/mock/tx.go +++ b/server/mock/tx.go @@ -6,6 +6,7 @@ import ( "fmt" sdk "github.com/cosmos/cosmos-sdk/types" + sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" ) // An sdk.Tx which is its own sdk.Msg. @@ -47,7 +48,7 @@ func (tx kvstoreTx) GetSignBytes() []byte { } // Should the app be calling this? Or only handlers? -func (tx kvstoreTx) ValidateBasic() sdk.Error { +func (tx kvstoreTx) ValidateBasic() error { return nil } @@ -57,7 +58,7 @@ func (tx kvstoreTx) GetSigners() []sdk.AccAddress { // takes raw transaction bytes and decodes them into an sdk.Tx. An sdk.Tx has // all the signatures and can be used to authenticate. -func decodeTx(txBytes []byte) (sdk.Tx, sdk.Error) { +func decodeTx(txBytes []byte) (sdk.Tx, error) { var tx sdk.Tx split := bytes.Split(txBytes, []byte("=")) @@ -68,7 +69,7 @@ func decodeTx(txBytes []byte) (sdk.Tx, sdk.Error) { k, v := split[0], split[1] tx = kvstoreTx{k, v, txBytes} } else { - return nil, sdk.ErrTxDecode("too many =") + return nil, sdkerrors.Wrap(sdkerrors.ErrTxDecode, "too many '='") } return tx, nil diff --git a/simapp/app.go b/simapp/app.go index 657054bfba33..117a63b46d9b 100644 --- a/simapp/app.go +++ b/simapp/app.go @@ -164,7 +164,7 @@ func NewSimApp( } // init params keeper and subspaces - app.ParamsKeeper = params.NewKeeper(app.cdc, keys[params.StoreKey], tkeys[params.TStoreKey], params.DefaultCodespace) + app.ParamsKeeper = params.NewKeeper(app.cdc, keys[params.StoreKey], tkeys[params.TStoreKey]) app.subspaces[auth.ModuleName] = app.ParamsKeeper.Subspace(auth.DefaultParamspace) app.subspaces[bank.ModuleName] = app.ParamsKeeper.Subspace(bank.DefaultParamspace) app.subspaces[staking.ModuleName] = app.ParamsKeeper.Subspace(staking.DefaultParamspace) @@ -180,25 +180,24 @@ func NewSimApp( app.cdc, keys[auth.StoreKey], app.subspaces[auth.ModuleName], auth.ProtoBaseAccount, ) app.BankKeeper = bank.NewBaseKeeper( - app.AccountKeeper, app.subspaces[bank.ModuleName], bank.DefaultCodespace, - app.BlacklistedAccAddrs(), + app.AccountKeeper, app.subspaces[bank.ModuleName], app.BlacklistedAccAddrs(), ) app.SupplyKeeper = supply.NewKeeper( app.cdc, keys[supply.StoreKey], app.AccountKeeper, app.BankKeeper, maccPerms, ) stakingKeeper := staking.NewKeeper( app.cdc, keys[staking.StoreKey], app.SupplyKeeper, app.subspaces[staking.ModuleName], - staking.DefaultCodespace) + ) app.MintKeeper = mint.NewKeeper( app.cdc, keys[mint.StoreKey], app.subspaces[mint.ModuleName], &stakingKeeper, app.SupplyKeeper, auth.FeeCollectorName, ) app.DistrKeeper = distr.NewKeeper( app.cdc, keys[distr.StoreKey], app.subspaces[distr.ModuleName], &stakingKeeper, - app.SupplyKeeper, distr.DefaultCodespace, auth.FeeCollectorName, app.ModuleAccountAddrs(), + app.SupplyKeeper, auth.FeeCollectorName, app.ModuleAccountAddrs(), ) app.SlashingKeeper = slashing.NewKeeper( - app.cdc, keys[slashing.StoreKey], &stakingKeeper, app.subspaces[slashing.ModuleName], slashing.DefaultCodespace, + app.cdc, keys[slashing.StoreKey], &stakingKeeper, app.subspaces[slashing.ModuleName], ) app.CrisisKeeper = crisis.NewKeeper( app.subspaces[crisis.ModuleName], invCheckPeriod, app.SupplyKeeper, auth.FeeCollectorName, @@ -207,8 +206,7 @@ func NewSimApp( // create evidence keeper with router evidenceKeeper := evidence.NewKeeper( - app.cdc, keys[evidence.StoreKey], app.subspaces[evidence.ModuleName], evidence.DefaultCodespace, - &app.StakingKeeper, app.SlashingKeeper, + app.cdc, keys[evidence.StoreKey], app.subspaces[evidence.ModuleName], &app.StakingKeeper, app.SlashingKeeper, ) evidenceRouter := evidence.NewRouter(). AddRoute(ibcclient.RouterKey, ibcclient.HandlerClientMisbehaviour(app.IBCKeeper.ClientKeeper)) @@ -224,7 +222,7 @@ func NewSimApp( AddRoute(upgrade.RouterKey, upgrade.NewSoftwareUpgradeProposalHandler(app.UpgradeKeeper)) app.GovKeeper = gov.NewKeeper( app.cdc, keys[gov.StoreKey], app.subspaces[gov.ModuleName], app.SupplyKeeper, - &stakingKeeper, gov.DefaultCodespace, govRouter, + &stakingKeeper, govRouter, ) // register the staking hooks @@ -233,7 +231,7 @@ func NewSimApp( staking.NewMultiStakingHooks(app.DistrKeeper.Hooks(), app.SlashingKeeper.Hooks()), ) - app.IBCKeeper = ibc.NewKeeper(app.cdc, keys[ibc.StoreKey], ibc.DefaultCodespace, app.BankKeeper, app.SupplyKeeper) + app.IBCKeeper = ibc.NewKeeper(app.cdc, keys[ibc.StoreKey], app.BankKeeper, app.SupplyKeeper) // NOTE: Any module instantiated in the module manager that is later modified // must be passed by reference here. diff --git a/simapp/test_helpers.go b/simapp/test_helpers.go index 0e6d22150255..d132394c9bc7 100644 --- a/simapp/test_helpers.go +++ b/simapp/test_helpers.go @@ -115,7 +115,7 @@ func CheckBalance(t *testing.T, app *SimApp, addr sdk.AccAddress, exp sdk.Coins) func SignCheckDeliver( t *testing.T, cdc *codec.Codec, app *bam.BaseApp, header abci.Header, msgs []sdk.Msg, accNums, seq []uint64, expSimPass, expPass bool, priv ...crypto.PrivKey, -) sdk.Result { +) (sdk.GasInfo, *sdk.Result, error) { tx := helpers.GenTx( msgs, @@ -131,28 +131,32 @@ func SignCheckDeliver( require.Nil(t, err) // Must simulate now as CheckTx doesn't run Msgs anymore - res := app.Simulate(txBytes, tx) + _, res, err := app.Simulate(txBytes, tx) if expSimPass { - require.Equal(t, sdk.CodeOK, res.Code, res.Log) + require.NoError(t, err) + require.NotNil(t, res) } else { - require.NotEqual(t, sdk.CodeOK, res.Code, res.Log) + require.Error(t, err) + require.Nil(t, res) } // Simulate a sending a transaction and committing a block app.BeginBlock(abci.RequestBeginBlock{Header: header}) - res = app.Deliver(tx) + gInfo, res, err := app.Deliver(tx) if expPass { - require.Equal(t, sdk.CodeOK, res.Code, res.Log) + require.NoError(t, err) + require.NotNil(t, res) } else { - require.NotEqual(t, sdk.CodeOK, res.Code, res.Log) + require.Error(t, err) + require.Nil(t, res) } app.EndBlock(abci.RequestEndBlock{}) app.Commit() - return res + return gInfo, res, err } // GenSequenceOfTxs generates a set of signed transactions of messages, such diff --git a/store/errors/errors.go b/store/errors/errors.go deleted file mode 100644 index 98e1b8aa1330..000000000000 --- a/store/errors/errors.go +++ /dev/null @@ -1,26 +0,0 @@ -package errors - -import ( - sdk "github.com/cosmos/cosmos-sdk/types" -) - -const ( - CodeOK = sdk.CodeOK - CodeInternal = sdk.CodeInternal - CodeTxDecode = sdk.CodeTxDecode - CodeUnknownRequest = sdk.CodeUnknownRequest - - CodespaceRoot = sdk.CodespaceRoot -) - -type Error = sdk.Error - -func ErrInternal(msg string) Error { - return sdk.ErrInternal(msg) -} -func ErrTxDecode(msg string) Error { - return sdk.ErrTxDecode(msg) -} -func ErrUnknownRequest(msg string) Error { - return sdk.ErrUnknownRequest(msg) -} diff --git a/store/iavl/store.go b/store/iavl/store.go index b7b94307bbe6..2faf786cd236 100644 --- a/store/iavl/store.go +++ b/store/iavl/store.go @@ -1,14 +1,13 @@ package iavl import ( - "fmt" "io" "sync" "github.com/cosmos/cosmos-sdk/store/cachekv" - serrors "github.com/cosmos/cosmos-sdk/store/errors" "github.com/cosmos/cosmos-sdk/store/tracekv" "github.com/cosmos/cosmos-sdk/store/types" + sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" "github.com/pkg/errors" "github.com/tendermint/iavl" @@ -236,8 +235,7 @@ func getHeight(tree Tree, req abci.RequestQuery) int64 { // explicitly set the height you want to see func (st *Store) Query(req abci.RequestQuery) (res abci.ResponseQuery) { if len(req.Data) == 0 { - msg := "Query cannot be zero length" - return serrors.ErrTxDecode(msg).QueryResult() + return sdkerrors.QueryResult(sdkerrors.Wrap(sdkerrors.ErrTxDecode, "query cannot be zero length")) } tree := st.tree @@ -296,8 +294,7 @@ func (st *Store) Query(req abci.RequestQuery) (res abci.ResponseQuery) { res.Value = cdc.MustMarshalBinaryLengthPrefixed(KVs) default: - msg := fmt.Sprintf("Unexpected Query path: %v", req.Path) - return serrors.ErrUnknownRequest(msg).QueryResult() + return sdkerrors.QueryResult(sdkerrors.Wrapf(sdkerrors.ErrUnknownRequest, "unexpected query path: %v", req.Path)) } return res diff --git a/store/iavl/store_test.go b/store/iavl/store_test.go index b70be1dee138..d7c38aa0d548 100644 --- a/store/iavl/store_test.go +++ b/store/iavl/store_test.go @@ -11,7 +11,6 @@ import ( cmn "github.com/tendermint/tendermint/libs/common" dbm "github.com/tendermint/tm-db" - "github.com/cosmos/cosmos-sdk/store/errors" "github.com/cosmos/cosmos-sdk/store/types" ) @@ -497,7 +496,7 @@ func TestIAVLStoreQuery(t *testing.T) { // query subspace before anything set qres := iavlStore.Query(querySub) - require.Equal(t, uint32(errors.CodeOK), qres.Code) + require.Equal(t, uint32(0), qres.Code) require.Equal(t, valExpSubEmpty, qres.Value) // set data @@ -506,24 +505,24 @@ func TestIAVLStoreQuery(t *testing.T) { // set data without commit, doesn't show up qres = iavlStore.Query(query) - require.Equal(t, uint32(errors.CodeOK), qres.Code) + require.Equal(t, uint32(0), qres.Code) require.Nil(t, qres.Value) // commit it, but still don't see on old version cid = iavlStore.Commit() qres = iavlStore.Query(query) - require.Equal(t, uint32(errors.CodeOK), qres.Code) + require.Equal(t, uint32(0), qres.Code) require.Nil(t, qres.Value) // but yes on the new version query.Height = cid.Version qres = iavlStore.Query(query) - require.Equal(t, uint32(errors.CodeOK), qres.Code) + require.Equal(t, uint32(0), qres.Code) require.Equal(t, v1, qres.Value) // and for the subspace qres = iavlStore.Query(querySub) - require.Equal(t, uint32(errors.CodeOK), qres.Code) + require.Equal(t, uint32(0), qres.Code) require.Equal(t, valExpSub1, qres.Value) // modify @@ -532,28 +531,28 @@ func TestIAVLStoreQuery(t *testing.T) { // query will return old values, as height is fixed qres = iavlStore.Query(query) - require.Equal(t, uint32(errors.CodeOK), qres.Code) + require.Equal(t, uint32(0), qres.Code) require.Equal(t, v1, qres.Value) // update to latest in the query and we are happy query.Height = cid.Version qres = iavlStore.Query(query) - require.Equal(t, uint32(errors.CodeOK), qres.Code) + require.Equal(t, uint32(0), qres.Code) require.Equal(t, v3, qres.Value) query2 := abci.RequestQuery{Path: "/key", Data: k2, Height: cid.Version} qres = iavlStore.Query(query2) - require.Equal(t, uint32(errors.CodeOK), qres.Code) + require.Equal(t, uint32(0), qres.Code) require.Equal(t, v2, qres.Value) // and for the subspace qres = iavlStore.Query(querySub) - require.Equal(t, uint32(errors.CodeOK), qres.Code) + require.Equal(t, uint32(0), qres.Code) require.Equal(t, valExpSub2, qres.Value) // default (height 0) will show latest -1 query0 := abci.RequestQuery{Path: "/key", Data: k1} qres = iavlStore.Query(query0) - require.Equal(t, uint32(errors.CodeOK), qres.Code) + require.Equal(t, uint32(0), qres.Code) require.Equal(t, v1, qres.Value) } diff --git a/store/rootmulti/store.go b/store/rootmulti/store.go index 4f3d212e4914..0b22d5442cb0 100644 --- a/store/rootmulti/store.go +++ b/store/rootmulti/store.go @@ -12,11 +12,11 @@ import ( "github.com/cosmos/cosmos-sdk/store/cachemulti" "github.com/cosmos/cosmos-sdk/store/dbadapter" - "github.com/cosmos/cosmos-sdk/store/errors" "github.com/cosmos/cosmos-sdk/store/iavl" "github.com/cosmos/cosmos-sdk/store/tracekv" "github.com/cosmos/cosmos-sdk/store/transient" "github.com/cosmos/cosmos-sdk/store/types" + sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" ) const ( @@ -408,19 +408,17 @@ func (rs *Store) Query(req abci.RequestQuery) abci.ResponseQuery { path := req.Path storeName, subpath, err := parsePath(path) if err != nil { - return err.QueryResult() + return sdkerrors.QueryResult(err) } store := rs.getStoreByName(storeName) if store == nil { - msg := fmt.Sprintf("no such store: %s", storeName) - return errors.ErrUnknownRequest(msg).QueryResult() + return sdkerrors.QueryResult(sdkerrors.Wrapf(sdkerrors.ErrUnknownRequest, "no such store: %s", storeName)) } queryable, ok := store.(types.Queryable) if !ok { - msg := fmt.Sprintf("store %s (type %T) doesn't support queries", storeName, store) - return errors.ErrUnknownRequest(msg).QueryResult() + return sdkerrors.QueryResult(sdkerrors.Wrapf(sdkerrors.ErrUnknownRequest, "store %s (type %T) doesn't support queries", storeName, store)) } // trim the path and make the query @@ -432,12 +430,12 @@ func (rs *Store) Query(req abci.RequestQuery) abci.ResponseQuery { } if res.Proof == nil || len(res.Proof.Ops) == 0 { - return errors.ErrInternal("proof is unexpectedly empty; ensure height has not been pruned").QueryResult() + return sdkerrors.QueryResult(sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "proof is unexpectedly empty; ensure height has not been pruned")) } commitInfo, errMsg := getCommitInfo(rs.db, res.Height) if errMsg != nil { - return errors.ErrInternal(errMsg.Error()).QueryResult() + return sdkerrors.QueryResult(err) } // Restore origin path and append proof op. @@ -454,10 +452,9 @@ func (rs *Store) Query(req abci.RequestQuery) abci.ResponseQuery { // parsePath expects a format like /[/] // Must start with /, subpath may be empty // Returns error if it doesn't start with / -func parsePath(path string) (storeName string, subpath string, err errors.Error) { +func parsePath(path string) (storeName string, subpath string, err error) { if !strings.HasPrefix(path, "/") { - err = errors.ErrUnknownRequest(fmt.Sprintf("invalid path: %s", path)) - return + return storeName, subpath, sdkerrors.Wrapf(sdkerrors.ErrUnknownRequest, "invalid path: %s", path) } paths := strings.SplitN(path[1:], "/", 2) @@ -467,7 +464,7 @@ func parsePath(path string) (storeName string, subpath string, err errors.Error) subpath = "/" + paths[1] } - return + return storeName, subpath, nil } //---------------------------------------- diff --git a/store/rootmulti/store_test.go b/store/rootmulti/store_test.go index 47b2ece360a0..16181c4080f2 100644 --- a/store/rootmulti/store_test.go +++ b/store/rootmulti/store_test.go @@ -8,9 +8,9 @@ import ( "github.com/tendermint/tendermint/crypto/merkle" dbm "github.com/tendermint/tm-db" - "github.com/cosmos/cosmos-sdk/store/errors" "github.com/cosmos/cosmos-sdk/store/iavl" "github.com/cosmos/cosmos-sdk/store/types" + sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" ) func TestStoreType(t *testing.T) { @@ -324,37 +324,37 @@ func TestMultiStoreQuery(t *testing.T) { // Test bad path. query := abci.RequestQuery{Path: "/key", Data: k, Height: ver} qres := multi.Query(query) - require.EqualValues(t, errors.CodeUnknownRequest, qres.Code) - require.EqualValues(t, errors.CodespaceRoot, qres.Codespace) + require.EqualValues(t, sdkerrors.ErrUnknownRequest.ABCICode(), qres.Code) + require.EqualValues(t, sdkerrors.ErrUnknownRequest.Codespace(), qres.Codespace) query.Path = "h897fy32890rf63296r92" qres = multi.Query(query) - require.EqualValues(t, errors.CodeUnknownRequest, qres.Code) - require.EqualValues(t, errors.CodespaceRoot, qres.Codespace) + require.EqualValues(t, sdkerrors.ErrUnknownRequest.ABCICode(), qres.Code) + require.EqualValues(t, sdkerrors.ErrUnknownRequest.Codespace(), qres.Codespace) // Test invalid store name. query.Path = "/garbage/key" qres = multi.Query(query) - require.EqualValues(t, errors.CodeUnknownRequest, qres.Code) - require.EqualValues(t, errors.CodespaceRoot, qres.Codespace) + require.EqualValues(t, sdkerrors.ErrUnknownRequest.ABCICode(), qres.Code) + require.EqualValues(t, sdkerrors.ErrUnknownRequest.Codespace(), qres.Codespace) // Test valid query with data. query.Path = "/store1/key" qres = multi.Query(query) - require.EqualValues(t, errors.CodeOK, qres.Code) + require.EqualValues(t, 0, qres.Code) require.Equal(t, v, qres.Value) // Test valid but empty query. query.Path = "/store2/key" query.Prove = true qres = multi.Query(query) - require.EqualValues(t, errors.CodeOK, qres.Code) + require.EqualValues(t, 0, qres.Code) require.Nil(t, qres.Value) // Test store2 data. query.Data = k2 qres = multi.Query(query) - require.EqualValues(t, errors.CodeOK, qres.Code) + require.EqualValues(t, 0, qres.Code) require.Equal(t, v2, qres.Value) } diff --git a/store/types/iterator.go b/store/types/iterator.go new file mode 100644 index 000000000000..cfce4124e397 --- /dev/null +++ b/store/types/iterator.go @@ -0,0 +1,61 @@ +package types + +import ( + "fmt" +) + +// KVStorePrefixIteratorPaginated returns iterator over items in the selected page. +// Items iterated and skipped in ascending order. +func KVStorePrefixIteratorPaginated(kvs KVStore, prefix []byte, page, limit uint) Iterator { + pi := &PaginatedIterator{ + Iterator: KVStorePrefixIterator(kvs, prefix), + page: page, + limit: limit, + } + pi.skip() + return pi +} + +// KVStoreReversePrefixIteratorPaginated returns iterator over items in the selected page. +// Items iterated and skipped in descending order. +func KVStoreReversePrefixIteratorPaginated(kvs KVStore, prefix []byte, page, limit uint) Iterator { + pi := &PaginatedIterator{ + Iterator: KVStoreReversePrefixIterator(kvs, prefix), + page: page, + limit: limit, + } + pi.skip() + return pi +} + +// PaginatedIterator is a wrapper around Iterator that iterates over values starting for given page and limit. +type PaginatedIterator struct { + Iterator + + page, limit uint // provided during initialization + iterated uint // incremented in a call to Next + +} + +func (pi *PaginatedIterator) skip() { + for i := (pi.page - 1) * pi.limit; i > 0 && pi.Iterator.Valid(); i-- { + pi.Iterator.Next() + } +} + +// Next will panic after limit is reached. +func (pi *PaginatedIterator) Next() { + if !pi.Valid() { + panic(fmt.Sprintf("PaginatedIterator reached limit %d", pi.limit)) + } + pi.Iterator.Next() + pi.iterated++ +} + +// Valid if below limit and underlying iterator is valid. +func (pi *PaginatedIterator) Valid() bool { + if pi.iterated >= pi.limit { + return false + } + return pi.Iterator.Valid() +} diff --git a/store/types/iterator_test.go b/store/types/iterator_test.go new file mode 100644 index 000000000000..e081de80a3d5 --- /dev/null +++ b/store/types/iterator_test.go @@ -0,0 +1,119 @@ +package types_test + +import ( + "testing" + + "github.com/stretchr/testify/require" + dbm "github.com/tendermint/tm-db" + + "github.com/cosmos/cosmos-sdk/store/iavl" + "github.com/cosmos/cosmos-sdk/store/types" +) + +func newMemTestKVStore(t *testing.T) types.KVStore { + db := dbm.NewMemDB() + store, err := iavl.LoadStore(db, types.CommitID{}, types.PruneNothing, false) + require.NoError(t, err) + return store +} + +func TestPaginatedIterator(t *testing.T) { + kvs := newMemTestKVStore(t) + total := 10 + lth := total - 1 + asc := make([][]byte, total) + desc := make([][]byte, total) + // store returns values in lexicographic order (or reverse lex order) + for i := 0; i < total; i++ { + key := []byte{byte(i)} + kvs.Set(key, key) + asc[i] = key + desc[lth-i] = key + } + type testCase struct { + desc string + page, limit uint + result [][]byte + reverse bool + } + for _, tc := range []testCase{ + { + desc: "FirstChunk", + page: 1, + limit: 4, + result: asc[:4], + }, + { + desc: "SecondChunk", + page: 2, + limit: 4, + result: asc[4:8], + }, + { + desc: "ThirdChunkHalf", + page: 3, + limit: 4, + result: asc[8:], + }, + { + desc: "OverLimit", + page: 10, + limit: 10, + result: [][]byte{}, + }, + { + desc: "ZeroLimit", + page: 1, + result: [][]byte{}, + }, + { + desc: "ReverseFirstChunk", + page: 1, + limit: 6, + result: desc[:6], + reverse: true, + }, + { + desc: "ReverseSecondChunk", + page: 2, + limit: 6, + result: desc[6:], + reverse: true, + }, + } { + tc := tc + t.Run(tc.desc, func(t *testing.T) { + var iter types.Iterator + if tc.reverse { + iter = types.KVStoreReversePrefixIteratorPaginated(kvs, nil, tc.page, tc.limit) + } else { + iter = types.KVStorePrefixIteratorPaginated(kvs, nil, tc.page, tc.limit) + } + defer iter.Close() + + result := [][]byte{} + for ; iter.Valid(); iter.Next() { + result = append(result, iter.Key()) + } + + require.Equal(t, tc.result, result) + require.False(t, iter.Valid()) + }) + } +} + +func TestPaginatedIteratorPanicIfInvalid(t *testing.T) { + kvs := newMemTestKVStore(t) + + iter := types.KVStorePrefixIteratorPaginated(kvs, nil, 1, 1) + defer iter.Close() + require.False(t, iter.Valid()) + require.Panics(t, func() { iter.Next() }) // "iterator is empty" + + kvs.Set([]byte{1}, []byte{}) + + iter = types.KVStorePrefixIteratorPaginated(kvs, nil, 1, 0) + defer iter.Close() + require.False(t, iter.Valid()) + require.Panics(t, func() { iter.Next() }) // "not empty but limit is zero" +} diff --git a/types/decimal.go b/types/decimal.go index b066c3e43374..63aecf6cab18 100644 --- a/types/decimal.go +++ b/types/decimal.go @@ -2,6 +2,7 @@ package types import ( "encoding/json" + "errors" "fmt" "math/big" "strconv" @@ -33,6 +34,13 @@ var ( tenInt = big.NewInt(10) ) +// Decimal errors +var ( + ErrEmptyDecimalStr = errors.New("decimal string cannot be empty") + ErrInvalidDecimalLength = errors.New("invalid decimal length") + ErrInvalidDecimalStr = errors.New("invalid decimal string") +) + // Set precision multipliers func init() { precisionMultipliers = make([]*big.Int, Precision+1) @@ -123,9 +131,9 @@ func NewDecFromIntWithPrec(i Int, prec int64) Dec { // are provided in the string than the constant Precision. // // CONTRACT - This function does not mutate the input str. -func NewDecFromStr(str string) (d Dec, err Error) { +func NewDecFromStr(str string) (Dec, error) { if len(str) == 0 { - return d, ErrUnknownRequest("decimal string is empty") + return Dec{}, ErrEmptyDecimalStr } // first extract any negative symbol @@ -136,7 +144,7 @@ func NewDecFromStr(str string) (d Dec, err Error) { } if len(str) == 0 { - return d, ErrUnknownRequest("decimal string is empty") + return Dec{}, ErrEmptyDecimalStr } strs := strings.Split(str, ".") @@ -146,17 +154,16 @@ func NewDecFromStr(str string) (d Dec, err Error) { if len(strs) == 2 { // has a decimal place lenDecs = len(strs[1]) if lenDecs == 0 || len(combinedStr) == 0 { - return d, ErrUnknownRequest("bad decimal length") + return Dec{}, ErrInvalidDecimalLength } combinedStr += strs[1] } else if len(strs) > 2 { - return d, ErrUnknownRequest("too many periods to be a decimal string") + return Dec{}, ErrInvalidDecimalStr } if lenDecs > Precision { - return d, ErrUnknownRequest( - fmt.Sprintf("too much precision, maximum %v, len decimal %v", Precision, lenDecs)) + return Dec{}, fmt.Errorf("invalid precision; max: %d, got: %d", Precision, lenDecs) } // add some extra zero's to correct to the Precision factor @@ -166,11 +173,12 @@ func NewDecFromStr(str string) (d Dec, err Error) { combined, ok := new(big.Int).SetString(combinedStr, 10) // base 10 if !ok { - return d, ErrUnknownRequest(fmt.Sprintf("bad string to integer conversion, combinedStr: %v", combinedStr)) + return Dec{}, fmt.Errorf("failed to set decimal string: %s", combinedStr) } if neg { combined = new(big.Int).Neg(combined) } + return Dec{combined}, nil } diff --git a/types/errors.go b/types/errors.go deleted file mode 100644 index c59571bfe540..000000000000 --- a/types/errors.go +++ /dev/null @@ -1,361 +0,0 @@ -package types - -import ( - "bytes" - "encoding/json" - "fmt" - "strings" - - "github.com/pkg/errors" - - abci "github.com/tendermint/tendermint/abci/types" - cmn "github.com/tendermint/tendermint/libs/common" - - sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" -) - -// CodeType - ABCI code identifier within codespace -type CodeType uint32 - -// CodespaceType - codespace identifier -type CodespaceType string - -// IsOK - is everything okay? -func (code CodeType) IsOK() bool { - return code == CodeOK -} - -// SDK error codes -const ( - // Base error codes - CodeOK CodeType = 0 - CodeInternal CodeType = 1 - CodeTxDecode CodeType = 2 - CodeInvalidSequence CodeType = 3 - CodeUnauthorized CodeType = 4 - CodeInsufficientFunds CodeType = 5 - CodeUnknownRequest CodeType = 6 - CodeInvalidAddress CodeType = 7 - CodeInvalidPubKey CodeType = 8 - CodeUnknownAddress CodeType = 9 - CodeInsufficientCoins CodeType = 10 - CodeInvalidCoins CodeType = 11 - CodeOutOfGas CodeType = 12 - CodeMemoTooLarge CodeType = 13 - CodeInsufficientFee CodeType = 14 - CodeTooManySignatures CodeType = 15 - CodeGasOverflow CodeType = 16 - CodeNoSignatures CodeType = 17 - CodeTxInMempoolCache CodeType = 18 - CodeMempoolIsFull CodeType = 19 - CodeTxTooLarge CodeType = 20 - - // CodespaceRoot is a codespace for error codes in this file only. - // Notice that 0 is an "unset" codespace, which can be overridden with - // Error.WithDefaultCodespace(). - CodespaceUndefined CodespaceType = "" - CodespaceRoot CodespaceType = "sdk" -) - -func unknownCodeMsg(code CodeType) string { - return fmt.Sprintf("unknown code %d", code) -} - -// NOTE: Don't stringer this, we'll put better messages in later. -func CodeToDefaultMsg(code CodeType) string { - switch code { - case CodeInternal: - return "internal error" - case CodeTxDecode: - return "tx parse error" - case CodeInvalidSequence: - return "invalid sequence" - case CodeUnauthorized: - return "unauthorized" - case CodeInsufficientFunds: - return "insufficient funds" - case CodeUnknownRequest: - return "unknown request" - case CodeInvalidAddress: - return "invalid address" - case CodeInvalidPubKey: - return "invalid pubkey" - case CodeUnknownAddress: - return "unknown address" - case CodeInsufficientCoins: - return "insufficient coins" - case CodeInvalidCoins: - return "invalid coins" - case CodeOutOfGas: - return "out of gas" - case CodeMemoTooLarge: - return "memo too large" - case CodeInsufficientFee: - return "insufficient fee" - case CodeTooManySignatures: - return "maximum numer of signatures exceeded" - case CodeNoSignatures: - return "no signatures supplied" - default: - return unknownCodeMsg(code) - } -} - -//-------------------------------------------------------------------------------- -// All errors are created via constructors so as to enable us to hijack them -// and inject stack traces if we really want to. - -// nolint -func ErrInternal(msg string) Error { - return newErrorWithRootCodespace(CodeInternal, msg) -} -func ErrTxDecode(msg string) Error { - return newErrorWithRootCodespace(CodeTxDecode, msg) -} -func ErrInvalidSequence(msg string) Error { - return newErrorWithRootCodespace(CodeInvalidSequence, msg) -} -func ErrUnauthorized(msg string) Error { - return newErrorWithRootCodespace(CodeUnauthorized, msg) -} -func ErrInsufficientFunds(msg string) Error { - return newErrorWithRootCodespace(CodeInsufficientFunds, msg) -} -func ErrUnknownRequest(msg string) Error { - return newErrorWithRootCodespace(CodeUnknownRequest, msg) -} -func ErrInvalidAddress(msg string) Error { - return newErrorWithRootCodespace(CodeInvalidAddress, msg) -} -func ErrUnknownAddress(msg string) Error { - return newErrorWithRootCodespace(CodeUnknownAddress, msg) -} -func ErrInvalidPubKey(msg string) Error { - return newErrorWithRootCodespace(CodeInvalidPubKey, msg) -} -func ErrInsufficientCoins(msg string) Error { - return newErrorWithRootCodespace(CodeInsufficientCoins, msg) -} -func ErrInvalidCoins(msg string) Error { - return newErrorWithRootCodespace(CodeInvalidCoins, msg) -} -func ErrOutOfGas(msg string) Error { - return newErrorWithRootCodespace(CodeOutOfGas, msg) -} -func ErrMemoTooLarge(msg string) Error { - return newErrorWithRootCodespace(CodeMemoTooLarge, msg) -} -func ErrInsufficientFee(msg string) Error { - return newErrorWithRootCodespace(CodeInsufficientFee, msg) -} -func ErrTooManySignatures(msg string) Error { - return newErrorWithRootCodespace(CodeTooManySignatures, msg) -} -func ErrNoSignatures(msg string) Error { - return newErrorWithRootCodespace(CodeNoSignatures, msg) -} -func ErrGasOverflow(msg string) Error { - return newErrorWithRootCodespace(CodeGasOverflow, msg) -} - -//---------------------------------------- -// Error & sdkError - -type cmnError = cmn.Error - -// sdk Error type -type Error interface { - // Implements cmn.Error - // Error() string - // Stacktrace() cmn.Error - // Trace(offset int, format string, args ...interface{}) cmn.Error - // Data() interface{} - cmnError - - // convenience - TraceSDK(format string, args ...interface{}) Error - - // set codespace - WithDefaultCodespace(CodespaceType) Error - - Code() CodeType - Codespace() CodespaceType - ABCILog() string - Result() Result - QueryResult() abci.ResponseQuery -} - -// NewError - create an error. -func NewError(codespace CodespaceType, code CodeType, format string, args ...interface{}) Error { - return newError(codespace, code, format, args...) -} - -func newErrorWithRootCodespace(code CodeType, format string, args ...interface{}) *sdkError { - return newError(CodespaceRoot, code, format, args...) -} - -func newError(codespace CodespaceType, code CodeType, format string, args ...interface{}) *sdkError { - if format == "" { - format = CodeToDefaultMsg(code) - } - return &sdkError{ - codespace: codespace, - code: code, - cmnError: cmn.NewError(format, args...), - } -} - -type sdkError struct { - codespace CodespaceType - code CodeType - cmnError -} - -// Implements Error. -func (err *sdkError) WithDefaultCodespace(cs CodespaceType) Error { - codespace := err.codespace - if codespace == CodespaceUndefined { - codespace = cs - } - return &sdkError{ - codespace: cs, - code: err.code, - cmnError: err.cmnError, - } -} - -// Implements ABCIError. -// nolint: errcheck -func (err *sdkError) TraceSDK(format string, args ...interface{}) Error { - err.Trace(1, format, args...) - return err -} - -// Implements ABCIError. -func (err *sdkError) Error() string { - return fmt.Sprintf(`ERROR: -Codespace: %s -Code: %d -Message: %#v -`, err.codespace, err.code, err.cmnError.Error()) -} - -// Implements Error. -func (err *sdkError) Codespace() CodespaceType { - return err.codespace -} - -// Implements Error. -func (err *sdkError) Code() CodeType { - return err.code -} - -// Implements ABCIError. -func (err *sdkError) ABCILog() string { - errMsg := err.cmnError.Error() - return encodeErrorLog(err.codespace, err.code, errMsg) -} - -func encodeErrorLog(codespace CodespaceType, code CodeType, msg string) string { - jsonErr := humanReadableError{ - Codespace: codespace, - Code: code, - Message: msg, - } - - var buff bytes.Buffer - enc := json.NewEncoder(&buff) - enc.SetEscapeHTML(false) - - if err := enc.Encode(jsonErr); err != nil { - panic(errors.Wrap(err, "failed to encode ABCI error log")) - } - - return strings.TrimSpace(buff.String()) -} - -func (err *sdkError) Result() Result { - return Result{ - Code: err.Code(), - Codespace: err.Codespace(), - Log: err.ABCILog(), - } -} - -// QueryResult allows us to return sdk.Error.QueryResult() in query responses -func (err *sdkError) QueryResult() abci.ResponseQuery { - return abci.ResponseQuery{ - Code: uint32(err.Code()), - Codespace: string(err.Codespace()), - Log: err.ABCILog(), - } -} - -// ResultFromError will return err.Result() if it implements sdk.Error -// Otherwise, it will use the reflecton from types/error to determine -// the code, codespace, and log. -// -// This is intended to provide a bridge to allow both error types -// to live side-by-side. -func ResultFromError(err error) Result { - if sdk, ok := err.(Error); ok { - return sdk.Result() - } - space, code, log := sdkerrors.ABCIInfo(err, false) - return Result{ - Codespace: CodespaceType(space), - Code: CodeType(code), - Log: encodeErrorLog(CodespaceType(space), CodeType(code), log), - } -} - -// ConvertError accepts a standard error and attempts to convert it to an sdk.Error. -// If the given error is already an sdk.Error, it'll simply be returned. Otherwise, -// it'll convert it to a types.Error. This is meant to provide a migration path -// away from sdk.Error in favor of types.Error. -func ConvertError(err error) Error { - if err == nil { - return nil - } - if sdkError, ok := err.(Error); ok { - return sdkError - } - - space, code, log := sdkerrors.ABCIInfo(err, false) - return NewError(CodespaceType(space), CodeType(code), log) -} - -//---------------------------------------- -// REST error utilities - -// appends a message to the head of the given error -func AppendMsgToErr(msg string, err string) string { - msgIdx := strings.Index(err, "message\":\"") - if msgIdx != -1 { - errMsg := err[msgIdx+len("message\":\"") : len(err)-2] - errMsg = fmt.Sprintf("%s; %s", msg, errMsg) - return fmt.Sprintf("%s%s%s", - err[:msgIdx+len("message\":\"")], - errMsg, - err[len(err)-2:], - ) - } - return fmt.Sprintf("%s; %s", msg, err) -} - -// returns the index of the message in the ABCI Log -// nolint:deadcode,unused -func mustGetMsgIndex(abciLog string) int { - msgIdx := strings.Index(abciLog, "message\":\"") - if msgIdx == -1 { - panic(fmt.Sprintf("invalid error format: %s", abciLog)) - } - return msgIdx + len("message\":\"") -} - -// parses the error into an object-like struct for exporting -type humanReadableError struct { - Codespace CodespaceType `json:"codespace"` - Code CodeType `json:"code"` - Message string `json:"message"` -} diff --git a/types/errors/abci.go b/types/errors/abci.go index 1f70758cdd1b..cc5633543192 100644 --- a/types/errors/abci.go +++ b/types/errors/abci.go @@ -4,6 +4,8 @@ import ( "errors" "fmt" "reflect" + + abci "github.com/tendermint/tendermint/abci/types" ) const ( @@ -40,6 +42,43 @@ func ABCIInfo(err error, debug bool) (codespace string, code uint32, log string) return abciCodespace(err), abciCode(err), encode(err) } +// ResponseCheckTx returns an ABCI ResponseCheckTx object with fields filled in +// from the given error and gas values. +func ResponseCheckTx(err error, gw, gu uint64) abci.ResponseCheckTx { + space, code, log := ABCIInfo(err, false) + return abci.ResponseCheckTx{ + Codespace: space, + Code: code, + Log: log, + GasWanted: int64(gw), + GasUsed: int64(gu), + } +} + +// ResponseDeliverTx returns an ABCI ResponseDeliverTx object with fields filled in +// from the given error and gas values. +func ResponseDeliverTx(err error, gw, gu uint64) abci.ResponseDeliverTx { + space, code, log := ABCIInfo(err, false) + return abci.ResponseDeliverTx{ + Codespace: space, + Code: code, + Log: log, + GasWanted: int64(gw), + GasUsed: int64(gu), + } +} + +// QueryResult returns a ResponseQuery from an error. It will try to parse ABCI +// info from the error. +func QueryResult(err error) abci.ResponseQuery { + space, code, log := ABCIInfo(err, false) + return abci.ResponseQuery{ + Codespace: space, + Code: code, + Log: log, + } +} + // The debugErrEncoder encodes the error with a stacktrace. func debugErrEncoder(err error) string { return fmt.Sprintf("%+v", err) diff --git a/types/errors/abci_test.go b/types/errors/abci_test.go index 20b4f74b6f8b..c098811ea474 100644 --- a/types/errors/abci_test.go +++ b/types/errors/abci_test.go @@ -15,17 +15,17 @@ func TestABCInfo(t *testing.T) { wantSpace string wantLog string }{ - "plain weave error": { + "plain SDK error": { err: ErrUnauthorized, debug: false, wantLog: "unauthorized", wantCode: ErrUnauthorized.code, wantSpace: RootCodespace, }, - "wrapped weave error": { + "wrapped SDK error": { err: Wrap(Wrap(ErrUnauthorized, "foo"), "bar"), debug: false, - wantLog: "bar: foo: unauthorized", + wantLog: "unauthorized: foo: bar", wantCode: ErrUnauthorized.code, wantSpace: RootCodespace, }, @@ -36,7 +36,7 @@ func TestABCInfo(t *testing.T) { wantCode: 0, wantSpace: "", }, - "nil weave error is not an error": { + "nil SDK error is not an error": { err: (*Error)(nil), debug: false, wantLog: "", @@ -112,23 +112,23 @@ func TestABCIInfoStacktrace(t *testing.T) { wantStacktrace bool wantErrMsg string }{ - "wrapped weave error in debug mode provides stacktrace": { + "wrapped SDK error in debug mode provides stacktrace": { err: Wrap(ErrUnauthorized, "wrapped"), debug: true, wantStacktrace: true, - wantErrMsg: "wrapped: unauthorized", + wantErrMsg: "unauthorized: wrapped", }, - "wrapped weave error in non-debug mode does not have stacktrace": { + "wrapped SDK error in non-debug mode does not have stacktrace": { err: Wrap(ErrUnauthorized, "wrapped"), debug: false, wantStacktrace: false, - wantErrMsg: "wrapped: unauthorized", + wantErrMsg: "unauthorized: wrapped", }, "wrapped stdlib error in debug mode provides stacktrace": { err: Wrap(fmt.Errorf("stdlib"), "wrapped"), debug: true, wantStacktrace: true, - wantErrMsg: "wrapped: stdlib", + wantErrMsg: "stdlib: wrapped", }, "wrapped stdlib error in non-debug mode does not have stacktrace": { err: Wrap(fmt.Errorf("stdlib"), "wrapped"), @@ -163,7 +163,7 @@ func TestABCIInfoHidesStacktrace(t *testing.T) { err := Wrap(ErrUnauthorized, "wrapped") _, _, log := ABCIInfo(err, false) - if log != "wrapped: unauthorized" { + if log != "unauthorized: wrapped" { t.Fatalf("unexpected message in non debug mode: %s", log) } } @@ -173,7 +173,7 @@ func TestRedact(t *testing.T) { t.Error("reduct must not pass through panic error") } if err := Redact(ErrUnauthorized); !ErrUnauthorized.Is(err) { - t.Error("reduct should pass through weave error") + t.Error("reduct should pass through SDK error") } var cerr customErr @@ -203,12 +203,12 @@ func TestABCIInfoSerializeErr(t *testing.T) { "single error": { src: myErrDecode, debug: false, - exp: "test: tx parse error", + exp: "tx parse error: test", }, "second error": { src: myErrAddr, debug: false, - exp: "tester: invalid address", + exp: "invalid address: tester", }, "single error with debug": { src: myErrDecode, diff --git a/types/errors/errors.go b/types/errors/errors.go index 22ed2f4c8c89..49624f784775 100644 --- a/types/errors/errors.go +++ b/types/errors/errors.go @@ -44,32 +44,43 @@ var ( // ErrUnknownAddress to doc ErrUnknownAddress = Register(RootCodespace, 9, "unknown address") - // ErrInsufficientCoins to doc (what is the difference between ErrInsufficientFunds???) - ErrInsufficientCoins = Register(RootCodespace, 10, "insufficient coins") - // ErrInvalidCoins to doc - ErrInvalidCoins = Register(RootCodespace, 11, "invalid coins") + ErrInvalidCoins = Register(RootCodespace, 10, "invalid coins") // ErrOutOfGas to doc - ErrOutOfGas = Register(RootCodespace, 12, "out of gas") + ErrOutOfGas = Register(RootCodespace, 11, "out of gas") // ErrMemoTooLarge to doc - ErrMemoTooLarge = Register(RootCodespace, 13, "memo too large") + ErrMemoTooLarge = Register(RootCodespace, 12, "memo too large") // ErrInsufficientFee to doc - ErrInsufficientFee = Register(RootCodespace, 14, "insufficient fee") + ErrInsufficientFee = Register(RootCodespace, 13, "insufficient fee") // ErrTooManySignatures to doc - ErrTooManySignatures = Register(RootCodespace, 15, "maximum numer of signatures exceeded") + ErrTooManySignatures = Register(RootCodespace, 14, "maximum number of signatures exceeded") // ErrNoSignatures to doc - ErrNoSignatures = Register(RootCodespace, 16, "no signatures supplied") + ErrNoSignatures = Register(RootCodespace, 15, "no signatures supplied") // ErrJSONMarshal defines an ABCI typed JSON marshalling error - ErrJSONMarshal = Register(RootCodespace, 17, "failed to marshal JSON bytes") + ErrJSONMarshal = Register(RootCodespace, 16, "failed to marshal JSON bytes") // ErrJSONUnmarshal defines an ABCI typed JSON unmarshalling error - ErrJSONUnmarshal = Register(RootCodespace, 18, "failed to unmarshal JSON bytes") + ErrJSONUnmarshal = Register(RootCodespace, 17, "failed to unmarshal JSON bytes") + + // ErrInvalidRequest defines an ABCI typed error where the request contains + // invalid data. + ErrInvalidRequest = Register(RootCodespace, 18, "invalid request") + + // ErrTxInMempoolCache defines an ABCI typed error where a tx already exists + // in the mempool. + ErrTxInMempoolCache = Register(RootCodespace, 19, "tx already in mempool") + + // ErrMempoolIsFull defines an ABCI typed error where the mempool is full. + ErrMempoolIsFull = Register(RootCodespace, 20, "mempool is full") + + // ErrTxTooLarge defines an ABCI typed error where tx is too large. + ErrTxTooLarge = Register(RootCodespace, 21, "tx too large") // ErrPanic is only set when we recover from a panic, so we know to // redact potentially sensitive system info @@ -89,12 +100,10 @@ func Register(codespace string, code uint32, description string) *Error { if e := getUsed(codespace, code); e != nil { panic(fmt.Sprintf("error with code %d is already registered: %q", code, e.desc)) } - err := &Error{ - code: code, - codespace: codespace, - desc: description, - } + + err := New(codespace, code, description) setUsed(err) + return err } @@ -247,7 +256,7 @@ type wrappedError struct { } func (e *wrappedError) Error() string { - return fmt.Sprintf("%s: %s", e.msg, e.parent.Error()) + return fmt.Sprintf("%s: %s", e.parent.Error(), e.msg) } func (e *wrappedError) Cause() error { diff --git a/types/errors/stacktrace_test.go b/types/errors/stacktrace_test.go index bef4bccb704e..042edc0b6919 100644 --- a/types/errors/stacktrace_test.go +++ b/types/errors/stacktrace_test.go @@ -15,19 +15,19 @@ func TestStackTrace(t *testing.T) { }{ "New gives us a stacktrace": { err: Wrap(ErrNoSignatures, "name"), - wantError: "name: no signatures supplied", + wantError: "no signatures supplied: name", }, "Wrapping stderr gives us a stacktrace": { err: Wrap(fmt.Errorf("foo"), "standard"), - wantError: "standard: foo", + wantError: "foo: standard", }, "Wrapping pkg/errors gives us clean stacktrace": { err: Wrap(errors.New("bar"), "pkg"), - wantError: "pkg: bar", + wantError: "bar: pkg", }, "Wrapping inside another function is still clean": { err: Wrap(fmt.Errorf("indirect"), "do the do"), - wantError: "do the do: indirect", + wantError: "indirect: do the do", }, } diff --git a/types/errors_test.go b/types/errors_test.go deleted file mode 100644 index 912de348a408..000000000000 --- a/types/errors_test.go +++ /dev/null @@ -1,138 +0,0 @@ -package types - -import ( - "fmt" - "testing" - - "github.com/stretchr/testify/require" - - sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" -) - -var codeTypes = []CodeType{ - CodeInternal, - CodeTxDecode, - CodeInvalidSequence, - CodeUnauthorized, - CodeInsufficientFunds, - CodeUnknownRequest, - CodeInvalidAddress, - CodeInvalidPubKey, - CodeUnknownAddress, - CodeInsufficientCoins, - CodeInvalidCoins, - CodeOutOfGas, - CodeMemoTooLarge, -} - -type errFn func(msg string) Error - -var errFns = []errFn{ - ErrInternal, - ErrTxDecode, - ErrInvalidSequence, - ErrUnauthorized, - ErrInsufficientFunds, - ErrUnknownRequest, - ErrInvalidAddress, - ErrInvalidPubKey, - ErrUnknownAddress, - ErrInsufficientCoins, - ErrInvalidCoins, - ErrOutOfGas, - ErrMemoTooLarge, -} - -func TestCodeType(t *testing.T) { - require.True(t, CodeOK.IsOK()) - - for tcnum, c := range codeTypes { - msg := CodeToDefaultMsg(c) - require.NotEqual(t, unknownCodeMsg(c), msg, "Code expected to be known. tc #%d, code %d, msg %s", tcnum, c, msg) - } - - msg := CodeToDefaultMsg(CodeOK) - require.Equal(t, unknownCodeMsg(CodeOK), msg) -} - -func TestErrFn(t *testing.T) { - for i, errFn := range errFns { - err := errFn("") - codeType := codeTypes[i] - require.Equal(t, err.Code(), codeType, "Err function expected to return proper code. tc #%d", i) - require.Equal(t, err.Codespace(), CodespaceRoot, "Err function expected to return proper codespace. tc #%d", i) - require.Equal(t, err.QueryResult().Code, uint32(err.Code()), "Err function expected to return proper Code from QueryResult. tc #%d") - require.Equal(t, err.QueryResult().Log, err.ABCILog(), "Err function expected to return proper ABCILog from QueryResult. tc #%d") - } -} - -func TestAppendMsgToErr(t *testing.T) { - for i, errFn := range errFns { - err := errFn("") - errMsg := err.Stacktrace().Error() - abciLog := err.ABCILog() - - // plain msg error - msg := AppendMsgToErr("something unexpected happened", errMsg) - require.Equal( - t, - fmt.Sprintf("something unexpected happened; %s", errMsg), - msg, - fmt.Sprintf("Should have formatted the error message of ABCI Log. tc #%d", i), - ) - - // ABCI Log msg error - msg = AppendMsgToErr("something unexpected happened", abciLog) - msgIdx := mustGetMsgIndex(abciLog) - require.Equal( - t, - fmt.Sprintf("%s%s; %s}", - abciLog[:msgIdx], - "something unexpected happened", - abciLog[msgIdx:len(abciLog)-1], - ), - msg, - fmt.Sprintf("Should have formatted the error message of ABCI Log. tc #%d", i)) - } -} - -func TestResultFromError(t *testing.T) { - cases := map[string]struct { - err error - expect Result - }{ - "sdk.Error": { - err: ErrUnauthorized("not owner"), - expect: Result{ - Codespace: CodespaceRoot, - Code: CodeUnauthorized, - Log: `{"codespace":"sdk","code":4,"message":"not owner"}`, - }, - }, - "types/errors": { - err: sdkerrors.Wrap(sdkerrors.ErrUnauthorized, "not owner"), - expect: Result{ - Codespace: CodespaceRoot, - Code: CodeUnauthorized, - Log: `{"codespace":"sdk","code":4,"message":"not owner: unauthorized"}`, - }, - }, - "stdlib errors": { - err: fmt.Errorf("not owner"), - expect: Result{ - Codespace: CodespaceType("undefined"), - Code: CodeInternal, - // note that we redact the internal errors in the new package to not leak eg. panics - Log: `{"codespace":"undefined","code":1,"message":"internal error"}`, - }, - }, - } - - for name, tc := range cases { - tc := tc - t.Run(name, func(t *testing.T) { - res := ResultFromError(tc.err) - require.Equal(t, tc.expect, res) - }) - } -} diff --git a/types/handler.go b/types/handler.go index d0cc41ec46dc..6815230a861f 100644 --- a/types/handler.go +++ b/types/handler.go @@ -1,7 +1,7 @@ package types // Handler defines the core of the state transition function of an application. -type Handler func(ctx Context, msg Msg) Result +type Handler func(ctx Context, msg Msg) (*Result, error) // AnteHandler authenticates transactions, before their internal messages are handled. // If newCtx.IsZero(), ctx is used instead. diff --git a/types/queryable.go b/types/queryable.go index 9223332bc833..f89965906af8 100644 --- a/types/queryable.go +++ b/types/queryable.go @@ -1,6 +1,9 @@ package types -import abci "github.com/tendermint/tendermint/abci/types" +import ( + abci "github.com/tendermint/tendermint/abci/types" +) -// Type for querier functions on keepers to implement to handle custom queries -type Querier = func(ctx Context, path []string, req abci.RequestQuery) (res []byte, err Error) +// Querier defines a function type that a module querier must implement to handle +// custom client queries. +type Querier = func(ctx Context, path []string, req abci.RequestQuery) ([]byte, error) diff --git a/types/result.go b/types/result.go index 5821cab538bc..8b9a28df502b 100644 --- a/types/result.go +++ b/types/result.go @@ -12,36 +12,27 @@ import ( ctypes "github.com/tendermint/tendermint/rpc/core/types" ) -// Result is the union of ResponseFormat and ResponseCheckTx. -type Result struct { - // Code is the response code, is stored back on the chain. - Code CodeType - - // Codespace is the string referring to the domain of an error - Codespace CodespaceType - - // Data is any data returned from the app. - // Data has to be length prefixed in order to separate - // results from multiple msgs executions - Data []byte - - // Log contains the txs log information. NOTE: nondeterministic. - Log string - +// GasInfo defines tx execution gas context. +type GasInfo struct { // GasWanted is the maximum units of work we allow this tx to perform. GasWanted uint64 // GasUsed is the amount of gas actually consumed. NOTE: unimplemented GasUsed uint64 - - // Events contains a slice of Event objects that were emitted during some - // execution. - Events Events } -// TODO: In the future, more codes may be OK. -func (res Result) IsOK() bool { - return res.Code.IsOK() +// Result is the union of ResponseFormat and ResponseCheckTx. +type Result struct { + // Data is any data returned from message or handler execution. It MUST be length + // prefixed in order to separate data from multiple message executions. + Data []byte + + // Log contains the log information from message or handler execution. + Log string + + // Events contains a slice of Event objects that were emitted during message or + // handler execution. + Events Events } // ABCIMessageLogs represents a slice of ABCIMessageLog. @@ -50,7 +41,6 @@ type ABCIMessageLogs []ABCIMessageLog // ABCIMessageLog defines a structure containing an indexed tx ABCI message log. type ABCIMessageLog struct { MsgIndex uint16 `json:"msg_index"` - Success bool `json:"success"` Log string `json:"log"` // Events contains a slice of Event objects that were emitted during some @@ -58,10 +48,9 @@ type ABCIMessageLog struct { Events StringEvents `json:"events"` } -func NewABCIMessageLog(i uint16, success bool, log string, events Events) ABCIMessageLog { +func NewABCIMessageLog(i uint16, log string, events Events) ABCIMessageLog { return ABCIMessageLog{ MsgIndex: i, - Success: success, Log: log, Events: StringifyEvents(events.ToABCIEvents()), } @@ -84,6 +73,7 @@ func (logs ABCIMessageLogs) String() (str string) { type TxResponse struct { Height int64 `json:"height"` TxHash string `json:"txhash"` + Codespace string `json:"codespace,omitempty"` Code uint32 `json:"code,omitempty"` Data string `json:"data,omitempty"` RawLog string `json:"raw_log,omitempty"` @@ -91,7 +81,6 @@ type TxResponse struct { Info string `json:"info,omitempty"` GasWanted int64 `json:"gas_wanted,omitempty"` GasUsed int64 `json:"gas_used,omitempty"` - Codespace string `json:"codespace,omitempty"` Tx Tx `json:"tx,omitempty"` Timestamp string `json:"timestamp,omitempty"` @@ -100,15 +89,6 @@ type TxResponse struct { Events StringEvents `json:"events,omitempty"` } -func (res TxResponse) IsOK() bool { - for _, lg := range res.Logs { - if !lg.Success { - return false - } - } - return true -} - // NewResponseResultTx returns a TxResponse given a ResultTx from tendermint func NewResponseResultTx(res *ctypes.ResultTx, tx Tx, timestamp string) TxResponse { if res == nil { @@ -120,6 +100,7 @@ func NewResponseResultTx(res *ctypes.ResultTx, tx Tx, timestamp string) TxRespon return TxResponse{ TxHash: res.Hash.String(), Height: res.Height, + Codespace: res.TxResult.Codespace, Code: res.TxResult.Code, Data: strings.ToUpper(hex.EncodeToString(res.TxResult.Data)), RawLog: res.TxResult.Log, @@ -162,6 +143,7 @@ func newTxResponseCheckTx(res *ctypes.ResultBroadcastTxCommit) TxResponse { return TxResponse{ Height: res.Height, TxHash: txHash, + Codespace: res.CheckTx.Codespace, Code: res.CheckTx.Code, Data: strings.ToUpper(hex.EncodeToString(res.CheckTx.Data)), RawLog: res.CheckTx.Log, @@ -170,7 +152,6 @@ func newTxResponseCheckTx(res *ctypes.ResultBroadcastTxCommit) TxResponse { GasWanted: res.CheckTx.GasWanted, GasUsed: res.CheckTx.GasUsed, Events: StringifyEvents(res.CheckTx.Events), - Codespace: res.CheckTx.Codespace, } } @@ -189,6 +170,7 @@ func newTxResponseDeliverTx(res *ctypes.ResultBroadcastTxCommit) TxResponse { return TxResponse{ Height: res.Height, TxHash: txHash, + Codespace: res.DeliverTx.Codespace, Code: res.DeliverTx.Code, Data: strings.ToUpper(hex.EncodeToString(res.DeliverTx.Data)), RawLog: res.DeliverTx.Log, @@ -197,7 +179,6 @@ func newTxResponseDeliverTx(res *ctypes.ResultBroadcastTxCommit) TxResponse { GasWanted: res.DeliverTx.GasWanted, GasUsed: res.DeliverTx.GasUsed, Events: StringifyEvents(res.DeliverTx.Events), - Codespace: res.DeliverTx.Codespace, } } diff --git a/types/result_test.go b/types/result_test.go index c4fedc2992f3..bbdf3b75e70a 100644 --- a/types/result_test.go +++ b/types/result_test.go @@ -7,17 +7,6 @@ import ( "github.com/stretchr/testify/require" ) -func TestResult(t *testing.T) { - var res Result - require.True(t, res.IsOK()) - - res.Data = []byte("data") - require.True(t, res.IsOK()) - - res.Code = CodeType(1) - require.False(t, res.IsOK()) -} - func TestParseABCILog(t *testing.T) { logs := `[{"log":"","msg_index":1,"success":true}]` @@ -26,12 +15,11 @@ func TestParseABCILog(t *testing.T) { require.Len(t, res, 1) require.Equal(t, res[0].Log, "") require.Equal(t, res[0].MsgIndex, uint16(1)) - require.True(t, res[0].Success) } func TestABCIMessageLog(t *testing.T) { events := Events{NewEvent("transfer", NewAttribute("sender", "foo"))} - msgLog := NewABCIMessageLog(0, true, "", events) + msgLog := NewABCIMessageLog(0, "", events) msgLogs := ABCIMessageLogs{msgLog} bz, err := codec.Cdc.MarshalJSON(msgLogs) diff --git a/types/store.go b/types/store.go index db18b127b69d..0a972bf7403c 100644 --- a/types/store.go +++ b/types/store.go @@ -40,6 +40,18 @@ func KVStoreReversePrefixIterator(kvs KVStore, prefix []byte) Iterator { return types.KVStoreReversePrefixIterator(kvs, prefix) } +// KVStorePrefixIteratorPaginated returns iterator over items in the selected page. +// Items iterated and skipped in ascending order. +func KVStorePrefixIteratorPaginated(kvs KVStore, prefix []byte, page, limit uint) Iterator { + return types.KVStorePrefixIteratorPaginated(kvs, prefix, page, limit) +} + +// KVStoreReversePrefixIteratorPaginated returns iterator over items in the selected page. +// Items iterated and skipped in descending order. +func KVStoreReversePrefixIteratorPaginated(kvs KVStore, prefix []byte, page, limit uint) Iterator { + return types.KVStorePrefixIteratorPaginated(kvs, prefix, page, limit) +} + // DiffKVStores compares two KVstores and returns all the key/value pairs // that differ from one another. It also skips value comparison for a set of provided prefixes func DiffKVStores(a KVStore, b KVStore, prefixesToSkip [][]byte) (kvAs, kvBs []cmn.KVPair) { diff --git a/types/tx_msg.go b/types/tx_msg.go index bc4c2540d911..1b0da612b736 100644 --- a/types/tx_msg.go +++ b/types/tx_msg.go @@ -17,7 +17,7 @@ type Msg interface { // ValidateBasic does a simple validation check that // doesn't require access to any other information. - ValidateBasic() Error + ValidateBasic() error // Get the canonical byte representation of the Msg. GetSignBytes() []byte @@ -37,13 +37,13 @@ type Tx interface { // ValidateBasic does a simple and lightweight validation check that doesn't // require access to any other information. - ValidateBasic() Error + ValidateBasic() error } //__________________________________________________________ // TxDecoder unmarshals transaction bytes -type TxDecoder func(txBytes []byte) (Tx, Error) +type TxDecoder func(txBytes []byte) (Tx, error) // TxEncoder marshals transaction to bytes type TxEncoder func(tx Tx) ([]byte, error) @@ -73,7 +73,7 @@ func (msg *TestMsg) GetSignBytes() []byte { } return MustSortJSON(bz) } -func (msg *TestMsg) ValidateBasic() Error { return nil } +func (msg *TestMsg) ValidateBasic() error { return nil } func (msg *TestMsg) GetSigners() []AccAddress { return msg.signers } diff --git a/types/uint.go b/types/uint.go index da43f5fb9094..1cc289b900dc 100644 --- a/types/uint.go +++ b/types/uint.go @@ -99,6 +99,14 @@ func (u Uint) MulUint64(u2 uint64) (res Uint) { return u.Mul(NewUint(u2)) } // Quo divides Uint with Uint func (u Uint) Quo(u2 Uint) (res Uint) { return NewUintFromBigInt(div(u.i, u2.i)) } +// Mod returns remainder after dividing with Uint +func (u Uint) Mod(u2 Uint) Uint { + if u2.IsZero() { + panic("division-by-zero") + } + return Uint{mod(u.i, u2.i)} +} + // Quo divides Uint with uint64 func (u Uint) QuoUint64(u2 uint64) Uint { return u.Quo(NewUint(u2)) } @@ -172,3 +180,39 @@ func checkNewUint(i *big.Int) (Uint, error) { } return Uint{i}, nil } + +// RelativePow raises x to the power of n, where x (and the result, z) are scaled by factor b +// for example, RelativePow(210, 2, 100) = 441 (2.1^2 = 4.41) +func RelativePow(x Uint, n Uint, b Uint) (z Uint) { + if x.IsZero() { + if n.IsZero() { + z = b // 0^0 = 1 + return + } + z = ZeroUint() // otherwise 0^a = 0 + return + } + + z = x + if n.Mod(NewUint(2)).Equal(ZeroUint()) { + z = b + } + + halfOfB := b.Quo(NewUint(2)) + n = n.Quo(NewUint(2)) + + for n.GT(ZeroUint()) { + xSquared := x.Mul(x) + xSquaredRounded := xSquared.Add(halfOfB) + + x = xSquaredRounded.Quo(b) + + if n.Mod(NewUint(2)).Equal(OneUint()) { + zx := z.Mul(x) + zxRounded := zx.Add(halfOfB) + z = zxRounded.Quo(b) + } + n = n.Quo(NewUint(2)) + } + return z +} diff --git a/types/uint_test.go b/types/uint_test.go index d371c81369a0..e90fbf7f509c 100644 --- a/types/uint_test.go +++ b/types/uint_test.go @@ -256,3 +256,22 @@ func TestParseUint(t *testing.T) { func randuint() Uint { return NewUint(rand.Uint64()) } + +func TestRelativePow(t *testing.T) { + tests := []struct { + args []Uint + want Uint + }{ + {[]Uint{ZeroUint(), ZeroUint(), OneUint()}, OneUint()}, + {[]Uint{ZeroUint(), ZeroUint(), NewUint(10)}, NewUint(10)}, + {[]Uint{ZeroUint(), OneUint(), NewUint(10)}, ZeroUint()}, + {[]Uint{NewUint(10), NewUint(2), OneUint()}, NewUint(100)}, + {[]Uint{NewUint(210), NewUint(2), NewUint(100)}, NewUint(441)}, + {[]Uint{NewUint(2100), NewUint(2), NewUint(1000)}, NewUint(4410)}, + {[]Uint{NewUint(1000000001547125958), NewUint(600), NewUint(1000000000000000000)}, NewUint(1000000928276004850)}, + } + for i, tc := range tests { + res := RelativePow(tc.args[0], tc.args[1], tc.args[2]) + require.Equal(t, tc.want, res, "unexpected result for test case %d, input: %v, got: %v", i, tc.args, res) + } +} diff --git a/x/auth/ante/ante_test.go b/x/auth/ante/ante_test.go index 5ac42a6dc855..1d55b4d320c3 100644 --- a/x/auth/ante/ante_test.go +++ b/x/auth/ante/ante_test.go @@ -2,6 +2,7 @@ package ante_test import ( "encoding/json" + "errors" "fmt" "math/rand" "strings" @@ -26,14 +27,10 @@ func checkValidTx(t *testing.T, anteHandler sdk.AnteHandler, ctx sdk.Context, tx } // run the tx through the anteHandler and ensure it fails with the given code -func checkInvalidTx(t *testing.T, anteHandler sdk.AnteHandler, ctx sdk.Context, tx sdk.Tx, simulate bool, code sdk.CodeType) { +func checkInvalidTx(t *testing.T, anteHandler sdk.AnteHandler, ctx sdk.Context, tx sdk.Tx, simulate bool, expErr error) { _, err := anteHandler(ctx, tx, simulate) require.NotNil(t, err) - - result := sdk.ResultFromError(err) - - require.Equal(t, code, result.Code, fmt.Sprintf("Expected %v, got %v", code, result)) - require.Equal(t, sdk.CodespaceRoot, result.Codespace) + require.True(t, errors.Is(expErr, err)) } // Test that simulate transaction accurately estimates gas cost @@ -117,23 +114,23 @@ func TestAnteHandlerSigErrors(t *testing.T) { require.Equal(t, expectedSigners, stdTx.GetSigners()) // Check no signatures fails - checkInvalidTx(t, anteHandler, ctx, tx, false, sdk.CodeNoSignatures) + checkInvalidTx(t, anteHandler, ctx, tx, false, sdkerrors.ErrNoSignatures) // test num sigs dont match GetSigners privs, accNums, seqs = []crypto.PrivKey{priv1}, []uint64{0}, []uint64{0} tx = types.NewTestTx(ctx, msgs, privs, accNums, seqs, fee) - checkInvalidTx(t, anteHandler, ctx, tx, false, sdk.CodeUnauthorized) + checkInvalidTx(t, anteHandler, ctx, tx, false, sdkerrors.ErrUnauthorized) // test an unrecognized account privs, accNums, seqs = []crypto.PrivKey{priv1, priv2, priv3}, []uint64{0, 1, 2}, []uint64{0, 0, 0} tx = types.NewTestTx(ctx, msgs, privs, accNums, seqs, fee) - checkInvalidTx(t, anteHandler, ctx, tx, false, sdk.CodeUnknownAddress) + checkInvalidTx(t, anteHandler, ctx, tx, false, sdkerrors.ErrUnknownAddress) // save the first account, but second is still unrecognized acc1 := app.AccountKeeper.NewAccountWithAddress(ctx, addr1) acc1.SetCoins(fee.Amount) app.AccountKeeper.SetAccount(ctx, acc1) - checkInvalidTx(t, anteHandler, ctx, tx, false, sdk.CodeUnknownAddress) + checkInvalidTx(t, anteHandler, ctx, tx, false, sdkerrors.ErrUnknownAddress) } // Test logic around account number checking with one signer and many signers. @@ -172,7 +169,7 @@ func TestAnteHandlerAccountNumbers(t *testing.T) { // new tx from wrong account number seqs = []uint64{1} tx = types.NewTestTx(ctx, msgs, privs, []uint64{1}, seqs, fee) - checkInvalidTx(t, anteHandler, ctx, tx, false, sdk.CodeUnauthorized) + checkInvalidTx(t, anteHandler, ctx, tx, false, sdkerrors.ErrUnauthorized) // from correct account number seqs = []uint64{1} @@ -185,7 +182,7 @@ func TestAnteHandlerAccountNumbers(t *testing.T) { msgs = []sdk.Msg{msg1, msg2} privs, accnums, seqs = []crypto.PrivKey{priv1, priv2}, []uint64{1, 0}, []uint64{2, 0} tx = types.NewTestTx(ctx, msgs, privs, accnums, seqs, fee) - checkInvalidTx(t, anteHandler, ctx, tx, false, sdk.CodeUnauthorized) + checkInvalidTx(t, anteHandler, ctx, tx, false, sdkerrors.ErrUnauthorized) // correct account numbers privs, accnums, seqs = []crypto.PrivKey{priv1, priv2}, []uint64{0, 1}, []uint64{2, 0} @@ -228,7 +225,7 @@ func TestAnteHandlerAccountNumbersAtBlockHeightZero(t *testing.T) { // new tx from wrong account number seqs = []uint64{1} tx = types.NewTestTx(ctx, msgs, privs, []uint64{1}, seqs, fee) - checkInvalidTx(t, anteHandler, ctx, tx, false, sdk.CodeUnauthorized) + checkInvalidTx(t, anteHandler, ctx, tx, false, sdkerrors.ErrUnauthorized) // from correct account number seqs = []uint64{1} @@ -241,7 +238,7 @@ func TestAnteHandlerAccountNumbersAtBlockHeightZero(t *testing.T) { msgs = []sdk.Msg{msg1, msg2} privs, accnums, seqs = []crypto.PrivKey{priv1, priv2}, []uint64{1, 0}, []uint64{2, 0} tx = types.NewTestTx(ctx, msgs, privs, accnums, seqs, fee) - checkInvalidTx(t, anteHandler, ctx, tx, false, sdk.CodeUnauthorized) + checkInvalidTx(t, anteHandler, ctx, tx, false, sdkerrors.ErrUnauthorized) // correct account numbers privs, accnums, seqs = []crypto.PrivKey{priv1, priv2}, []uint64{0, 0}, []uint64{2, 0} @@ -288,7 +285,7 @@ func TestAnteHandlerSequences(t *testing.T) { checkValidTx(t, anteHandler, ctx, tx, false) // test sending it again fails (replay protection) - checkInvalidTx(t, anteHandler, ctx, tx, false, sdk.CodeUnauthorized) + checkInvalidTx(t, anteHandler, ctx, tx, false, sdkerrors.ErrUnauthorized) // fix sequence, should pass seqs = []uint64{1} @@ -305,14 +302,14 @@ func TestAnteHandlerSequences(t *testing.T) { checkValidTx(t, anteHandler, ctx, tx, false) // replay fails - checkInvalidTx(t, anteHandler, ctx, tx, false, sdk.CodeUnauthorized) + checkInvalidTx(t, anteHandler, ctx, tx, false, sdkerrors.ErrUnauthorized) // tx from just second signer with incorrect sequence fails msg = types.NewTestMsg(addr2) msgs = []sdk.Msg{msg} privs, accnums, seqs = []crypto.PrivKey{priv2}, []uint64{1}, []uint64{0} tx = types.NewTestTx(ctx, msgs, privs, accnums, seqs, fee) - checkInvalidTx(t, anteHandler, ctx, tx, false, sdk.CodeUnauthorized) + checkInvalidTx(t, anteHandler, ctx, tx, false, sdkerrors.ErrUnauthorized) // fix the sequence and it passes tx = types.NewTestTx(ctx, msgs, []crypto.PrivKey{priv2}, []uint64{1}, []uint64{1}, fee) @@ -348,11 +345,11 @@ func TestAnteHandlerFees(t *testing.T) { // signer does not have enough funds to pay the fee tx = types.NewTestTx(ctx, msgs, privs, accnums, seqs, fee) - checkInvalidTx(t, anteHandler, ctx, tx, false, sdk.CodeInsufficientFunds) + checkInvalidTx(t, anteHandler, ctx, tx, false, sdkerrors.ErrInsufficientFunds) acc1.SetCoins(sdk.NewCoins(sdk.NewInt64Coin("atom", 149))) app.AccountKeeper.SetAccount(ctx, acc1) - checkInvalidTx(t, anteHandler, ctx, tx, false, sdk.CodeInsufficientFunds) + checkInvalidTx(t, anteHandler, ctx, tx, false, sdkerrors.ErrInsufficientFunds) require.True(t, app.SupplyKeeper.GetModuleAccount(ctx, types.FeeCollectorName).GetCoins().Empty()) require.True(sdk.IntEq(t, app.AccountKeeper.GetAccount(ctx, addr1).GetCoins().AmountOf("atom"), sdk.NewInt(149))) @@ -388,17 +385,17 @@ func TestAnteHandlerMemoGas(t *testing.T) { // tx does not have enough gas tx = types.NewTestTx(ctx, []sdk.Msg{msg}, privs, accnums, seqs, fee) - checkInvalidTx(t, anteHandler, ctx, tx, false, sdk.CodeOutOfGas) + checkInvalidTx(t, anteHandler, ctx, tx, false, sdkerrors.ErrOutOfGas) // tx with memo doesn't have enough gas fee = types.NewStdFee(801, sdk.NewCoins(sdk.NewInt64Coin("atom", 0))) tx = types.NewTestTxWithMemo(ctx, []sdk.Msg{msg}, privs, accnums, seqs, fee, "abcininasidniandsinasindiansdiansdinaisndiasndiadninsd") - checkInvalidTx(t, anteHandler, ctx, tx, false, sdk.CodeOutOfGas) + checkInvalidTx(t, anteHandler, ctx, tx, false, sdkerrors.ErrOutOfGas) // memo too large fee = types.NewStdFee(50000, sdk.NewCoins(sdk.NewInt64Coin("atom", 0))) tx = types.NewTestTxWithMemo(ctx, []sdk.Msg{msg}, privs, accnums, seqs, fee, strings.Repeat("01234567890", 500)) - checkInvalidTx(t, anteHandler, ctx, tx, false, sdk.CodeMemoTooLarge) + checkInvalidTx(t, anteHandler, ctx, tx, false, sdkerrors.ErrMemoTooLarge) // tx with memo has enough gas fee = types.NewStdFee(50000, sdk.NewCoins(sdk.NewInt64Coin("atom", 0))) @@ -492,7 +489,7 @@ func TestAnteHandlerBadSignBytes(t *testing.T) { chainID := ctx.ChainID() chainID2 := chainID + "somemorestuff" - codeUnauth := sdk.CodeUnauthorized + errUnauth := sdkerrors.ErrUnauthorized cases := []struct { chainID string @@ -500,14 +497,14 @@ func TestAnteHandlerBadSignBytes(t *testing.T) { seq uint64 fee types.StdFee msgs []sdk.Msg - code sdk.CodeType + err error }{ - {chainID2, 0, 1, fee, msgs, codeUnauth}, // test wrong chain_id - {chainID, 0, 2, fee, msgs, codeUnauth}, // test wrong seqs - {chainID, 1, 1, fee, msgs, codeUnauth}, // test wrong accnum - {chainID, 0, 1, fee, []sdk.Msg{types.NewTestMsg(addr2)}, codeUnauth}, // test wrong msg - {chainID, 0, 1, fee2, msgs, codeUnauth}, // test wrong fee - {chainID, 0, 1, fee3, msgs, codeUnauth}, // test wrong fee + {chainID2, 0, 1, fee, msgs, errUnauth}, // test wrong chain_id + {chainID, 0, 2, fee, msgs, errUnauth}, // test wrong seqs + {chainID, 1, 1, fee, msgs, errUnauth}, // test wrong accnum + {chainID, 0, 1, fee, []sdk.Msg{types.NewTestMsg(addr2)}, errUnauth}, // test wrong msg + {chainID, 0, 1, fee2, msgs, errUnauth}, // test wrong fee + {chainID, 0, 1, fee3, msgs, errUnauth}, // test wrong fee } privs, seqs = []crypto.PrivKey{priv1}, []uint64{1} @@ -517,20 +514,20 @@ func TestAnteHandlerBadSignBytes(t *testing.T) { types.StdSignBytes(cs.chainID, cs.accnum, cs.seq, cs.fee, cs.msgs, ""), "", ) - checkInvalidTx(t, anteHandler, ctx, tx, false, cs.code) + checkInvalidTx(t, anteHandler, ctx, tx, false, cs.err) } // test wrong signer if public key exist privs, accnums, seqs = []crypto.PrivKey{priv2}, []uint64{0}, []uint64{1} tx = types.NewTestTx(ctx, msgs, privs, accnums, seqs, fee) - checkInvalidTx(t, anteHandler, ctx, tx, false, sdk.CodeInvalidPubKey) + checkInvalidTx(t, anteHandler, ctx, tx, false, sdkerrors.ErrInvalidPubKey) // test wrong signer if public doesn't exist msg = types.NewTestMsg(addr2) msgs = []sdk.Msg{msg} privs, accnums, seqs = []crypto.PrivKey{priv1}, []uint64{1}, []uint64{0} tx = types.NewTestTx(ctx, msgs, privs, accnums, seqs, fee) - checkInvalidTx(t, anteHandler, ctx, tx, false, sdk.CodeInvalidPubKey) + checkInvalidTx(t, anteHandler, ctx, tx, false, sdkerrors.ErrInvalidPubKey) } func TestAnteHandlerSetPubKey(t *testing.T) { @@ -572,14 +569,14 @@ func TestAnteHandlerSetPubKey(t *testing.T) { tx = types.NewTestTx(ctx, msgs, privs, []uint64{1}, seqs, fee) sigs := tx.(types.StdTx).Signatures sigs[0].PubKey = nil - checkInvalidTx(t, anteHandler, ctx, tx, false, sdk.CodeInvalidPubKey) + checkInvalidTx(t, anteHandler, ctx, tx, false, sdkerrors.ErrInvalidPubKey) acc2 = app.AccountKeeper.GetAccount(ctx, addr2) require.Nil(t, acc2.GetPubKey()) // test invalid signature and public key tx = types.NewTestTx(ctx, msgs, privs, []uint64{1}, seqs, fee) - checkInvalidTx(t, anteHandler, ctx, tx, false, sdk.CodeInvalidPubKey) + checkInvalidTx(t, anteHandler, ctx, tx, false, sdkerrors.ErrInvalidPubKey) acc2 = app.AccountKeeper.GetAccount(ctx, addr2) require.Nil(t, acc2.GetPubKey()) @@ -686,7 +683,7 @@ func TestAnteHandlerSigLimitExceeded(t *testing.T) { privs, accnums, seqs := []crypto.PrivKey{priv1, priv2, priv3, priv4, priv5, priv6, priv7, priv8}, []uint64{0, 1, 2, 3, 4, 5, 6, 7}, []uint64{0, 0, 0, 0, 0, 0, 0, 0} tx = types.NewTestTx(ctx, msgs, privs, accnums, seqs, fee) - checkInvalidTx(t, anteHandler, ctx, tx, false, sdk.CodeTooManySignatures) + checkInvalidTx(t, anteHandler, ctx, tx, false, sdkerrors.ErrTooManySignatures) } // Test custom SignatureVerificationGasConsumer @@ -717,7 +714,7 @@ func TestCustomSignatureVerificationGasConsumer(t *testing.T) { fee := types.NewTestStdFee() msgs := []sdk.Msg{msg} tx = types.NewTestTx(ctx, msgs, privs, accnums, seqs, fee) - checkInvalidTx(t, anteHandler, ctx, tx, false, sdk.CodeInvalidPubKey) + checkInvalidTx(t, anteHandler, ctx, tx, false, sdkerrors.ErrInvalidPubKey) // verify that an ed25519 account gets accepted priv2 := ed25519.GenPrivKey() diff --git a/x/auth/client/cli/decode.go b/x/auth/client/cli/decode.go index 370f4fe72d7f..c9253d8fb4a3 100644 --- a/x/auth/client/cli/decode.go +++ b/x/auth/client/cli/decode.go @@ -1,98 +1,54 @@ package cli import ( - "bytes" "encoding/base64" "encoding/hex" - "encoding/json" - "fmt" "github.com/spf13/cobra" + "github.com/spf13/viper" "github.com/tendermint/go-amino" - "github.com/cosmos/cosmos-sdk/client" "github.com/cosmos/cosmos-sdk/client/context" - "github.com/cosmos/cosmos-sdk/codec" - "github.com/cosmos/cosmos-sdk/version" - "github.com/cosmos/cosmos-sdk/x/auth/types" + "github.com/cosmos/cosmos-sdk/client/flags" authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" ) +const flagHex = "hex" + // GetDecodeCommand returns the decode command to take Amino-serialized bytes // and turn it into a JSONified transaction. func GetDecodeCommand(codec *amino.Codec) *cobra.Command { cmd := &cobra.Command{ Use: "decode [amino-byte-string]", - Short: "Decode an amino-encoded transaction string", + Short: "Decode an amino-encoded transaction string.", Args: cobra.ExactArgs(1), - RunE: func(cmd *cobra.Command, args []string) (err error) { - cliCtx := context.NewCLIContext().WithCodec(codec) - - txBytes, err := base64.StdEncoding.DecodeString(args[0]) - if err != nil { - return err - } - - var stdTx authtypes.StdTx - err = cliCtx.Codec.UnmarshalBinaryLengthPrefixed(txBytes, &stdTx) - if err != nil { - return err - } - - return cliCtx.PrintOutput(stdTx) - }, + RunE: runDecodeTxString(codec), } - return client.PostCommands(cmd)[0] + cmd.Flags().BoolP(flagHex, "x", false, "Treat input as hexadecimal instead of base64") + return flags.PostCommands(cmd)[0] } -// GetDecodeTxCmd - returns the command to decode a tx from hex or base64 -func GetDecodeTxCmd(cdc *codec.Codec) *cobra.Command { - return &cobra.Command{ - Use: "decode-tx [tx]", - Short: "Decode a tx from hex or base64", - Long: fmt.Sprintf(`Decode a tx from hex, base64. - -Example: - $ %s tx decode-tx TWFuIGlzIGRpc3Rpbmd1aXNoZWQsIG5vdCBvbmx5IGJ5IGhpcyByZWFzb24sIGJ1dCBieSB0aGlz - `, version.ClientName), - Args: cobra.ExactArgs(1), - RunE: func(cmd *cobra.Command, args []string) error { - - txString := args[0] - - // try hex, then base64 - txBytes, err := hex.DecodeString(txString) - if err != nil { - var err2 error - txBytes, err2 = base64.StdEncoding.DecodeString(txString) - if err2 != nil { - return fmt.Errorf(`expected hex or base64. Got errors: - hex: %v, - base64: %v - `, err, err2) - } - } - - var tx = types.StdTx{} - - err = cdc.UnmarshalBinaryLengthPrefixed(txBytes, &tx) - if err != nil { - return err - } - - bz, err := cdc.MarshalJSON(tx) - if err != nil { - return err - } - - buf := bytes.NewBuffer([]byte{}) - if err = json.Indent(buf, bz, "", " "); err != nil { - return err - } - - fmt.Println(buf.String()) - return nil - }, +func runDecodeTxString(codec *amino.Codec) func(cmd *cobra.Command, args []string) (err error) { + return func(cmd *cobra.Command, args []string) (err error) { + cliCtx := context.NewCLIContext().WithCodec(codec).WithOutput(cmd.OutOrStdout()) + var txBytes []byte + + if viper.GetBool(flagHex) { + txBytes, err = hex.DecodeString(args[0]) + } else { + txBytes, err = base64.StdEncoding.DecodeString(args[0]) + } + if err != nil { + return err + } + + var stdTx authtypes.StdTx + err = cliCtx.Codec.UnmarshalBinaryLengthPrefixed(txBytes, &stdTx) + if err != nil { + return err + } + + return cliCtx.PrintOutput(stdTx) } } diff --git a/x/auth/client/rest/query.go b/x/auth/client/rest/query.go index be094b6c69a4..77cba3e59c1e 100644 --- a/x/auth/client/rest/query.go +++ b/x/auth/client/rest/query.go @@ -61,8 +61,10 @@ func QueryTxsRequestHandlerFn(cliCtx context.CLIContext) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { err := r.ParseForm() if err != nil { - rest.WriteErrorResponse(w, http.StatusBadRequest, - sdk.AppendMsgToErr("could not parse query parameters", err.Error())) + rest.WriteErrorResponse( + w, http.StatusBadRequest, + fmt.Sprintf("failed to parse query parameters: %s", err), + ) return } diff --git a/x/auth/client/utils/tx.go b/x/auth/client/utils/tx.go index ba8c81d59262..e6a038f24cb7 100644 --- a/x/auth/client/utils/tx.go +++ b/x/auth/client/utils/tx.go @@ -10,10 +10,10 @@ import ( "github.com/pkg/errors" "github.com/spf13/viper" - "github.com/cosmos/cosmos-sdk/client" "github.com/cosmos/cosmos-sdk/client/context" "github.com/cosmos/cosmos-sdk/client/flags" "github.com/cosmos/cosmos-sdk/client/input" + "github.com/cosmos/cosmos-sdk/client/keys" "github.com/cosmos/cosmos-sdk/codec" sdk "github.com/cosmos/cosmos-sdk/types" authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" @@ -94,7 +94,7 @@ func CompleteAndBroadcastTxCLI(txBldr authtypes.TxBuilder, cliCtx context.CLICon } // build and sign the transaction - txBytes, err := txBldr.BuildAndSign(fromName, client.DefaultKeyPass, msgs) + txBytes, err := txBldr.BuildAndSign(fromName, keys.DefaultKeyPass, msgs) if err != nil { return err } @@ -231,7 +231,7 @@ func SignStdTx( } } - return txBldr.SignStdTx(name, client.DefaultKeyPass, stdTx, appendSig) + return txBldr.SignStdTx(name, keys.DefaultKeyPass, stdTx, appendSig) } // SignStdTxWithSignerAddress attaches a signature to a StdTx and returns a copy of a it. @@ -253,7 +253,7 @@ func SignStdTxWithSignerAddress(txBldr authtypes.TxBuilder, cliCtx context.CLICo } } - return txBldr.SignStdTx(name, client.DefaultKeyPass, stdTx, false) + return txBldr.SignStdTx(name, keys.DefaultKeyPass, stdTx, false) } // Read and decode a StdTx from the given filename. Can pass "-" to read from stdin. @@ -317,12 +317,12 @@ func adjustGasEstimate(estimate uint64, adjustment float64) uint64 { } func parseQueryResponse(cdc *codec.Codec, rawRes []byte) (uint64, error) { - var simulationResult sdk.Result - if err := cdc.UnmarshalBinaryLengthPrefixed(rawRes, &simulationResult); err != nil { + var gasUsed uint64 + if err := cdc.UnmarshalBinaryLengthPrefixed(rawRes, &gasUsed); err != nil { return 0, err } - return simulationResult.GasUsed, nil + return gasUsed, nil } // PrepareTxBuilder populates a TxBuilder in preparation for the build of a Tx. diff --git a/x/auth/client/utils/tx_test.go b/x/auth/client/utils/tx_test.go index cde10cc56029..a9c33b232053 100644 --- a/x/auth/client/utils/tx_test.go +++ b/x/auth/client/utils/tx_test.go @@ -23,7 +23,7 @@ var ( func TestParseQueryResponse(t *testing.T) { cdc := makeCodec() - sdkResBytes := cdc.MustMarshalBinaryLengthPrefixed(sdk.Result{GasUsed: 10}) + sdkResBytes := cdc.MustMarshalBinaryLengthPrefixed(uint64(10)) gas, err := parseQueryResponse(cdc, sdkResBytes) assert.Equal(t, gas, uint64(10)) assert.Nil(t, err) @@ -39,14 +39,16 @@ func TestCalculateGas(t *testing.T) { if wantErr { return nil, 0, errors.New("") } - return cdc.MustMarshalBinaryLengthPrefixed(sdk.Result{GasUsed: gasUsed}), 0, nil + return cdc.MustMarshalBinaryLengthPrefixed(gasUsed), 0, nil } } + type args struct { queryFuncGasUsed uint64 queryFuncWantErr bool adjustment float64 } + tests := []struct { name string args args @@ -57,6 +59,7 @@ func TestCalculateGas(t *testing.T) { {"error", args{0, true, 1.2}, 0, 0, true}, {"adjusted gas", args{10, false, 1.2}, 10, 12, false}, } + for _, tt := range tests { tt := tt t.Run(tt.name, func(t *testing.T) { diff --git a/x/auth/keeper/keeper.go b/x/auth/keeper/keeper.go index d60a396d342b..244dec7c193b 100644 --- a/x/auth/keeper/keeper.go +++ b/x/auth/keeper/keeper.go @@ -8,6 +8,7 @@ import ( "github.com/cosmos/cosmos-sdk/codec" sdk "github.com/cosmos/cosmos-sdk/types" + sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" "github.com/cosmos/cosmos-sdk/x/auth/exported" "github.com/cosmos/cosmos-sdk/x/auth/types" "github.com/cosmos/cosmos-sdk/x/params/subspace" @@ -49,19 +50,19 @@ func (ak AccountKeeper) Logger(ctx sdk.Context) log.Logger { } // GetPubKey Returns the PubKey of the account at address -func (ak AccountKeeper) GetPubKey(ctx sdk.Context, addr sdk.AccAddress) (crypto.PubKey, sdk.Error) { +func (ak AccountKeeper) GetPubKey(ctx sdk.Context, addr sdk.AccAddress) (crypto.PubKey, error) { acc := ak.GetAccount(ctx, addr) if acc == nil { - return nil, sdk.ErrUnknownAddress(fmt.Sprintf("account %s does not exist", addr)) + return nil, sdkerrors.Wrapf(sdkerrors.ErrUnknownAddress, "account %s does not exist", addr) } return acc.GetPubKey(), nil } // GetSequence Returns the Sequence of the account at address -func (ak AccountKeeper) GetSequence(ctx sdk.Context, addr sdk.AccAddress) (uint64, sdk.Error) { +func (ak AccountKeeper) GetSequence(ctx sdk.Context, addr sdk.AccAddress) (uint64, error) { acc := ak.GetAccount(ctx, addr) if acc == nil { - return 0, sdk.ErrUnknownAddress(fmt.Sprintf("account %s does not exist", addr)) + return 0, sdkerrors.Wrapf(sdkerrors.ErrUnknownAddress, "account %s does not exist", addr) } return acc.GetSequence(), nil } diff --git a/x/auth/keeper/querier.go b/x/auth/keeper/querier.go index b40dc0135d8f..28e505970b45 100644 --- a/x/auth/keeper/querier.go +++ b/x/auth/keeper/querier.go @@ -1,41 +1,40 @@ package keeper import ( - "fmt" - abci "github.com/tendermint/tendermint/abci/types" "github.com/cosmos/cosmos-sdk/codec" sdk "github.com/cosmos/cosmos-sdk/types" + sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" "github.com/cosmos/cosmos-sdk/x/auth/types" ) // NewQuerier creates a querier for auth REST endpoints func NewQuerier(keeper AccountKeeper) sdk.Querier { - return func(ctx sdk.Context, path []string, req abci.RequestQuery) ([]byte, sdk.Error) { + return func(ctx sdk.Context, path []string, req abci.RequestQuery) ([]byte, error) { switch path[0] { case types.QueryAccount: return queryAccount(ctx, req, keeper) default: - return nil, sdk.ErrUnknownRequest("unknown auth query endpoint") + return nil, sdkerrors.Wrapf(sdkerrors.ErrUnknownRequest, "unknown query path: %s", path[0]) } } } -func queryAccount(ctx sdk.Context, req abci.RequestQuery, keeper AccountKeeper) ([]byte, sdk.Error) { +func queryAccount(ctx sdk.Context, req abci.RequestQuery, keeper AccountKeeper) ([]byte, error) { var params types.QueryAccountParams if err := keeper.cdc.UnmarshalJSON(req.Data, ¶ms); err != nil { - return nil, sdk.ErrInternal(fmt.Sprintf("failed to parse params: %s", err)) + return nil, sdkerrors.Wrap(sdkerrors.ErrJSONUnmarshal, err.Error()) } account := keeper.GetAccount(ctx, params.Address) if account == nil { - return nil, sdk.ErrUnknownAddress(fmt.Sprintf("account %s does not exist", params.Address)) + return nil, sdkerrors.Wrapf(sdkerrors.ErrUnknownAddress, "account %s does not exist", params.Address) } bz, err := codec.MarshalJSONIndent(keeper.cdc, account) if err != nil { - return nil, sdk.ErrInternal(sdk.AppendMsgToErr("could not marshal result to JSON", err.Error())) + return nil, sdkerrors.Wrap(sdkerrors.ErrJSONMarshal, err.Error()) } return bz, nil diff --git a/x/auth/types/expected_keepers.go b/x/auth/types/expected_keepers.go index 11e03ef36cb8..499bc288c849 100644 --- a/x/auth/types/expected_keepers.go +++ b/x/auth/types/expected_keepers.go @@ -7,7 +7,7 @@ import ( // SupplyKeeper defines the expected supply Keeper (noalias) type SupplyKeeper interface { - SendCoinsFromAccountToModule(ctx sdk.Context, senderAddr sdk.AccAddress, recipientModule string, amt sdk.Coins) sdk.Error + SendCoinsFromAccountToModule(ctx sdk.Context, senderAddr sdk.AccAddress, recipientModule string, amt sdk.Coins) error GetModuleAccount(ctx sdk.Context, moduleName string) exported.ModuleAccountI GetModuleAddress(moduleName string) sdk.AccAddress } diff --git a/x/auth/types/stdtx.go b/x/auth/types/stdtx.go index fa8b5d100d5f..bc6042abbbb2 100644 --- a/x/auth/types/stdtx.go +++ b/x/auth/types/stdtx.go @@ -10,6 +10,7 @@ import ( "github.com/cosmos/cosmos-sdk/codec" sdk "github.com/cosmos/cosmos-sdk/types" + sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" "github.com/cosmos/cosmos-sdk/x/auth/exported" ) @@ -42,20 +43,29 @@ func (tx StdTx) GetMsgs() []sdk.Msg { return tx.Msgs } // ValidateBasic does a simple and lightweight validation check that doesn't // require access to any other information. -func (tx StdTx) ValidateBasic() sdk.Error { +func (tx StdTx) ValidateBasic() error { stdSigs := tx.GetSignatures() if tx.Fee.Gas > maxGasWanted { - return sdk.ErrGasOverflow(fmt.Sprintf("invalid gas supplied; %d > %d", tx.Fee.Gas, maxGasWanted)) + return sdkerrors.Wrapf( + sdkerrors.ErrInvalidRequest, + "invalid gas supplied; %d > %d", tx.Fee.Gas, maxGasWanted, + ) } if tx.Fee.Amount.IsAnyNegative() { - return sdk.ErrInsufficientFee(fmt.Sprintf("invalid fee %s amount provided", tx.Fee.Amount)) + return sdkerrors.Wrapf( + sdkerrors.ErrInsufficientFee, + "invalid fee provided: %s", tx.Fee.Amount, + ) } if len(stdSigs) == 0 { - return sdk.ErrNoSignatures("no signers") + return sdkerrors.ErrNoSignatures } if len(stdSigs) != len(tx.GetSigners()) { - return sdk.ErrUnauthorized("wrong number of signers") + return sdkerrors.Wrapf( + sdkerrors.ErrUnauthorized, + "wrong number of signers; expected %d, got %d", tx.GetSigners(), len(stdSigs), + ) } return nil @@ -240,18 +250,18 @@ type StdSignature struct { // DefaultTxDecoder logic for standard transaction decoding func DefaultTxDecoder(cdc *codec.Codec) sdk.TxDecoder { - return func(txBytes []byte) (sdk.Tx, sdk.Error) { + return func(txBytes []byte) (sdk.Tx, error) { var tx = StdTx{} if len(txBytes) == 0 { - return nil, sdk.ErrTxDecode("txBytes are empty") + return nil, sdkerrors.Wrap(sdkerrors.ErrTxDecode, "tx bytes are empty") } // StdTx.Msg is an interface. The concrete types // are registered by MakeTxCodec err := cdc.UnmarshalBinaryLengthPrefixed(txBytes, &tx) if err != nil { - return nil, sdk.ErrTxDecode("error decoding transaction").TraceSDK(err.Error()) + return nil, sdkerrors.Wrap(sdkerrors.ErrTxDecode, err.Error()) } return tx, nil diff --git a/x/auth/types/stdtx_test.go b/x/auth/types/stdtx_test.go index 375a15c49cc4..8131006f59d5 100644 --- a/x/auth/types/stdtx_test.go +++ b/x/auth/types/stdtx_test.go @@ -13,6 +13,7 @@ import ( "github.com/cosmos/cosmos-sdk/codec" sdk "github.com/cosmos/cosmos-sdk/types" + sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" ) var ( @@ -78,7 +79,8 @@ func TestTxValidateBasic(t *testing.T) { err := tx.ValidateBasic() require.Error(t, err) - require.Equal(t, sdk.CodeInsufficientFee, err.Result().Code) + _, code, _ := sdkerrors.ABCIInfo(err, false) + require.Equal(t, sdkerrors.ErrInsufficientFee.ABCICode(), code) // require to fail validation when no signatures exist privs, accNums, seqs := []crypto.PrivKey{}, []uint64{}, []uint64{} @@ -86,7 +88,8 @@ func TestTxValidateBasic(t *testing.T) { err = tx.ValidateBasic() require.Error(t, err) - require.Equal(t, sdk.CodeNoSignatures, err.Result().Code) + _, code, _ = sdkerrors.ABCIInfo(err, false) + require.Equal(t, sdkerrors.ErrNoSignatures.ABCICode(), code) // require to fail validation when signatures do not match expected signers privs, accNums, seqs = []crypto.PrivKey{priv1}, []uint64{0, 1}, []uint64{0, 0} @@ -94,7 +97,8 @@ func TestTxValidateBasic(t *testing.T) { err = tx.ValidateBasic() require.Error(t, err) - require.Equal(t, sdk.CodeUnauthorized, err.Result().Code) + _, code, _ = sdkerrors.ABCIInfo(err, false) + require.Equal(t, sdkerrors.ErrUnauthorized.ABCICode(), code) // require to fail with invalid gas supplied badFee = NewTestStdFee() @@ -103,7 +107,8 @@ func TestTxValidateBasic(t *testing.T) { err = tx.ValidateBasic() require.Error(t, err) - require.Equal(t, sdk.CodeGasOverflow, err.Result().Code) + _, code, _ = sdkerrors.ABCIInfo(err, false) + require.Equal(t, sdkerrors.ErrInvalidRequest.ABCICode(), code) // require to pass when above criteria are matched privs, accNums, seqs = []crypto.PrivKey{priv1, priv2}, []uint64{0, 1}, []uint64{0, 0} diff --git a/x/bank/alias.go b/x/bank/alias.go index 3533e3084d9d..1ac7cecebd90 100644 --- a/x/bank/alias.go +++ b/x/bank/alias.go @@ -1,25 +1,19 @@ -// nolint -// autogenerated code using github.com/rigelrozanski/multitool -// aliases generated for the following subdirectories: -// ALIASGEN: github.com/cosmos/cosmos-sdk/x/bank/internal/keeper -// ALIASGEN: github.com/cosmos/cosmos-sdk/x/bank/internal/types package bank +// nolint + import ( "github.com/cosmos/cosmos-sdk/x/bank/internal/keeper" "github.com/cosmos/cosmos-sdk/x/bank/internal/types" ) const ( - QueryBalance = keeper.QueryBalance - DefaultCodespace = types.DefaultCodespace - CodeSendDisabled = types.CodeSendDisabled - CodeInvalidInputsOutputs = types.CodeInvalidInputsOutputs - ModuleName = types.ModuleName - QuerierRoute = types.QuerierRoute - RouterKey = types.RouterKey - DefaultParamspace = types.DefaultParamspace - DefaultSendEnabled = types.DefaultSendEnabled + QueryBalance = keeper.QueryBalance + ModuleName = types.ModuleName + QuerierRoute = types.QuerierRoute + RouterKey = types.RouterKey + DefaultParamspace = types.DefaultParamspace + DefaultSendEnabled = types.DefaultSendEnabled EventTypeTransfer = types.EventTypeTransfer AttributeKeyRecipient = types.AttributeKeyRecipient @@ -28,7 +22,6 @@ const ( ) var ( - // functions aliases RegisterInvariants = keeper.RegisterInvariants NonnegativeBalanceInvariant = keeper.NonnegativeBalanceInvariant NewBaseKeeper = keeper.NewBaseKeeper @@ -50,10 +43,8 @@ var ( ValidateInputsOutputs = types.ValidateInputsOutputs ParamKeyTable = types.ParamKeyTable NewQueryBalanceParams = types.NewQueryBalanceParams - - // variable aliases - ModuleCdc = types.ModuleCdc - ParamStoreKeySendEnabled = types.ParamStoreKeySendEnabled + ModuleCdc = types.ModuleCdc + ParamStoreKeySendEnabled = types.ParamStoreKeySendEnabled ) type ( diff --git a/x/bank/bench_test.go b/x/bank/bench_test.go index 9e0bd735484d..9161a88c31ba 100644 --- a/x/bank/bench_test.go +++ b/x/bank/bench_test.go @@ -34,10 +34,11 @@ func BenchmarkOneBankSendTxPerBlock(b *testing.B) { // Committing, and what time comes from Check/Deliver Tx. for i := 0; i < b.N; i++ { benchmarkApp.BeginBlock(abci.RequestBeginBlock{}) - x := benchmarkApp.Check(txs[i]) - if !x.IsOK() { + _, _, err := benchmarkApp.Check(txs[i]) + if err != nil { panic("something is broken in checking transaction") } + benchmarkApp.Deliver(txs[i]) benchmarkApp.EndBlock(abci.RequestEndBlock{}) benchmarkApp.Commit() @@ -63,10 +64,11 @@ func BenchmarkOneBankMultiSendTxPerBlock(b *testing.B) { // Committing, and what time comes from Check/Deliver Tx. for i := 0; i < b.N; i++ { benchmarkApp.BeginBlock(abci.RequestBeginBlock{}) - x := benchmarkApp.Check(txs[i]) - if !x.IsOK() { + _, _, err := benchmarkApp.Check(txs[i]) + if err != nil { panic("something is broken in checking transaction") } + benchmarkApp.Deliver(txs[i]) benchmarkApp.EndBlock(abci.RequestEndBlock{}) benchmarkApp.Commit() diff --git a/x/bank/client/cli/tx.go b/x/bank/client/cli/tx.go index 71e1392b968a..58bce19eba6f 100644 --- a/x/bank/client/cli/tx.go +++ b/x/bank/client/cli/tx.go @@ -7,6 +7,7 @@ import ( "github.com/cosmos/cosmos-sdk/client" "github.com/cosmos/cosmos-sdk/client/context" + "github.com/cosmos/cosmos-sdk/client/flags" "github.com/cosmos/cosmos-sdk/codec" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/x/auth" @@ -57,7 +58,7 @@ func SendTxCmd(cdc *codec.Codec) *cobra.Command { }, } - cmd = client.PostCommands(cmd)[0] + cmd = flags.PostCommands(cmd)[0] return cmd } diff --git a/x/bank/handler.go b/x/bank/handler.go index 8e6133347715..3c83ec4c2af4 100644 --- a/x/bank/handler.go +++ b/x/bank/handler.go @@ -1,16 +1,15 @@ package bank import ( - "fmt" - sdk "github.com/cosmos/cosmos-sdk/types" + sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" "github.com/cosmos/cosmos-sdk/x/bank/internal/keeper" "github.com/cosmos/cosmos-sdk/x/bank/internal/types" ) // NewHandler returns a handler for "bank" type messages. func NewHandler(k keeper.Keeper) sdk.Handler { - return func(ctx sdk.Context, msg sdk.Msg) sdk.Result { + return func(ctx sdk.Context, msg sdk.Msg) (*sdk.Result, error) { ctx = ctx.WithEventManager(sdk.NewEventManager()) switch msg := msg.(type) { @@ -21,25 +20,24 @@ func NewHandler(k keeper.Keeper) sdk.Handler { return handleMsgMultiSend(ctx, k, msg) default: - errMsg := fmt.Sprintf("unrecognized bank message type: %T", msg) - return sdk.ErrUnknownRequest(errMsg).Result() + return nil, sdkerrors.Wrapf(sdkerrors.ErrUnknownRequest, "unrecognized bank message type: %T", msg) } } } // Handle MsgSend. -func handleMsgSend(ctx sdk.Context, k keeper.Keeper, msg types.MsgSend) sdk.Result { +func handleMsgSend(ctx sdk.Context, k keeper.Keeper, msg types.MsgSend) (*sdk.Result, error) { if !k.GetSendEnabled(ctx) { - return types.ErrSendDisabled(k.Codespace()).Result() + return nil, types.ErrSendDisabled } if k.BlacklistedAddr(msg.ToAddress) { - return sdk.ErrUnauthorized(fmt.Sprintf("%s is not allowed to receive transactions", msg.ToAddress)).Result() + return nil, sdkerrors.Wrapf(sdkerrors.ErrUnauthorized, "%s is not allowed to receive transactions", msg.ToAddress) } err := k.SendCoins(ctx, msg.FromAddress, msg.ToAddress, msg.Amount) if err != nil { - return err.Result() + return nil, err } ctx.EventManager().EmitEvent( @@ -49,25 +47,25 @@ func handleMsgSend(ctx sdk.Context, k keeper.Keeper, msg types.MsgSend) sdk.Resu ), ) - return sdk.Result{Events: ctx.EventManager().Events()} + return &sdk.Result{Events: ctx.EventManager().Events()}, nil } // Handle MsgMultiSend. -func handleMsgMultiSend(ctx sdk.Context, k keeper.Keeper, msg types.MsgMultiSend) sdk.Result { +func handleMsgMultiSend(ctx sdk.Context, k keeper.Keeper, msg types.MsgMultiSend) (*sdk.Result, error) { // NOTE: totalIn == totalOut should already have been checked if !k.GetSendEnabled(ctx) { - return types.ErrSendDisabled(k.Codespace()).Result() + return nil, types.ErrSendDisabled } for _, out := range msg.Outputs { if k.BlacklistedAddr(out.Address) { - return sdk.ErrUnauthorized(fmt.Sprintf("%s is not allowed to receive transactions", out.Address)).Result() + return nil, sdkerrors.Wrapf(sdkerrors.ErrUnauthorized, "%s is not allowed to receive transactions", out.Address) } } err := k.InputOutputCoins(ctx, msg.Inputs, msg.Outputs) if err != nil { - return err.Result() + return nil, err } ctx.EventManager().EmitEvent( @@ -77,5 +75,5 @@ func handleMsgMultiSend(ctx sdk.Context, k keeper.Keeper, msg types.MsgMultiSend ), ) - return sdk.Result{Events: ctx.EventManager().Events()} + return &sdk.Result{Events: ctx.EventManager().Events()}, nil } diff --git a/x/bank/handler_test.go b/x/bank/handler_test.go index 457afc8e69d9..f9d313385f0a 100644 --- a/x/bank/handler_test.go +++ b/x/bank/handler_test.go @@ -4,17 +4,20 @@ import ( "strings" "testing" + "github.com/stretchr/testify/require" abci "github.com/tendermint/tendermint/abci/types" sdk "github.com/cosmos/cosmos-sdk/types" - - "github.com/stretchr/testify/require" + sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" ) func TestInvalidMsg(t *testing.T) { h := NewHandler(nil) - res := h(sdk.NewContext(nil, abci.Header{}, false, nil), sdk.NewTestMsg()) - require.False(t, res.IsOK()) - require.True(t, strings.Contains(res.Log, "unrecognized bank message type")) + res, err := h(sdk.NewContext(nil, abci.Header{}, false, nil), sdk.NewTestMsg()) + require.Error(t, err) + require.Nil(t, res) + + _, _, log := sdkerrors.ABCIInfo(err, false) + require.True(t, strings.Contains(log, "unrecognized bank message type")) } diff --git a/x/bank/internal/keeper/keeper.go b/x/bank/internal/keeper/keeper.go index cd0242e23f17..f36477f3c3b1 100644 --- a/x/bank/internal/keeper/keeper.go +++ b/x/bank/internal/keeper/keeper.go @@ -7,6 +7,7 @@ import ( "github.com/tendermint/tendermint/libs/log" sdk "github.com/cosmos/cosmos-sdk/types" + sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" authexported "github.com/cosmos/cosmos-sdk/x/auth/exported" vestexported "github.com/cosmos/cosmos-sdk/x/auth/vesting/exported" "github.com/cosmos/cosmos-sdk/x/bank/internal/types" @@ -20,8 +21,8 @@ var _ Keeper = (*BaseKeeper)(nil) type Keeper interface { SendKeeper - DelegateCoins(ctx sdk.Context, delegatorAddr, moduleAccAddr sdk.AccAddress, amt sdk.Coins) sdk.Error - UndelegateCoins(ctx sdk.Context, moduleAccAddr, delegatorAddr sdk.AccAddress, amt sdk.Coins) sdk.Error + DelegateCoins(ctx sdk.Context, delegatorAddr, moduleAccAddr sdk.AccAddress, amt sdk.Coins) error + UndelegateCoins(ctx sdk.Context, moduleAccAddr, delegatorAddr sdk.AccAddress, amt sdk.Coins) error } // BaseKeeper manages transfers between accounts. It implements the Keeper interface. @@ -33,13 +34,13 @@ type BaseKeeper struct { } // NewBaseKeeper returns a new BaseKeeper -func NewBaseKeeper(ak types.AccountKeeper, - paramSpace params.Subspace, - codespace sdk.CodespaceType, blacklistedAddrs map[string]bool) BaseKeeper { +func NewBaseKeeper( + ak types.AccountKeeper, paramSpace params.Subspace, blacklistedAddrs map[string]bool, +) BaseKeeper { ps := paramSpace.WithKeyTable(types.ParamKeyTable()) return BaseKeeper{ - BaseSendKeeper: NewBaseSendKeeper(ak, ps, codespace, blacklistedAddrs), + BaseSendKeeper: NewBaseSendKeeper(ak, ps, blacklistedAddrs), ak: ak, paramSpace: ps, } @@ -50,33 +51,32 @@ func NewBaseKeeper(ak types.AccountKeeper, // vesting and vested coins. // The coins are then transferred from the delegator address to a ModuleAccount address. // If any of the delegation amounts are negative, an error is returned. -func (keeper BaseKeeper) DelegateCoins(ctx sdk.Context, delegatorAddr, moduleAccAddr sdk.AccAddress, amt sdk.Coins) sdk.Error { - +func (keeper BaseKeeper) DelegateCoins(ctx sdk.Context, delegatorAddr, moduleAccAddr sdk.AccAddress, amt sdk.Coins) error { delegatorAcc := keeper.ak.GetAccount(ctx, delegatorAddr) if delegatorAcc == nil { - return sdk.ErrUnknownAddress(fmt.Sprintf("account %s does not exist", delegatorAddr)) + return sdkerrors.Wrapf(sdkerrors.ErrUnknownAddress, "account %s does not exist", delegatorAddr) } moduleAcc := keeper.ak.GetAccount(ctx, moduleAccAddr) if moduleAcc == nil { - return sdk.ErrUnknownAddress(fmt.Sprintf("module account %s does not exist", moduleAccAddr)) + return sdkerrors.Wrapf(sdkerrors.ErrUnknownAddress, "module account %s does not exist", moduleAccAddr) } if !amt.IsValid() { - return sdk.ErrInvalidCoins(amt.String()) + return sdkerrors.Wrap(sdkerrors.ErrInvalidCoins, amt.String()) } oldCoins := delegatorAcc.GetCoins() _, hasNeg := oldCoins.SafeSub(amt) if hasNeg { - return sdk.ErrInsufficientCoins( - fmt.Sprintf("insufficient account funds; %s < %s", oldCoins, amt), + return sdkerrors.Wrapf( + sdkerrors.ErrInsufficientFunds, "insufficient account funds; %s < %s", oldCoins, amt, ) } if err := trackDelegation(delegatorAcc, ctx.BlockHeader().Time, amt); err != nil { - return sdk.ErrInternal(fmt.Sprintf("failed to track delegation: %v", err)) + return sdkerrors.Wrap(err, "failed to track delegation") } keeper.ak.SetAccount(ctx, delegatorAcc) @@ -94,28 +94,27 @@ func (keeper BaseKeeper) DelegateCoins(ctx sdk.Context, delegatorAddr, moduleAcc // vesting and vested coins. // The coins are then transferred from a ModuleAccount address to the delegator address. // If any of the undelegation amounts are negative, an error is returned. -func (keeper BaseKeeper) UndelegateCoins(ctx sdk.Context, moduleAccAddr, delegatorAddr sdk.AccAddress, amt sdk.Coins) sdk.Error { - +func (keeper BaseKeeper) UndelegateCoins(ctx sdk.Context, moduleAccAddr, delegatorAddr sdk.AccAddress, amt sdk.Coins) error { delegatorAcc := keeper.ak.GetAccount(ctx, delegatorAddr) if delegatorAcc == nil { - return sdk.ErrUnknownAddress(fmt.Sprintf("account %s does not exist", delegatorAddr)) + return sdkerrors.Wrapf(sdkerrors.ErrUnknownAddress, "account %s does not exist", delegatorAddr) } moduleAcc := keeper.ak.GetAccount(ctx, moduleAccAddr) if moduleAcc == nil { - return sdk.ErrUnknownAddress(fmt.Sprintf("module account %s does not exist", moduleAccAddr)) + return sdkerrors.Wrapf(sdkerrors.ErrUnknownAddress, "module account %s does not exist", moduleAccAddr) } if !amt.IsValid() { - return sdk.ErrInvalidCoins(amt.String()) + return sdkerrors.Wrap(sdkerrors.ErrInvalidCoins, amt.String()) } oldCoins := moduleAcc.GetCoins() newCoins, hasNeg := oldCoins.SafeSub(amt) if hasNeg { - return sdk.ErrInsufficientCoins( - fmt.Sprintf("insufficient account funds; %s < %s", oldCoins, amt), + return sdkerrors.Wrapf( + sdkerrors.ErrInsufficientFunds, "insufficient account funds; %s < %s", oldCoins, amt, ) } @@ -125,7 +124,7 @@ func (keeper BaseKeeper) UndelegateCoins(ctx sdk.Context, moduleAccAddr, delegat } if err := trackUndelegation(delegatorAcc, amt); err != nil { - return sdk.ErrInternal(fmt.Sprintf("failed to track undelegation: %v", err)) + return sdkerrors.Wrap(err, "failed to track undelegation") } keeper.ak.SetAccount(ctx, delegatorAcc) @@ -137,12 +136,12 @@ func (keeper BaseKeeper) UndelegateCoins(ctx sdk.Context, moduleAccAddr, delegat type SendKeeper interface { ViewKeeper - InputOutputCoins(ctx sdk.Context, inputs []types.Input, outputs []types.Output) sdk.Error - SendCoins(ctx sdk.Context, fromAddr sdk.AccAddress, toAddr sdk.AccAddress, amt sdk.Coins) sdk.Error + InputOutputCoins(ctx sdk.Context, inputs []types.Input, outputs []types.Output) error + SendCoins(ctx sdk.Context, fromAddr sdk.AccAddress, toAddr sdk.AccAddress, amt sdk.Coins) error - SubtractCoins(ctx sdk.Context, addr sdk.AccAddress, amt sdk.Coins) (sdk.Coins, sdk.Error) - AddCoins(ctx sdk.Context, addr sdk.AccAddress, amt sdk.Coins) (sdk.Coins, sdk.Error) - SetCoins(ctx sdk.Context, addr sdk.AccAddress, amt sdk.Coins) sdk.Error + SubtractCoins(ctx sdk.Context, addr sdk.AccAddress, amt sdk.Coins) (sdk.Coins, error) + AddCoins(ctx sdk.Context, addr sdk.AccAddress, amt sdk.Coins) (sdk.Coins, error) + SetCoins(ctx sdk.Context, addr sdk.AccAddress, amt sdk.Coins) error GetSendEnabled(ctx sdk.Context) bool SetSendEnabled(ctx sdk.Context, enabled bool) @@ -165,11 +164,12 @@ type BaseSendKeeper struct { } // NewBaseSendKeeper returns a new BaseSendKeeper. -func NewBaseSendKeeper(ak types.AccountKeeper, - paramSpace params.Subspace, codespace sdk.CodespaceType, blacklistedAddrs map[string]bool) BaseSendKeeper { +func NewBaseSendKeeper( + ak types.AccountKeeper, paramSpace params.Subspace, blacklistedAddrs map[string]bool, +) BaseSendKeeper { return BaseSendKeeper{ - BaseViewKeeper: NewBaseViewKeeper(ak, codespace), + BaseViewKeeper: NewBaseViewKeeper(ak), ak: ak, paramSpace: paramSpace, blacklistedAddrs: blacklistedAddrs, @@ -177,7 +177,7 @@ func NewBaseSendKeeper(ak types.AccountKeeper, } // InputOutputCoins handles a list of inputs and outputs -func (keeper BaseSendKeeper) InputOutputCoins(ctx sdk.Context, inputs []types.Input, outputs []types.Output) sdk.Error { +func (keeper BaseSendKeeper) InputOutputCoins(ctx sdk.Context, inputs []types.Input, outputs []types.Output) error { // Safety check ensuring that when sending coins the keeper must maintain the // Check supply invariant and validity of Coins. if err := types.ValidateInputsOutputs(inputs, outputs); err != nil { @@ -216,7 +216,7 @@ func (keeper BaseSendKeeper) InputOutputCoins(ctx sdk.Context, inputs []types.In } // SendCoins moves coins from one account to another -func (keeper BaseSendKeeper) SendCoins(ctx sdk.Context, fromAddr sdk.AccAddress, toAddr sdk.AccAddress, amt sdk.Coins) sdk.Error { +func (keeper BaseSendKeeper) SendCoins(ctx sdk.Context, fromAddr sdk.AccAddress, toAddr sdk.AccAddress, amt sdk.Coins) error { ctx.EventManager().EmitEvents(sdk.Events{ sdk.NewEvent( types.EventTypeTransfer, @@ -245,10 +245,9 @@ func (keeper BaseSendKeeper) SendCoins(ctx sdk.Context, fromAddr sdk.AccAddress, // SubtractCoins subtracts amt from the coins at the addr. // // CONTRACT: If the account is a vesting account, the amount has to be spendable. -func (keeper BaseSendKeeper) SubtractCoins(ctx sdk.Context, addr sdk.AccAddress, amt sdk.Coins) (sdk.Coins, sdk.Error) { - +func (keeper BaseSendKeeper) SubtractCoins(ctx sdk.Context, addr sdk.AccAddress, amt sdk.Coins) (sdk.Coins, error) { if !amt.IsValid() { - return nil, sdk.ErrInvalidCoins(amt.String()) + return nil, sdkerrors.Wrap(sdkerrors.ErrInvalidCoins, amt.String()) } oldCoins, spendableCoins := sdk.NewCoins(), sdk.NewCoins() @@ -263,8 +262,8 @@ func (keeper BaseSendKeeper) SubtractCoins(ctx sdk.Context, addr sdk.AccAddress, // So the check here is sufficient instead of subtracting from oldCoins. _, hasNeg := spendableCoins.SafeSub(amt) if hasNeg { - return amt, sdk.ErrInsufficientCoins( - fmt.Sprintf("insufficient account funds; %s < %s", spendableCoins, amt), + return amt, sdkerrors.Wrapf( + sdkerrors.ErrInsufficientFunds, "insufficient account funds; %s < %s", spendableCoins, amt, ) } @@ -275,18 +274,17 @@ func (keeper BaseSendKeeper) SubtractCoins(ctx sdk.Context, addr sdk.AccAddress, } // AddCoins adds amt to the coins at the addr. -func (keeper BaseSendKeeper) AddCoins(ctx sdk.Context, addr sdk.AccAddress, amt sdk.Coins) (sdk.Coins, sdk.Error) { - +func (keeper BaseSendKeeper) AddCoins(ctx sdk.Context, addr sdk.AccAddress, amt sdk.Coins) (sdk.Coins, error) { if !amt.IsValid() { - return nil, sdk.ErrInvalidCoins(amt.String()) + return nil, sdkerrors.Wrap(sdkerrors.ErrInvalidCoins, amt.String()) } oldCoins := keeper.GetCoins(ctx, addr) newCoins := oldCoins.Add(amt) if newCoins.IsAnyNegative() { - return amt, sdk.ErrInsufficientCoins( - fmt.Sprintf("insufficient account funds; %s < %s", oldCoins, amt), + return amt, sdkerrors.Wrapf( + sdkerrors.ErrInsufficientFunds, "insufficient account funds; %s < %s", oldCoins, amt, ) } @@ -295,10 +293,9 @@ func (keeper BaseSendKeeper) AddCoins(ctx sdk.Context, addr sdk.AccAddress, amt } // SetCoins sets the coins at the addr. -func (keeper BaseSendKeeper) SetCoins(ctx sdk.Context, addr sdk.AccAddress, amt sdk.Coins) sdk.Error { - +func (keeper BaseSendKeeper) SetCoins(ctx sdk.Context, addr sdk.AccAddress, amt sdk.Coins) error { if !amt.IsValid() { - return sdk.ErrInvalidCoins(amt.String()) + sdkerrors.Wrap(sdkerrors.ErrInvalidCoins, amt.String()) } acc := keeper.ak.GetAccount(ctx, addr) @@ -340,19 +337,16 @@ var _ ViewKeeper = (*BaseViewKeeper)(nil) type ViewKeeper interface { GetCoins(ctx sdk.Context, addr sdk.AccAddress) sdk.Coins HasCoins(ctx sdk.Context, addr sdk.AccAddress, amt sdk.Coins) bool - - Codespace() sdk.CodespaceType } // BaseViewKeeper implements a read only keeper implementation of ViewKeeper. type BaseViewKeeper struct { - ak types.AccountKeeper - codespace sdk.CodespaceType + ak types.AccountKeeper } // NewBaseViewKeeper returns a new BaseViewKeeper. -func NewBaseViewKeeper(ak types.AccountKeeper, codespace sdk.CodespaceType) BaseViewKeeper { - return BaseViewKeeper{ak: ak, codespace: codespace} +func NewBaseViewKeeper(ak types.AccountKeeper) BaseViewKeeper { + return BaseViewKeeper{ak: ak} } // Logger returns a module-specific logger. @@ -374,11 +368,6 @@ func (keeper BaseViewKeeper) HasCoins(ctx sdk.Context, addr sdk.AccAddress, amt return keeper.GetCoins(ctx, addr).IsAllGTE(amt) } -// Codespace returns the keeper's codespace. -func (keeper BaseViewKeeper) Codespace() sdk.CodespaceType { - return keeper.codespace -} - // CONTRACT: assumes that amt is valid. func trackDelegation(acc authexported.Account, blockTime time.Time, amt sdk.Coins) error { vacc, ok := acc.(vestexported.VestingAccount) diff --git a/x/bank/internal/keeper/keeper_test.go b/x/bank/internal/keeper/keeper_test.go index ba6c3f56c440..f93ddaa52969 100644 --- a/x/bank/internal/keeper/keeper_test.go +++ b/x/bank/internal/keeper/keeper_test.go @@ -65,8 +65,7 @@ func TestKeeper(t *testing.T) { require.True(t, app.BankKeeper.GetCoins(ctx, addr).IsEqual(sdk.NewCoins(sdk.NewInt64Coin("foocoin", 10)))) require.True(t, app.BankKeeper.GetCoins(ctx, addr2).IsEqual(sdk.NewCoins(sdk.NewInt64Coin("foocoin", 5)))) - err2 := app.BankKeeper.SendCoins(ctx, addr, addr2, sdk.NewCoins(sdk.NewInt64Coin("foocoin", 50))) - require.Implements(t, (*sdk.Error)(nil), err2) + app.BankKeeper.SendCoins(ctx, addr, addr2, sdk.NewCoins(sdk.NewInt64Coin("foocoin", 50))) require.True(t, app.BankKeeper.GetCoins(ctx, addr).IsEqual(sdk.NewCoins(sdk.NewInt64Coin("foocoin", 10)))) require.True(t, app.BankKeeper.GetCoins(ctx, addr2).IsEqual(sdk.NewCoins(sdk.NewInt64Coin("foocoin", 5)))) @@ -109,7 +108,7 @@ func TestSendKeeper(t *testing.T) { blacklistedAddrs := make(map[string]bool) paramSpace := app.ParamsKeeper.Subspace("newspace") - sendKeeper := keep.NewBaseSendKeeper(app.AccountKeeper, paramSpace, types.DefaultCodespace, blacklistedAddrs) + sendKeeper := keep.NewBaseSendKeeper(app.AccountKeeper, paramSpace, blacklistedAddrs) app.BankKeeper.SetSendEnabled(ctx, true) addr := sdk.AccAddress([]byte("addr1")) @@ -136,8 +135,7 @@ func TestSendKeeper(t *testing.T) { require.True(t, sendKeeper.GetCoins(ctx, addr).IsEqual(sdk.NewCoins(sdk.NewInt64Coin("foocoin", 10)))) require.True(t, sendKeeper.GetCoins(ctx, addr2).IsEqual(sdk.NewCoins(sdk.NewInt64Coin("foocoin", 5)))) - err := sendKeeper.SendCoins(ctx, addr, addr2, sdk.NewCoins(sdk.NewInt64Coin("foocoin", 50))) - require.Implements(t, (*sdk.Error)(nil), err) + sendKeeper.SendCoins(ctx, addr, addr2, sdk.NewCoins(sdk.NewInt64Coin("foocoin", 50))) require.True(t, sendKeeper.GetCoins(ctx, addr).IsEqual(sdk.NewCoins(sdk.NewInt64Coin("foocoin", 10)))) require.True(t, sendKeeper.GetCoins(ctx, addr2).IsEqual(sdk.NewCoins(sdk.NewInt64Coin("foocoin", 5)))) @@ -149,7 +147,7 @@ func TestSendKeeper(t *testing.T) { // validate coins with invalid denoms or negative values cannot be sent // NOTE: We must use the Coin literal as the constructor does not allow // negative values. - err = sendKeeper.SendCoins(ctx, addr, addr2, sdk.Coins{sdk.Coin{Denom: "FOOCOIN", Amount: sdk.NewInt(-5)}}) + err := sendKeeper.SendCoins(ctx, addr, addr2, sdk.Coins{sdk.Coin{Denom: "FOOCOIN", Amount: sdk.NewInt(-5)}}) require.Error(t, err) } @@ -202,7 +200,7 @@ func TestViewKeeper(t *testing.T) { app, ctx := createTestApp(false) //paramSpace := app.ParamsKeeper.Subspace(types.DefaultParamspace) - viewKeeper := keep.NewBaseViewKeeper(app.AccountKeeper, types.DefaultCodespace) + viewKeeper := keep.NewBaseViewKeeper(app.AccountKeeper) addr := sdk.AccAddress([]byte("addr1")) acc := app.AccountKeeper.NewAccountWithAddress(ctx, addr) diff --git a/x/bank/internal/keeper/querier.go b/x/bank/internal/keeper/querier.go index bf303e2930fa..165d01879621 100644 --- a/x/bank/internal/keeper/querier.go +++ b/x/bank/internal/keeper/querier.go @@ -1,12 +1,11 @@ package keeper import ( - "fmt" - abci "github.com/tendermint/tendermint/abci/types" "github.com/cosmos/cosmos-sdk/codec" sdk "github.com/cosmos/cosmos-sdk/types" + sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" "github.com/cosmos/cosmos-sdk/x/bank/internal/types" ) @@ -17,24 +16,24 @@ const ( // NewQuerier returns a new sdk.Keeper instance. func NewQuerier(k Keeper) sdk.Querier { - return func(ctx sdk.Context, path []string, req abci.RequestQuery) ([]byte, sdk.Error) { + return func(ctx sdk.Context, path []string, req abci.RequestQuery) ([]byte, error) { switch path[0] { case QueryBalance: return queryBalance(ctx, req, k) default: - return nil, sdk.ErrUnknownRequest("unknown bank query endpoint") + return nil, sdkerrors.Wrapf(sdkerrors.ErrUnknownRequest, "unknown query path: %s", path[0]) } } } // queryBalance fetch an account's balance for the supplied height. // Height and account address are passed as first and second path components respectively. -func queryBalance(ctx sdk.Context, req abci.RequestQuery, k Keeper) ([]byte, sdk.Error) { +func queryBalance(ctx sdk.Context, req abci.RequestQuery, k Keeper) ([]byte, error) { var params types.QueryBalanceParams if err := types.ModuleCdc.UnmarshalJSON(req.Data, ¶ms); err != nil { - return nil, sdk.ErrInternal(fmt.Sprintf("failed to parse params: %s", err)) + return nil, sdkerrors.Wrap(sdkerrors.ErrJSONUnmarshal, err.Error()) } coins := k.GetCoins(ctx, params.Address) @@ -44,7 +43,7 @@ func queryBalance(ctx sdk.Context, req abci.RequestQuery, k Keeper) ([]byte, sdk bz, err := codec.MarshalJSONIndent(types.ModuleCdc, coins) if err != nil { - return nil, sdk.ErrInternal(sdk.AppendMsgToErr("could not marshal result to JSON", err.Error())) + return nil, sdkerrors.Wrap(sdkerrors.ErrJSONMarshal, err.Error()) } return bz, nil diff --git a/x/bank/internal/types/errors.go b/x/bank/internal/types/errors.go index d9c0c7d11d1d..157408c941b7 100644 --- a/x/bank/internal/types/errors.go +++ b/x/bank/internal/types/errors.go @@ -1,33 +1,13 @@ package types import ( - sdk "github.com/cosmos/cosmos-sdk/types" + sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" ) -// Bank errors reserve 100 ~ 199. -const ( - DefaultCodespace sdk.CodespaceType = ModuleName - - CodeSendDisabled sdk.CodeType = 101 - CodeInvalidInputsOutputs sdk.CodeType = 102 +// x/bank module sentinel errors +var ( + ErrNoInputs = sdkerrors.Register(ModuleName, 1, "no inputs to send transaction") + ErrNoOutputs = sdkerrors.Register(ModuleName, 2, "no outputs to send transaction") + ErrInputOutputMismatch = sdkerrors.Register(ModuleName, 3, "sum inputs != sum outputs") + ErrSendDisabled = sdkerrors.Register(ModuleName, 4, "send transactions are disabled") ) - -// ErrNoInputs is an error -func ErrNoInputs(codespace sdk.CodespaceType) sdk.Error { - return sdk.NewError(codespace, CodeInvalidInputsOutputs, "no inputs to send transaction") -} - -// ErrNoOutputs is an error -func ErrNoOutputs(codespace sdk.CodespaceType) sdk.Error { - return sdk.NewError(codespace, CodeInvalidInputsOutputs, "no outputs to send transaction") -} - -// ErrInputOutputMismatch is an error -func ErrInputOutputMismatch(codespace sdk.CodespaceType) sdk.Error { - return sdk.NewError(codespace, CodeInvalidInputsOutputs, "sum inputs != sum outputs") -} - -// ErrSendDisabled is an error -func ErrSendDisabled(codespace sdk.CodespaceType) sdk.Error { - return sdk.NewError(codespace, CodeSendDisabled, "send transactions are currently disabled") -} diff --git a/x/bank/internal/types/msgs.go b/x/bank/internal/types/msgs.go index 58336e24d9e4..c8fdaa5afe92 100644 --- a/x/bank/internal/types/msgs.go +++ b/x/bank/internal/types/msgs.go @@ -2,6 +2,7 @@ package types import ( sdk "github.com/cosmos/cosmos-sdk/types" + sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" ) // RouterKey is they name of the bank module @@ -28,18 +29,18 @@ func (msg MsgSend) Route() string { return RouterKey } func (msg MsgSend) Type() string { return "send" } // ValidateBasic Implements Msg. -func (msg MsgSend) ValidateBasic() sdk.Error { +func (msg MsgSend) ValidateBasic() error { if msg.FromAddress.Empty() { - return sdk.ErrInvalidAddress("missing sender address") + return sdkerrors.Wrap(sdkerrors.ErrInvalidAddress, "missing sender address") } if msg.ToAddress.Empty() { - return sdk.ErrInvalidAddress("missing recipient address") + return sdkerrors.Wrap(sdkerrors.ErrInvalidAddress, "missing recipient address") } if !msg.Amount.IsValid() { - return sdk.ErrInvalidCoins("send amount is invalid: " + msg.Amount.String()) + return sdkerrors.Wrap(sdkerrors.ErrInvalidCoins, msg.Amount.String()) } if !msg.Amount.IsAllPositive() { - return sdk.ErrInsufficientCoins("send amount must be positive") + return sdkerrors.Wrap(sdkerrors.ErrInvalidCoins, msg.Amount.String()) } return nil } @@ -74,14 +75,14 @@ func (msg MsgMultiSend) Route() string { return RouterKey } func (msg MsgMultiSend) Type() string { return "multisend" } // ValidateBasic Implements Msg. -func (msg MsgMultiSend) ValidateBasic() sdk.Error { +func (msg MsgMultiSend) ValidateBasic() error { // this just makes sure all the inputs and outputs are properly formatted, // not that they actually have the money inside if len(msg.Inputs) == 0 { - return ErrNoInputs(DefaultCodespace).TraceSDK("") + return ErrNoInputs } if len(msg.Outputs) == 0 { - return ErrNoOutputs(DefaultCodespace).TraceSDK("") + return ErrNoOutputs } return ValidateInputsOutputs(msg.Inputs, msg.Outputs) @@ -108,15 +109,15 @@ type Input struct { } // ValidateBasic - validate transaction input -func (in Input) ValidateBasic() sdk.Error { +func (in Input) ValidateBasic() error { if len(in.Address) == 0 { - return sdk.ErrInvalidAddress(in.Address.String()) + return sdkerrors.Wrap(sdkerrors.ErrInvalidAddress, "input address missing") } if !in.Coins.IsValid() { - return sdk.ErrInvalidCoins(in.Coins.String()) + return sdkerrors.Wrap(sdkerrors.ErrInvalidCoins, in.Coins.String()) } if !in.Coins.IsAllPositive() { - return sdk.ErrInvalidCoins(in.Coins.String()) + return sdkerrors.Wrap(sdkerrors.ErrInvalidCoins, in.Coins.String()) } return nil } @@ -136,15 +137,15 @@ type Output struct { } // ValidateBasic - validate transaction output -func (out Output) ValidateBasic() sdk.Error { +func (out Output) ValidateBasic() error { if len(out.Address) == 0 { - return sdk.ErrInvalidAddress(out.Address.String()) + return sdkerrors.Wrap(sdkerrors.ErrInvalidAddress, "output address missing") } if !out.Coins.IsValid() { - return sdk.ErrInvalidCoins(out.Coins.String()) + return sdkerrors.Wrap(sdkerrors.ErrInvalidCoins, out.Coins.String()) } if !out.Coins.IsAllPositive() { - return sdk.ErrInvalidCoins(out.Coins.String()) + return sdkerrors.Wrap(sdkerrors.ErrInvalidCoins, out.Coins.String()) } return nil } @@ -159,26 +160,28 @@ func NewOutput(addr sdk.AccAddress, coins sdk.Coins) Output { // ValidateInputsOutputs validates that each respective input and output is // valid and that the sum of inputs is equal to the sum of outputs. -func ValidateInputsOutputs(inputs []Input, outputs []Output) sdk.Error { +func ValidateInputsOutputs(inputs []Input, outputs []Output) error { var totalIn, totalOut sdk.Coins for _, in := range inputs { if err := in.ValidateBasic(); err != nil { - return err.TraceSDK("") + return err } + totalIn = totalIn.Add(in.Coins) } for _, out := range outputs { if err := out.ValidateBasic(); err != nil { - return err.TraceSDK("") + return err } + totalOut = totalOut.Add(out.Coins) } // make sure inputs and outputs match if !totalIn.IsEqual(totalOut) { - return ErrInputOutputMismatch(DefaultCodespace) + return ErrInputOutputMismatch } return nil diff --git a/x/bank/simulation/operations.go b/x/bank/simulation/operations.go index 71a88386c960..7cf08a8452f2 100644 --- a/x/bank/simulation/operations.go +++ b/x/bank/simulation/operations.go @@ -1,7 +1,6 @@ package simulation import ( - "errors" "math/rand" "github.com/tendermint/tendermint/crypto" @@ -115,9 +114,9 @@ func sendMsgSend( privkeys..., ) - res := app.Deliver(tx) - if !res.IsOK() { - return errors.New(res.Log) + _, _, err = app.Deliver(tx) + if err != nil { + return err } return nil @@ -259,9 +258,9 @@ func sendMsgMultiSend( privkeys..., ) - res := app.Deliver(tx) - if !res.IsOK() { - return errors.New(res.Log) + _, _, err = app.Deliver(tx) + if err != nil { + return err } return nil diff --git a/x/crisis/alias.go b/x/crisis/alias.go index 6c176e265544..1b05371f376b 100644 --- a/x/crisis/alias.go +++ b/x/crisis/alias.go @@ -1,38 +1,30 @@ -// nolint -// autogenerated code using github.com/rigelrozanski/multitool -// aliases generated for the following subdirectories: -// ALIASGEN: github.com/cosmos/cosmos-sdk/x/crisis/types package crisis +// nolint + import ( "github.com/cosmos/cosmos-sdk/x/crisis/internal/keeper" "github.com/cosmos/cosmos-sdk/x/crisis/internal/types" ) const ( - DefaultCodespace = types.DefaultCodespace - CodeInvalidInput = types.CodeInvalidInput - ModuleName = types.ModuleName - DefaultParamspace = types.DefaultParamspace - + ModuleName = types.ModuleName + DefaultParamspace = types.DefaultParamspace EventTypeInvariant = types.EventTypeInvariant AttributeValueCrisis = types.AttributeValueCrisis AttributeKeyRoute = types.AttributeKeyRoute ) var ( - // functions aliases - RegisterCodec = types.RegisterCodec - ErrNilSender = types.ErrNilSender - ErrUnknownInvariant = types.ErrUnknownInvariant - NewGenesisState = types.NewGenesisState - DefaultGenesisState = types.DefaultGenesisState - NewMsgVerifyInvariant = types.NewMsgVerifyInvariant - ParamKeyTable = types.ParamKeyTable - NewInvarRoute = types.NewInvarRoute - NewKeeper = keeper.NewKeeper - - // variable aliases + RegisterCodec = types.RegisterCodec + ErrNoSender = types.ErrNoSender + ErrUnknownInvariant = types.ErrUnknownInvariant + NewGenesisState = types.NewGenesisState + DefaultGenesisState = types.DefaultGenesisState + NewMsgVerifyInvariant = types.NewMsgVerifyInvariant + ParamKeyTable = types.ParamKeyTable + NewInvarRoute = types.NewInvarRoute + NewKeeper = keeper.NewKeeper ModuleCdc = types.ModuleCdc ParamStoreKeyConstantFee = types.ParamStoreKeyConstantFee ) diff --git a/x/crisis/client/cli/tx.go b/x/crisis/client/cli/tx.go index cdea9206fbe6..e2df844db639 100644 --- a/x/crisis/client/cli/tx.go +++ b/x/crisis/client/cli/tx.go @@ -8,6 +8,7 @@ import ( "github.com/cosmos/cosmos-sdk/client" "github.com/cosmos/cosmos-sdk/client/context" + "github.com/cosmos/cosmos-sdk/client/flags" "github.com/cosmos/cosmos-sdk/codec" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/x/auth" @@ -46,7 +47,7 @@ func GetTxCmd(cdc *codec.Codec) *cobra.Command { RunE: client.ValidateCmd, } - txCmd.AddCommand(client.PostCommands( + txCmd.AddCommand(flags.PostCommands( GetCmdInvariantBroken(cdc), )...) return txCmd diff --git a/x/crisis/handler.go b/x/crisis/handler.go index 9ff52c2f339e..c7e58b6861be 100644 --- a/x/crisis/handler.go +++ b/x/crisis/handler.go @@ -1,9 +1,8 @@ package crisis import ( - "fmt" - sdk "github.com/cosmos/cosmos-sdk/types" + sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" "github.com/cosmos/cosmos-sdk/x/crisis/internal/keeper" "github.com/cosmos/cosmos-sdk/x/crisis/internal/types" ) @@ -12,7 +11,7 @@ import ( const RouterKey = types.ModuleName func NewHandler(k keeper.Keeper) sdk.Handler { - return func(ctx sdk.Context, msg sdk.Msg) sdk.Result { + return func(ctx sdk.Context, msg sdk.Msg) (*sdk.Result, error) { ctx = ctx.WithEventManager(sdk.NewEventManager()) switch msg := msg.(type) { @@ -20,18 +19,16 @@ func NewHandler(k keeper.Keeper) sdk.Handler { return handleMsgVerifyInvariant(ctx, msg, k) default: - errMsg := fmt.Sprintf("unrecognized crisis message type: %T", msg) - return sdk.ErrUnknownRequest(errMsg).Result() + return nil, sdkerrors.Wrapf(sdkerrors.ErrUnknownRequest, "unrecognized crisis message type: %T", msg) } } } -func handleMsgVerifyInvariant(ctx sdk.Context, msg types.MsgVerifyInvariant, k keeper.Keeper) sdk.Result { - // remove the constant fee +func handleMsgVerifyInvariant(ctx sdk.Context, msg types.MsgVerifyInvariant, k keeper.Keeper) (*sdk.Result, error) { constantFee := sdk.NewCoins(k.GetConstantFee(ctx)) if err := k.SendCoinsFromAccountToFeeCollector(ctx, msg.Sender, constantFee); err != nil { - return err.Result() + return nil, err } // use a cached context to avoid gas costs during invariants @@ -51,7 +48,7 @@ func handleMsgVerifyInvariant(ctx sdk.Context, msg types.MsgVerifyInvariant, k k } if !found { - return types.ErrUnknownInvariant(types.DefaultCodespace).Result() + return nil, types.ErrUnknownInvariant } if stop { @@ -86,5 +83,5 @@ func handleMsgVerifyInvariant(ctx sdk.Context, msg types.MsgVerifyInvariant, k k ), }) - return sdk.Result{Events: ctx.EventManager().Events()} + return &sdk.Result{Events: ctx.EventManager().Events()}, nil } diff --git a/x/crisis/handler_test.go b/x/crisis/handler_test.go index 064d6234bc9b..f4c2f8182dbf 100644 --- a/x/crisis/handler_test.go +++ b/x/crisis/handler_test.go @@ -69,14 +69,18 @@ func TestHandleMsgVerifyInvariant(t *testing.T) { switch tc.expectedResult { case "fail": - res := h(ctx, tc.msg) - require.False(t, res.IsOK()) + res, err := h(ctx, tc.msg) + require.Error(t, err) + require.Nil(t, res) + case "pass": - res := h(ctx, tc.msg) - require.True(t, res.IsOK()) + res, err := h(ctx, tc.msg) + require.NoError(t, err) + require.NotNil(t, res) + case "panic": require.Panics(t, func() { - _ = h(ctx, tc.msg) + h(ctx, tc.msg) }) } }) @@ -92,7 +96,10 @@ func TestHandleMsgVerifyInvariantWithNotEnoughSenderCoins(t *testing.T) { h := crisis.NewHandler(app.CrisisKeeper) msg := crisis.NewMsgVerifyInvariant(sender, testModuleName, dummyRouteWhichPasses.Route) - require.False(t, h(ctx, msg).IsOK()) + + res, err := h(ctx, msg) + require.Error(t, err) + require.Nil(t, res) } func TestHandleMsgVerifyInvariantWithInvariantBrokenAndNotEnoughPoolCoins(t *testing.T) { @@ -106,8 +113,9 @@ func TestHandleMsgVerifyInvariantWithInvariantBrokenAndNotEnoughPoolCoins(t *tes h := crisis.NewHandler(app.CrisisKeeper) msg := crisis.NewMsgVerifyInvariant(sender, testModuleName, dummyRouteWhichFails.Route) - var res sdk.Result + + var res *sdk.Result require.Panics(t, func() { - res = h(ctx, msg) + res, _ = h(ctx, msg) }, fmt.Sprintf("%v", res)) } diff --git a/x/crisis/internal/keeper/keeper.go b/x/crisis/internal/keeper/keeper.go index cb6f9a6548d8..f4c8163bb740 100644 --- a/x/crisis/internal/keeper/keeper.go +++ b/x/crisis/internal/keeper/keeper.go @@ -90,6 +90,6 @@ func (k Keeper) AssertInvariants(ctx sdk.Context) { func (k Keeper) InvCheckPeriod() uint { return k.invCheckPeriod } // SendCoinsFromAccountToFeeCollector transfers amt to the fee collector account. -func (k Keeper) SendCoinsFromAccountToFeeCollector(ctx sdk.Context, senderAddr sdk.AccAddress, amt sdk.Coins) sdk.Error { +func (k Keeper) SendCoinsFromAccountToFeeCollector(ctx sdk.Context, senderAddr sdk.AccAddress, amt sdk.Coins) error { return k.supplyKeeper.SendCoinsFromAccountToModule(ctx, senderAddr, k.feeCollectorName, amt) } diff --git a/x/crisis/internal/types/errors.go b/x/crisis/internal/types/errors.go index 3b7392abfae6..ac63f3ff43de 100644 --- a/x/crisis/internal/types/errors.go +++ b/x/crisis/internal/types/errors.go @@ -1,23 +1,11 @@ package types import ( - sdk "github.com/cosmos/cosmos-sdk/types" + sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" ) -const ( - // default codespace for crisis module - DefaultCodespace sdk.CodespaceType = ModuleName - - // CodeInvalidInput is the codetype for invalid input for the crisis module - CodeInvalidInput sdk.CodeType = 103 +// x/crisis module sentinel errors +var ( + ErrNoSender = sdkerrors.Register(ModuleName, 1, "sender address is empty") + ErrUnknownInvariant = sdkerrors.Register(ModuleName, 2, "unknown invariant") ) - -// ErrNilSender - no sender provided for the input -func ErrNilSender(codespace sdk.CodespaceType) sdk.Error { - return sdk.NewError(codespace, CodeInvalidInput, "sender address is nil") -} - -// ErrUnknownInvariant - unknown invariant provided -func ErrUnknownInvariant(codespace sdk.CodespaceType) sdk.Error { - return sdk.NewError(codespace, CodeInvalidInput, "unknown invariant") -} diff --git a/x/crisis/internal/types/expected_keepers.go b/x/crisis/internal/types/expected_keepers.go index 5690c0c38688..3cd0e9e7f57a 100644 --- a/x/crisis/internal/types/expected_keepers.go +++ b/x/crisis/internal/types/expected_keepers.go @@ -6,5 +6,5 @@ import ( // SupplyKeeper defines the expected supply keeper (noalias) type SupplyKeeper interface { - SendCoinsFromAccountToModule(ctx sdk.Context, senderAddr sdk.AccAddress, recipientModule string, amt sdk.Coins) sdk.Error + SendCoinsFromAccountToModule(ctx sdk.Context, senderAddr sdk.AccAddress, recipientModule string, amt sdk.Coins) error } diff --git a/x/crisis/internal/types/msgs.go b/x/crisis/internal/types/msgs.go index e16ffb528e0c..f496df636b60 100644 --- a/x/crisis/internal/types/msgs.go +++ b/x/crisis/internal/types/msgs.go @@ -39,9 +39,9 @@ func (msg MsgVerifyInvariant) GetSignBytes() []byte { } // quick validity check -func (msg MsgVerifyInvariant) ValidateBasic() sdk.Error { +func (msg MsgVerifyInvariant) ValidateBasic() error { if msg.Sender.Empty() { - return ErrNilSender(DefaultCodespace) + return ErrNoSender } return nil } diff --git a/x/distribution/alias.go b/x/distribution/alias.go index de6f269e6a1c..ff181d7331e3 100644 --- a/x/distribution/alias.go +++ b/x/distribution/alias.go @@ -10,11 +10,6 @@ import ( const ( DefaultParamspace = keeper.DefaultParamspace - DefaultCodespace = types.DefaultCodespace - CodeInvalidInput = types.CodeInvalidInput - CodeNoDistributionInfo = types.CodeNoDistributionInfo - CodeNoValidatorCommission = types.CodeNoValidatorCommission - CodeSetWithdrawAddrDisabled = types.CodeSetWithdrawAddrDisabled ModuleName = types.ModuleName StoreKey = types.StoreKey RouterKey = types.RouterKey @@ -70,11 +65,13 @@ var ( CreateTestInputAdvanced = keeper.CreateTestInputAdvanced RegisterCodec = types.RegisterCodec NewDelegatorStartingInfo = types.NewDelegatorStartingInfo - ErrNilDelegatorAddr = types.ErrNilDelegatorAddr - ErrNilWithdrawAddr = types.ErrNilWithdrawAddr - ErrNilValidatorAddr = types.ErrNilValidatorAddr - ErrNoDelegationDistInfo = types.ErrNoDelegationDistInfo + ErrEmptyDelegatorAddr = types.ErrEmptyDelegatorAddr + ErrEmptyWithdrawAddr = types.ErrEmptyWithdrawAddr + ErrEmptyValidatorAddr = types.ErrEmptyValidatorAddr + ErrEmptyDelegationDistInfo = types.ErrEmptyDelegationDistInfo ErrNoValidatorDistInfo = types.ErrNoValidatorDistInfo + ErrNoValidatorExists = types.ErrNoValidatorExists + ErrNoDelegationExists = types.ErrNoDelegationExists ErrNoValidatorCommission = types.ErrNoValidatorCommission ErrSetWithdrawAddrDisabled = types.ErrSetWithdrawAddrDisabled ErrBadDistribution = types.ErrBadDistribution @@ -134,7 +131,6 @@ type ( Hooks = keeper.Hooks Keeper = keeper.Keeper DelegatorStartingInfo = types.DelegatorStartingInfo - CodeType = types.CodeType FeePool = types.FeePool DelegatorWithdrawInfo = types.DelegatorWithdrawInfo ValidatorOutstandingRewardsRecord = types.ValidatorOutstandingRewardsRecord diff --git a/x/distribution/client/cli/query.go b/x/distribution/client/cli/query.go index 36d12e57fb1d..dff8e5e06a5d 100644 --- a/x/distribution/client/cli/query.go +++ b/x/distribution/client/cli/query.go @@ -9,6 +9,7 @@ import ( "github.com/cosmos/cosmos-sdk/client" "github.com/cosmos/cosmos-sdk/client/context" + "github.com/cosmos/cosmos-sdk/client/flags" "github.com/cosmos/cosmos-sdk/codec" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/version" @@ -26,7 +27,7 @@ func GetQueryCmd(queryRoute string, cdc *codec.Codec) *cobra.Command { RunE: client.ValidateCmd, } - distQueryCmd.AddCommand(client.GetCommands( + distQueryCmd.AddCommand(flags.GetCommands( GetCmdQueryParams(queryRoute, cdc), GetCmdQueryValidatorOutstandingRewards(queryRoute, cdc), GetCmdQueryValidatorCommission(queryRoute, cdc), @@ -66,7 +67,7 @@ func GetCmdQueryValidatorOutstandingRewards(queryRoute string, cdc *codec.Codec) for a validator and all their delegations. Example: -$ %s query distr validator-outstanding-rewards cosmosvaloper1lwjmdnks33xwnmfayc64ycprww49n33mtm92ne +$ %s query distribution validator-outstanding-rewards cosmosvaloper1lwjmdnks33xwnmfayc64ycprww49n33mtm92ne `, version.ClientName, ), @@ -113,7 +114,7 @@ func GetCmdQueryValidatorCommission(queryRoute string, cdc *codec.Codec) *cobra. fmt.Sprintf(`Query validator commission rewards from delegators to that validator. Example: -$ %s query distr commission cosmosvaloper1gghjut3ccd8ay0zduzj64hwre2fxs9ldmqhffj +$ %s query distribution commission cosmosvaloper1gghjut3ccd8ay0zduzj64hwre2fxs9ldmqhffj `, version.ClientName, ), @@ -148,7 +149,7 @@ func GetCmdQueryValidatorSlashes(queryRoute string, cdc *codec.Codec) *cobra.Com fmt.Sprintf(`Query all slashes of a validator for a given block range. Example: -$ %s query distr slashes cosmosvaloper1gghjut3ccd8ay0zduzj64hwre2fxs9ldmqhffj 0 100 +$ %s query distribution slashes cosmosvaloper1gghjut3ccd8ay0zduzj64hwre2fxs9ldmqhffj 0 100 `, version.ClientName, ), @@ -199,8 +200,8 @@ func GetCmdQueryDelegatorRewards(queryRoute string, cdc *codec.Codec) *cobra.Com fmt.Sprintf(`Query all rewards earned by a delegator, optionally restrict to rewards from a single validator. Example: -$ %s query distr rewards cosmos1gghjut3ccd8ay0zduzj64hwre2fxs9ld75ru9p -$ %s query distr rewards cosmos1gghjut3ccd8ay0zduzj64hwre2fxs9ld75ru9p cosmosvaloper1gghjut3ccd8ay0zduzj64hwre2fxs9ldmqhffj +$ %s query distribution rewards cosmos1gghjut3ccd8ay0zduzj64hwre2fxs9ld75ru9p +$ %s query distribution rewards cosmos1gghjut3ccd8ay0zduzj64hwre2fxs9ld75ru9p cosmosvaloper1gghjut3ccd8ay0zduzj64hwre2fxs9ldmqhffj `, version.ClientName, version.ClientName, ), @@ -243,7 +244,7 @@ func GetCmdQueryCommunityPool(queryRoute string, cdc *codec.Codec) *cobra.Comman fmt.Sprintf(`Query all coins in the community pool which is under Governance control. Example: -$ %s query distr community-pool +$ %s query distribution community-pool `, version.ClientName, ), diff --git a/x/distribution/client/cli/tx.go b/x/distribution/client/cli/tx.go index 29d0c17fc263..6eaee60992b6 100644 --- a/x/distribution/client/cli/tx.go +++ b/x/distribution/client/cli/tx.go @@ -11,6 +11,7 @@ import ( "github.com/cosmos/cosmos-sdk/client" "github.com/cosmos/cosmos-sdk/client/context" + "github.com/cosmos/cosmos-sdk/client/flags" "github.com/cosmos/cosmos-sdk/codec" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/version" @@ -43,7 +44,7 @@ func GetTxCmd(storeKey string, cdc *codec.Codec) *cobra.Command { RunE: client.ValidateCmd, } - distTxCmd.AddCommand(client.PostCommands( + distTxCmd.AddCommand(flags.PostCommands( GetCmdWithdrawRewards(cdc), GetCmdSetWithdrawAddr(cdc), GetCmdWithdrawAllRewards(cdc, storeKey), @@ -95,8 +96,8 @@ func GetCmdWithdrawRewards(cdc *codec.Codec) *cobra.Command { and optionally withdraw validator commission if the delegation address given is a validator operator. Example: -$ %s tx distr withdraw-rewards cosmosvaloper1gghjut3ccd8ay0zduzj64hwre2fxs9ldmqhffj --from mykey -$ %s tx distr withdraw-rewards cosmosvaloper1gghjut3ccd8ay0zduzj64hwre2fxs9ldmqhffj --from mykey --commission +$ %s tx distribution withdraw-rewards cosmosvaloper1gghjut3ccd8ay0zduzj64hwre2fxs9ldmqhffj --from mykey +$ %s tx distribution withdraw-rewards cosmosvaloper1gghjut3ccd8ay0zduzj64hwre2fxs9ldmqhffj --from mykey --commission `, version.ClientName, version.ClientName, ), @@ -134,7 +135,7 @@ func GetCmdWithdrawAllRewards(cdc *codec.Codec, queryRoute string) *cobra.Comman fmt.Sprintf(`Withdraw all rewards for a single delegator. Example: -$ %s tx distr withdraw-all-rewards --from mykey +$ %s tx distribution withdraw-all-rewards --from mykey `, version.ClientName, ), @@ -150,7 +151,7 @@ $ %s tx distr withdraw-all-rewards --from mykey // The transaction cannot be generated offline since it requires a query // to get all the validators. if cliCtx.GenerateOnly { - return fmt.Errorf("command disabled with the provided flag: %s", client.FlagGenerateOnly) + return fmt.Errorf("command disabled with the provided flag: %s", flags.FlagGenerateOnly) } msgs, err := common.WithdrawAllDelegatorRewards(cliCtx, queryRoute, delAddr) @@ -176,7 +177,7 @@ func GetCmdSetWithdrawAddr(cdc *codec.Codec) *cobra.Command { fmt.Sprintf(`Set the withdraw address for rewards associated with a delegator address. Example: -$ %s tx set-withdraw-addr cosmos1gghjut3ccd8ay0zduzj64hwre2fxs9ld75ru9p --from mykey +$ %s tx distribution set-withdraw-addr cosmos1gghjut3ccd8ay0zduzj64hwre2fxs9ld75ru9p --from mykey `, version.ClientName, ), @@ -272,7 +273,7 @@ func GetCmdFundCommunityPool(cdc *codec.Codec) *cobra.Command { fmt.Sprintf(`Funds the community pool with the specified amount Example: -$ %s tx fund-community-pool 100uatom --from mykey +$ %s tx distribution fund-community-pool 100uatom --from mykey `, version.ClientName, ), diff --git a/x/distribution/handler.go b/x/distribution/handler.go index 90c4bc14de93..642b9e0d89a1 100644 --- a/x/distribution/handler.go +++ b/x/distribution/handler.go @@ -1,16 +1,15 @@ package distribution import ( - "fmt" - sdk "github.com/cosmos/cosmos-sdk/types" + sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" "github.com/cosmos/cosmos-sdk/x/distribution/keeper" "github.com/cosmos/cosmos-sdk/x/distribution/types" govtypes "github.com/cosmos/cosmos-sdk/x/gov/types" ) func NewHandler(k keeper.Keeper) sdk.Handler { - return func(ctx sdk.Context, msg sdk.Msg) sdk.Result { + return func(ctx sdk.Context, msg sdk.Msg) (*sdk.Result, error) { ctx = ctx.WithEventManager(sdk.NewEventManager()) switch msg := msg.(type) { @@ -27,18 +26,17 @@ func NewHandler(k keeper.Keeper) sdk.Handler { return handleMsgFundCommunityPool(ctx, msg, k) default: - errMsg := fmt.Sprintf("unrecognized distribution message type: %T", msg) - return sdk.ErrUnknownRequest(errMsg).Result() + return nil, sdkerrors.Wrapf(sdkerrors.ErrUnknownRequest, "unrecognized distribution message type: %T", msg) } } } // These functions assume everything has been authenticated (ValidateBasic passed, and signatures checked) -func handleMsgModifyWithdrawAddress(ctx sdk.Context, msg types.MsgSetWithdrawAddress, k keeper.Keeper) sdk.Result { +func handleMsgModifyWithdrawAddress(ctx sdk.Context, msg types.MsgSetWithdrawAddress, k keeper.Keeper) (*sdk.Result, error) { err := k.SetWithdrawAddr(ctx, msg.DelegatorAddress, msg.WithdrawAddress) if err != nil { - return err.Result() + return nil, err } ctx.EventManager().EmitEvent( @@ -49,13 +47,13 @@ func handleMsgModifyWithdrawAddress(ctx sdk.Context, msg types.MsgSetWithdrawAdd ), ) - return sdk.Result{Events: ctx.EventManager().Events()} + return &sdk.Result{Events: ctx.EventManager().Events()}, nil } -func handleMsgWithdrawDelegatorReward(ctx sdk.Context, msg types.MsgWithdrawDelegatorReward, k keeper.Keeper) sdk.Result { +func handleMsgWithdrawDelegatorReward(ctx sdk.Context, msg types.MsgWithdrawDelegatorReward, k keeper.Keeper) (*sdk.Result, error) { _, err := k.WithdrawDelegationRewards(ctx, msg.DelegatorAddress, msg.ValidatorAddress) if err != nil { - return err.Result() + return nil, err } ctx.EventManager().EmitEvent( @@ -66,13 +64,13 @@ func handleMsgWithdrawDelegatorReward(ctx sdk.Context, msg types.MsgWithdrawDele ), ) - return sdk.Result{Events: ctx.EventManager().Events()} + return &sdk.Result{Events: ctx.EventManager().Events()}, nil } -func handleMsgWithdrawValidatorCommission(ctx sdk.Context, msg types.MsgWithdrawValidatorCommission, k keeper.Keeper) sdk.Result { +func handleMsgWithdrawValidatorCommission(ctx sdk.Context, msg types.MsgWithdrawValidatorCommission, k keeper.Keeper) (*sdk.Result, error) { _, err := k.WithdrawValidatorCommission(ctx, msg.ValidatorAddress) if err != nil { - return err.Result() + return nil, err } ctx.EventManager().EmitEvent( @@ -83,12 +81,12 @@ func handleMsgWithdrawValidatorCommission(ctx sdk.Context, msg types.MsgWithdraw ), ) - return sdk.Result{Events: ctx.EventManager().Events()} + return &sdk.Result{Events: ctx.EventManager().Events()}, nil } -func handleMsgFundCommunityPool(ctx sdk.Context, msg types.MsgFundCommunityPool, k keeper.Keeper) sdk.Result { +func handleMsgFundCommunityPool(ctx sdk.Context, msg types.MsgFundCommunityPool, k keeper.Keeper) (*sdk.Result, error) { if err := k.FundCommunityPool(ctx, msg.Amount, msg.Depositor); err != nil { - return sdk.ResultFromError(err) + return nil, err } ctx.EventManager().EmitEvent( @@ -99,18 +97,17 @@ func handleMsgFundCommunityPool(ctx sdk.Context, msg types.MsgFundCommunityPool, ), ) - return sdk.Result{Events: ctx.EventManager().Events()} + return &sdk.Result{Events: ctx.EventManager().Events()}, nil } func NewCommunityPoolSpendProposalHandler(k Keeper) govtypes.Handler { - return func(ctx sdk.Context, content govtypes.Content) sdk.Error { + return func(ctx sdk.Context, content govtypes.Content) error { switch c := content.(type) { case types.CommunityPoolSpendProposal: return keeper.HandleCommunityPoolSpendProposal(ctx, k, c) default: - errMsg := fmt.Sprintf("unrecognized distr proposal content type: %T", c) - return sdk.ErrUnknownRequest(errMsg) + return sdkerrors.Wrapf(sdkerrors.ErrUnknownRequest, "unrecognized distr proposal content type: %T", c) } } } diff --git a/x/distribution/keeper/allocation_test.go b/x/distribution/keeper/allocation_test.go index 8f1b84c5f35c..83821ea3820d 100644 --- a/x/distribution/keeper/allocation_test.go +++ b/x/distribution/keeper/allocation_test.go @@ -16,9 +16,15 @@ func TestAllocateTokensToValidatorWithCommission(t *testing.T) { // create validator with 50% commission commission := staking.NewCommissionRates(sdk.NewDecWithPrec(5, 1), sdk.NewDecWithPrec(5, 1), sdk.NewDec(0)) - msg := staking.NewMsgCreateValidator(valOpAddr1, valConsPk1, - sdk.NewCoin(sdk.DefaultBondDenom, sdk.NewInt(100)), staking.Description{}, commission, sdk.OneInt()) - require.True(t, sh(ctx, msg).IsOK()) + msg := staking.NewMsgCreateValidator( + valOpAddr1, valConsPk1, + sdk.NewCoin(sdk.DefaultBondDenom, sdk.NewInt(100)), staking.Description{}, commission, sdk.OneInt(), + ) + + res, err := sh(ctx, msg) + require.NoError(t, err) + require.NotNil(t, res) + val := sk.Validator(ctx, valOpAddr1) // allocate tokens @@ -45,13 +51,19 @@ func TestAllocateTokensToManyValidators(t *testing.T) { commission := staking.NewCommissionRates(sdk.NewDecWithPrec(5, 1), sdk.NewDecWithPrec(5, 1), sdk.NewDec(0)) msg := staking.NewMsgCreateValidator(valOpAddr1, valConsPk1, sdk.NewCoin(sdk.DefaultBondDenom, sdk.NewInt(100)), staking.Description{}, commission, sdk.OneInt()) - require.True(t, sh(ctx, msg).IsOK()) + + res, err := sh(ctx, msg) + require.NoError(t, err) + require.NotNil(t, res) // create second validator with 0% commission commission = staking.NewCommissionRates(sdk.NewDec(0), sdk.NewDec(0), sdk.NewDec(0)) msg = staking.NewMsgCreateValidator(valOpAddr2, valConsPk2, sdk.NewCoin(sdk.DefaultBondDenom, sdk.NewInt(100)), staking.Description{}, commission, sdk.OneInt()) - require.True(t, sh(ctx, msg).IsOK()) + + res, err = sh(ctx, msg) + require.NoError(t, err) + require.NotNil(t, res) abciValA := abci.Validator{ Address: valConsPk1.Address(), @@ -76,7 +88,7 @@ func TestAllocateTokensToManyValidators(t *testing.T) { feeCollector := supplyKeeper.GetModuleAccount(ctx, k.feeCollectorName) require.NotNil(t, feeCollector) - err := feeCollector.SetCoins(fees) + err = feeCollector.SetCoins(fees) require.NoError(t, err) ak.SetAccount(ctx, feeCollector) @@ -116,19 +128,25 @@ func TestAllocateTokensTruncation(t *testing.T) { commission := staking.NewCommissionRates(sdk.NewDecWithPrec(1, 1), sdk.NewDecWithPrec(1, 1), sdk.NewDec(0)) msg := staking.NewMsgCreateValidator(valOpAddr1, valConsPk1, sdk.NewCoin(sdk.DefaultBondDenom, sdk.NewInt(110)), staking.Description{}, commission, sdk.OneInt()) - require.True(t, sh(ctx, msg).IsOK()) + res, err := sh(ctx, msg) + require.NoError(t, err) + require.NotNil(t, res) // create second validator with 10% commission commission = staking.NewCommissionRates(sdk.NewDecWithPrec(1, 1), sdk.NewDecWithPrec(1, 1), sdk.NewDec(0)) msg = staking.NewMsgCreateValidator(valOpAddr2, valConsPk2, sdk.NewCoin(sdk.DefaultBondDenom, sdk.NewInt(100)), staking.Description{}, commission, sdk.OneInt()) - require.True(t, sh(ctx, msg).IsOK()) + res, err = sh(ctx, msg) + require.NoError(t, err) + require.NotNil(t, res) // create third validator with 10% commission commission = staking.NewCommissionRates(sdk.NewDecWithPrec(1, 1), sdk.NewDecWithPrec(1, 1), sdk.NewDec(0)) msg = staking.NewMsgCreateValidator(valOpAddr3, valConsPk3, sdk.NewCoin(sdk.DefaultBondDenom, sdk.NewInt(100)), staking.Description{}, commission, sdk.OneInt()) - require.True(t, sh(ctx, msg).IsOK()) + res, err = sh(ctx, msg) + require.NoError(t, err) + require.NotNil(t, res) abciValA := abci.Validator{ Address: valConsPk1.Address(), @@ -159,7 +177,7 @@ func TestAllocateTokensTruncation(t *testing.T) { feeCollector := supplyKeeper.GetModuleAccount(ctx, k.feeCollectorName) require.NotNil(t, feeCollector) - err := feeCollector.SetCoins(fees) + err = feeCollector.SetCoins(fees) require.NoError(t, err) ak.SetAccount(ctx, feeCollector) diff --git a/x/distribution/keeper/delegation.go b/x/distribution/keeper/delegation.go index 4044c4d1961a..7b28b6048eaf 100644 --- a/x/distribution/keeper/delegation.go +++ b/x/distribution/keeper/delegation.go @@ -136,10 +136,10 @@ func (k Keeper) calculateDelegationRewards(ctx sdk.Context, val exported.Validat return rewards } -func (k Keeper) withdrawDelegationRewards(ctx sdk.Context, val exported.ValidatorI, del exported.DelegationI) (sdk.Coins, sdk.Error) { +func (k Keeper) withdrawDelegationRewards(ctx sdk.Context, val exported.ValidatorI, del exported.DelegationI) (sdk.Coins, error) { // check existence of delegator starting info if !k.HasDelegatorStartingInfo(ctx, del.GetValidatorAddr(), del.GetDelegatorAddr()) { - return nil, types.ErrNoDelegationDistInfo(k.codespace) + return nil, types.ErrEmptyDelegationDistInfo } // end current period and calculate rewards diff --git a/x/distribution/keeper/delegation_test.go b/x/distribution/keeper/delegation_test.go index db6f6fb434ea..6d23ad958991 100644 --- a/x/distribution/keeper/delegation_test.go +++ b/x/distribution/keeper/delegation_test.go @@ -15,9 +15,13 @@ func TestCalculateRewardsBasic(t *testing.T) { // create validator with 50% commission commission := staking.NewCommissionRates(sdk.NewDecWithPrec(5, 1), sdk.NewDecWithPrec(5, 1), sdk.NewDec(0)) - msg := staking.NewMsgCreateValidator(valOpAddr1, valConsPk1, - sdk.NewCoin(sdk.DefaultBondDenom, sdk.NewInt(100)), staking.Description{}, commission, sdk.OneInt()) - require.True(t, sh(ctx, msg).IsOK()) + msg := staking.NewMsgCreateValidator( + valOpAddr1, valConsPk1, sdk.NewCoin(sdk.DefaultBondDenom, sdk.NewInt(100)), staking.Description{}, commission, sdk.OneInt(), + ) + + res, err := sh(ctx, msg) + require.NoError(t, err) + require.NotNil(t, res) // end block to bond validator staking.EndBlocker(ctx, sk) @@ -72,8 +76,10 @@ func TestCalculateRewardsAfterSlash(t *testing.T) { valTokens := sdk.TokensFromConsensusPower(valPower) msg := staking.NewMsgCreateValidator(valOpAddr1, valConsPk1, sdk.NewCoin(sdk.DefaultBondDenom, valTokens), staking.Description{}, commission, sdk.OneInt()) - got := sh(ctx, msg) - require.True(t, got.IsOK(), "%v", got) + + res, err := sh(ctx, msg) + require.NoError(t, err) + require.NotNil(t, res) // end block to bond validator staking.EndBlocker(ctx, sk) @@ -135,7 +141,10 @@ func TestCalculateRewardsAfterManySlashes(t *testing.T) { commission := staking.NewCommissionRates(sdk.NewDecWithPrec(5, 1), sdk.NewDecWithPrec(5, 1), sdk.NewDec(0)) msg := staking.NewMsgCreateValidator(valOpAddr1, valConsPk1, sdk.NewCoin(sdk.DefaultBondDenom, valTokens), staking.Description{}, commission, sdk.OneInt()) - require.True(t, sh(ctx, msg).IsOK()) + + res, err := sh(ctx, msg) + require.NoError(t, err) + require.NotNil(t, res) // end block to bond validator staking.EndBlocker(ctx, sk) @@ -207,7 +216,10 @@ func TestCalculateRewardsMultiDelegator(t *testing.T) { commission := staking.NewCommissionRates(sdk.NewDecWithPrec(5, 1), sdk.NewDecWithPrec(5, 1), sdk.NewDec(0)) msg := staking.NewMsgCreateValidator(valOpAddr1, valConsPk1, sdk.NewCoin(sdk.DefaultBondDenom, sdk.NewInt(100)), staking.Description{}, commission, sdk.OneInt()) - require.True(t, sh(ctx, msg).IsOK()) + + res, err := sh(ctx, msg) + require.NoError(t, err) + require.NotNil(t, res) // end block to bond validator staking.EndBlocker(ctx, sk) @@ -226,7 +238,11 @@ func TestCalculateRewardsMultiDelegator(t *testing.T) { // second delegation msg2 := staking.NewMsgDelegate(sdk.AccAddress(valOpAddr2), valOpAddr1, sdk.NewCoin(sdk.DefaultBondDenom, sdk.NewInt(100))) - require.True(t, sh(ctx, msg2).IsOK()) + + res, err = sh(ctx, msg2) + require.NoError(t, err) + require.NotNil(t, res) + del2 := sk.Delegation(ctx, sdk.AccAddress(valOpAddr2), valOpAddr1) // fetch updated validator @@ -280,7 +296,10 @@ func TestWithdrawDelegationRewardsBasic(t *testing.T) { sdk.NewCoin(sdk.DefaultBondDenom, valTokens), staking.Description{}, commission, sdk.OneInt(), ) - require.True(t, sh(ctx, msg).IsOK()) + + res, err := sh(ctx, msg) + require.NoError(t, err) + require.NotNil(t, res) // assert correct initial balance expTokens := balanceTokens.Sub(valTokens) @@ -308,7 +327,7 @@ func TestWithdrawDelegationRewardsBasic(t *testing.T) { require.Equal(t, uint64(2), k.GetValidatorHistoricalReferenceCount(ctx)) // withdraw rewards - _, err := k.WithdrawDelegationRewards(ctx, sdk.AccAddress(valOpAddr1), valOpAddr1) + _, err = k.WithdrawDelegationRewards(ctx, sdk.AccAddress(valOpAddr1), valOpAddr1) require.Nil(t, err) // historical count should still be 2 (added one record, cleared one) @@ -343,7 +362,10 @@ func TestCalculateRewardsAfterManySlashesInSameBlock(t *testing.T) { commission := staking.NewCommissionRates(sdk.NewDecWithPrec(5, 1), sdk.NewDecWithPrec(5, 1), sdk.NewDec(0)) msg := staking.NewMsgCreateValidator(valOpAddr1, valConsPk1, sdk.NewCoin(sdk.DefaultBondDenom, valTokens), staking.Description{}, commission, sdk.OneInt()) - require.True(t, sh(ctx, msg).IsOK()) + + res, err := sh(ctx, msg) + require.NoError(t, err) + require.NotNil(t, res) // end block to bond validator staking.EndBlocker(ctx, sk) @@ -410,7 +432,10 @@ func TestCalculateRewardsMultiDelegatorMultiSlash(t *testing.T) { valTokens := sdk.TokensFromConsensusPower(power) msg := staking.NewMsgCreateValidator(valOpAddr1, valConsPk1, sdk.NewCoin(sdk.DefaultBondDenom, valTokens), staking.Description{}, commission, sdk.OneInt()) - require.True(t, sh(ctx, msg).IsOK()) + + res, err := sh(ctx, msg) + require.NoError(t, err) + require.NotNil(t, res) // end block to bond validator staking.EndBlocker(ctx, sk) @@ -436,7 +461,11 @@ func TestCalculateRewardsMultiDelegatorMultiSlash(t *testing.T) { delTokens := sdk.TokensFromConsensusPower(100) msg2 := staking.NewMsgDelegate(sdk.AccAddress(valOpAddr2), valOpAddr1, sdk.NewCoin(sdk.DefaultBondDenom, delTokens)) - require.True(t, sh(ctx, msg2).IsOK()) + + res, err = sh(ctx, msg2) + require.NoError(t, err) + require.NotNil(t, res) + del2 := sk.Delegation(ctx, sdk.AccAddress(valOpAddr2), valOpAddr1) // end block @@ -491,7 +520,10 @@ func TestCalculateRewardsMultiDelegatorMultWithdraw(t *testing.T) { commission := staking.NewCommissionRates(sdk.NewDecWithPrec(5, 1), sdk.NewDecWithPrec(5, 1), sdk.NewDec(0)) msg := staking.NewMsgCreateValidator(valOpAddr1, valConsPk1, sdk.NewCoin(sdk.DefaultBondDenom, sdk.NewInt(100)), staking.Description{}, commission, sdk.OneInt()) - require.True(t, sh(ctx, msg).IsOK()) + + res, err := sh(ctx, msg) + require.NoError(t, err) + require.NotNil(t, res) // end block to bond validator staking.EndBlocker(ctx, sk) @@ -511,7 +543,9 @@ func TestCalculateRewardsMultiDelegatorMultWithdraw(t *testing.T) { // second delegation msg2 := staking.NewMsgDelegate(sdk.AccAddress(valOpAddr2), valOpAddr1, sdk.NewCoin(sdk.DefaultBondDenom, sdk.NewInt(100))) - require.True(t, sh(ctx, msg2).IsOK()) + res, err = sh(ctx, msg2) + require.NoError(t, err) + require.NotNil(t, res) // historical count should be 3 (second delegation init) require.Equal(t, uint64(3), k.GetValidatorHistoricalReferenceCount(ctx)) diff --git a/x/distribution/keeper/fee_pool.go b/x/distribution/keeper/fee_pool.go index a16e8258c029..34ad5f0d0d06 100644 --- a/x/distribution/keeper/fee_pool.go +++ b/x/distribution/keeper/fee_pool.go @@ -7,7 +7,7 @@ import ( // DistributeFromFeePool distributes funds from the distribution module account to // a receiver address while updating the community pool -func (k Keeper) DistributeFromFeePool(ctx sdk.Context, amount sdk.Coins, receiveAddr sdk.AccAddress) sdk.Error { +func (k Keeper) DistributeFromFeePool(ctx sdk.Context, amount sdk.Coins, receiveAddr sdk.AccAddress) error { feePool := k.GetFeePool(ctx) // NOTE the community pool isn't a module account, however its coins @@ -15,8 +15,9 @@ func (k Keeper) DistributeFromFeePool(ctx sdk.Context, amount sdk.Coins, receive // must be reduced separately from the SendCoinsFromModuleToAccount call newPool, negative := feePool.CommunityPool.SafeSub(sdk.NewDecCoins(amount)) if negative { - return types.ErrBadDistribution(k.codespace) + return types.ErrBadDistribution } + feePool.CommunityPool = newPool err := k.supplyKeeper.SendCoinsFromModuleToAccount(ctx, types.ModuleName, receiveAddr, amount) diff --git a/x/distribution/keeper/keeper.go b/x/distribution/keeper/keeper.go index 6aca0d86fa10..76b582bae209 100644 --- a/x/distribution/keeper/keeper.go +++ b/x/distribution/keeper/keeper.go @@ -5,6 +5,7 @@ import ( "github.com/cosmos/cosmos-sdk/codec" sdk "github.com/cosmos/cosmos-sdk/types" + sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" "github.com/cosmos/cosmos-sdk/x/distribution/types" "github.com/cosmos/cosmos-sdk/x/params" @@ -19,17 +20,17 @@ type Keeper struct { stakingKeeper types.StakingKeeper supplyKeeper types.SupplyKeeper - codespace sdk.CodespaceType - blacklistedAddrs map[string]bool feeCollectorName string // name of the FeeCollector ModuleAccount } // NewKeeper creates a new distribution Keeper instance -func NewKeeper(cdc *codec.Codec, key sdk.StoreKey, paramSpace params.Subspace, - sk types.StakingKeeper, supplyKeeper types.SupplyKeeper, codespace sdk.CodespaceType, - feeCollectorName string, blacklistedAddrs map[string]bool) Keeper { +func NewKeeper( + cdc *codec.Codec, key sdk.StoreKey, paramSpace params.Subspace, + sk types.StakingKeeper, supplyKeeper types.SupplyKeeper, feeCollectorName string, + blacklistedAddrs map[string]bool, +) Keeper { // ensure distribution module account is set if addr := supplyKeeper.GetModuleAddress(types.ModuleName); addr == nil { @@ -42,7 +43,6 @@ func NewKeeper(cdc *codec.Codec, key sdk.StoreKey, paramSpace params.Subspace, paramSpace: paramSpace.WithKeyTable(ParamKeyTable()), stakingKeeper: sk, supplyKeeper: supplyKeeper, - codespace: codespace, feeCollectorName: feeCollectorName, blacklistedAddrs: blacklistedAddrs, } @@ -54,13 +54,13 @@ func (k Keeper) Logger(ctx sdk.Context) log.Logger { } // SetWithdrawAddr sets a new address that will receive the rewards upon withdrawal -func (k Keeper) SetWithdrawAddr(ctx sdk.Context, delegatorAddr sdk.AccAddress, withdrawAddr sdk.AccAddress) sdk.Error { +func (k Keeper) SetWithdrawAddr(ctx sdk.Context, delegatorAddr sdk.AccAddress, withdrawAddr sdk.AccAddress) error { if k.blacklistedAddrs[withdrawAddr.String()] { - return sdk.ErrUnauthorized(fmt.Sprintf("%s is blacklisted from receiving external funds", withdrawAddr)) + return sdkerrors.Wrapf(sdkerrors.ErrUnauthorized, "%s is blacklisted from receiving external funds", withdrawAddr) } if !k.GetWithdrawAddrEnabled(ctx) { - return types.ErrSetWithdrawAddrDisabled(k.codespace) + return types.ErrSetWithdrawAddrDisabled } ctx.EventManager().EmitEvent( @@ -75,15 +75,15 @@ func (k Keeper) SetWithdrawAddr(ctx sdk.Context, delegatorAddr sdk.AccAddress, w } // withdraw rewards from a delegation -func (k Keeper) WithdrawDelegationRewards(ctx sdk.Context, delAddr sdk.AccAddress, valAddr sdk.ValAddress) (sdk.Coins, sdk.Error) { +func (k Keeper) WithdrawDelegationRewards(ctx sdk.Context, delAddr sdk.AccAddress, valAddr sdk.ValAddress) (sdk.Coins, error) { val := k.stakingKeeper.Validator(ctx, valAddr) if val == nil { - return nil, types.ErrNoValidatorDistInfo(k.codespace) + return nil, types.ErrNoValidatorDistInfo } del := k.stakingKeeper.Delegation(ctx, delAddr, valAddr) if del == nil { - return nil, types.ErrNoDelegationDistInfo(k.codespace) + return nil, types.ErrEmptyDelegationDistInfo } // withdraw rewards @@ -106,11 +106,11 @@ func (k Keeper) WithdrawDelegationRewards(ctx sdk.Context, delAddr sdk.AccAddres } // withdraw validator commission -func (k Keeper) WithdrawValidatorCommission(ctx sdk.Context, valAddr sdk.ValAddress) (sdk.Coins, sdk.Error) { +func (k Keeper) WithdrawValidatorCommission(ctx sdk.Context, valAddr sdk.ValAddress) (sdk.Coins, error) { // fetch validator accumulated commission accumCommission := k.GetValidatorAccumulatedCommission(ctx, valAddr) if accumCommission.IsZero() { - return nil, types.ErrNoValidatorCommission(k.codespace) + return nil, types.ErrNoValidatorCommission } commission, remainder := accumCommission.TruncateDecimal() @@ -147,6 +147,7 @@ func (k Keeper) GetTotalRewards(ctx sdk.Context) (totalRewards sdk.DecCoins) { return false }, ) + return totalRewards } diff --git a/x/distribution/keeper/proposal_handler.go b/x/distribution/keeper/proposal_handler.go index 2daf2245ed76..f60a3f88154d 100644 --- a/x/distribution/keeper/proposal_handler.go +++ b/x/distribution/keeper/proposal_handler.go @@ -4,13 +4,14 @@ import ( "fmt" sdk "github.com/cosmos/cosmos-sdk/types" + sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" "github.com/cosmos/cosmos-sdk/x/distribution/types" ) // HandleCommunityPoolSpendProposal is a handler for executing a passed community spend proposal -func HandleCommunityPoolSpendProposal(ctx sdk.Context, k Keeper, p types.CommunityPoolSpendProposal) sdk.Error { +func HandleCommunityPoolSpendProposal(ctx sdk.Context, k Keeper, p types.CommunityPoolSpendProposal) error { if k.blacklistedAddrs[p.Recipient.String()] { - return sdk.ErrUnauthorized(fmt.Sprintf("%s is blacklisted from receiving external funds", p.Recipient)) + return sdkerrors.Wrapf(sdkerrors.ErrUnauthorized, "%s is blacklisted from receiving external funds", p.Recipient) } err := k.DistributeFromFeePool(ctx, p.Amount, p.Recipient) diff --git a/x/distribution/keeper/querier.go b/x/distribution/keeper/querier.go index a057340340db..7e7c404cee14 100644 --- a/x/distribution/keeper/querier.go +++ b/x/distribution/keeper/querier.go @@ -2,18 +2,18 @@ package keeper import ( "encoding/json" - "fmt" abci "github.com/tendermint/tendermint/abci/types" "github.com/cosmos/cosmos-sdk/codec" sdk "github.com/cosmos/cosmos-sdk/types" + sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" "github.com/cosmos/cosmos-sdk/x/distribution/types" "github.com/cosmos/cosmos-sdk/x/staking/exported" ) func NewQuerier(k Keeper) sdk.Querier { - return func(ctx sdk.Context, path []string, req abci.RequestQuery) ([]byte, sdk.Error) { + return func(ctx sdk.Context, path []string, req abci.RequestQuery) ([]byte, error) { switch path[0] { case types.QueryParams: return queryParams(ctx, path[1:], req, k) @@ -43,82 +43,93 @@ func NewQuerier(k Keeper) sdk.Querier { return queryCommunityPool(ctx, path[1:], req, k) default: - return nil, sdk.ErrUnknownRequest("unknown distr query endpoint") + return nil, sdkerrors.Wrapf(sdkerrors.ErrUnknownRequest, "unknown query path: %s", path[0]) } } } -func queryParams(ctx sdk.Context, path []string, req abci.RequestQuery, k Keeper) ([]byte, sdk.Error) { +func queryParams(ctx sdk.Context, path []string, req abci.RequestQuery, k Keeper) ([]byte, error) { switch path[0] { case types.ParamCommunityTax: bz, err := codec.MarshalJSONIndent(k.cdc, k.GetCommunityTax(ctx)) if err != nil { - return nil, sdk.ErrInternal(sdk.AppendMsgToErr("could not marshal result to JSON", err.Error())) + return nil, sdkerrors.Wrap(sdkerrors.ErrJSONMarshal, err.Error()) } return bz, nil + case types.ParamBaseProposerReward: bz, err := codec.MarshalJSONIndent(k.cdc, k.GetBaseProposerReward(ctx)) if err != nil { - return nil, sdk.ErrInternal(sdk.AppendMsgToErr("could not marshal result to JSON", err.Error())) + return nil, sdkerrors.Wrap(sdkerrors.ErrJSONMarshal, err.Error()) } return bz, nil + case types.ParamBonusProposerReward: bz, err := codec.MarshalJSONIndent(k.cdc, k.GetBonusProposerReward(ctx)) if err != nil { - return nil, sdk.ErrInternal(sdk.AppendMsgToErr("could not marshal result to JSON", err.Error())) + return nil, sdkerrors.Wrap(sdkerrors.ErrJSONMarshal, err.Error()) } return bz, nil + case types.ParamWithdrawAddrEnabled: bz, err := codec.MarshalJSONIndent(k.cdc, k.GetWithdrawAddrEnabled(ctx)) if err != nil { - return nil, sdk.ErrInternal(sdk.AppendMsgToErr("could not marshal result to JSON", err.Error())) + return nil, sdkerrors.Wrap(sdkerrors.ErrJSONMarshal, err.Error()) } return bz, nil + default: - return nil, sdk.ErrUnknownRequest(fmt.Sprintf("%s is not a valid query request path", req.Path)) + return nil, sdkerrors.Wrapf(sdkerrors.ErrUnknownRequest, "%s is not a valid query request path", req.Path) } } -func queryValidatorOutstandingRewards(ctx sdk.Context, path []string, req abci.RequestQuery, k Keeper) ([]byte, sdk.Error) { +func queryValidatorOutstandingRewards(ctx sdk.Context, path []string, req abci.RequestQuery, k Keeper) ([]byte, error) { var params types.QueryValidatorOutstandingRewardsParams err := k.cdc.UnmarshalJSON(req.Data, ¶ms) if err != nil { - return nil, sdk.ErrUnknownRequest(sdk.AppendMsgToErr("incorrectly formatted request data", err.Error())) + return nil, sdkerrors.Wrap(sdkerrors.ErrJSONUnmarshal, err.Error()) } + rewards := k.GetValidatorOutstandingRewards(ctx, params.ValidatorAddress) if rewards == nil { rewards = sdk.DecCoins{} } + bz, err := codec.MarshalJSONIndent(k.cdc, rewards) if err != nil { - return nil, sdk.ErrInternal(sdk.AppendMsgToErr("could not marshal result to JSON", err.Error())) + return nil, sdkerrors.Wrap(sdkerrors.ErrJSONMarshal, err.Error()) } + return bz, nil } -func queryValidatorCommission(ctx sdk.Context, path []string, req abci.RequestQuery, k Keeper) ([]byte, sdk.Error) { +func queryValidatorCommission(ctx sdk.Context, path []string, req abci.RequestQuery, k Keeper) ([]byte, error) { var params types.QueryValidatorCommissionParams err := k.cdc.UnmarshalJSON(req.Data, ¶ms) if err != nil { - return nil, sdk.ErrUnknownRequest(sdk.AppendMsgToErr("incorrectly formatted request data", err.Error())) + return nil, sdkerrors.Wrap(sdkerrors.ErrJSONUnmarshal, err.Error()) } + commission := k.GetValidatorAccumulatedCommission(ctx, params.ValidatorAddress) if commission == nil { commission = sdk.DecCoins{} } + bz, err := codec.MarshalJSONIndent(k.cdc, commission) if err != nil { - return nil, sdk.ErrInternal(sdk.AppendMsgToErr("could not marshal result to JSON", err.Error())) + return nil, sdkerrors.Wrap(sdkerrors.ErrJSONMarshal, err.Error()) } + return bz, nil } -func queryValidatorSlashes(ctx sdk.Context, path []string, req abci.RequestQuery, k Keeper) ([]byte, sdk.Error) { +func queryValidatorSlashes(ctx sdk.Context, path []string, req abci.RequestQuery, k Keeper) ([]byte, error) { var params types.QueryValidatorSlashesParams err := k.cdc.UnmarshalJSON(req.Data, ¶ms) if err != nil { - return nil, sdk.ErrUnknownRequest(sdk.AppendMsgToErr("incorrectly formatted request data", err.Error())) + return nil, sdkerrors.Wrap(sdkerrors.ErrJSONUnmarshal, err.Error()) } + events := make([]types.ValidatorSlashEvent, 0) k.IterateValidatorSlashEventsBetween(ctx, params.ValidatorAddress, params.StartingHeight, params.EndingHeight, func(height uint64, event types.ValidatorSlashEvent) (stop bool) { @@ -126,18 +137,20 @@ func queryValidatorSlashes(ctx sdk.Context, path []string, req abci.RequestQuery return false }, ) + bz, err := codec.MarshalJSONIndent(k.cdc, events) if err != nil { - return nil, sdk.ErrInternal(sdk.AppendMsgToErr("could not marshal result to JSON", err.Error())) + return nil, sdkerrors.Wrap(sdkerrors.ErrJSONMarshal, err.Error()) } + return bz, nil } -func queryDelegationRewards(ctx sdk.Context, _ []string, req abci.RequestQuery, k Keeper) ([]byte, sdk.Error) { +func queryDelegationRewards(ctx sdk.Context, _ []string, req abci.RequestQuery, k Keeper) ([]byte, error) { var params types.QueryDelegationRewardsParams err := k.cdc.UnmarshalJSON(req.Data, ¶ms) if err != nil { - return nil, sdk.ErrUnknownRequest(sdk.AppendMsgToErr("incorrectly formatted request data", err.Error())) + return nil, sdkerrors.Wrap(sdkerrors.ErrJSONUnmarshal, err.Error()) } // cache-wrap context as to not persist state changes during querying @@ -145,14 +158,12 @@ func queryDelegationRewards(ctx sdk.Context, _ []string, req abci.RequestQuery, val := k.stakingKeeper.Validator(ctx, params.ValidatorAddress) if val == nil { - // TODO: Should use ErrNoValidatorFound from staking/types - return nil, sdk.ErrInternal(fmt.Sprintf("validator %s does not exist", params.ValidatorAddress)) + return nil, sdkerrors.Wrap(types.ErrNoValidatorExists, params.ValidatorAddress.String()) } del := k.stakingKeeper.Delegation(ctx, params.DelegatorAddress, params.ValidatorAddress) if del == nil { - // TODO: Should use ErrNoDelegation from staking/types - return nil, sdk.ErrInternal("delegation does not exist") + return nil, types.ErrNoDelegationExists } endingPeriod := k.incrementValidatorPeriod(ctx, val) @@ -163,17 +174,17 @@ func queryDelegationRewards(ctx sdk.Context, _ []string, req abci.RequestQuery, bz, err := codec.MarshalJSONIndent(k.cdc, rewards) if err != nil { - return nil, sdk.ErrInternal(sdk.AppendMsgToErr("could not marshal result to JSON", err.Error())) + return nil, sdkerrors.Wrap(sdkerrors.ErrJSONMarshal, err.Error()) } return bz, nil } -func queryDelegatorTotalRewards(ctx sdk.Context, _ []string, req abci.RequestQuery, k Keeper) ([]byte, sdk.Error) { +func queryDelegatorTotalRewards(ctx sdk.Context, _ []string, req abci.RequestQuery, k Keeper) ([]byte, error) { var params types.QueryDelegatorParams err := k.cdc.UnmarshalJSON(req.Data, ¶ms) if err != nil { - return nil, sdk.ErrUnknownRequest(sdk.AppendMsgToErr("incorrectly formatted request data", err.Error())) + return nil, sdkerrors.Wrap(sdkerrors.ErrJSONUnmarshal, err.Error()) } // cache-wrap context as to not persist state changes during querying @@ -192,24 +203,26 @@ func queryDelegatorTotalRewards(ctx sdk.Context, _ []string, req abci.RequestQue delRewards = append(delRewards, types.NewDelegationDelegatorReward(valAddr, delReward)) total = total.Add(delReward) + return false }, ) totalRewards := types.NewQueryDelegatorTotalRewardsResponse(delRewards, total) + bz, err := json.Marshal(totalRewards) if err != nil { - return nil, sdk.ErrInternal(sdk.AppendMsgToErr("could not marshal result to JSON", err.Error())) + return nil, sdkerrors.Wrap(sdkerrors.ErrJSONMarshal, err.Error()) } return bz, nil } -func queryDelegatorValidators(ctx sdk.Context, _ []string, req abci.RequestQuery, k Keeper) ([]byte, sdk.Error) { +func queryDelegatorValidators(ctx sdk.Context, _ []string, req abci.RequestQuery, k Keeper) ([]byte, error) { var params types.QueryDelegatorParams err := k.cdc.UnmarshalJSON(req.Data, ¶ms) if err != nil { - return nil, sdk.ErrUnknownRequest(sdk.AppendMsgToErr("incorrectly formatted request data", err.Error())) + return nil, sdkerrors.Wrap(sdkerrors.ErrJSONUnmarshal, err.Error()) } // cache-wrap context as to not persist state changes during querying @@ -227,16 +240,17 @@ func queryDelegatorValidators(ctx sdk.Context, _ []string, req abci.RequestQuery bz, err := codec.MarshalJSONIndent(k.cdc, validators) if err != nil { - return nil, sdk.ErrInternal(sdk.AppendMsgToErr("could not marshal result to JSON", err.Error())) + return nil, sdkerrors.Wrap(sdkerrors.ErrJSONMarshal, err.Error()) } + return bz, nil } -func queryDelegatorWithdrawAddress(ctx sdk.Context, _ []string, req abci.RequestQuery, k Keeper) ([]byte, sdk.Error) { +func queryDelegatorWithdrawAddress(ctx sdk.Context, _ []string, req abci.RequestQuery, k Keeper) ([]byte, error) { var params types.QueryDelegatorWithdrawAddrParams err := k.cdc.UnmarshalJSON(req.Data, ¶ms) if err != nil { - return nil, sdk.ErrUnknownRequest(sdk.AppendMsgToErr("incorrectly formatted request data", err.Error())) + return nil, sdkerrors.Wrap(sdkerrors.ErrJSONUnmarshal, err.Error()) } // cache-wrap context as to not persist state changes during querying @@ -245,20 +259,22 @@ func queryDelegatorWithdrawAddress(ctx sdk.Context, _ []string, req abci.Request bz, err := codec.MarshalJSONIndent(k.cdc, withdrawAddr) if err != nil { - return nil, sdk.ErrInternal(sdk.AppendMsgToErr("could not marshal result to JSON", err.Error())) + return nil, sdkerrors.Wrap(sdkerrors.ErrJSONMarshal, err.Error()) } return bz, nil } -func queryCommunityPool(ctx sdk.Context, _ []string, req abci.RequestQuery, k Keeper) ([]byte, sdk.Error) { +func queryCommunityPool(ctx sdk.Context, _ []string, req abci.RequestQuery, k Keeper) ([]byte, error) { pool := k.GetFeePoolCommunityCoins(ctx) if pool == nil { pool = sdk.DecCoins{} } + bz, err := k.cdc.MarshalJSON(pool) if err != nil { - return nil, sdk.ErrInternal(sdk.AppendMsgToErr("could not marshal result to JSON", err.Error())) + return nil, sdkerrors.Wrap(sdkerrors.ErrJSONMarshal, err.Error()) } + return bz, nil } diff --git a/x/distribution/keeper/querier_test.go b/x/distribution/keeper/querier_test.go index 2a2d1455f9db..e70ca2ea0f4b 100644 --- a/x/distribution/keeper/querier_test.go +++ b/x/distribution/keeper/querier_test.go @@ -189,10 +189,16 @@ func TestQueries(t *testing.T) { // test delegation rewards query sh := staking.NewHandler(sk) comm := staking.NewCommissionRates(sdk.NewDecWithPrec(5, 1), sdk.NewDecWithPrec(5, 1), sdk.NewDec(0)) - msg := staking.NewMsgCreateValidator(valOpAddr1, valConsPk1, - sdk.NewCoin(sdk.DefaultBondDenom, sdk.NewInt(100)), staking.Description{}, comm, sdk.OneInt()) - require.True(t, sh(ctx, msg).IsOK()) + msg := staking.NewMsgCreateValidator( + valOpAddr1, valConsPk1, sdk.NewCoin(sdk.DefaultBondDenom, sdk.NewInt(100)), staking.Description{}, comm, sdk.OneInt(), + ) + + res, err := sh(ctx, msg) + require.NoError(t, err) + require.NotNil(t, res) + staking.EndBlocker(ctx, sk) + val := sk.Validator(ctx, valOpAddr1) rewards := getQueriedDelegationRewards(t, ctx, cdc, querier, sdk.AccAddress(valOpAddr1), valOpAddr1) require.True(t, rewards.IsZero()) diff --git a/x/distribution/keeper/test_common.go b/x/distribution/keeper/test_common.go index 73c709e317e1..1d53c9d1816a 100644 --- a/x/distribution/keeper/test_common.go +++ b/x/distribution/keeper/test_common.go @@ -119,11 +119,11 @@ func CreateTestInputAdvanced(t *testing.T, isCheckTx bool, initPower int64, blacklistedAddrs[distrAcc.GetAddress().String()] = true cdc := MakeTestCodec() - pk := params.NewKeeper(cdc, keyParams, tkeyParams, params.DefaultCodespace) + pk := params.NewKeeper(cdc, keyParams, tkeyParams) ctx := sdk.NewContext(ms, abci.Header{ChainID: "foochainid"}, isCheckTx, log.NewNopLogger()) accountKeeper := auth.NewAccountKeeper(cdc, keyAcc, pk.Subspace(auth.DefaultParamspace), auth.ProtoBaseAccount) - bankKeeper := bank.NewBaseKeeper(accountKeeper, pk.Subspace(bank.DefaultParamspace), bank.DefaultCodespace, blacklistedAddrs) + bankKeeper := bank.NewBaseKeeper(accountKeeper, pk.Subspace(bank.DefaultParamspace), blacklistedAddrs) maccPerms := map[string][]string{ auth.FeeCollectorName: nil, types.ModuleName: nil, @@ -132,10 +132,10 @@ func CreateTestInputAdvanced(t *testing.T, isCheckTx bool, initPower int64, } supplyKeeper := supply.NewKeeper(cdc, keySupply, accountKeeper, bankKeeper, maccPerms) - sk := staking.NewKeeper(cdc, keyStaking, supplyKeeper, pk.Subspace(staking.DefaultParamspace), staking.DefaultCodespace) + sk := staking.NewKeeper(cdc, keyStaking, supplyKeeper, pk.Subspace(staking.DefaultParamspace)) sk.SetParams(ctx, staking.DefaultParams()) - keeper := NewKeeper(cdc, keyDistr, pk.Subspace(DefaultParamspace), sk, supplyKeeper, types.DefaultCodespace, auth.FeeCollectorName, blacklistedAddrs) + keeper := NewKeeper(cdc, keyDistr, pk.Subspace(DefaultParamspace), sk, supplyKeeper, auth.FeeCollectorName, blacklistedAddrs) initCoins := sdk.NewCoins(sdk.NewCoin(sk.BondDenom(ctx), initTokens)) totalSupply := sdk.NewCoins(sdk.NewCoin(sk.BondDenom(ctx), initTokens.MulRaw(int64(len(TestAddrs))))) diff --git a/x/distribution/simulation/operations.go b/x/distribution/simulation/operations.go index 9a9dea6b8d4b..d2857e6c5aff 100644 --- a/x/distribution/simulation/operations.go +++ b/x/distribution/simulation/operations.go @@ -1,7 +1,6 @@ package simulation import ( - "errors" "fmt" "math/rand" @@ -109,9 +108,9 @@ func SimulateMsgSetWithdrawAddress(ak types.AccountKeeper, k keeper.Keeper) simu simAccount.PrivKey, ) - res := app.Deliver(tx) - if !res.IsOK() { - return simulation.NoOpMsg(types.ModuleName), nil, errors.New(res.Log) + _, _, err = app.Deliver(tx) + if err != nil { + return simulation.NoOpMsg(types.ModuleName), nil, err } return simulation.NewOperationMsg(msg, true, ""), nil, nil @@ -155,9 +154,9 @@ func SimulateMsgWithdrawDelegatorReward(ak types.AccountKeeper, k keeper.Keeper, simAccount.PrivKey, ) - res := app.Deliver(tx) - if !res.IsOK() { - return simulation.NoOpMsg(types.ModuleName), nil, errors.New(res.Log) + _, _, err = app.Deliver(tx) + if err != nil { + return simulation.NoOpMsg(types.ModuleName), nil, err } return simulation.NewOperationMsg(msg, true, ""), nil, nil @@ -204,9 +203,9 @@ func SimulateMsgWithdrawValidatorCommission(ak types.AccountKeeper, k keeper.Kee simAccount.PrivKey, ) - res := app.Deliver(tx) - if !res.IsOK() { - return simulation.NoOpMsg(types.ModuleName), nil, errors.New(res.Log) + _, _, err = app.Deliver(tx) + if err != nil { + return simulation.NoOpMsg(types.ModuleName), nil, err } return simulation.NewOperationMsg(msg, true, ""), nil, nil @@ -254,9 +253,9 @@ func SimulateMsgFundCommunityPool(ak types.AccountKeeper, k keeper.Keeper, sk st funder.PrivKey, ) - res := app.Deliver(tx) - if !res.IsOK() { - return simulation.NoOpMsg(types.ModuleName), nil, errors.New(res.Log) + _, _, err = app.Deliver(tx) + if err != nil { + return simulation.NoOpMsg(types.ModuleName), nil, err } return simulation.NewOperationMsg(msg, true, ""), nil, nil diff --git a/x/distribution/types/errors.go b/x/distribution/types/errors.go index 2b6394114133..c06b731b6ee4 100644 --- a/x/distribution/types/errors.go +++ b/x/distribution/types/errors.go @@ -1,47 +1,21 @@ -// nolint package types import ( - sdk "github.com/cosmos/cosmos-sdk/types" + sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" ) -type CodeType = sdk.CodeType - -const ( - DefaultCodespace sdk.CodespaceType = "distr" - CodeInvalidInput CodeType = 103 - CodeNoDistributionInfo CodeType = 104 - CodeNoValidatorCommission CodeType = 105 - CodeSetWithdrawAddrDisabled CodeType = 106 +// x/distribution module sentinel errors +var ( + ErrEmptyDelegatorAddr = sdkerrors.Register(ModuleName, 1, "delegator address is empty") + ErrEmptyWithdrawAddr = sdkerrors.Register(ModuleName, 2, "withdraw address is empty") + ErrEmptyValidatorAddr = sdkerrors.Register(ModuleName, 3, "validator address is empty") + ErrEmptyDelegationDistInfo = sdkerrors.Register(ModuleName, 4, "no delegation distribution info") + ErrNoValidatorDistInfo = sdkerrors.Register(ModuleName, 5, "no validator distribution info") + ErrNoValidatorCommission = sdkerrors.Register(ModuleName, 6, "no validator commission to withdraw") + ErrSetWithdrawAddrDisabled = sdkerrors.Register(ModuleName, 7, "set withdraw address disabled") + ErrBadDistribution = sdkerrors.Register(ModuleName, 8, "community pool does not have sufficient coins to distribute") + ErrInvalidProposalAmount = sdkerrors.Register(ModuleName, 9, "invalid community pool spend proposal amount") + ErrEmptyProposalRecipient = sdkerrors.Register(ModuleName, 10, "invalid community pool spend proposal recipient") + ErrNoValidatorExists = sdkerrors.Register(ModuleName, 11, "validator does not exist") + ErrNoDelegationExists = sdkerrors.Register(ModuleName, 12, "delegation does not exist") ) - -func ErrNilDelegatorAddr(codespace sdk.CodespaceType) sdk.Error { - return sdk.NewError(codespace, CodeInvalidInput, "delegator address is nil") -} -func ErrNilWithdrawAddr(codespace sdk.CodespaceType) sdk.Error { - return sdk.NewError(codespace, CodeInvalidInput, "withdraw address is nil") -} -func ErrNilValidatorAddr(codespace sdk.CodespaceType) sdk.Error { - return sdk.NewError(codespace, CodeInvalidInput, "validator address is nil") -} -func ErrNoDelegationDistInfo(codespace sdk.CodespaceType) sdk.Error { - return sdk.NewError(codespace, CodeNoDistributionInfo, "no delegation distribution info") -} -func ErrNoValidatorDistInfo(codespace sdk.CodespaceType) sdk.Error { - return sdk.NewError(codespace, CodeNoDistributionInfo, "no validator distribution info") -} -func ErrNoValidatorCommission(codespace sdk.CodespaceType) sdk.Error { - return sdk.NewError(codespace, CodeNoValidatorCommission, "no validator commission to withdraw") -} -func ErrSetWithdrawAddrDisabled(codespace sdk.CodespaceType) sdk.Error { - return sdk.NewError(codespace, CodeSetWithdrawAddrDisabled, "set withdraw address disabled") -} -func ErrBadDistribution(codespace sdk.CodespaceType) sdk.Error { - return sdk.NewError(codespace, CodeInvalidInput, "community pool does not have sufficient coins to distribute") -} -func ErrInvalidProposalAmount(codespace sdk.CodespaceType) sdk.Error { - return sdk.NewError(codespace, CodeInvalidInput, "invalid community pool spend proposal amount") -} -func ErrEmptyProposalRecipient(codespace sdk.CodespaceType) sdk.Error { - return sdk.NewError(codespace, CodeInvalidInput, "invalid community pool spend proposal recipient") -} diff --git a/x/distribution/types/expected_keepers.go b/x/distribution/types/expected_keepers.go index a51bc9d0403f..faa2f37235da 100644 --- a/x/distribution/types/expected_keepers.go +++ b/x/distribution/types/expected_keepers.go @@ -70,7 +70,7 @@ type SupplyKeeper interface { // TODO remove with genesis 2-phases refactor https://github.com/cosmos/cosmos-sdk/issues/2862 SetModuleAccount(sdk.Context, supplyexported.ModuleAccountI) - SendCoinsFromModuleToModule(ctx sdk.Context, senderModule string, recipientModule string, amt sdk.Coins) sdk.Error - SendCoinsFromModuleToAccount(ctx sdk.Context, senderModule string, recipientAddr sdk.AccAddress, amt sdk.Coins) sdk.Error - SendCoinsFromAccountToModule(ctx sdk.Context, senderAddr sdk.AccAddress, recipientModule string, amt sdk.Coins) sdk.Error + SendCoinsFromModuleToModule(ctx sdk.Context, senderModule string, recipientModule string, amt sdk.Coins) error + SendCoinsFromModuleToAccount(ctx sdk.Context, senderModule string, recipientAddr sdk.AccAddress, amt sdk.Coins) error + SendCoinsFromAccountToModule(ctx sdk.Context, senderAddr sdk.AccAddress, recipientModule string, amt sdk.Coins) error } diff --git a/x/distribution/types/msg.go b/x/distribution/types/msg.go index 408983cb0ff2..2068caef149e 100644 --- a/x/distribution/types/msg.go +++ b/x/distribution/types/msg.go @@ -3,6 +3,7 @@ package types import ( sdk "github.com/cosmos/cosmos-sdk/types" + sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" ) // Verify interface at compile time @@ -36,13 +37,14 @@ func (msg MsgSetWithdrawAddress) GetSignBytes() []byte { } // quick validity check -func (msg MsgSetWithdrawAddress) ValidateBasic() sdk.Error { +func (msg MsgSetWithdrawAddress) ValidateBasic() error { if msg.DelegatorAddress.Empty() { - return ErrNilDelegatorAddr(DefaultCodespace) + return ErrEmptyDelegatorAddr } if msg.WithdrawAddress.Empty() { - return ErrNilWithdrawAddr(DefaultCodespace) + return ErrEmptyWithdrawAddr } + return nil } @@ -74,12 +76,12 @@ func (msg MsgWithdrawDelegatorReward) GetSignBytes() []byte { } // quick validity check -func (msg MsgWithdrawDelegatorReward) ValidateBasic() sdk.Error { +func (msg MsgWithdrawDelegatorReward) ValidateBasic() error { if msg.DelegatorAddress.Empty() { - return ErrNilDelegatorAddr(DefaultCodespace) + return ErrEmptyDelegatorAddr } if msg.ValidatorAddress.Empty() { - return ErrNilValidatorAddr(DefaultCodespace) + return ErrEmptyValidatorAddr } return nil } @@ -110,9 +112,9 @@ func (msg MsgWithdrawValidatorCommission) GetSignBytes() []byte { } // quick validity check -func (msg MsgWithdrawValidatorCommission) ValidateBasic() sdk.Error { +func (msg MsgWithdrawValidatorCommission) ValidateBasic() error { if msg.ValidatorAddress.Empty() { - return ErrNilValidatorAddr(DefaultCodespace) + return ErrEmptyValidatorAddr } return nil } @@ -155,12 +157,12 @@ func (msg MsgFundCommunityPool) GetSignBytes() []byte { } // ValidateBasic performs basic MsgFundCommunityPool message validation. -func (msg MsgFundCommunityPool) ValidateBasic() sdk.Error { +func (msg MsgFundCommunityPool) ValidateBasic() error { if !msg.Amount.IsValid() { - return sdk.ErrInvalidCoins(msg.Amount.String()) + return sdkerrors.Wrap(sdkerrors.ErrInvalidCoins, msg.Amount.String()) } if msg.Depositor.Empty() { - return sdk.ErrInvalidAddress(msg.Depositor.String()) + return sdkerrors.Wrap(sdkerrors.ErrInvalidAddress, msg.Depositor.String()) } return nil diff --git a/x/distribution/types/proposal.go b/x/distribution/types/proposal.go index 0562d81df18d..931e111ba719 100644 --- a/x/distribution/types/proposal.go +++ b/x/distribution/types/proposal.go @@ -47,17 +47,18 @@ func (csp CommunityPoolSpendProposal) ProposalRoute() string { return RouterKey func (csp CommunityPoolSpendProposal) ProposalType() string { return ProposalTypeCommunityPoolSpend } // ValidateBasic runs basic stateless validity checks -func (csp CommunityPoolSpendProposal) ValidateBasic() sdk.Error { - err := govtypes.ValidateAbstract(DefaultCodespace, csp) +func (csp CommunityPoolSpendProposal) ValidateBasic() error { + err := govtypes.ValidateAbstract(csp) if err != nil { return err } if !csp.Amount.IsValid() { - return ErrInvalidProposalAmount(DefaultCodespace) + return ErrInvalidProposalAmount } if csp.Recipient.Empty() { - return ErrEmptyProposalRecipient(DefaultCodespace) + return ErrEmptyProposalRecipient } + return nil } diff --git a/x/evidence/alias.go b/x/evidence/alias.go index 411f39751578..29b8447a365e 100644 --- a/x/evidence/alias.go +++ b/x/evidence/alias.go @@ -8,23 +8,19 @@ import ( // nolint const ( - ModuleName = types.ModuleName - StoreKey = types.StoreKey - RouterKey = types.RouterKey - QuerierRoute = types.QuerierRoute - DefaultParamspace = types.DefaultParamspace - QueryEvidence = types.QueryEvidence - QueryAllEvidence = types.QueryAllEvidence - QueryParameters = types.QueryParameters - CodeNoEvidenceHandlerExists = types.CodeNoEvidenceHandlerExists - CodeInvalidEvidence = types.CodeInvalidEvidence - CodeNoEvidenceExists = types.CodeNoEvidenceExists - TypeMsgSubmitEvidence = types.TypeMsgSubmitEvidence - DefaultCodespace = types.DefaultCodespace - EventTypeSubmitEvidence = types.EventTypeSubmitEvidence - AttributeValueCategory = types.AttributeValueCategory - AttributeKeyEvidenceHash = types.AttributeKeyEvidenceHash - DefaultMaxEvidenceAge = types.DefaultMaxEvidenceAge + ModuleName = types.ModuleName + StoreKey = types.StoreKey + RouterKey = types.RouterKey + QuerierRoute = types.QuerierRoute + DefaultParamspace = types.DefaultParamspace + QueryEvidence = types.QueryEvidence + QueryAllEvidence = types.QueryAllEvidence + QueryParameters = types.QueryParameters + TypeMsgSubmitEvidence = types.TypeMsgSubmitEvidence + EventTypeSubmitEvidence = types.EventTypeSubmitEvidence + AttributeValueCategory = types.AttributeValueCategory + AttributeKeyEvidenceHash = types.AttributeKeyEvidenceHash + DefaultMaxEvidenceAge = types.DefaultMaxEvidenceAge ) var ( diff --git a/x/evidence/client/cli/query.go b/x/evidence/client/cli/query.go index 4c5eb13abaf1..b4a1dffd0af5 100644 --- a/x/evidence/client/cli/query.go +++ b/x/evidence/client/cli/query.go @@ -10,6 +10,7 @@ import ( "github.com/cosmos/cosmos-sdk/client" "github.com/cosmos/cosmos-sdk/client/context" + "github.com/cosmos/cosmos-sdk/client/flags" "github.com/cosmos/cosmos-sdk/codec" "github.com/cosmos/cosmos-sdk/version" "github.com/cosmos/cosmos-sdk/x/evidence/exported" @@ -46,9 +47,9 @@ $ %s query %s --page=2 --limit=50 cmd.Flags().Int(flagPage, 1, "pagination page of evidence to to query for") cmd.Flags().Int(flagLimit, 100, "pagination limit of evidence to query for") - cmd.AddCommand(client.GetCommands(QueryParamsCmd(cdc))...) + cmd.AddCommand(flags.GetCommands(QueryParamsCmd(cdc))...) - return client.GetCommands(cmd)[0] + return flags.GetCommands(cmd)[0] } // QueryParamsCmd returns the command handler for evidence parameter querying. diff --git a/x/evidence/client/cli/tx.go b/x/evidence/client/cli/tx.go index 7cf6c5f6eadb..b97b56c0a23d 100644 --- a/x/evidence/client/cli/tx.go +++ b/x/evidence/client/cli/tx.go @@ -2,6 +2,7 @@ package cli import ( "github.com/cosmos/cosmos-sdk/client" + "github.com/cosmos/cosmos-sdk/client/flags" "github.com/cosmos/cosmos-sdk/codec" "github.com/cosmos/cosmos-sdk/x/evidence/internal/types" @@ -24,7 +25,7 @@ func GetTxCmd(storeKey string, cdc *codec.Codec, childCmds []*cobra.Command) *co submitEvidenceCmd := SubmitEvidenceCmd(cdc) for _, childCmd := range childCmds { - submitEvidenceCmd.AddCommand(client.PostCommands(childCmd)[0]) + submitEvidenceCmd.AddCommand(flags.PostCommands(childCmd)[0]) } // TODO: Add tx commands. diff --git a/x/evidence/genesis_test.go b/x/evidence/genesis_test.go index a77b847db177..10a8a2c75730 100644 --- a/x/evidence/genesis_test.go +++ b/x/evidence/genesis_test.go @@ -32,8 +32,7 @@ func (suite *GenesisTestSuite) SetupTest() { // recreate keeper in order to use custom testing types evidenceKeeper := evidence.NewKeeper( - cdc, app.GetKey(evidence.StoreKey), app.GetSubspace(evidence.ModuleName), - evidence.DefaultCodespace, app.StakingKeeper, app.SlashingKeeper, + cdc, app.GetKey(evidence.StoreKey), app.GetSubspace(evidence.ModuleName), app.StakingKeeper, app.SlashingKeeper, ) router := evidence.NewRouter() router = router.AddRoute(types.TestEvidenceRouteEquivocation, types.TestEquivocationHandler(*evidenceKeeper)) diff --git a/x/evidence/handler.go b/x/evidence/handler.go index 714da444c444..d5af1206bc01 100644 --- a/x/evidence/handler.go +++ b/x/evidence/handler.go @@ -1,13 +1,12 @@ package evidence import ( - "fmt" - sdk "github.com/cosmos/cosmos-sdk/types" + sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" ) func NewHandler(k Keeper) sdk.Handler { - return func(ctx sdk.Context, msg sdk.Msg) sdk.Result { + return func(ctx sdk.Context, msg sdk.Msg) (*sdk.Result, error) { ctx = ctx.WithEventManager(sdk.NewEventManager()) switch msg := msg.(type) { @@ -15,14 +14,14 @@ func NewHandler(k Keeper) sdk.Handler { return handleMsgSubmitEvidence(ctx, k, msg) default: - return sdk.ErrUnknownRequest(fmt.Sprintf("unrecognized %s message type: %T", ModuleName, msg)).Result() + return nil, sdkerrors.Wrapf(sdkerrors.ErrUnknownRequest, "unrecognized %s message type: %T", ModuleName, msg) } } } -func handleMsgSubmitEvidence(ctx sdk.Context, k Keeper, msg MsgSubmitEvidence) sdk.Result { +func handleMsgSubmitEvidence(ctx sdk.Context, k Keeper, msg MsgSubmitEvidence) (*sdk.Result, error) { if err := k.SubmitEvidence(ctx, msg.Evidence); err != nil { - return sdk.ConvertError(err).Result() + return nil, err } ctx.EventManager().EmitEvent( @@ -33,8 +32,8 @@ func handleMsgSubmitEvidence(ctx sdk.Context, k Keeper, msg MsgSubmitEvidence) s ), ) - return sdk.Result{ + return &sdk.Result{ Data: msg.Evidence.Hash(), Events: ctx.EventManager().Events(), - } + }, nil } diff --git a/x/evidence/handler_test.go b/x/evidence/handler_test.go index 1957778950ad..e5798bd01482 100644 --- a/x/evidence/handler_test.go +++ b/x/evidence/handler_test.go @@ -31,8 +31,7 @@ func (suite *HandlerTestSuite) SetupTest() { // recreate keeper in order to use custom testing types evidenceKeeper := evidence.NewKeeper( - cdc, app.GetKey(evidence.StoreKey), app.GetSubspace(evidence.ModuleName), - evidence.DefaultCodespace, app.StakingKeeper, app.SlashingKeeper, + cdc, app.GetKey(evidence.StoreKey), app.GetSubspace(evidence.ModuleName), app.StakingKeeper, app.SlashingKeeper, ) router := evidence.NewRouter() router = router.AddRoute(types.TestEvidenceRouteEquivocation, types.TestEquivocationHandler(*evidenceKeeper)) @@ -66,8 +65,9 @@ func (suite *HandlerTestSuite) TestMsgSubmitEvidence_Valid() { ctx := suite.ctx.WithIsCheckTx(false) msg := evidence.NewMsgSubmitEvidence(e, s) - res := suite.handler(ctx, msg) - suite.True(res.IsOK()) + res, err := suite.handler(ctx, msg) + suite.NoError(err) + suite.NotNil(res) suite.Equal(e.Hash().Bytes(), res.Data) } @@ -94,8 +94,9 @@ func (suite *HandlerTestSuite) TestMsgSubmitEvidence_Invalid() { ctx := suite.ctx.WithIsCheckTx(false) msg := evidence.NewMsgSubmitEvidence(e, s) - res := suite.handler(ctx, msg) - suite.False(res.IsOK()) + res, err := suite.handler(ctx, msg) + suite.Error(err) + suite.Nil(res) } func TestHandlerTestSuite(t *testing.T) { diff --git a/x/evidence/internal/keeper/infraction_test.go b/x/evidence/internal/keeper/infraction_test.go index ca68948f5eb1..cbef53de1921 100644 --- a/x/evidence/internal/keeper/infraction_test.go +++ b/x/evidence/internal/keeper/infraction_test.go @@ -28,8 +28,9 @@ func (suite *KeeperTestSuite) TestHandleDoubleSign() { operatorAddr, val := valAddresses[0], pubkeys[0] // create validator - res := staking.NewHandler(suite.app.StakingKeeper)(ctx, newTestMsgCreateValidator(operatorAddr, val, amt)) - suite.True(res.IsOK(), res.Log) + res, err := staking.NewHandler(suite.app.StakingKeeper)(ctx, newTestMsgCreateValidator(operatorAddr, val, amt)) + suite.NoError(err) + suite.NotNil(res) // execute end-blocker and verify validator attributes staking.EndBlocker(ctx, suite.app.StakingKeeper) @@ -78,8 +79,9 @@ func (suite *KeeperTestSuite) TestHandleDoubleSign() { validator, _ := suite.app.StakingKeeper.GetValidator(ctx, operatorAddr) totalBond := validator.TokensFromShares(del.GetShares()).TruncateInt() msgUnbond := staking.NewMsgUndelegate(sdk.AccAddress(operatorAddr), operatorAddr, sdk.NewCoin(stakingParams.BondDenom, totalBond)) - res = staking.NewHandler(suite.app.StakingKeeper)(ctx, msgUnbond) - suite.True(res.IsOK()) + res, err = staking.NewHandler(suite.app.StakingKeeper)(ctx, msgUnbond) + suite.NoError(err) + suite.NotNil(res) } func (suite *KeeperTestSuite) TestHandleDoubleSign_TooOld() { @@ -92,8 +94,9 @@ func (suite *KeeperTestSuite) TestHandleDoubleSign_TooOld() { operatorAddr, val := valAddresses[0], pubkeys[0] // create validator - res := staking.NewHandler(suite.app.StakingKeeper)(ctx, newTestMsgCreateValidator(operatorAddr, val, amt)) - suite.True(res.IsOK(), res.Log) + res, err := staking.NewHandler(suite.app.StakingKeeper)(ctx, newTestMsgCreateValidator(operatorAddr, val, amt)) + suite.NoError(err) + suite.NotNil(res) // execute end-blocker and verify validator attributes staking.EndBlocker(ctx, suite.app.StakingKeeper) diff --git a/x/evidence/internal/keeper/keeper.go b/x/evidence/internal/keeper/keeper.go index 26b45db7d69d..fd6c8027d8fd 100644 --- a/x/evidence/internal/keeper/keeper.go +++ b/x/evidence/internal/keeper/keeper.go @@ -9,6 +9,7 @@ import ( "github.com/cosmos/cosmos-sdk/codec" "github.com/cosmos/cosmos-sdk/store/prefix" sdk "github.com/cosmos/cosmos-sdk/types" + sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" "github.com/cosmos/cosmos-sdk/x/evidence/exported" "github.com/cosmos/cosmos-sdk/x/evidence/internal/types" "github.com/cosmos/cosmos-sdk/x/params" @@ -24,11 +25,10 @@ type Keeper struct { router types.Router stakingKeeper types.StakingKeeper slashingKeeper types.SlashingKeeper - codespace sdk.CodespaceType } func NewKeeper( - cdc *codec.Codec, storeKey sdk.StoreKey, paramSpace params.Subspace, codespace sdk.CodespaceType, + cdc *codec.Codec, storeKey sdk.StoreKey, paramSpace params.Subspace, stakingKeeper types.StakingKeeper, slashingKeeper types.SlashingKeeper, ) *Keeper { @@ -43,7 +43,6 @@ func NewKeeper( paramSpace: paramSpace, stakingKeeper: stakingKeeper, slashingKeeper: slashingKeeper, - codespace: codespace, } } @@ -74,7 +73,7 @@ func (k *Keeper) SetRouter(rtr types.Router) { // no handler exists, an error is returned. func (k Keeper) GetEvidenceHandler(evidenceRoute string) (types.Handler, error) { if !k.router.HasRoute(evidenceRoute) { - return nil, types.ErrNoEvidenceHandlerExists(k.codespace, evidenceRoute) + return nil, sdkerrors.Wrap(types.ErrNoEvidenceHandlerExists, evidenceRoute) } return k.router.GetRoute(evidenceRoute), nil @@ -86,15 +85,15 @@ func (k Keeper) GetEvidenceHandler(evidenceRoute string) (types.Handler, error) // persisted. func (k Keeper) SubmitEvidence(ctx sdk.Context, evidence exported.Evidence) error { if _, ok := k.GetEvidence(ctx, evidence.Hash()); ok { - return types.ErrEvidenceExists(k.codespace, evidence.Hash().String()) + return sdkerrors.Wrap(types.ErrEvidenceExists, evidence.Hash().String()) } if !k.router.HasRoute(evidence.Route()) { - return types.ErrNoEvidenceHandlerExists(k.codespace, evidence.Route()) + return sdkerrors.Wrap(types.ErrNoEvidenceHandlerExists, evidence.Route()) } handler := k.router.GetRoute(evidence.Route()) if err := handler(ctx, evidence); err != nil { - return types.ErrInvalidEvidence(k.codespace, err.Error()) + return sdkerrors.Wrap(types.ErrInvalidEvidence, err.Error()) } ctx.EventManager().EmitEvent( diff --git a/x/evidence/internal/keeper/keeper_test.go b/x/evidence/internal/keeper/keeper_test.go index bde9f08f02ce..45347ab96be0 100644 --- a/x/evidence/internal/keeper/keeper_test.go +++ b/x/evidence/internal/keeper/keeper_test.go @@ -66,8 +66,7 @@ func (suite *KeeperTestSuite) SetupTest() { // recreate keeper in order to use custom testing types evidenceKeeper := evidence.NewKeeper( - cdc, app.GetKey(evidence.StoreKey), app.GetSubspace(evidence.ModuleName), - evidence.DefaultCodespace, app.StakingKeeper, app.SlashingKeeper, + cdc, app.GetKey(evidence.StoreKey), app.GetSubspace(evidence.ModuleName), app.StakingKeeper, app.SlashingKeeper, ) router := evidence.NewRouter() router = router.AddRoute(types.TestEvidenceRouteEquivocation, types.TestEquivocationHandler(*evidenceKeeper)) diff --git a/x/evidence/internal/keeper/querier.go b/x/evidence/internal/keeper/querier.go index dfbda68f66d6..cbb616677e8f 100644 --- a/x/evidence/internal/keeper/querier.go +++ b/x/evidence/internal/keeper/querier.go @@ -14,7 +14,7 @@ import ( ) func NewQuerier(k Keeper) sdk.Querier { - return func(ctx sdk.Context, path []string, req abci.RequestQuery) ([]byte, sdk.Error) { + return func(ctx sdk.Context, path []string, req abci.RequestQuery) ([]byte, error) { var ( res []byte err error @@ -31,10 +31,10 @@ func NewQuerier(k Keeper) sdk.Querier { res, err = queryAllEvidence(ctx, req, k) default: - err = sdkerrors.Wrapf(sdkerrors.ErrUnknownRequest, "unknown %s query endpoint", types.ModuleName) + err = sdkerrors.Wrapf(sdkerrors.ErrUnknownRequest, "unknown %s query endpoint: %s", types.ModuleName, path[0]) } - return res, sdk.ConvertError(err) + return res, err } } @@ -64,7 +64,7 @@ func queryEvidence(ctx sdk.Context, req abci.RequestQuery, k Keeper) ([]byte, er evidence, ok := k.GetEvidence(ctx, hash) if !ok { - return nil, types.ErrNoEvidenceExists(k.codespace, params.EvidenceHash) + return nil, sdkerrors.Wrap(types.ErrNoEvidenceExists, params.EvidenceHash) } res, err := codec.MarshalJSONIndent(k.cdc, evidence) diff --git a/x/evidence/internal/types/errors.go b/x/evidence/internal/types/errors.go index 2054cee9fb66..83ffe06002ae 100644 --- a/x/evidence/internal/types/errors.go +++ b/x/evidence/internal/types/errors.go @@ -2,57 +2,13 @@ package types import ( - "fmt" - - sdk "github.com/cosmos/cosmos-sdk/types" sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" ) -// Error codes specific to the evidence module -const ( - DefaultCodespace sdk.CodespaceType = ModuleName - - CodeNoEvidenceHandlerExists sdk.CodeType = 1 - CodeInvalidEvidence sdk.CodeType = 2 - CodeNoEvidenceExists sdk.CodeType = 3 - CodeEvidenceExists sdk.CodeType = 4 +// x/evidence module sentinel errors +var ( + ErrNoEvidenceHandlerExists = sdkerrors.Register(ModuleName, 1, "unregistered handler for evidence type") + ErrInvalidEvidence = sdkerrors.Register(ModuleName, 2, "invalid evidence") + ErrNoEvidenceExists = sdkerrors.Register(ModuleName, 3, "evidence does not exist") + ErrEvidenceExists = sdkerrors.Register(ModuleName, 4, "evidence already exists") ) - -// ErrNoEvidenceHandlerExists returns a typed ABCI error for an invalid evidence -// handler route. -func ErrNoEvidenceHandlerExists(codespace sdk.CodespaceType, route string) error { - return sdkerrors.New( - string(codespace), - uint32(CodeNoEvidenceHandlerExists), - fmt.Sprintf("route '%s' does not have a registered evidence handler", route), - ) -} - -// ErrInvalidEvidence returns a typed ABCI error for invalid evidence. -func ErrInvalidEvidence(codespace sdk.CodespaceType, msg string) error { - return sdkerrors.New( - string(codespace), - uint32(CodeInvalidEvidence), - fmt.Sprintf("invalid evidence: %s", msg), - ) -} - -// ErrNoEvidenceExists returns a typed ABCI error for Evidence that does not exist -// for a given hash. -func ErrNoEvidenceExists(codespace sdk.CodespaceType, hash string) error { - return sdkerrors.New( - string(codespace), - uint32(CodeNoEvidenceExists), - fmt.Sprintf("evidence with hash %s does not exist", hash), - ) -} - -// ErrEvidenceExists returns a typed ABCI error for Evidence that already exists -// by hash in state. -func ErrEvidenceExists(codespace sdk.CodespaceType, hash string) error { - return sdkerrors.New( - string(codespace), - uint32(CodeEvidenceExists), - fmt.Sprintf("evidence with hash %s already exists", hash), - ) -} diff --git a/x/evidence/internal/types/msgs.go b/x/evidence/internal/types/msgs.go index b09f120da927..3fbb50844f57 100644 --- a/x/evidence/internal/types/msgs.go +++ b/x/evidence/internal/types/msgs.go @@ -33,15 +33,15 @@ func (m MsgSubmitEvidence) Route() string { return RouterKey } func (m MsgSubmitEvidence) Type() string { return TypeMsgSubmitEvidence } // ValidateBasic performs basic (non-state-dependant) validation on a MsgSubmitEvidence. -func (m MsgSubmitEvidence) ValidateBasic() sdk.Error { +func (m MsgSubmitEvidence) ValidateBasic() error { if m.Evidence == nil { - return sdk.ConvertError(ErrInvalidEvidence(DefaultCodespace, "missing evidence")) + return sdkerrors.Wrap(ErrInvalidEvidence, "missing evidence") } if err := m.Evidence.ValidateBasic(); err != nil { - return sdk.ConvertError(err) + return err } if m.Submitter.Empty() { - return sdk.ConvertError(sdkerrors.Wrap(sdkerrors.ErrInvalidAddress, m.Submitter.String())) + return sdkerrors.Wrap(sdkerrors.ErrInvalidAddress, m.Submitter.String()) } return nil diff --git a/x/genutil/client/cli/collect.go b/x/genutil/client/cli/collect.go index fe1c864eca9f..bc38ab74d287 100644 --- a/x/genutil/client/cli/collect.go +++ b/x/genutil/client/cli/collect.go @@ -10,7 +10,7 @@ import ( "github.com/tendermint/tendermint/libs/cli" tmtypes "github.com/tendermint/tendermint/types" - "github.com/cosmos/cosmos-sdk/client" + "github.com/cosmos/cosmos-sdk/client/flags" "github.com/cosmos/cosmos-sdk/codec" "github.com/cosmos/cosmos-sdk/server" "github.com/cosmos/cosmos-sdk/x/genutil" @@ -29,7 +29,7 @@ func CollectGenTxsCmd(ctx *server.Context, cdc *codec.Codec, RunE: func(_ *cobra.Command, _ []string) error { config := ctx.Config config.SetRoot(viper.GetString(cli.HomeFlag)) - name := viper.GetString(client.FlagName) + name := viper.GetString(flags.FlagName) nodeID, valPubKey, err := genutil.InitializeNodeValidatorFiles(config) if err != nil { return errors.Wrap(err, "failed to initialize node validator files") diff --git a/x/genutil/client/cli/gentx.go b/x/genutil/client/cli/gentx.go index ebfdded23a96..aae33d6b8b7c 100644 --- a/x/genutil/client/cli/gentx.go +++ b/x/genutil/client/cli/gentx.go @@ -21,9 +21,9 @@ import ( "github.com/tendermint/tendermint/libs/common" tmtypes "github.com/tendermint/tendermint/types" - "github.com/cosmos/cosmos-sdk/client" "github.com/cosmos/cosmos-sdk/client/context" "github.com/cosmos/cosmos-sdk/client/flags" + "github.com/cosmos/cosmos-sdk/client/keys" "github.com/cosmos/cosmos-sdk/codec" kbkeys "github.com/cosmos/cosmos-sdk/crypto/keys" "github.com/cosmos/cosmos-sdk/server" @@ -64,7 +64,7 @@ func GenTxCmd(ctx *server.Context, cdc *codec.Codec, mbm module.BasicManager, sm RunE: func(cmd *cobra.Command, args []string) error { config := ctx.Config - config.SetRoot(viper.GetString(client.FlagHome)) + config.SetRoot(viper.GetString(flags.FlagHome)) nodeID, valPubKey, err := genutil.InitializeNodeValidatorFiles(ctx.Config) if err != nil { return errors.Wrap(err, "failed to initialize node validator files") @@ -97,19 +97,19 @@ func GenTxCmd(ctx *server.Context, cdc *codec.Codec, mbm module.BasicManager, sm } inBuf := bufio.NewReader(cmd.InOrStdin()) - kb, err := client.NewKeyringFromDir(viper.GetString(flagClientHome), inBuf) + kb, err := keys.NewKeyringFromDir(viper.GetString(flagClientHome), inBuf) if err != nil { return errors.Wrap(err, "failed to initialize keybase") } - name := viper.GetString(client.FlagName) + name := viper.GetString(flags.FlagName) key, err := kb.Get(name) if err != nil { return errors.Wrap(err, "failed to read from keybase") } // Set flags for creating gentx - viper.Set(client.FlagHome, viper.GetString(flagClientHome)) + viper.Set(flags.FlagHome, viper.GetString(flagClientHome)) smbh.PrepareFlagsForTxCreateValidator(config, nodeID, genDoc.ChainID, valPubKey) // Fetch the amount of coins staked @@ -125,14 +125,14 @@ func GenTxCmd(ctx *server.Context, cdc *codec.Codec, mbm module.BasicManager, sm } txBldr := auth.NewTxBuilderFromCLI(inBuf).WithTxEncoder(utils.GetTxEncoder(cdc)) - cliCtx := client.NewCLIContextWithInput(inBuf).WithCodec(cdc) + cliCtx := context.NewCLIContextWithInput(inBuf).WithCodec(cdc) // Set the generate-only flag here after the CLI context has // been created. This allows the from name/key to be correctly populated. // // TODO: Consider removing the manual setting of generate-only in // favor of a 'gentx' flag in the create-validator command. - viper.Set(client.FlagGenerateOnly, true) + viper.Set(flags.FlagGenerateOnly, true) // create a 'create-validator' message txBldr, msg, err := smbh.BuildCreateValidatorMsg(cliCtx, txBldr) @@ -166,7 +166,7 @@ func GenTxCmd(ctx *server.Context, cdc *codec.Codec, mbm module.BasicManager, sm } // Fetch output file name - outputDocument := viper.GetString(client.FlagOutputDocument) + outputDocument := viper.GetString(flags.FlagOutputDocument) if outputDocument == "" { outputDocument, err = makeOutputFilepath(config.RootDir, nodeID) if err != nil { @@ -184,16 +184,16 @@ func GenTxCmd(ctx *server.Context, cdc *codec.Codec, mbm module.BasicManager, sm }, } - cmd.Flags().String(client.FlagHome, defaultNodeHome, "node's home directory") + cmd.Flags().String(flags.FlagHome, defaultNodeHome, "node's home directory") cmd.Flags().String(flagClientHome, defaultCLIHome, "client's home directory") - cmd.Flags().String(client.FlagName, "", "name of private key with which to sign the gentx") - cmd.Flags().String(client.FlagOutputDocument, "", + cmd.Flags().String(flags.FlagName, "", "name of private key with which to sign the gentx") + cmd.Flags().String(flags.FlagOutputDocument, "", "write the genesis transaction JSON document to the given file instead of the default location") cmd.Flags().AddFlagSet(fsCreateValidator) - cmd.Flags().String(client.FlagKeyringBackend, client.DefaultKeyringBackend, "Select keyring's backend (os|file|test)") + cmd.Flags().String(flags.FlagKeyringBackend, flags.DefaultKeyringBackend, "Select keyring's backend (os|file|test)") viper.BindPFlag(flags.FlagKeyringBackend, cmd.Flags().Lookup(flags.FlagKeyringBackend)) - cmd.MarkFlagRequired(client.FlagName) + cmd.MarkFlagRequired(flags.FlagName) return cmd } diff --git a/x/genutil/client/cli/init.go b/x/genutil/client/cli/init.go index aed60d17f839..c611556ae8f1 100644 --- a/x/genutil/client/cli/init.go +++ b/x/genutil/client/cli/init.go @@ -14,7 +14,7 @@ import ( "github.com/tendermint/tendermint/libs/common" "github.com/tendermint/tendermint/types" - "github.com/cosmos/cosmos-sdk/client" + "github.com/cosmos/cosmos-sdk/client/flags" "github.com/cosmos/cosmos-sdk/codec" "github.com/cosmos/cosmos-sdk/server" sdk "github.com/cosmos/cosmos-sdk/types" @@ -70,7 +70,7 @@ func InitCmd(ctx *server.Context, cdc *codec.Codec, mbm module.BasicManager, config := ctx.Config config.SetRoot(viper.GetString(cli.HomeFlag)) - chainID := viper.GetString(client.FlagChainID) + chainID := viper.GetString(flags.FlagChainID) if chainID == "" { chainID = fmt.Sprintf("test-chain-%v", common.RandStr(6)) } @@ -119,7 +119,7 @@ func InitCmd(ctx *server.Context, cdc *codec.Codec, mbm module.BasicManager, cmd.Flags().String(cli.HomeFlag, defaultNodeHome, "node's home directory") cmd.Flags().BoolP(flagOverwrite, "o", false, "overwrite the genesis.json file") - cmd.Flags().String(client.FlagChainID, "", "genesis file chain-id, if left blank will be randomly created") + cmd.Flags().String(flags.FlagChainID, "", "genesis file chain-id, if left blank will be randomly created") return cmd } diff --git a/x/genutil/client/cli/init_test.go b/x/genutil/client/cli/init_test.go index 540e57cfb5f2..6ab1ef208abe 100644 --- a/x/genutil/client/cli/init_test.go +++ b/x/genutil/client/cli/init_test.go @@ -14,7 +14,7 @@ import ( "github.com/tendermint/tendermint/libs/cli" "github.com/tendermint/tendermint/libs/log" - "github.com/cosmos/cosmos-sdk/client" + "github.com/cosmos/cosmos-sdk/client/flags" "github.com/cosmos/cosmos-sdk/codec" "github.com/cosmos/cosmos-sdk/server" "github.com/cosmos/cosmos-sdk/server/mock" @@ -126,7 +126,7 @@ func TestInitNodeValidatorFiles(t *testing.T) { home, cleanup := tests.NewTestCaseDir(t) defer cleanup() viper.Set(cli.HomeFlag, home) - viper.Set(client.FlagName, "moniker") + viper.Set(flags.FlagName, "moniker") cfg, err := tcmd.ParseConfig() require.Nil(t, err) nodeID, valPubKey, err := genutil.InitializeNodeValidatorFiles(cfg) diff --git a/x/genutil/client/cli/migrate_test.go b/x/genutil/client/cli/migrate_test.go index fca36a4dfc28..423629efcb13 100644 --- a/x/genutil/client/cli/migrate_test.go +++ b/x/genutil/client/cli/migrate_test.go @@ -12,7 +12,7 @@ import ( "github.com/tendermint/tendermint/libs/cli" "github.com/tendermint/tendermint/libs/log" - "github.com/cosmos/cosmos-sdk/client" + "github.com/cosmos/cosmos-sdk/client/flags" "github.com/cosmos/cosmos-sdk/server" "github.com/cosmos/cosmos-sdk/tests" ) @@ -39,7 +39,7 @@ func TestGetMigrationCallback(t *testing.T) { func TestMigrateGenesis(t *testing.T) { home, cleanup := tests.NewTestCaseDir(t) viper.Set(cli.HomeFlag, home) - viper.Set(client.FlagName, "moniker") + viper.Set(flags.FlagName, "moniker") logger := log.NewNopLogger() cfg, err := tcmd.ParseConfig() require.Nil(t, err) diff --git a/x/genutil/client/rest/query.go b/x/genutil/client/rest/query.go index 4f0f318aa201..0159223e8e7c 100644 --- a/x/genutil/client/rest/query.go +++ b/x/genutil/client/rest/query.go @@ -1,6 +1,7 @@ package rest import ( + "fmt" "net/http" "github.com/cosmos/cosmos-sdk/client/context" @@ -14,15 +15,19 @@ import ( func QueryGenesisTxs(cliCtx context.CLIContext, w http.ResponseWriter) { resultGenesis, err := cliCtx.Client.Genesis() if err != nil { - rest.WriteErrorResponse(w, http.StatusInternalServerError, - sdk.AppendMsgToErr("could not retrieve genesis from client", err.Error())) + rest.WriteErrorResponse( + w, http.StatusInternalServerError, + fmt.Sprintf("failed to retrieve genesis from client: %s", err), + ) return } appState, err := types.GenesisStateFromGenDoc(cliCtx.Codec, *resultGenesis.Genesis) if err != nil { - rest.WriteErrorResponse(w, http.StatusInternalServerError, - sdk.AppendMsgToErr("could not decode genesis doc", err.Error())) + rest.WriteErrorResponse( + w, http.StatusInternalServerError, + fmt.Sprintf("failed to decode genesis doc: %s", err), + ) return } @@ -31,8 +36,10 @@ func QueryGenesisTxs(cliCtx context.CLIContext, w http.ResponseWriter) { for i, tx := range genState.GenTxs { err := cliCtx.Codec.UnmarshalJSON(tx, &genTxs[i]) if err != nil { - rest.WriteErrorResponse(w, http.StatusInternalServerError, - sdk.AppendMsgToErr("could not decode genesis transaction", err.Error())) + rest.WriteErrorResponse( + w, http.StatusInternalServerError, + fmt.Sprintf("failed to decode genesis transaction: %s", err), + ) return } } diff --git a/x/gov/abci.go b/x/gov/abci.go index 31b1f40c9d2a..21db8f5cd2c2 100644 --- a/x/gov/abci.go +++ b/x/gov/abci.go @@ -65,7 +65,7 @@ func EndBlocker(ctx sdk.Context, keeper Keeper) { } else { proposal.Status = StatusFailed tagValue = types.AttributeValueProposalFailed - logMsg = fmt.Sprintf("passed, but failed on execution: %s", err.ABCILog()) + logMsg = fmt.Sprintf("passed, but failed on execution: %s", err) } } else { proposal.Status = StatusRejected diff --git a/x/gov/abci_test.go b/x/gov/abci_test.go index 42616b36c00b..6ee3a3075920 100644 --- a/x/gov/abci_test.go +++ b/x/gov/abci_test.go @@ -32,8 +32,9 @@ func TestTickExpiredDepositPeriod(t *testing.T) { input.addrs[0], ) - res := govHandler(ctx, newProposalMsg) - require.True(t, res.IsOK()) + res, err := govHandler(ctx, newProposalMsg) + require.NoError(t, err) + require.NotNil(t, res) inactiveQueue = input.keeper.InactiveProposalQueueIterator(ctx, ctx.BlockHeader().Time) require.False(t, inactiveQueue.Valid()) @@ -81,8 +82,9 @@ func TestTickMultipleExpiredDepositPeriod(t *testing.T) { input.addrs[0], ) - res := govHandler(ctx, newProposalMsg) - require.True(t, res.IsOK()) + res, err := govHandler(ctx, newProposalMsg) + require.NoError(t, err) + require.NotNil(t, res) inactiveQueue = input.keeper.InactiveProposalQueueIterator(ctx, ctx.BlockHeader().Time) require.False(t, inactiveQueue.Valid()) @@ -102,8 +104,9 @@ func TestTickMultipleExpiredDepositPeriod(t *testing.T) { input.addrs[0], ) - res = govHandler(ctx, newProposalMsg2) - require.True(t, res.IsOK()) + res, err = govHandler(ctx, newProposalMsg2) + require.NoError(t, err) + require.NotNil(t, res) newHeader = ctx.BlockHeader() newHeader.Time = ctx.BlockHeader().Time.Add(input.keeper.GetDepositParams(ctx).MaxDepositPeriod).Add(time.Duration(-1) * time.Second) @@ -152,8 +155,10 @@ func TestTickPassedDepositPeriod(t *testing.T) { input.addrs[0], ) - res := govHandler(ctx, newProposalMsg) - require.True(t, res.IsOK()) + res, err := govHandler(ctx, newProposalMsg) + require.NoError(t, err) + require.NotNil(t, res) + proposalID := GetProposalIDFromBytes(res.Data) inactiveQueue = input.keeper.InactiveProposalQueueIterator(ctx, ctx.BlockHeader().Time) @@ -169,8 +174,10 @@ func TestTickPassedDepositPeriod(t *testing.T) { inactiveQueue.Close() newDepositMsg := NewMsgDeposit(input.addrs[1], proposalID, sdk.Coins{sdk.NewInt64Coin(sdk.DefaultBondDenom, 5)}) - res = govHandler(ctx, newDepositMsg) - require.True(t, res.IsOK()) + + res, err = govHandler(ctx, newDepositMsg) + require.NoError(t, err) + require.NotNil(t, res) activeQueue = input.keeper.ActiveProposalQueueIterator(ctx, ctx.BlockHeader().Time) require.False(t, activeQueue.Valid()) @@ -197,8 +204,10 @@ func TestTickPassedVotingPeriod(t *testing.T) { proposalCoins := sdk.Coins{sdk.NewCoin(sdk.DefaultBondDenom, sdk.TokensFromConsensusPower(5))} newProposalMsg := NewMsgSubmitProposal(keep.TestProposal, proposalCoins, input.addrs[0]) - res := govHandler(ctx, newProposalMsg) - require.True(t, res.IsOK()) + res, err := govHandler(ctx, newProposalMsg) + require.NoError(t, err) + require.NotNil(t, res) + proposalID := GetProposalIDFromBytes(res.Data) newHeader := ctx.BlockHeader() @@ -206,8 +215,10 @@ func TestTickPassedVotingPeriod(t *testing.T) { ctx = ctx.WithBlockHeader(newHeader) newDepositMsg := NewMsgDeposit(input.addrs[1], proposalID, proposalCoins) - res = govHandler(ctx, newDepositMsg) - require.True(t, res.IsOK()) + + res, err = govHandler(ctx, newDepositMsg) + require.NoError(t, err) + require.NotNil(t, res) newHeader = ctx.BlockHeader() newHeader.Time = ctx.BlockHeader().Time.Add(input.keeper.GetDepositParams(ctx).MaxDepositPeriod).Add(input.keeper.GetVotingParams(ctx).VotingPeriod) @@ -259,8 +270,10 @@ func TestProposalPassedEndblocker(t *testing.T) { proposalCoins := sdk.Coins{sdk.NewCoin(sdk.DefaultBondDenom, sdk.TokensFromConsensusPower(10))} newDepositMsg := NewMsgDeposit(input.addrs[0], proposal.ProposalID, proposalCoins) - res := handler(ctx, newDepositMsg) - require.True(t, res.IsOK()) + + res, err := handler(ctx, newDepositMsg) + require.NoError(t, err) + require.NotNil(t, res) macc = input.keeper.GetGovernanceAccount(ctx) require.NotNil(t, macc) @@ -308,8 +321,10 @@ func TestEndBlockerProposalHandlerFailed(t *testing.T) { proposalCoins := sdk.NewCoins(sdk.NewCoin(sdk.DefaultBondDenom, sdk.TokensFromConsensusPower(10))) newDepositMsg := NewMsgDeposit(input.addrs[0], proposal.ProposalID, proposalCoins) - res := handler(ctx, newDepositMsg) - require.True(t, res.IsOK()) + + res, err := handler(ctx, newDepositMsg) + require.NoError(t, err) + require.NotNil(t, res) err = input.keeper.AddVote(ctx, proposal.ProposalID, input.addrs[0], OptionYes) require.NoError(t, err) diff --git a/x/gov/alias.go b/x/gov/alias.go index 0ca57b7a39fc..df5f2cb9ce77 100644 --- a/x/gov/alias.go +++ b/x/gov/alias.go @@ -1,62 +1,47 @@ -// nolint -// autogenerated code using github.com/rigelrozanski/multitool -// aliases generated for the following subdirectories: -// ALIASGEN: github.com/cosmos/cosmos-sdk/x/gov/keeper -// ALIASGEN: github.com/cosmos/cosmos-sdk/x/gov/types package gov +// nolint + import ( "github.com/cosmos/cosmos-sdk/x/gov/keeper" "github.com/cosmos/cosmos-sdk/x/gov/types" ) const ( - MaxDescriptionLength = types.MaxDescriptionLength - MaxTitleLength = types.MaxTitleLength - DefaultCodespace = types.DefaultCodespace - CodeUnknownProposal = types.CodeUnknownProposal - CodeInactiveProposal = types.CodeInactiveProposal - CodeAlreadyActiveProposal = types.CodeAlreadyActiveProposal - CodeAlreadyFinishedProposal = types.CodeAlreadyFinishedProposal - CodeAddressNotStaked = types.CodeAddressNotStaked - CodeInvalidContent = types.CodeInvalidContent - CodeInvalidProposalType = types.CodeInvalidProposalType - CodeInvalidVote = types.CodeInvalidVote - CodeInvalidGenesis = types.CodeInvalidGenesis - CodeInvalidProposalStatus = types.CodeInvalidProposalStatus - CodeProposalHandlerNotExists = types.CodeProposalHandlerNotExists - DefaultPeriod = types.DefaultPeriod - ModuleName = types.ModuleName - StoreKey = types.StoreKey - RouterKey = types.RouterKey - QuerierRoute = types.QuerierRoute - DefaultParamspace = types.DefaultParamspace - TypeMsgDeposit = types.TypeMsgDeposit - TypeMsgVote = types.TypeMsgVote - TypeMsgSubmitProposal = types.TypeMsgSubmitProposal - StatusNil = types.StatusNil - StatusDepositPeriod = types.StatusDepositPeriod - StatusVotingPeriod = types.StatusVotingPeriod - StatusPassed = types.StatusPassed - StatusRejected = types.StatusRejected - StatusFailed = types.StatusFailed - ProposalTypeText = types.ProposalTypeText - QueryParams = types.QueryParams - QueryProposals = types.QueryProposals - QueryProposal = types.QueryProposal - QueryDeposits = types.QueryDeposits - QueryDeposit = types.QueryDeposit - QueryVotes = types.QueryVotes - QueryVote = types.QueryVote - QueryTally = types.QueryTally - ParamDeposit = types.ParamDeposit - ParamVoting = types.ParamVoting - ParamTallying = types.ParamTallying - OptionEmpty = types.OptionEmpty - OptionYes = types.OptionYes - OptionAbstain = types.OptionAbstain - OptionNo = types.OptionNo - OptionNoWithVeto = types.OptionNoWithVeto + MaxDescriptionLength = types.MaxDescriptionLength + MaxTitleLength = types.MaxTitleLength + DefaultPeriod = types.DefaultPeriod + ModuleName = types.ModuleName + StoreKey = types.StoreKey + RouterKey = types.RouterKey + QuerierRoute = types.QuerierRoute + DefaultParamspace = types.DefaultParamspace + TypeMsgDeposit = types.TypeMsgDeposit + TypeMsgVote = types.TypeMsgVote + TypeMsgSubmitProposal = types.TypeMsgSubmitProposal + StatusNil = types.StatusNil + StatusDepositPeriod = types.StatusDepositPeriod + StatusVotingPeriod = types.StatusVotingPeriod + StatusPassed = types.StatusPassed + StatusRejected = types.StatusRejected + StatusFailed = types.StatusFailed + ProposalTypeText = types.ProposalTypeText + QueryParams = types.QueryParams + QueryProposals = types.QueryProposals + QueryProposal = types.QueryProposal + QueryDeposits = types.QueryDeposits + QueryDeposit = types.QueryDeposit + QueryVotes = types.QueryVotes + QueryVote = types.QueryVote + QueryTally = types.QueryTally + ParamDeposit = types.ParamDeposit + ParamVoting = types.ParamVoting + ParamTallying = types.ParamTallying + OptionEmpty = types.OptionEmpty + OptionYes = types.OptionYes + OptionAbstain = types.OptionAbstain + OptionNo = types.OptionNo + OptionNoWithVeto = types.OptionNoWithVeto ) var ( diff --git a/x/gov/client/cli/query.go b/x/gov/client/cli/query.go index 69f89e7a7d05..1a0c0a179ef7 100644 --- a/x/gov/client/cli/query.go +++ b/x/gov/client/cli/query.go @@ -10,10 +10,10 @@ import ( "github.com/cosmos/cosmos-sdk/client" "github.com/cosmos/cosmos-sdk/client/context" + "github.com/cosmos/cosmos-sdk/client/flags" "github.com/cosmos/cosmos-sdk/codec" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/version" - "github.com/cosmos/cosmos-sdk/x/auth/client/utils" gcutils "github.com/cosmos/cosmos-sdk/x/gov/client/utils" "github.com/cosmos/cosmos-sdk/x/gov/types" ) @@ -29,7 +29,7 @@ func GetQueryCmd(queryRoute string, cdc *codec.Codec) *cobra.Command { RunE: client.ValidateCmd, } - govQueryCmd.AddCommand(client.GetCommands( + govQueryCmd.AddCommand(flags.GetCommands( GetCmdQueryProposal(queryRoute, cdc), GetCmdQueryProposals(queryRoute, cdc), GetCmdQueryVote(queryRoute, cdc), @@ -285,7 +285,7 @@ $ %[1]s query gov votes 1 --page=2 --limit=100 propStatus := proposal.Status if !(propStatus == types.StatusVotingPeriod || propStatus == types.StatusDepositPeriod) { - res, err = gcutils.QueryVotesByTxQuery(cliCtx, params, utils.QueryTxsByEvents) + res, err = gcutils.QueryVotesByTxQuery(cliCtx, params) } else { res, _, err = cliCtx.QueryWithData(fmt.Sprintf("custom/%s/votes", queryRoute), bz) } diff --git a/x/gov/client/cli/tx.go b/x/gov/client/cli/tx.go index 4bd49a610e95..8c6c1109c9d4 100644 --- a/x/gov/client/cli/tx.go +++ b/x/gov/client/cli/tx.go @@ -10,6 +10,7 @@ import ( "github.com/cosmos/cosmos-sdk/client" "github.com/cosmos/cosmos-sdk/client/context" + "github.com/cosmos/cosmos-sdk/client/flags" "github.com/cosmos/cosmos-sdk/codec" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/version" @@ -66,10 +67,10 @@ func GetTxCmd(storeKey string, cdc *codec.Codec, pcmds []*cobra.Command) *cobra. cmdSubmitProp := GetCmdSubmitProposal(cdc) for _, pcmd := range pcmds { - cmdSubmitProp.AddCommand(client.PostCommands(pcmd)[0]) + cmdSubmitProp.AddCommand(flags.PostCommands(pcmd)[0]) } - govTxCmd.AddCommand(client.PostCommands( + govTxCmd.AddCommand(flags.PostCommands( GetCmdDeposit(cdc), GetCmdVote(cdc), cmdSubmitProp, diff --git a/x/gov/client/rest/query.go b/x/gov/client/rest/query.go index de9ccf379dd5..3eb5800d7a99 100644 --- a/x/gov/client/rest/query.go +++ b/x/gov/client/rest/query.go @@ -10,7 +10,6 @@ import ( "github.com/cosmos/cosmos-sdk/client/context" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/types/rest" - "github.com/cosmos/cosmos-sdk/x/auth/client/utils" gcutils "github.com/cosmos/cosmos-sdk/x/gov/client/utils" "github.com/cosmos/cosmos-sdk/x/gov/types" ) @@ -382,7 +381,7 @@ func queryVotesOnProposalHandlerFn(cliCtx context.CLIContext) http.HandlerFunc { // as they're no longer in state. propStatus := proposal.Status if !(propStatus == types.StatusVotingPeriod || propStatus == types.StatusDepositPeriod) { - res, err = gcutils.QueryVotesByTxQuery(cliCtx, params, utils.QueryTxsByEvents) + res, err = gcutils.QueryVotesByTxQuery(cliCtx, params) } else { res, _, err = cliCtx.QueryWithData("custom/gov/votes", bz) } diff --git a/x/gov/client/utils/query.go b/x/gov/client/utils/query.go index 2eaf2c5a7a78..d4be3c010f93 100644 --- a/x/gov/client/utils/query.go +++ b/x/gov/client/utils/query.go @@ -73,15 +73,10 @@ func QueryDepositsByTxQuery(cliCtx context.CLIContext, params types.QueryProposa return cliCtx.Codec.MarshalJSON(deposits) } -// TxQuerier is a type that accepts query parameters (target events and pagination options) and returns sdk.SearchTxsResult. -// Mainly used for easier mocking of utils.QueryTxsByEvents in tests. -type TxQuerier func(cliCtx context.CLIContext, events []string, page, limit int) (*sdk.SearchTxsResult, error) - -// QueryVotesByTxQuery will query for votes using provided TxQuerier implementation. -// In general utils.QueryTxsByEvents should be used that will do a direct tx query to a tendermint node. -// It will fetch and build votes directly from the returned txs and return a JSON +// QueryVotesByTxQuery will query for votes via a direct txs tags query. It +// will fetch and build votes directly from the returned txs and return a JSON // marshalled result or any error that occurred. -func QueryVotesByTxQuery(cliCtx context.CLIContext, params types.QueryProposalVotesParams, querier TxQuerier) ([]byte, error) { +func QueryVotesByTxQuery(cliCtx context.CLIContext, params types.QueryProposalVotesParams) ([]byte, error) { var ( events = []string{ fmt.Sprintf("%s.%s='%s'", sdk.EventTypeMessage, sdk.AttributeKeyAction, types.TypeMsgVote), @@ -93,7 +88,7 @@ func QueryVotesByTxQuery(cliCtx context.CLIContext, params types.QueryProposalVo ) // query interrupted either if we collected enough votes or tx indexer run out of relevant txs for len(votes) < totalLimit { - searchResult, err := querier(cliCtx, events, nextTxPage, defaultLimit) + searchResult, err := utils.QueryTxsByEvents(cliCtx, events, nextTxPage, defaultLimit) if err != nil { return nil, err } diff --git a/x/gov/client/utils/query_test.go b/x/gov/client/utils/query_test.go index ce9b548b93bb..68762b248066 100644 --- a/x/gov/client/utils/query_test.go +++ b/x/gov/client/utils/query_test.go @@ -7,72 +7,87 @@ import ( "github.com/cosmos/cosmos-sdk/client/context" "github.com/cosmos/cosmos-sdk/codec" sdk "github.com/cosmos/cosmos-sdk/types" + authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" "github.com/cosmos/cosmos-sdk/x/gov/types" "github.com/stretchr/testify/require" + "github.com/tendermint/tendermint/rpc/client/mock" + ctypes "github.com/tendermint/tendermint/rpc/core/types" + tmtypes "github.com/tendermint/tendermint/types" ) -type txMock struct { - address sdk.AccAddress - msgNum int +type TxSearchMock struct { + mock.Client + txs []tmtypes.Tx } -func (tx txMock) ValidateBasic() sdk.Error { - return nil +func (mock TxSearchMock) TxSearch(query string, prove bool, page, perPage int) (*ctypes.ResultTxSearch, error) { + start, end := client.Paginate(len(mock.txs), page, perPage, 100) + if start < 0 || end < 0 { + // nil result with nil error crashes utils.QueryTxsByEvents + return &ctypes.ResultTxSearch{}, nil + } + txs := mock.txs[start:end] + rst := &ctypes.ResultTxSearch{Txs: make([]*ctypes.ResultTx, len(txs)), TotalCount: len(txs)} + for i := range txs { + rst.Txs[i] = &ctypes.ResultTx{Tx: txs[i]} + } + return rst, nil } -func (tx txMock) GetMsgs() (msgs []sdk.Msg) { - for i := 0; i < tx.msgNum; i++ { - msgs = append(msgs, types.NewMsgVote(tx.address, 0, types.OptionYes)) - } - return +func (mock TxSearchMock) Block(height *int64) (*ctypes.ResultBlock, error) { + // any non nil Block needs to be returned. used to get time value + return &ctypes.ResultBlock{Block: &tmtypes.Block{}}, nil } -func makeQuerier(txs []sdk.Tx) TxQuerier { - return func(cliCtx context.CLIContext, events []string, page, limit int) (*sdk.SearchTxsResult, error) { - start, end := client.Paginate(len(txs), page, limit, 100) - if start < 0 || end < 0 { - return nil, nil - } - rst := &sdk.SearchTxsResult{ - TotalCount: len(txs), - PageNumber: page, - PageTotal: len(txs) / limit, - Limit: limit, - Count: end - start, - } - for _, tx := range txs[start:end] { - rst.Txs = append(rst.Txs, sdk.TxResponse{Tx: tx}) - } - return rst, nil - } +func newTestCodec() *codec.Codec { + cdc := codec.New() + sdk.RegisterCodec(cdc) + types.RegisterCodec(cdc) + authtypes.RegisterCodec(cdc) + return cdc } func TestGetPaginatedVotes(t *testing.T) { type testCase struct { description string page, limit int - txs []sdk.Tx + txs []authtypes.StdTx votes []types.Vote } acc1 := make(sdk.AccAddress, 20) acc1[0] = 1 acc2 := make(sdk.AccAddress, 20) acc2[0] = 2 + acc1Msgs := []sdk.Msg{ + types.NewMsgVote(acc1, 0, types.OptionYes), + types.NewMsgVote(acc1, 0, types.OptionYes), + } + acc2Msgs := []sdk.Msg{ + types.NewMsgVote(acc2, 0, types.OptionYes), + types.NewMsgVote(acc2, 0, types.OptionYes), + } for _, tc := range []testCase{ { description: "1MsgPerTxAll", page: 1, limit: 2, - txs: []sdk.Tx{txMock{acc1, 1}, txMock{acc2, 1}}, + txs: []authtypes.StdTx{ + {Msgs: acc1Msgs[:1]}, + {Msgs: acc2Msgs[:1]}, + }, votes: []types.Vote{ types.NewVote(0, acc1, types.OptionYes), types.NewVote(0, acc2, types.OptionYes)}, }, + { description: "2MsgPerTx1Chunk", page: 1, limit: 2, - txs: []sdk.Tx{txMock{acc1, 2}, txMock{acc2, 2}}, + txs: []authtypes.StdTx{ + {Msgs: acc1Msgs}, + {Msgs: acc2Msgs}, + }, votes: []types.Vote{ types.NewVote(0, acc1, types.OptionYes), types.NewVote(0, acc1, types.OptionYes)}, @@ -81,7 +96,10 @@ func TestGetPaginatedVotes(t *testing.T) { description: "2MsgPerTx2Chunk", page: 2, limit: 2, - txs: []sdk.Tx{txMock{acc1, 2}, txMock{acc2, 2}}, + txs: []authtypes.StdTx{ + {Msgs: acc1Msgs}, + {Msgs: acc2Msgs}, + }, votes: []types.Vote{ types.NewVote(0, acc2, types.OptionYes), types.NewVote(0, acc2, types.OptionYes)}, @@ -90,33 +108,43 @@ func TestGetPaginatedVotes(t *testing.T) { description: "IncompleteSearchTx", page: 1, limit: 2, - txs: []sdk.Tx{txMock{acc1, 1}}, - votes: []types.Vote{types.NewVote(0, acc1, types.OptionYes)}, - }, - { - description: "IncompleteSearchTx", - page: 1, - limit: 2, - txs: []sdk.Tx{txMock{acc1, 1}}, - votes: []types.Vote{types.NewVote(0, acc1, types.OptionYes)}, + txs: []authtypes.StdTx{ + {Msgs: acc1Msgs[:1]}, + }, + votes: []types.Vote{types.NewVote(0, acc1, types.OptionYes)}, }, { description: "InvalidPage", page: -1, - txs: []sdk.Tx{txMock{acc1, 1}}, + txs: []authtypes.StdTx{ + {Msgs: acc1Msgs[:1]}, + }, }, { description: "OutOfBounds", page: 2, limit: 10, - txs: []sdk.Tx{txMock{acc1, 1}}, + txs: []authtypes.StdTx{ + {Msgs: acc1Msgs[:1]}, + }, }, } { tc := tc t.Run(tc.description, func(t *testing.T) { - ctx := context.CLIContext{}.WithCodec(codec.New()) + var ( + marshalled = make([]tmtypes.Tx, len(tc.txs)) + cdc = newTestCodec() + ) + for i := range tc.txs { + tx, err := cdc.MarshalBinaryLengthPrefixed(&tc.txs[i]) + require.NoError(t, err) + marshalled[i] = tmtypes.Tx(tx) + } + client := TxSearchMock{txs: marshalled} + ctx := context.CLIContext{}.WithCodec(cdc).WithTrustNode(true).WithClient(client) + params := types.NewQueryProposalVotesParams(0, tc.page, tc.limit) - votesData, err := QueryVotesByTxQuery(ctx, params, makeQuerier(tc.txs)) + votesData, err := QueryVotesByTxQuery(ctx, params) require.NoError(t, err) votes := []types.Vote{} require.NoError(t, ctx.Codec.UnmarshalJSON(votesData, &votes)) diff --git a/x/gov/genesis_test.go b/x/gov/genesis_test.go index 1beb0baecaa6..8626e7821e5f 100644 --- a/x/gov/genesis_test.go +++ b/x/gov/genesis_test.go @@ -29,7 +29,7 @@ func TestImportExportQueues(t *testing.T) { require.NoError(t, err) proposalID2 := proposal2.ProposalID - err, votingStarted := input.keeper.AddDeposit(ctx, proposalID2, input.addrs[0], input.keeper.GetDepositParams(ctx).MinDeposit) + votingStarted, err := input.keeper.AddDeposit(ctx, proposalID2, input.addrs[0], input.keeper.GetDepositParams(ctx).MinDeposit) require.NoError(t, err) require.True(t, votingStarted) diff --git a/x/gov/handler.go b/x/gov/handler.go index 47efe4473cd4..4e4aee2c5334 100644 --- a/x/gov/handler.go +++ b/x/gov/handler.go @@ -4,12 +4,13 @@ import ( "fmt" sdk "github.com/cosmos/cosmos-sdk/types" + sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" "github.com/cosmos/cosmos-sdk/x/gov/types" ) // NewHandler creates an sdk.Handler for all the gov type messages func NewHandler(keeper Keeper) sdk.Handler { - return func(ctx sdk.Context, msg sdk.Msg) sdk.Result { + return func(ctx sdk.Context, msg sdk.Msg) (*sdk.Result, error) { ctx = ctx.WithEventManager(sdk.NewEventManager()) switch msg := msg.(type) { @@ -23,21 +24,20 @@ func NewHandler(keeper Keeper) sdk.Handler { return handleMsgVote(ctx, keeper, msg) default: - errMsg := fmt.Sprintf("unrecognized gov message type: %T", msg) - return sdk.ErrUnknownRequest(errMsg).Result() + return nil, sdkerrors.Wrapf(sdkerrors.ErrUnknownRequest, "unrecognized %s message type: %T", ModuleName, msg) } } } -func handleMsgSubmitProposal(ctx sdk.Context, keeper Keeper, msg MsgSubmitProposal) sdk.Result { +func handleMsgSubmitProposal(ctx sdk.Context, keeper Keeper, msg MsgSubmitProposal) (*sdk.Result, error) { proposal, err := keeper.SubmitProposal(ctx, msg.Content) if err != nil { - return err.Result() + return nil, err } - err, votingStarted := keeper.AddDeposit(ctx, proposal.ProposalID, msg.Proposer, msg.InitialDeposit) + votingStarted, err := keeper.AddDeposit(ctx, proposal.ProposalID, msg.Proposer, msg.InitialDeposit) if err != nil { - return err.Result() + return nil, err } ctx.EventManager().EmitEvent( @@ -56,16 +56,16 @@ func handleMsgSubmitProposal(ctx sdk.Context, keeper Keeper, msg MsgSubmitPropos } ctx.EventManager().EmitEvent(submitEvent) - return sdk.Result{ + return &sdk.Result{ Data: GetProposalIDBytes(proposal.ProposalID), Events: ctx.EventManager().Events(), - } + }, nil } -func handleMsgDeposit(ctx sdk.Context, keeper Keeper, msg MsgDeposit) sdk.Result { - err, votingStarted := keeper.AddDeposit(ctx, msg.ProposalID, msg.Depositor, msg.Amount) +func handleMsgDeposit(ctx sdk.Context, keeper Keeper, msg MsgDeposit) (*sdk.Result, error) { + votingStarted, err := keeper.AddDeposit(ctx, msg.ProposalID, msg.Depositor, msg.Amount) if err != nil { - return err.Result() + return nil, err } ctx.EventManager().EmitEvent( @@ -85,13 +85,13 @@ func handleMsgDeposit(ctx sdk.Context, keeper Keeper, msg MsgDeposit) sdk.Result ) } - return sdk.Result{Events: ctx.EventManager().Events()} + return &sdk.Result{Events: ctx.EventManager().Events()}, nil } -func handleMsgVote(ctx sdk.Context, keeper Keeper, msg MsgVote) sdk.Result { +func handleMsgVote(ctx sdk.Context, keeper Keeper, msg MsgVote) (*sdk.Result, error) { err := keeper.AddVote(ctx, msg.ProposalID, msg.Voter, msg.Option) if err != nil { - return err.Result() + return nil, err } ctx.EventManager().EmitEvent( @@ -102,6 +102,5 @@ func handleMsgVote(ctx sdk.Context, keeper Keeper, msg MsgVote) sdk.Result { ), ) - return sdk.Result{Events: ctx.EventManager().Events()} - + return &sdk.Result{Events: ctx.EventManager().Events()}, nil } diff --git a/x/gov/handler_test.go b/x/gov/handler_test.go index 33dec83ff121..134b25ff0fc5 100644 --- a/x/gov/handler_test.go +++ b/x/gov/handler_test.go @@ -15,7 +15,8 @@ func TestInvalidMsg(t *testing.T) { k := Keeper{} h := NewHandler(k) - res := h(sdk.NewContext(nil, abci.Header{}, false, nil), sdk.NewTestMsg()) - require.False(t, res.IsOK()) - require.True(t, strings.Contains(res.Log, "unrecognized gov message type")) + res, err := h(sdk.NewContext(nil, abci.Header{}, false, nil), sdk.NewTestMsg()) + require.Error(t, err) + require.Nil(t, res) + require.True(t, strings.Contains(err.Error(), "unrecognized gov message type")) } diff --git a/x/gov/keeper/deposit.go b/x/gov/keeper/deposit.go index 426d43d4f14e..c86df046e5e0 100644 --- a/x/gov/keeper/deposit.go +++ b/x/gov/keeper/deposit.go @@ -4,6 +4,7 @@ import ( "fmt" sdk "github.com/cosmos/cosmos-sdk/types" + sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" "github.com/cosmos/cosmos-sdk/x/gov/types" ) @@ -93,22 +94,22 @@ func (keeper Keeper) IterateDeposits(ctx sdk.Context, proposalID uint64, cb func // AddDeposit adds or updates a deposit of a specific depositor on a specific proposal // Activates voting period when appropriate -func (keeper Keeper) AddDeposit(ctx sdk.Context, proposalID uint64, depositorAddr sdk.AccAddress, depositAmount sdk.Coins) (sdk.Error, bool) { +func (keeper Keeper) AddDeposit(ctx sdk.Context, proposalID uint64, depositorAddr sdk.AccAddress, depositAmount sdk.Coins) (bool, error) { // Checks to see if proposal exists proposal, ok := keeper.GetProposal(ctx, proposalID) if !ok { - return types.ErrUnknownProposal(keeper.codespace, proposalID), false + return false, sdkerrors.Wrapf(types.ErrUnknownProposal, "%d", proposalID) } // Check if proposal is still depositable if (proposal.Status != types.StatusDepositPeriod) && (proposal.Status != types.StatusVotingPeriod) { - return types.ErrInactiveProposal(keeper.codespace, proposalID), false + return false, sdkerrors.Wrapf(types.ErrInactiveProposal, "%d", proposalID) } // update the governance module's account coins pool err := keeper.supplyKeeper.SendCoinsFromAccountToModule(ctx, depositorAddr, types.ModuleName, depositAmount) if err != nil { - return err, false + return false, err } // Update proposal @@ -139,7 +140,7 @@ func (keeper Keeper) AddDeposit(ctx sdk.Context, proposalID uint64, depositorAdd ) keeper.SetDeposit(ctx, deposit) - return nil, activatedVotingPeriod + return activatedVotingPeriod, nil } // RefundDeposits refunds and deletes all the deposits on a specific proposal diff --git a/x/gov/keeper/deposit_test.go b/x/gov/keeper/deposit_test.go index c6c229893119..b5d6cce405a2 100644 --- a/x/gov/keeper/deposit_test.go +++ b/x/gov/keeper/deposit_test.go @@ -33,7 +33,7 @@ func TestDeposits(t *testing.T) { require.True(t, proposal.VotingStartTime.Equal(time.Time{})) // Check first deposit - err, votingStarted := keeper.AddDeposit(ctx, proposalID, TestAddrs[0], fourStake) + votingStarted, err := keeper.AddDeposit(ctx, proposalID, TestAddrs[0], fourStake) require.NoError(t, err) require.False(t, votingStarted) deposit, found = keeper.GetDeposit(ctx, proposalID, TestAddrs[0]) @@ -46,7 +46,7 @@ func TestDeposits(t *testing.T) { require.Equal(t, addr0Initial.Sub(fourStake), ak.GetAccount(ctx, TestAddrs[0]).GetCoins()) // Check a second deposit from same address - err, votingStarted = keeper.AddDeposit(ctx, proposalID, TestAddrs[0], fiveStake) + votingStarted, err = keeper.AddDeposit(ctx, proposalID, TestAddrs[0], fiveStake) require.NoError(t, err) require.False(t, votingStarted) deposit, found = keeper.GetDeposit(ctx, proposalID, TestAddrs[0]) @@ -59,7 +59,7 @@ func TestDeposits(t *testing.T) { require.Equal(t, addr0Initial.Sub(fourStake).Sub(fiveStake), ak.GetAccount(ctx, TestAddrs[0]).GetCoins()) // Check third deposit from a new address - err, votingStarted = keeper.AddDeposit(ctx, proposalID, TestAddrs[1], fourStake) + votingStarted, err = keeper.AddDeposit(ctx, proposalID, TestAddrs[1], fourStake) require.NoError(t, err) require.True(t, votingStarted) deposit, found = keeper.GetDeposit(ctx, proposalID, TestAddrs[1]) diff --git a/x/gov/keeper/keeper.go b/x/gov/keeper/keeper.go index b322d3e6b4cd..7a51e6e2bf29 100644 --- a/x/gov/keeper/keeper.go +++ b/x/gov/keeper/keeper.go @@ -29,9 +29,6 @@ type Keeper struct { // The codec codec for binary encoding/decoding. cdc *codec.Codec - // Reserved codespace - codespace sdk.CodespaceType - // Proposal router router types.Router } @@ -45,7 +42,7 @@ type Keeper struct { // CONTRACT: the parameter Subspace must have the param key table already initialized func NewKeeper( cdc *codec.Codec, key sdk.StoreKey, paramSpace types.ParamSubspace, - supplyKeeper types.SupplyKeeper, sk types.StakingKeeper, codespace sdk.CodespaceType, rtr types.Router, + supplyKeeper types.SupplyKeeper, sk types.StakingKeeper, rtr types.Router, ) Keeper { // ensure governance module account is set @@ -64,7 +61,6 @@ func NewKeeper( supplyKeeper: supplyKeeper, sk: sk, cdc: cdc, - codespace: codespace, router: rtr, } } diff --git a/x/gov/keeper/proposal.go b/x/gov/keeper/proposal.go index 2580565d38d4..c5d569314fb2 100644 --- a/x/gov/keeper/proposal.go +++ b/x/gov/keeper/proposal.go @@ -5,13 +5,14 @@ import ( "github.com/cosmos/cosmos-sdk/client" sdk "github.com/cosmos/cosmos-sdk/types" + sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" "github.com/cosmos/cosmos-sdk/x/gov/types" ) // SubmitProposal create new proposal given a content -func (keeper Keeper) SubmitProposal(ctx sdk.Context, content types.Content) (types.Proposal, sdk.Error) { +func (keeper Keeper) SubmitProposal(ctx sdk.Context, content types.Content) (types.Proposal, error) { if !keeper.router.HasRoute(content.ProposalRoute()) { - return types.Proposal{}, types.ErrNoProposalHandlerExists(keeper.codespace, content) + return types.Proposal{}, sdkerrors.Wrap(types.ErrNoProposalHandlerExists, content.ProposalRoute()) } // Execute the proposal content in a cache-wrapped context to validate the @@ -20,7 +21,7 @@ func (keeper Keeper) SubmitProposal(ctx sdk.Context, content types.Content) (typ cacheCtx, _ := ctx.CacheContext() handler := keeper.router.GetRoute(content.ProposalRoute()) if err := handler(cacheCtx, content); err != nil { - return types.Proposal{}, types.ErrInvalidProposalContent(keeper.codespace, err.Result().Log) + return types.Proposal{}, sdkerrors.Wrap(types.ErrInvalidProposalContent, err.Error()) } proposalID, err := keeper.GetProposalID(ctx) @@ -149,12 +150,13 @@ func (keeper Keeper) GetProposalsFiltered(ctx sdk.Context, params types.QueryPro } // GetProposalID gets the highest proposal ID -func (keeper Keeper) GetProposalID(ctx sdk.Context) (proposalID uint64, err sdk.Error) { +func (keeper Keeper) GetProposalID(ctx sdk.Context) (proposalID uint64, err error) { store := ctx.KVStore(keeper.storeKey) bz := store.Get(types.ProposalIDKey) if bz == nil { - return 0, types.ErrInvalidGenesis(keeper.codespace, "initial proposal ID hasn't been set") + return 0, sdkerrors.Wrap(types.ErrInvalidGenesis, "initial proposal ID hasn't been set") } + proposalID = types.GetProposalIDFromBytes(bz) return proposalID, nil } diff --git a/x/gov/keeper/proposal_test.go b/x/gov/keeper/proposal_test.go index c359f1e5e1c8..67208bef6101 100644 --- a/x/gov/keeper/proposal_test.go +++ b/x/gov/keeper/proposal_test.go @@ -1,6 +1,7 @@ package keeper import ( + "errors" "strings" "testing" "time" @@ -51,12 +52,12 @@ func TestActivateVotingPeriod(t *testing.T) { type validProposal struct{} -func (validProposal) GetTitle() string { return "title" } -func (validProposal) GetDescription() string { return "description" } -func (validProposal) ProposalRoute() string { return types.RouterKey } -func (validProposal) ProposalType() string { return types.ProposalTypeText } -func (validProposal) String() string { return "" } -func (validProposal) ValidateBasic() sdk.Error { return nil } +func (validProposal) GetTitle() string { return "title" } +func (validProposal) GetDescription() string { return "description" } +func (validProposal) ProposalRoute() string { return types.RouterKey } +func (validProposal) ProposalType() string { return types.ProposalTypeText } +func (validProposal) String() string { return "" } +func (validProposal) ValidateBasic() error { return nil } type invalidProposalTitle1 struct{ validProposal } @@ -80,8 +81,8 @@ func (invalidProposalRoute) ProposalRoute() string { return "nonexistingroute" } type invalidProposalValidation struct{ validProposal } -func (invalidProposalValidation) ValidateBasic() sdk.Error { - return sdk.NewError(sdk.CodespaceUndefined, sdk.CodeInternal, "") +func (invalidProposalValidation) ValidateBasic() error { + return errors.New("invalid proposal") } func registerTestCodec(cdc *codec.Codec) { @@ -101,7 +102,7 @@ func TestSubmitProposal(t *testing.T) { testCases := []struct { content types.Content - expectedErr sdk.Error + expectedErr error }{ {validProposal{}, nil}, // Keeper does not check the validity of title and description, no error @@ -110,14 +111,14 @@ func TestSubmitProposal(t *testing.T) { {invalidProposalDesc1{}, nil}, {invalidProposalDesc2{}, nil}, // error only when invalid route - {invalidProposalRoute{}, types.ErrNoProposalHandlerExists(types.DefaultCodespace, invalidProposalRoute{})}, + {invalidProposalRoute{}, types.ErrNoProposalHandlerExists}, // Keeper does not call ValidateBasic, msg.ValidateBasic does {invalidProposalValidation{}, nil}, } - for _, tc := range testCases { + for i, tc := range testCases { _, err := keeper.SubmitProposal(ctx, tc.content) - require.Equal(t, tc.expectedErr, err, "unexpected type of error: %s", err) + require.True(t, errors.Is(tc.expectedErr, err), "tc #%d; got: %v, expected: %v", i, err, tc.expectedErr) } } diff --git a/x/gov/keeper/querier.go b/x/gov/keeper/querier.go index b5efc7619b05..9545e5e29b83 100644 --- a/x/gov/keeper/querier.go +++ b/x/gov/keeper/querier.go @@ -1,19 +1,18 @@ package keeper import ( - "fmt" - abci "github.com/tendermint/tendermint/abci/types" "github.com/cosmos/cosmos-sdk/client" "github.com/cosmos/cosmos-sdk/codec" sdk "github.com/cosmos/cosmos-sdk/types" + sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" "github.com/cosmos/cosmos-sdk/x/gov/types" ) // NewQuerier creates a new gov Querier instance func NewQuerier(keeper Keeper) sdk.Querier { - return func(ctx sdk.Context, path []string, req abci.RequestQuery) ([]byte, sdk.Error) { + return func(ctx sdk.Context, path []string, req abci.RequestQuery) ([]byte, error) { switch path[0] { case types.QueryParams: return queryParams(ctx, path[1:], req, keeper) @@ -40,94 +39,100 @@ func NewQuerier(keeper Keeper) sdk.Querier { return queryTally(ctx, path[1:], req, keeper) default: - return nil, sdk.ErrUnknownRequest("unknown gov query endpoint") + return nil, sdkerrors.Wrapf(sdkerrors.ErrUnknownRequest, "unknown query path: %s", path[0]) } } } -func queryParams(ctx sdk.Context, path []string, req abci.RequestQuery, keeper Keeper) ([]byte, sdk.Error) { +func queryParams(ctx sdk.Context, path []string, req abci.RequestQuery, keeper Keeper) ([]byte, error) { switch path[0] { case types.ParamDeposit: bz, err := codec.MarshalJSONIndent(keeper.cdc, keeper.GetDepositParams(ctx)) if err != nil { - return nil, sdk.ErrInternal(sdk.AppendMsgToErr("could not marshal result to JSON", err.Error())) + return nil, sdkerrors.Wrap(sdkerrors.ErrJSONMarshal, err.Error()) } return bz, nil + case types.ParamVoting: bz, err := codec.MarshalJSONIndent(keeper.cdc, keeper.GetVotingParams(ctx)) if err != nil { - return nil, sdk.ErrInternal(sdk.AppendMsgToErr("could not marshal result to JSON", err.Error())) + return nil, sdkerrors.Wrap(sdkerrors.ErrJSONMarshal, err.Error()) } return bz, nil + case types.ParamTallying: bz, err := codec.MarshalJSONIndent(keeper.cdc, keeper.GetTallyParams(ctx)) if err != nil { - return nil, sdk.ErrInternal(sdk.AppendMsgToErr("could not marshal result to JSON", err.Error())) + return nil, sdkerrors.Wrap(sdkerrors.ErrJSONMarshal, err.Error()) } return bz, nil + default: - return nil, sdk.ErrUnknownRequest(fmt.Sprintf("%s is not a valid query request path", req.Path)) + return nil, sdkerrors.Wrapf(sdkerrors.ErrUnknownRequest, "%s is not a valid query request path", req.Path) } } // nolint: unparam -func queryProposal(ctx sdk.Context, path []string, req abci.RequestQuery, keeper Keeper) ([]byte, sdk.Error) { +func queryProposal(ctx sdk.Context, path []string, req abci.RequestQuery, keeper Keeper) ([]byte, error) { var params types.QueryProposalParams err := keeper.cdc.UnmarshalJSON(req.Data, ¶ms) if err != nil { - return nil, sdk.ErrUnknownRequest(sdk.AppendMsgToErr("incorrectly formatted request data", err.Error())) + return nil, sdkerrors.Wrap(sdkerrors.ErrJSONUnmarshal, err.Error()) } proposal, ok := keeper.GetProposal(ctx, params.ProposalID) if !ok { - return nil, types.ErrUnknownProposal(types.DefaultCodespace, params.ProposalID) + return nil, sdkerrors.Wrapf(types.ErrUnknownProposal, "%d", params.ProposalID) } bz, err := codec.MarshalJSONIndent(keeper.cdc, proposal) if err != nil { - return nil, sdk.ErrInternal(sdk.AppendMsgToErr("could not marshal result to JSON", err.Error())) + return nil, sdkerrors.Wrap(sdkerrors.ErrJSONMarshal, err.Error()) } + return bz, nil } // nolint: unparam -func queryDeposit(ctx sdk.Context, path []string, req abci.RequestQuery, keeper Keeper) ([]byte, sdk.Error) { +func queryDeposit(ctx sdk.Context, path []string, req abci.RequestQuery, keeper Keeper) ([]byte, error) { var params types.QueryDepositParams err := keeper.cdc.UnmarshalJSON(req.Data, ¶ms) if err != nil { - return nil, sdk.ErrUnknownRequest(sdk.AppendMsgToErr("incorrectly formatted request data", err.Error())) + return nil, sdkerrors.Wrap(sdkerrors.ErrJSONUnmarshal, err.Error()) } deposit, _ := keeper.GetDeposit(ctx, params.ProposalID, params.Depositor) bz, err := codec.MarshalJSONIndent(keeper.cdc, deposit) if err != nil { - return nil, sdk.ErrInternal(sdk.AppendMsgToErr("could not marshal result to JSON", err.Error())) + return nil, sdkerrors.Wrap(sdkerrors.ErrJSONMarshal, err.Error()) } + return bz, nil } // nolint: unparam -func queryVote(ctx sdk.Context, path []string, req abci.RequestQuery, keeper Keeper) ([]byte, sdk.Error) { +func queryVote(ctx sdk.Context, path []string, req abci.RequestQuery, keeper Keeper) ([]byte, error) { var params types.QueryVoteParams err := keeper.cdc.UnmarshalJSON(req.Data, ¶ms) if err != nil { - return nil, sdk.ErrUnknownRequest(sdk.AppendMsgToErr("incorrectly formatted request data", err.Error())) + return nil, sdkerrors.Wrap(sdkerrors.ErrJSONUnmarshal, err.Error()) } vote, _ := keeper.GetVote(ctx, params.ProposalID, params.Voter) bz, err := codec.MarshalJSONIndent(keeper.cdc, vote) if err != nil { - return nil, sdk.ErrInternal(sdk.AppendMsgToErr("could not marshal result to JSON", err.Error())) + return nil, sdkerrors.Wrap(sdkerrors.ErrJSONMarshal, err.Error()) } + return bz, nil } // nolint: unparam -func queryDeposits(ctx sdk.Context, path []string, req abci.RequestQuery, keeper Keeper) ([]byte, sdk.Error) { +func queryDeposits(ctx sdk.Context, path []string, req abci.RequestQuery, keeper Keeper) ([]byte, error) { var params types.QueryProposalParams err := keeper.cdc.UnmarshalJSON(req.Data, ¶ms) if err != nil { - return nil, sdk.ErrUnknownRequest(sdk.AppendMsgToErr("incorrectly formatted request data", err.Error())) + return nil, sdkerrors.Wrap(sdkerrors.ErrJSONUnmarshal, err.Error()) } deposits := keeper.GetDeposits(ctx, params.ProposalID) @@ -137,24 +142,25 @@ func queryDeposits(ctx sdk.Context, path []string, req abci.RequestQuery, keeper bz, err := codec.MarshalJSONIndent(keeper.cdc, deposits) if err != nil { - return nil, sdk.ErrInternal(sdk.AppendMsgToErr("could not marshal result to JSON", err.Error())) + return nil, sdkerrors.Wrap(sdkerrors.ErrJSONMarshal, err.Error()) } + return bz, nil } // nolint: unparam -func queryTally(ctx sdk.Context, path []string, req abci.RequestQuery, keeper Keeper) ([]byte, sdk.Error) { +func queryTally(ctx sdk.Context, path []string, req abci.RequestQuery, keeper Keeper) ([]byte, error) { var params types.QueryProposalParams err := keeper.cdc.UnmarshalJSON(req.Data, ¶ms) if err != nil { - return nil, sdk.ErrUnknownRequest(sdk.AppendMsgToErr("incorrectly formatted request data", err.Error())) + return nil, sdkerrors.Wrap(sdkerrors.ErrJSONUnmarshal, err.Error()) } proposalID := params.ProposalID proposal, ok := keeper.GetProposal(ctx, proposalID) if !ok { - return nil, types.ErrUnknownProposal(types.DefaultCodespace, proposalID) + return nil, sdkerrors.Wrapf(types.ErrUnknownProposal, "%d", proposalID) } var tallyResult types.TallyResult @@ -162,8 +168,10 @@ func queryTally(ctx sdk.Context, path []string, req abci.RequestQuery, keeper Ke switch { case proposal.Status == types.StatusDepositPeriod: tallyResult = types.EmptyTallyResult() + case proposal.Status == types.StatusPassed || proposal.Status == types.StatusRejected: tallyResult = proposal.FinalTallyResult + default: // proposal is in voting period _, _, tallyResult = keeper.Tally(ctx, proposal) @@ -171,18 +179,18 @@ func queryTally(ctx sdk.Context, path []string, req abci.RequestQuery, keeper Ke bz, err := codec.MarshalJSONIndent(keeper.cdc, tallyResult) if err != nil { - return nil, sdk.ErrInternal(sdk.AppendMsgToErr("could not marshal result to JSON", err.Error())) + return nil, sdkerrors.Wrap(sdkerrors.ErrJSONMarshal, err.Error()) } + return bz, nil } // nolint: unparam -func queryVotes(ctx sdk.Context, path []string, req abci.RequestQuery, keeper Keeper) ([]byte, sdk.Error) { +func queryVotes(ctx sdk.Context, path []string, req abci.RequestQuery, keeper Keeper) ([]byte, error) { var params types.QueryProposalVotesParams err := keeper.cdc.UnmarshalJSON(req.Data, ¶ms) - if err != nil { - return nil, sdk.ErrUnknownRequest(sdk.AppendMsgToErr("incorrectly formatted request data", err.Error())) + return nil, sdkerrors.Wrap(sdkerrors.ErrJSONUnmarshal, err.Error()) } votes := keeper.GetVotes(ctx, params.ProposalID) @@ -199,17 +207,17 @@ func queryVotes(ctx sdk.Context, path []string, req abci.RequestQuery, keeper Ke bz, err := codec.MarshalJSONIndent(keeper.cdc, votes) if err != nil { - return nil, sdk.ErrInternal(sdk.AppendMsgToErr("could not marshal result to JSON", err.Error())) + return nil, sdkerrors.Wrap(sdkerrors.ErrJSONMarshal, err.Error()) } + return bz, nil } -func queryProposals(ctx sdk.Context, _ []string, req abci.RequestQuery, keeper Keeper) ([]byte, sdk.Error) { +func queryProposals(ctx sdk.Context, _ []string, req abci.RequestQuery, keeper Keeper) ([]byte, error) { var params types.QueryProposalsParams - err := keeper.cdc.UnmarshalJSON(req.Data, ¶ms) if err != nil { - return nil, sdk.ErrUnknownRequest(sdk.AppendMsgToErr("failed to parse params", err.Error())) + return nil, sdkerrors.Wrap(sdkerrors.ErrJSONUnmarshal, err.Error()) } proposals := keeper.GetProposalsFiltered(ctx, params) @@ -219,7 +227,7 @@ func queryProposals(ctx sdk.Context, _ []string, req abci.RequestQuery, keeper K bz, err := codec.MarshalJSONIndent(keeper.cdc, proposals) if err != nil { - return nil, sdk.ErrInternal(sdk.AppendMsgToErr("failed to JSON marshal result: %s", err.Error())) + return nil, sdkerrors.Wrap(sdkerrors.ErrJSONMarshal, err.Error()) } return bz, nil diff --git a/x/gov/keeper/querier_test.go b/x/gov/keeper/querier_test.go index a5f781da1807..b8cce877608c 100644 --- a/x/gov/keeper/querier_test.go +++ b/x/gov/keeper/querier_test.go @@ -156,7 +156,7 @@ func TestQueries(t *testing.T) { proposal1, err := keeper.SubmitProposal(ctx, tp) require.NoError(t, err) deposit1 := types.NewDeposit(proposal1.ProposalID, TestAddrs[0], oneCoins) - err, _ = keeper.AddDeposit(ctx, deposit1.ProposalID, deposit1.Depositor, deposit1.Amount) + _, err = keeper.AddDeposit(ctx, deposit1.ProposalID, deposit1.Depositor, deposit1.Amount) require.NoError(t, err) proposal1.TotalDeposit = proposal1.TotalDeposit.Add(deposit1.Amount) @@ -164,7 +164,7 @@ func TestQueries(t *testing.T) { proposal2, err := keeper.SubmitProposal(ctx, tp) require.NoError(t, err) deposit2 := types.NewDeposit(proposal2.ProposalID, TestAddrs[0], consCoins) - err, _ = keeper.AddDeposit(ctx, deposit2.ProposalID, deposit2.Depositor, deposit2.Amount) + _, err = keeper.AddDeposit(ctx, deposit2.ProposalID, deposit2.Depositor, deposit2.Amount) require.NoError(t, err) proposal2.TotalDeposit = proposal2.TotalDeposit.Add(deposit2.Amount) @@ -173,14 +173,14 @@ func TestQueries(t *testing.T) { proposal3, err := keeper.SubmitProposal(ctx, tp) require.NoError(t, err) deposit3 := types.NewDeposit(proposal3.ProposalID, TestAddrs[1], oneCoins) - err, _ = keeper.AddDeposit(ctx, deposit3.ProposalID, deposit3.Depositor, deposit3.Amount) + _, err = keeper.AddDeposit(ctx, deposit3.ProposalID, deposit3.Depositor, deposit3.Amount) require.NoError(t, err) proposal3.TotalDeposit = proposal3.TotalDeposit.Add(deposit3.Amount) // TestAddrs[1] deposits on proposals #2 & #3 deposit4 := types.NewDeposit(proposal2.ProposalID, TestAddrs[1], depositParams.MinDeposit) - err, _ = keeper.AddDeposit(ctx, deposit4.ProposalID, deposit4.Depositor, deposit4.Amount) + _, err = keeper.AddDeposit(ctx, deposit4.ProposalID, deposit4.Depositor, deposit4.Amount) require.NoError(t, err) proposal2.TotalDeposit = proposal2.TotalDeposit.Add(deposit4.Amount) @@ -188,7 +188,7 @@ func TestQueries(t *testing.T) { proposal2.VotingEndTime = proposal2.VotingEndTime.Add(types.DefaultPeriod) deposit5 := types.NewDeposit(proposal3.ProposalID, TestAddrs[1], depositParams.MinDeposit) - err, _ = keeper.AddDeposit(ctx, deposit5.ProposalID, deposit5.Depositor, deposit5.Amount) + _, err = keeper.AddDeposit(ctx, deposit5.ProposalID, deposit5.Depositor, deposit5.Amount) require.NoError(t, err) proposal3.TotalDeposit = proposal3.TotalDeposit.Add(deposit5.Amount) diff --git a/x/gov/keeper/test_common.go b/x/gov/keeper/test_common.go index 781964a206d5..777d71a8c887 100644 --- a/x/gov/keeper/test_common.go +++ b/x/gov/keeper/test_common.go @@ -139,19 +139,19 @@ func createTestInput(t *testing.T, isCheckTx bool, initPower int64) (sdk.Context blacklistedAddrs[notBondedPool.GetAddress().String()] = true blacklistedAddrs[bondPool.GetAddress().String()] = true - pk := params.NewKeeper(cdc, keyParams, tkeyParams, params.DefaultCodespace) + pk := params.NewKeeper(cdc, keyParams, tkeyParams) accountKeeper := auth.NewAccountKeeper(cdc, keyAcc, pk.Subspace(auth.DefaultParamspace), auth.ProtoBaseAccount) - bankKeeper := bank.NewBaseKeeper(accountKeeper, pk.Subspace(bank.DefaultParamspace), bank.DefaultCodespace, blacklistedAddrs) + bankKeeper := bank.NewBaseKeeper(accountKeeper, pk.Subspace(bank.DefaultParamspace), blacklistedAddrs) supplyKeeper := supply.NewKeeper(cdc, keySupply, accountKeeper, bankKeeper, maccPerms) - sk := staking.NewKeeper(cdc, keyStaking, supplyKeeper, pk.Subspace(staking.DefaultParamspace), staking.DefaultCodespace) + sk := staking.NewKeeper(cdc, keyStaking, supplyKeeper, pk.Subspace(staking.DefaultParamspace)) sk.SetParams(ctx, staking.DefaultParams()) rtr := types.NewRouter(). AddRoute(types.RouterKey, types.ProposalHandler) keeper := NewKeeper( - cdc, keyGov, pk.Subspace(types.DefaultParamspace).WithKeyTable(types.ParamKeyTable()), supplyKeeper, sk, types.DefaultCodespace, rtr, + cdc, keyGov, pk.Subspace(types.DefaultParamspace).WithKeyTable(types.ParamKeyTable()), supplyKeeper, sk, rtr, ) keeper.SetProposalID(ctx, types.DefaultStartingProposalID) diff --git a/x/gov/keeper/vote.go b/x/gov/keeper/vote.go index 0204e56be273..309446714287 100644 --- a/x/gov/keeper/vote.go +++ b/x/gov/keeper/vote.go @@ -4,21 +4,22 @@ import ( "fmt" sdk "github.com/cosmos/cosmos-sdk/types" + sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" "github.com/cosmos/cosmos-sdk/x/gov/types" ) // AddVote adds a vote on a specific proposal -func (keeper Keeper) AddVote(ctx sdk.Context, proposalID uint64, voterAddr sdk.AccAddress, option types.VoteOption) sdk.Error { +func (keeper Keeper) AddVote(ctx sdk.Context, proposalID uint64, voterAddr sdk.AccAddress, option types.VoteOption) error { proposal, ok := keeper.GetProposal(ctx, proposalID) if !ok { - return types.ErrUnknownProposal(keeper.codespace, proposalID) + return sdkerrors.Wrapf(types.ErrUnknownProposal, "%d", proposalID) } if proposal.Status != types.StatusVotingPeriod { - return types.ErrInactiveProposal(keeper.codespace, proposalID) + return sdkerrors.Wrapf(types.ErrInactiveProposal, "%d", proposalID) } if !types.ValidVoteOption(option) { - return types.ErrInvalidVote(keeper.codespace, option.String()) + return sdkerrors.Wrap(types.ErrInvalidVote, option.String()) } vote := types.NewVote(proposalID, voterAddr, option) diff --git a/x/gov/legacy/v0_36/types.go b/x/gov/legacy/v0_36/types.go index f18cddac1c50..faaaa4e32171 100644 --- a/x/gov/legacy/v0_36/types.go +++ b/x/gov/legacy/v0_36/types.go @@ -16,14 +16,10 @@ const ( ModuleName = "gov" RouterKey = ModuleName - DefaultCodespace sdk.CodespaceType = "gov" - ProposalTypeText string = "Text" MaxDescriptionLength int = 5000 MaxTitleLength int = 140 - - CodeInvalidContent sdk.CodeType = 6 ) var ( @@ -44,7 +40,7 @@ type ( GetDescription() string ProposalRoute() string ProposalType() string - ValidateBasic() sdk.Error + ValidateBasic() error String() string } @@ -94,11 +90,11 @@ func NewTextProposal(title, description string) Content { return TextProposal{title, description} } -func (tp TextProposal) GetTitle() string { return tp.Title } -func (tp TextProposal) GetDescription() string { return tp.Description } -func (tp TextProposal) ProposalRoute() string { return RouterKey } -func (tp TextProposal) ProposalType() string { return ProposalTypeText } -func (tp TextProposal) ValidateBasic() sdk.Error { return ValidateAbstract(DefaultCodespace, tp) } +func (tp TextProposal) GetTitle() string { return tp.Title } +func (tp TextProposal) GetDescription() string { return tp.Description } +func (tp TextProposal) ProposalRoute() string { return RouterKey } +func (tp TextProposal) ProposalType() string { return ProposalTypeText } +func (tp TextProposal) ValidateBasic() error { return ValidateAbstract(tp) } func (tp TextProposal) String() string { return fmt.Sprintf(`Text Proposal: @@ -107,25 +103,25 @@ func (tp TextProposal) String() string { `, tp.Title, tp.Description) } -func ErrInvalidProposalContent(cs sdk.CodespaceType, msg string) sdk.Error { - return sdk.NewError(cs, CodeInvalidContent, fmt.Sprintf("invalid proposal content: %s", msg)) +func ErrInvalidProposalContent(msg string) error { + return fmt.Errorf("invalid proposal content: %s", msg) } -func ValidateAbstract(codespace sdk.CodespaceType, c Content) sdk.Error { +func ValidateAbstract(c Content) error { title := c.GetTitle() if len(strings.TrimSpace(title)) == 0 { - return ErrInvalidProposalContent(codespace, "proposal title cannot be blank") + return ErrInvalidProposalContent("proposal title cannot be blank") } if len(title) > MaxTitleLength { - return ErrInvalidProposalContent(codespace, fmt.Sprintf("proposal title is longer than max length of %d", MaxTitleLength)) + return ErrInvalidProposalContent(fmt.Sprintf("proposal title is longer than max length of %d", MaxTitleLength)) } description := c.GetDescription() if len(description) == 0 { - return ErrInvalidProposalContent(codespace, "proposal description cannot be blank") + return ErrInvalidProposalContent("proposal description cannot be blank") } if len(description) > MaxDescriptionLength { - return ErrInvalidProposalContent(codespace, fmt.Sprintf("proposal description is longer than max length of %d", MaxDescriptionLength)) + return ErrInvalidProposalContent(fmt.Sprintf("proposal description is longer than max length of %d", MaxDescriptionLength)) } return nil diff --git a/x/gov/simulation/operations.go b/x/gov/simulation/operations.go index 0e0bcd06f600..b53a97350146 100644 --- a/x/gov/simulation/operations.go +++ b/x/gov/simulation/operations.go @@ -1,7 +1,6 @@ package simulation import ( - "errors" "math" "math/rand" "time" @@ -148,9 +147,9 @@ func SimulateSubmitProposal( simAccount.PrivKey, ) - res := app.Deliver(tx) - if !res.IsOK() { - return simulation.NoOpMsg(types.ModuleName), nil, errors.New(res.Log) + _, _, err = app.Deliver(tx) + if err != nil { + return simulation.NoOpMsg(types.ModuleName), nil, err } opMsg := simulation.NewOperationMsg(msg, true, "") @@ -231,9 +230,9 @@ func SimulateMsgDeposit(ak types.AccountKeeper, k keeper.Keeper) simulation.Oper simAccount.PrivKey, ) - res := app.Deliver(tx) - if !res.IsOK() { - return simulation.NoOpMsg(types.ModuleName), nil, errors.New(res.Log) + _, _, err = app.Deliver(tx) + if err != nil { + return simulation.NoOpMsg(types.ModuleName), nil, err } return simulation.NewOperationMsg(msg, true, ""), nil, nil @@ -289,9 +288,9 @@ func operationSimulateMsgVote(ak types.AccountKeeper, k keeper.Keeper, simAccount.PrivKey, ) - res := app.Deliver(tx) - if !res.IsOK() { - return simulation.NoOpMsg(types.ModuleName), nil, errors.New(res.Log) + _, _, err = app.Deliver(tx) + if err != nil { + return simulation.NoOpMsg(types.ModuleName), nil, err } return simulation.NewOperationMsg(msg, true, ""), nil, nil diff --git a/x/gov/test_common.go b/x/gov/test_common.go index 36479f7fa0c2..7ecd4bd50f68 100644 --- a/x/gov/test_common.go +++ b/x/gov/test_common.go @@ -4,7 +4,7 @@ package gov import ( "bytes" - "fmt" + "errors" "log" "sort" "testing" @@ -16,6 +16,7 @@ import ( "github.com/tendermint/tendermint/crypto" sdk "github.com/cosmos/cosmos-sdk/types" + sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" authexported "github.com/cosmos/cosmos-sdk/x/auth/exported" "github.com/cosmos/cosmos-sdk/x/bank" keep "github.com/cosmos/cosmos-sdk/x/gov/keeper" @@ -43,8 +44,11 @@ type testInput struct { privKeys []crypto.PrivKey } -func getMockApp(t *testing.T, numGenAccs int, genState types.GenesisState, genAccs []authexported.Account, - handler func(ctx sdk.Context, c types.Content) sdk.Error) testInput { +func getMockApp( + t *testing.T, numGenAccs int, genState types.GenesisState, genAccs []authexported.Account, + handler func(ctx sdk.Context, c types.Content) error, +) testInput { + mApp := mock.NewApp() staking.RegisterCodec(mApp.Cdc) @@ -69,7 +73,7 @@ func getMockApp(t *testing.T, numGenAccs int, genState types.GenesisState, genAc rtr := types.NewRouter(). AddRoute(types.RouterKey, handler) - bk := bank.NewBaseKeeper(mApp.AccountKeeper, mApp.ParamsKeeper.Subspace(bank.DefaultParamspace), bank.DefaultCodespace, blacklistedAddrs) + bk := bank.NewBaseKeeper(mApp.AccountKeeper, mApp.ParamsKeeper.Subspace(bank.DefaultParamspace), blacklistedAddrs) maccPerms := map[string][]string{ types.ModuleName: {supply.Burner}, @@ -78,11 +82,11 @@ func getMockApp(t *testing.T, numGenAccs int, genState types.GenesisState, genAc } supplyKeeper := supply.NewKeeper(mApp.Cdc, keySupply, mApp.AccountKeeper, bk, maccPerms) sk := staking.NewKeeper( - mApp.Cdc, keyStaking, supplyKeeper, pk.Subspace(staking.DefaultParamspace), staking.DefaultCodespace, + mApp.Cdc, keyStaking, supplyKeeper, pk.Subspace(staking.DefaultParamspace), ) keeper := keep.NewKeeper( - mApp.Cdc, keyGov, pk.Subspace(DefaultParamspace).WithKeyTable(ParamKeyTable()), supplyKeeper, sk, types.DefaultCodespace, rtr, + mApp.Cdc, keyGov, pk.Subspace(DefaultParamspace).WithKeyTable(ParamKeyTable()), supplyKeeper, sk, rtr, ) mApp.Router().AddRoute(types.RouterKey, NewHandler(keeper)) @@ -193,20 +197,19 @@ const contextKeyBadProposal = "contextKeyBadProposal" // badProposalHandler implements a governance proposal handler that is identical // to the actual handler except this fails if the context doesn't contain a value // for the key contextKeyBadProposal or if the value is false. -func badProposalHandler(ctx sdk.Context, c types.Content) sdk.Error { +func badProposalHandler(ctx sdk.Context, c types.Content) error { switch c.ProposalType() { case types.ProposalTypeText: v := ctx.Value(contextKeyBadProposal) if v == nil || !v.(bool) { - return sdk.ErrInternal("proposal failed") + return errors.New("proposal failed") } return nil default: - msg := fmt.Sprintf("unrecognized gov proposal type: %s", c.ProposalType()) - return sdk.ErrUnknownRequest(msg) + return sdkerrors.Wrapf(sdkerrors.ErrUnknownRequest, "unrecognized gov proposal type: %s", c.ProposalType()) } } @@ -229,7 +232,8 @@ func createValidators(t *testing.T, stakingHandler sdk.Handler, ctx sdk.Context, keep.TestDescription, keep.TestCommissionRates, sdk.OneInt(), ) - res := stakingHandler(ctx, valCreateMsg) - require.True(t, res.IsOK()) + res, err := stakingHandler(ctx, valCreateMsg) + require.NoError(t, err) + require.NotNil(t, res) } } diff --git a/x/gov/types/content.go b/x/gov/types/content.go index 22a7f7a4af62..21d70d5ab1e8 100644 --- a/x/gov/types/content.go +++ b/x/gov/types/content.go @@ -1,10 +1,10 @@ package types import ( - "fmt" "strings" sdk "github.com/cosmos/cosmos-sdk/types" + sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" ) // Constants pertaining to a Content object @@ -22,31 +22,31 @@ type Content interface { GetDescription() string ProposalRoute() string ProposalType() string - ValidateBasic() sdk.Error + ValidateBasic() error String() string } // Handler defines a function that handles a proposal after it has passed the // governance process. -type Handler func(ctx sdk.Context, content Content) sdk.Error +type Handler func(ctx sdk.Context, content Content) error // ValidateAbstract validates a proposal's abstract contents returning an error // if invalid. -func ValidateAbstract(codespace sdk.CodespaceType, c Content) sdk.Error { +func ValidateAbstract(c Content) error { title := c.GetTitle() if len(strings.TrimSpace(title)) == 0 { - return ErrInvalidProposalContent(codespace, "proposal title cannot be blank") + return sdkerrors.Wrap(ErrInvalidProposalContent, "proposal title cannot be blank") } if len(title) > MaxTitleLength { - return ErrInvalidProposalContent(codespace, fmt.Sprintf("proposal title is longer than max length of %d", MaxTitleLength)) + return sdkerrors.Wrapf(ErrInvalidProposalContent, "proposal title is longer than max length of %d", MaxTitleLength) } description := c.GetDescription() if len(description) == 0 { - return ErrInvalidProposalContent(codespace, "proposal description cannot be blank") + return sdkerrors.Wrap(ErrInvalidProposalContent, "proposal description cannot be blank") } if len(description) > MaxDescriptionLength { - return ErrInvalidProposalContent(codespace, fmt.Sprintf("proposal description is longer than max length of %d", MaxDescriptionLength)) + return sdkerrors.Wrapf(ErrInvalidProposalContent, "proposal description is longer than max length of %d", MaxDescriptionLength) } return nil diff --git a/x/gov/types/errors.go b/x/gov/types/errors.go index dfc7bf5a4596..2327a6f05b5e 100644 --- a/x/gov/types/errors.go +++ b/x/gov/types/errors.go @@ -1,66 +1,17 @@ package types -// DONTCOVER - import ( - "fmt" - - sdk "github.com/cosmos/cosmos-sdk/types" + sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" ) -// Codes for governance errors -const ( - DefaultCodespace sdk.CodespaceType = ModuleName - - CodeUnknownProposal sdk.CodeType = 1 - CodeInactiveProposal sdk.CodeType = 2 - CodeAlreadyActiveProposal sdk.CodeType = 3 - CodeAlreadyFinishedProposal sdk.CodeType = 4 - CodeAddressNotStaked sdk.CodeType = 5 - CodeInvalidContent sdk.CodeType = 6 - CodeInvalidProposalType sdk.CodeType = 7 - CodeInvalidVote sdk.CodeType = 8 - CodeInvalidGenesis sdk.CodeType = 9 - CodeInvalidProposalStatus sdk.CodeType = 10 - CodeProposalHandlerNotExists sdk.CodeType = 11 +// x/gov module sentinel errors +var ( + ErrUnknownProposal = sdkerrors.Register(ModuleName, 1, "unknown proposal") + ErrInactiveProposal = sdkerrors.Register(ModuleName, 2, "inactive proposal") + ErrAlreadyActiveProposal = sdkerrors.Register(ModuleName, 3, "proposal already active") + ErrInvalidProposalContent = sdkerrors.Register(ModuleName, 4, "invalid proposal content") + ErrInvalidProposalType = sdkerrors.Register(ModuleName, 5, "invalid proposal type") + ErrInvalidVote = sdkerrors.Register(ModuleName, 6, "invalid vote option") + ErrInvalidGenesis = sdkerrors.Register(ModuleName, 7, "invalid genesis state") + ErrNoProposalHandlerExists = sdkerrors.Register(ModuleName, 8, "no handler exists for proposal type") ) - -// ErrUnknownProposal error for unknown proposals -func ErrUnknownProposal(codespace sdk.CodespaceType, proposalID uint64) sdk.Error { - return sdk.NewError(codespace, CodeUnknownProposal, fmt.Sprintf("unknown proposal with id %d", proposalID)) -} - -// ErrInactiveProposal error for inactive (i.e finalized) proposals -func ErrInactiveProposal(codespace sdk.CodespaceType, proposalID uint64) sdk.Error { - return sdk.NewError(codespace, CodeInactiveProposal, fmt.Sprintf("inactive proposal with id %d", proposalID)) -} - -// ErrAlreadyActiveProposal error for proposals that are already active -func ErrAlreadyActiveProposal(codespace sdk.CodespaceType, proposalID uint64) sdk.Error { - return sdk.NewError(codespace, CodeAlreadyActiveProposal, fmt.Sprintf("proposal %d has been already active", proposalID)) -} - -// ErrInvalidProposalContent error for invalid proposal title or description -func ErrInvalidProposalContent(cs sdk.CodespaceType, msg string) sdk.Error { - return sdk.NewError(cs, CodeInvalidContent, fmt.Sprintf("invalid proposal content: %s", msg)) -} - -// ErrInvalidProposalType error for non registered proposal types -func ErrInvalidProposalType(codespace sdk.CodespaceType, proposalType string) sdk.Error { - return sdk.NewError(codespace, CodeInvalidProposalType, fmt.Sprintf("proposal type '%s' is not valid", proposalType)) -} - -// ErrInvalidVote error for an invalid vote option -func ErrInvalidVote(codespace sdk.CodespaceType, voteOption string) sdk.Error { - return sdk.NewError(codespace, CodeInvalidVote, fmt.Sprintf("'%v' is not a valid voting option", voteOption)) -} - -// ErrInvalidGenesis error for an invalid governance GenesisState -func ErrInvalidGenesis(codespace sdk.CodespaceType, msg string) sdk.Error { - return sdk.NewError(codespace, CodeInvalidVote, msg) -} - -// ErrNoProposalHandlerExists error when proposal handler is not defined -func ErrNoProposalHandlerExists(codespace sdk.CodespaceType, content interface{}) sdk.Error { - return sdk.NewError(codespace, CodeProposalHandlerNotExists, fmt.Sprintf("'%T' does not have a corresponding handler", content)) -} diff --git a/x/gov/types/expected_keepers.go b/x/gov/types/expected_keepers.go index c0fda62d61fe..31e5d1e05cff 100644 --- a/x/gov/types/expected_keepers.go +++ b/x/gov/types/expected_keepers.go @@ -21,21 +21,23 @@ type SupplyKeeper interface { // TODO remove with genesis 2-phases refactor https://github.com/cosmos/cosmos-sdk/issues/2862 SetModuleAccount(sdk.Context, supplyexported.ModuleAccountI) - SendCoinsFromModuleToAccount(ctx sdk.Context, senderModule string, recipientAddr sdk.AccAddress, amt sdk.Coins) sdk.Error - SendCoinsFromAccountToModule(ctx sdk.Context, senderAddr sdk.AccAddress, recipientModule string, amt sdk.Coins) sdk.Error - BurnCoins(ctx sdk.Context, name string, amt sdk.Coins) sdk.Error + SendCoinsFromModuleToAccount(ctx sdk.Context, senderModule string, recipientAddr sdk.AccAddress, amt sdk.Coins) error + SendCoinsFromAccountToModule(ctx sdk.Context, senderAddr sdk.AccAddress, recipientModule string, amt sdk.Coins) error + BurnCoins(ctx sdk.Context, name string, amt sdk.Coins) error } // StakingKeeper expected staking keeper (Validator and Delegator sets) (noalias) type StakingKeeper interface { // iterate through bonded validators by operator address, execute func for each validator - IterateBondedValidatorsByPower(sdk.Context, - func(index int64, validator stakingexported.ValidatorI) (stop bool)) + IterateBondedValidatorsByPower( + sdk.Context, func(index int64, validator stakingexported.ValidatorI) (stop bool), + ) TotalBondedTokens(sdk.Context) sdk.Int // total bonded tokens within the validator set - - IterateDelegations(ctx sdk.Context, delegator sdk.AccAddress, - fn func(index int64, delegation stakingexported.DelegationI) (stop bool)) + IterateDelegations( + ctx sdk.Context, delegator sdk.AccAddress, + fn func(index int64, delegation stakingexported.DelegationI) (stop bool), + ) } // AccountKeeper defines the expected account keeper (noalias) diff --git a/x/gov/types/msgs.go b/x/gov/types/msgs.go index b5b85ca167ea..882e0c560c31 100644 --- a/x/gov/types/msgs.go +++ b/x/gov/types/msgs.go @@ -4,6 +4,7 @@ import ( "fmt" sdk "github.com/cosmos/cosmos-sdk/types" + sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" ) // Governance message types and routes @@ -35,21 +36,21 @@ func (msg MsgSubmitProposal) Route() string { return RouterKey } func (msg MsgSubmitProposal) Type() string { return TypeMsgSubmitProposal } // ValidateBasic implements Msg -func (msg MsgSubmitProposal) ValidateBasic() sdk.Error { +func (msg MsgSubmitProposal) ValidateBasic() error { if msg.Content == nil { - return ErrInvalidProposalContent(DefaultCodespace, "missing content") + return sdkerrors.Wrap(ErrInvalidProposalContent, "missing content") } if msg.Proposer.Empty() { - return sdk.ErrInvalidAddress(msg.Proposer.String()) + return sdkerrors.Wrap(sdkerrors.ErrInvalidAddress, msg.Proposer.String()) } if !msg.InitialDeposit.IsValid() { - return sdk.ErrInvalidCoins(msg.InitialDeposit.String()) + return sdkerrors.Wrap(sdkerrors.ErrInvalidCoins, msg.InitialDeposit.String()) } if msg.InitialDeposit.IsAnyNegative() { - return sdk.ErrInvalidCoins(msg.InitialDeposit.String()) + return sdkerrors.Wrap(sdkerrors.ErrInvalidCoins, msg.InitialDeposit.String()) } if !IsValidProposalType(msg.Content.ProposalType()) { - return ErrInvalidProposalType(DefaultCodespace, msg.Content.ProposalType()) + return sdkerrors.Wrap(ErrInvalidProposalType, msg.Content.ProposalType()) } return msg.Content.ValidateBasic() @@ -93,15 +94,15 @@ func (msg MsgDeposit) Route() string { return RouterKey } func (msg MsgDeposit) Type() string { return TypeMsgDeposit } // ValidateBasic implements Msg -func (msg MsgDeposit) ValidateBasic() sdk.Error { +func (msg MsgDeposit) ValidateBasic() error { if msg.Depositor.Empty() { - return sdk.ErrInvalidAddress(msg.Depositor.String()) + return sdkerrors.Wrap(sdkerrors.ErrInvalidAddress, msg.Depositor.String()) } if !msg.Amount.IsValid() { - return sdk.ErrInvalidCoins(msg.Amount.String()) + return sdkerrors.Wrap(sdkerrors.ErrInvalidCoins, msg.Amount.String()) } if msg.Amount.IsAnyNegative() { - return sdk.ErrInvalidCoins(msg.Amount.String()) + return sdkerrors.Wrap(sdkerrors.ErrInvalidCoins, msg.Amount.String()) } return nil @@ -146,12 +147,12 @@ func (msg MsgVote) Route() string { return RouterKey } func (msg MsgVote) Type() string { return TypeMsgVote } // ValidateBasic implements Msg -func (msg MsgVote) ValidateBasic() sdk.Error { +func (msg MsgVote) ValidateBasic() error { if msg.Voter.Empty() { - return sdk.ErrInvalidAddress(msg.Voter.String()) + return sdkerrors.Wrap(sdkerrors.ErrInvalidAddress, msg.Voter.String()) } if !ValidVoteOption(msg.Option) { - return ErrInvalidVote(DefaultCodespace, msg.Option.String()) + return sdkerrors.Wrap(ErrInvalidVote, msg.Option.String()) } return nil diff --git a/x/gov/types/proposal.go b/x/gov/types/proposal.go index a02f7b54d6b9..945cf786687b 100644 --- a/x/gov/types/proposal.go +++ b/x/gov/types/proposal.go @@ -7,6 +7,7 @@ import ( "time" sdk "github.com/cosmos/cosmos-sdk/types" + sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" ) // DefaultStartingProposalID is 1 @@ -232,7 +233,7 @@ func (tp TextProposal) ProposalRoute() string { return RouterKey } func (tp TextProposal) ProposalType() string { return ProposalTypeText } // ValidateBasic validates the content's title and description of the proposal -func (tp TextProposal) ValidateBasic() sdk.Error { return ValidateAbstract(DefaultCodespace, tp) } +func (tp TextProposal) ValidateBasic() error { return ValidateAbstract(tp) } // String implements Stringer interface func (tp TextProposal) String() string { @@ -280,14 +281,13 @@ func IsValidProposalType(ty string) bool { // proposals (ie. TextProposal ). Since these are // merely signaling mechanisms at the moment and do not affect state, it // performs a no-op. -func ProposalHandler(_ sdk.Context, c Content) sdk.Error { +func ProposalHandler(_ sdk.Context, c Content) error { switch c.ProposalType() { case ProposalTypeText: // both proposal types do not change state so this performs a no-op return nil default: - errMsg := fmt.Sprintf("unrecognized gov proposal type: %s", c.ProposalType()) - return sdk.ErrUnknownRequest(errMsg) + return sdkerrors.Wrapf(sdkerrors.ErrUnknownRequest, "unrecognized gov proposal type: %s", c.ProposalType()) } } diff --git a/x/ibc/02-client/alias.go b/x/ibc/02-client/alias.go index 02f3aa623668..d818bbb99572 100644 --- a/x/ibc/02-client/alias.go +++ b/x/ibc/02-client/alias.go @@ -13,26 +13,15 @@ import ( ) const ( - DefaultCodespace = errors.DefaultCodespace - CodeClientExists = errors.CodeClientExists - CodeClientNotFound = errors.CodeClientNotFound - CodeClientFrozen = errors.CodeClientFrozen - CodeConsensusStateNotFound = errors.CodeConsensusStateNotFound - CodeInvalidConsensusState = errors.CodeInvalidConsensusState - CodeClientTypeNotFound = errors.CodeClientTypeNotFound - CodeInvalidClientType = errors.CodeInvalidClientType - CodeRootNotFound = errors.CodeRootNotFound - CodeInvalidHeader = errors.CodeInvalidHeader - CodeInvalidEvidence = errors.CodeInvalidEvidence - AttributeKeyClientID = types.AttributeKeyClientID - SubModuleName = types.SubModuleName - StoreKey = types.StoreKey - RouterKey = types.RouterKey - QuerierRoute = types.QuerierRoute - QueryAllClients = types.QueryAllClients - QueryClientState = types.QueryClientState - QueryConsensusState = types.QueryConsensusState - QueryVerifiedRoot = types.QueryVerifiedRoot + AttributeKeyClientID = types.AttributeKeyClientID + SubModuleName = types.SubModuleName + StoreKey = types.StoreKey + RouterKey = types.RouterKey + QuerierRoute = types.QuerierRoute + QueryAllClients = types.QueryAllClients + QueryClientState = types.QueryClientState + QueryConsensusState = types.QueryConsensusState + QueryVerifiedRoot = types.QueryVerifiedRoot ) var ( diff --git a/x/ibc/02-client/client/cli/cli.go b/x/ibc/02-client/client/cli/cli.go index d2db4d2be958..4a36894faf35 100644 --- a/x/ibc/02-client/client/cli/cli.go +++ b/x/ibc/02-client/client/cli/cli.go @@ -3,7 +3,7 @@ package cli import ( "github.com/spf13/cobra" - "github.com/cosmos/cosmos-sdk/client" + "github.com/cosmos/cosmos-sdk/client/flags" "github.com/cosmos/cosmos-sdk/codec" ) @@ -16,7 +16,7 @@ func GetQueryCmd(queryRoute string, cdc *codec.Codec) *cobra.Command { SuggestionsMinimumDistance: 2, } - ics02ClientQueryCmd.AddCommand(client.GetCommands( + ics02ClientQueryCmd.AddCommand(flags.GetCommands( GetCmdQueryClientStates(queryRoute, cdc), GetCmdQueryClientState(queryRoute, cdc), GetCmdQueryConsensusState(queryRoute, cdc), @@ -37,7 +37,7 @@ func GetTxCmd(storeKey string, cdc *codec.Codec) *cobra.Command { SuggestionsMinimumDistance: 2, } - ics02ClientTxCmd.AddCommand(client.PostCommands( + ics02ClientTxCmd.AddCommand(flags.PostCommands( GetCmdCreateClient(cdc), GetCmdUpdateClient(cdc), )...) diff --git a/x/ibc/02-client/client/utils/utils.go b/x/ibc/02-client/client/utils/utils.go index 848d489b2308..02f1163b3d32 100644 --- a/x/ibc/02-client/client/utils/utils.go +++ b/x/ibc/02-client/client/utils/utils.go @@ -6,7 +6,6 @@ import ( abci "github.com/tendermint/tendermint/abci/types" tmtypes "github.com/tendermint/tendermint/types" - "github.com/cosmos/cosmos-sdk/client" "github.com/cosmos/cosmos-sdk/client/context" "github.com/cosmos/cosmos-sdk/x/ibc/02-client/types" "github.com/cosmos/cosmos-sdk/x/ibc/02-client/types/tendermint" @@ -62,10 +61,10 @@ func QueryClientState( return clientStateRes, nil } -// QueryConsensusStateProof queries the store to get the consensus state and a -// merkle proof. +// QueryConsensusState queries the store to get the consensus state and a merkle +// proof. func QueryConsensusState( - cliCtx client.CLIContext, clientID string, prove bool) (types.ConsensusStateResponse, error) { + cliCtx context.CLIContext, clientID string, prove bool) (types.ConsensusStateResponse, error) { var conStateRes types.ConsensusStateResponse req := abci.RequestQuery{ diff --git a/x/ibc/02-client/handler.go b/x/ibc/02-client/handler.go index 7363053f2319..0525e115a014 100644 --- a/x/ibc/02-client/handler.go +++ b/x/ibc/02-client/handler.go @@ -1,9 +1,8 @@ package client import ( - "fmt" - sdk "github.com/cosmos/cosmos-sdk/types" + sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" "github.com/cosmos/cosmos-sdk/x/evidence" evidenceexported "github.com/cosmos/cosmos-sdk/x/evidence/exported" "github.com/cosmos/cosmos-sdk/x/ibc/02-client/exported" @@ -11,17 +10,15 @@ import ( ) // HandleMsgCreateClient defines the sdk.Handler for MsgCreateClient -func HandleMsgCreateClient(ctx sdk.Context, k Keeper, msg MsgCreateClient) sdk.Result { +func HandleMsgCreateClient(ctx sdk.Context, k Keeper, msg MsgCreateClient) (*sdk.Result, error) { clientType := exported.ClientTypeFromString(msg.ClientType) if clientType == 0 { - return sdk.ResultFromError( - ErrInvalidClientType(DefaultCodespace, fmt.Sprintf("invalid client type '%s'", msg.ClientType)), - ) + return nil, sdkerrors.Wrap(ErrInvalidClientType, msg.ClientType) } _, err := k.CreateClient(ctx, msg.ClientID, clientType, msg.ConsensusState) if err != nil { - return sdk.ResultFromError(err) + return nil, err } ctx.EventManager().EmitEvents(sdk.Events{ @@ -36,14 +33,16 @@ func HandleMsgCreateClient(ctx sdk.Context, k Keeper, msg MsgCreateClient) sdk.R ), }) - return sdk.Result{Events: ctx.EventManager().Events()} + return &sdk.Result{ + Events: ctx.EventManager().Events(), + }, nil } // HandleMsgUpdateClient defines the sdk.Handler for MsgUpdateClient -func HandleMsgUpdateClient(ctx sdk.Context, k Keeper, msg MsgUpdateClient) sdk.Result { +func HandleMsgUpdateClient(ctx sdk.Context, k Keeper, msg MsgUpdateClient) (*sdk.Result, error) { err := k.UpdateClient(ctx, msg.ClientID, msg.Header) if err != nil { - return sdk.ResultFromError(err) + return nil, err } ctx.EventManager().EmitEvents(sdk.Events{ @@ -58,7 +57,9 @@ func HandleMsgUpdateClient(ctx sdk.Context, k Keeper, msg MsgUpdateClient) sdk.R ), }) - return sdk.Result{Events: ctx.EventManager().Events()} + return &sdk.Result{ + Events: ctx.EventManager().Events(), + }, nil } // HandlerClientMisbehaviour defines the Evidence module handler for submitting a @@ -70,8 +71,7 @@ func HandlerClientMisbehaviour(k Keeper) evidence.Handler { return k.CheckMisbehaviourAndUpdateState(ctx, evidence) default: - errMsg := fmt.Sprintf("unrecognized IBC client evidence type: %T", e) - return sdk.ErrUnknownRequest(errMsg) + return sdkerrors.Wrapf(sdkerrors.ErrUnknownRequest, "unrecognized IBC client evidence type: %T", e) } } } diff --git a/x/ibc/02-client/keeper/client.go b/x/ibc/02-client/keeper/client.go index 9b72ef4a2c2c..91cadfe4a016 100644 --- a/x/ibc/02-client/keeper/client.go +++ b/x/ibc/02-client/keeper/client.go @@ -20,7 +20,7 @@ func (k Keeper) CreateClient( ) (types.State, error) { _, found := k.GetClientState(ctx, clientID) if found { - return types.State{}, errors.ErrClientExists(k.codespace, clientID) + return types.State{}, sdkerrors.Wrapf(errors.ErrClientExists, "cannot create client with ID %s", clientID) } _, found = k.GetClientType(ctx, clientID) @@ -41,31 +41,31 @@ func (k Keeper) CreateClient( func (k Keeper) UpdateClient(ctx sdk.Context, clientID string, header exported.Header) error { clientType, found := k.GetClientType(ctx, clientID) if !found { - return sdkerrors.Wrap(errors.ErrClientTypeNotFound(k.codespace), "cannot update client") + return sdkerrors.Wrapf(errors.ErrClientTypeNotFound, "cannot update client with ID %s", clientID) } // check that the header consensus matches the client one if header.ClientType() != clientType { - return sdkerrors.Wrap(errors.ErrInvalidConsensus(k.codespace), "cannot update client") + return sdkerrors.Wrapf(errors.ErrInvalidConsensus, "cannot update client with ID %s", clientID) } clientState, found := k.GetClientState(ctx, clientID) if !found { - return sdkerrors.Wrap(errors.ErrClientNotFound(k.codespace, clientID), "cannot update client") + return sdkerrors.Wrapf(errors.ErrClientNotFound, "cannot update client with ID %s", clientID) } if clientState.Frozen { - return sdkerrors.Wrap(errors.ErrClientFrozen(k.codespace, clientID), "cannot update client") + return sdkerrors.Wrapf(errors.ErrClientFrozen, "cannot update client with ID %s", clientID) } consensusState, found := k.GetConsensusState(ctx, clientID) if !found { - return sdkerrors.Wrap(errors.ErrConsensusStateNotFound(k.codespace), "cannot update client") + return sdkerrors.Wrapf(errors.ErrConsensusStateNotFound, "cannot update client with ID %s", clientID) } consensusState, err := consensusState.CheckValidityAndUpdateState(header) if err != nil { - return sdkerrors.Wrap(err, "cannot update client") + return sdkerrors.Wrapf(err, "cannot update client with ID %s", clientID) } k.SetConsensusState(ctx, clientID, consensusState) @@ -83,25 +83,25 @@ func (k Keeper) UpdateClient(ctx sdk.Context, clientID string, header exported.H func (k Keeper) CheckMisbehaviourAndUpdateState(ctx sdk.Context, evidence evidenceexported.Evidence) error { misbehaviour, ok := evidence.(tendermint.Misbehaviour) if !ok { - return errors.ErrInvalidClientType(k.codespace, "consensus type is not Tendermint") + return sdkerrors.Wrap(errors.ErrInvalidClientType, "consensus type is not Tendermint") } clientState, found := k.GetClientState(ctx, misbehaviour.ClientID) if !found { - return errors.ErrClientNotFound(k.codespace, misbehaviour.ClientID) + return sdkerrors.Wrap(errors.ErrClientNotFound, misbehaviour.ClientID) } committer, found := k.GetCommitter(ctx, misbehaviour.ClientID, uint64(misbehaviour.GetHeight())) if !found { - return errors.ErrCommitterNotFound(k.codespace, fmt.Sprintf("committer not found for height %d", misbehaviour.GetHeight())) + return errors.ErrCommitterNotFound } tmCommitter, ok := committer.(tendermint.Committer) if !ok { - return errors.ErrInvalidCommitter(k.codespace, "committer type is not Tendermint") + return sdkerrors.Wrap(errors.ErrInvalidCommitter, "committer type is not Tendermint") } if err := tendermint.CheckMisbehaviour(tmCommitter, misbehaviour); err != nil { - return errors.ErrInvalidEvidence(k.codespace, err.Error()) + return sdkerrors.Wrap(errors.ErrInvalidEvidence, err.Error()) } clientState, err := k.freeze(ctx, clientState) diff --git a/x/ibc/02-client/keeper/keeper.go b/x/ibc/02-client/keeper/keeper.go index a8b1876d1e41..5732913247b3 100644 --- a/x/ibc/02-client/keeper/keeper.go +++ b/x/ibc/02-client/keeper/keeper.go @@ -18,17 +18,15 @@ import ( // Keeper represents a type that grants read and write permissions to any client // state information type Keeper struct { - storeKey sdk.StoreKey - cdc *codec.Codec - codespace sdk.CodespaceType + storeKey sdk.StoreKey + cdc *codec.Codec } // NewKeeper creates a new NewKeeper instance -func NewKeeper(cdc *codec.Codec, key sdk.StoreKey, codespace sdk.CodespaceType) Keeper { +func NewKeeper(cdc *codec.Codec, key sdk.StoreKey) Keeper { return Keeper{ - storeKey: key, - cdc: cdc, - codespace: sdk.CodespaceType(fmt.Sprintf("%s/%s", codespace, errors.DefaultCodespace)), // "ibc/client", + storeKey: key, + cdc: cdc, } } @@ -181,7 +179,7 @@ func (k Keeper) initialize(ctx sdk.Context, clientID string, consensusState expo // freeze updates the state of the client in the event of a misbehaviour func (k Keeper) freeze(ctx sdk.Context, clientState types.State) (types.State, error) { if clientState.Frozen { - return types.State{}, sdkerrors.Wrap(errors.ErrClientFrozen(k.codespace, clientState.ID), "already frozen") + return types.State{}, sdkerrors.Wrap(errors.ErrClientFrozen, clientState.ID) } clientState.Frozen = true diff --git a/x/ibc/02-client/keeper/querier.go b/x/ibc/02-client/keeper/querier.go index 104ad554c700..87da8c1eea5f 100644 --- a/x/ibc/02-client/keeper/querier.go +++ b/x/ibc/02-client/keeper/querier.go @@ -1,8 +1,6 @@ package keeper import ( - "fmt" - abci "github.com/tendermint/tendermint/abci/types" "github.com/cosmos/cosmos-sdk/client" @@ -48,7 +46,7 @@ func QuerierClientState(ctx sdk.Context, req abci.RequestQuery, k Keeper) ([]byt clientState, found := k.GetClientState(ctx, params.ClientID) if !found { - return nil, errors.ErrClientTypeNotFound(k.codespace) + return nil, sdkerrors.Wrap(errors.ErrClientTypeNotFound, params.ClientID) } bz, err := codec.MarshalJSONIndent(k.cdc, clientState) @@ -69,7 +67,7 @@ func QuerierConsensusState(ctx sdk.Context, req abci.RequestQuery, k Keeper) ([] consensusState, found := k.GetConsensusState(ctx, params.ClientID) if !found { - return nil, errors.ErrConsensusStateNotFound(k.codespace) + return nil, errors.ErrConsensusStateNotFound } bz, err := codec.MarshalJSONIndent(k.cdc, consensusState) @@ -90,7 +88,7 @@ func QuerierVerifiedRoot(ctx sdk.Context, req abci.RequestQuery, k Keeper) ([]by root, found := k.GetVerifiedRoot(ctx, params.ClientID, params.Height) if !found { - return nil, errors.ErrRootNotFound(k.codespace) + return nil, errors.ErrRootNotFound } bz, err := codec.MarshalJSONIndent(k.cdc, root) @@ -111,10 +109,7 @@ func QuerierCommitter(ctx sdk.Context, req abci.RequestQuery, k Keeper) ([]byte, committer, found := k.GetCommitter(ctx, params.ClientID, params.Height) if !found { - return nil, errors.ErrCommitterNotFound( - k.codespace, - fmt.Sprintf("committer not found on height: %d", params.Height), - ) + return nil, errors.ErrCommitterNotFound } bz, err := codec.MarshalJSONIndent(k.cdc, committer) diff --git a/x/ibc/02-client/types/errors/errors.go b/x/ibc/02-client/types/errors/errors.go index 1a7272ca1fcb..b6786a6113f6 100644 --- a/x/ibc/02-client/types/errors/errors.go +++ b/x/ibc/02-client/types/errors/errors.go @@ -1,134 +1,24 @@ package errors import ( - "fmt" - - sdk "github.com/cosmos/cosmos-sdk/types" sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" ) -// client error codes -const ( - DefaultCodespace sdk.CodespaceType = "client" - - CodeClientExists sdk.CodeType = 200 - CodeClientNotFound sdk.CodeType = 201 - CodeClientFrozen sdk.CodeType = 202 - CodeConsensusStateNotFound sdk.CodeType = 203 - CodeInvalidConsensusState sdk.CodeType = 204 - CodeClientTypeNotFound sdk.CodeType = 205 - CodeInvalidClientType sdk.CodeType = 206 - CodeRootNotFound sdk.CodeType = 207 - CodeInvalidHeader sdk.CodeType = 208 - CodeInvalidEvidence sdk.CodeType = 209 - CodeCommitterNotFound sdk.CodeType = 210 - CodeInvalidCommitter sdk.CodeType = 211 +// SubModuleName is the error codespace +const SubModuleName string = "ibc/client" + +// IBC client sentinel errors +var ( + ErrClientExists = sdkerrors.Register(SubModuleName, 1, "light client already exists") + ErrClientNotFound = sdkerrors.Register(SubModuleName, 2, "light client not found") + ErrClientFrozen = sdkerrors.Register(SubModuleName, 3, "light client is frozen due to misbehaviour") + ErrConsensusStateNotFound = sdkerrors.Register(SubModuleName, 4, "consensus state not found") + ErrInvalidConsensus = sdkerrors.Register(SubModuleName, 5, "invalid consensus state") + ErrClientTypeNotFound = sdkerrors.Register(SubModuleName, 6, "client type not found") + ErrInvalidClientType = sdkerrors.Register(SubModuleName, 7, "invalid client type") + ErrRootNotFound = sdkerrors.Register(SubModuleName, 8, "commitment root not found") + ErrInvalidHeader = sdkerrors.Register(SubModuleName, 9, "invalid block header") + ErrInvalidEvidence = sdkerrors.Register(SubModuleName, 10, "invalid light client misbehaviour evidence") + ErrCommitterNotFound = sdkerrors.Register(SubModuleName, 11, "commiter not found") + ErrInvalidCommitter = sdkerrors.Register(SubModuleName, 12, "invalid commiter") ) - -// ErrClientExists implements sdk.Error -func ErrClientExists(codespace sdk.CodespaceType, clientID string) error { - return sdkerrors.New( - string(codespace), - uint32(CodeClientExists), - fmt.Sprintf("client with ID %s already exists", clientID), - ) -} - -// ErrClientNotFound implements sdk.Error -func ErrClientNotFound(codespace sdk.CodespaceType, clientID string) error { - return sdkerrors.New( - string(codespace), - uint32(CodeClientNotFound), - fmt.Sprintf("client with ID %s not found", clientID), - ) -} - -// ErrClientFrozen implements sdk.Error -func ErrClientFrozen(codespace sdk.CodespaceType, clientID string) error { - return sdkerrors.New( - string(codespace), - uint32(CodeClientFrozen), - fmt.Sprintf("client with ID %s is frozen due to misbehaviour", clientID), - ) -} - -// ErrConsensusStateNotFound implements sdk.Error -func ErrConsensusStateNotFound(codespace sdk.CodespaceType) error { - return sdkerrors.New( - string(codespace), - uint32(CodeConsensusStateNotFound), - "consensus state not found", - ) -} - -// ErrInvalidConsensus implements sdk.Error -func ErrInvalidConsensus(codespace sdk.CodespaceType) error { - return sdkerrors.New( - string(codespace), - uint32(CodeInvalidConsensusState), - "invalid consensus state", - ) -} - -// ErrClientTypeNotFound implements sdk.Error -func ErrClientTypeNotFound(codespace sdk.CodespaceType) error { - return sdkerrors.New( - string(codespace), - uint32(CodeClientTypeNotFound), - "client type not found", - ) -} - -// ErrInvalidClientType implements sdk.Error -func ErrInvalidClientType(codespace sdk.CodespaceType, msg string) error { - return sdkerrors.New( - string(codespace), - uint32(CodeInvalidClientType), - msg, - ) -} - -// ErrRootNotFound implements sdk.Error -func ErrRootNotFound(codespace sdk.CodespaceType) error { - return sdkerrors.New( - string(codespace), - uint32(CodeRootNotFound), - "commitment root not found", - ) -} - -// ErrInvalidHeader implements sdk.Error -func ErrInvalidHeader(codespace sdk.CodespaceType) error { - return sdkerrors.New( - string(codespace), - uint32(CodeInvalidHeader), - "invalid header", - ) -} - -// ErrInvalidEvidence implements sdk.Error -func ErrInvalidEvidence(codespace sdk.CodespaceType, msg string) error { - return sdkerrors.New( - string(codespace), - uint32(CodeInvalidEvidence), - fmt.Sprintf("invalid evidence: %s", msg), - ) -} - -// ErrCommitterNotFound implements sdk.Error -func ErrCommitterNotFound(codespace sdk.CodespaceType, msg string) error { - return sdkerrors.New( - string(codespace), - uint32(CodeCommitterNotFound), - fmt.Sprintf("invalid evidence: %s", msg), - ) -} - -// ErrInvalidEvidence implements sdk.Error -func ErrInvalidCommitter(codespace sdk.CodespaceType, msg string) error { - return sdkerrors.New( - string(codespace), - uint32(CodeInvalidCommitter), - fmt.Sprintf("invalid evidence: %s", msg), - ) -} diff --git a/x/ibc/02-client/types/msgs.go b/x/ibc/02-client/types/msgs.go index d52c0a614a44..128c76e4144b 100644 --- a/x/ibc/02-client/types/msgs.go +++ b/x/ibc/02-client/types/msgs.go @@ -1,9 +1,8 @@ package types import ( - "fmt" - sdk "github.com/cosmos/cosmos-sdk/types" + sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" evidenceexported "github.com/cosmos/cosmos-sdk/x/evidence/exported" "github.com/cosmos/cosmos-sdk/x/ibc/02-client/exported" "github.com/cosmos/cosmos-sdk/x/ibc/02-client/types/errors" @@ -49,22 +48,17 @@ func (msg MsgCreateClient) Type() string { } // ValidateBasic implements sdk.Msg -func (msg MsgCreateClient) ValidateBasic() sdk.Error { - if err := host.DefaultClientIdentifierValidator(msg.ClientID); err != nil { - return sdk.ConvertError(err) - } +func (msg MsgCreateClient) ValidateBasic() error { if clientType := exported.ClientTypeFromString(msg.ClientType); clientType == 0 { - return sdk.ConvertError( - errors.ErrInvalidClientType(errors.DefaultCodespace, fmt.Sprintf("invalid client type '%s'", msg.ClientType)), - ) + return sdkerrors.Wrap(errors.ErrInvalidClientType, msg.ClientType) } if msg.ConsensusState == nil { - return sdk.ConvertError(errors.ErrInvalidConsensus(errors.DefaultCodespace)) + return errors.ErrInvalidConsensus } if msg.Signer.Empty() { - return sdk.ErrInvalidAddress("empty address") + return sdkerrors.ErrInvalidAddress } - return nil + return host.DefaultClientIdentifierValidator(msg.ClientID) } // GetSignBytes implements sdk.Msg @@ -106,17 +100,14 @@ func (msg MsgUpdateClient) Type() string { } // ValidateBasic implements sdk.Msg -func (msg MsgUpdateClient) ValidateBasic() sdk.Error { - if err := host.DefaultClientIdentifierValidator(msg.ClientID); err != nil { - return sdk.ConvertError(err) - } +func (msg MsgUpdateClient) ValidateBasic() error { if msg.Header == nil { - return sdk.ConvertError(errors.ErrInvalidHeader(errors.DefaultCodespace)) + return errors.ErrInvalidHeader } if msg.Signer.Empty() { - return sdk.ErrInvalidAddress("empty address") + return sdkerrors.ErrInvalidAddress } - return nil + return host.DefaultClientIdentifierValidator(msg.ClientID) } // GetSignBytes implements sdk.Msg @@ -156,20 +147,17 @@ func (msg MsgSubmitMisbehaviour) Type() string { } // ValidateBasic implements sdk.Msg -func (msg MsgSubmitMisbehaviour) ValidateBasic() sdk.Error { - if err := host.DefaultClientIdentifierValidator(msg.ClientID); err != nil { - return sdk.ConvertError(err) - } +func (msg MsgSubmitMisbehaviour) ValidateBasic() error { if msg.Evidence == nil { - return sdk.ConvertError(errors.ErrInvalidEvidence(errors.DefaultCodespace, "evidence is nil")) + return sdkerrors.Wrap(errors.ErrInvalidEvidence, "evidence cannot be nil") } if err := msg.Evidence.ValidateBasic(); err != nil { - return sdk.ConvertError(errors.ErrInvalidEvidence(errors.DefaultCodespace, err.Error())) + return sdkerrors.Wrap(errors.ErrInvalidEvidence, err.Error()) } if msg.Signer.Empty() { - return sdk.ErrInvalidAddress("empty address") + return sdkerrors.ErrInvalidAddress } - return nil + return host.DefaultClientIdentifierValidator(msg.ClientID) } // GetSignBytes implements sdk.Msg diff --git a/x/ibc/02-client/types/msgs_test.go b/x/ibc/02-client/types/msgs_test.go index b29633420ed4..844276b3ae6b 100644 --- a/x/ibc/02-client/types/msgs_test.go +++ b/x/ibc/02-client/types/msgs_test.go @@ -38,7 +38,7 @@ type mockBadEvidence struct { // Override ValidateBasic func (mbe mockBadEvidence) ValidateBasic() error { - return errors.ErrInvalidEvidence(errors.DefaultCodespace, "invalid evidence") + return errors.ErrInvalidEvidence } func TestMsgCreateClientValidateBasic(t *testing.T) { diff --git a/x/ibc/02-client/types/tendermint/consensus_state.go b/x/ibc/02-client/types/tendermint/consensus_state.go index 25c2f8d990f8..cb7e2e42e849 100644 --- a/x/ibc/02-client/types/tendermint/consensus_state.go +++ b/x/ibc/02-client/types/tendermint/consensus_state.go @@ -53,7 +53,9 @@ func (cs ConsensusState) GetCommitter() exported.Committer { func (cs ConsensusState) CheckValidityAndUpdateState(header exported.Header) (exported.ConsensusState, error) { tmHeader, ok := header.(Header) if !ok { - return nil, clienterrors.ErrInvalidHeader(clienterrors.DefaultCodespace) + return nil, sdkerrors.Wrap( + clienterrors.ErrInvalidHeader, "header is not from Tendermint", + ) } if err := cs.checkValidity(tmHeader); err != nil { @@ -69,7 +71,7 @@ func (cs ConsensusState) CheckValidityAndUpdateState(header exported.Header) (ex func (cs ConsensusState) checkValidity(header Header) error { if header.GetHeight() < cs.Height { return sdkerrors.Wrap( - clienterrors.ErrInvalidHeader(clienterrors.DefaultCodespace), + clienterrors.ErrInvalidHeader, fmt.Sprintf("header height < consensus height (%d < %d)", header.GetHeight(), cs.Height), ) } diff --git a/x/ibc/02-client/types/tendermint/evidence.go b/x/ibc/02-client/types/tendermint/evidence.go index a8d1154a27ae..bc60b413b4e6 100644 --- a/x/ibc/02-client/types/tendermint/evidence.go +++ b/x/ibc/02-client/types/tendermint/evidence.go @@ -1,14 +1,13 @@ package tendermint import ( - "fmt" - yaml "gopkg.in/yaml.v2" "github.com/tendermint/tendermint/crypto/tmhash" cmn "github.com/tendermint/tendermint/libs/common" tmtypes "github.com/tendermint/tendermint/types" + sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" evidenceexported "github.com/cosmos/cosmos-sdk/x/evidence/exported" "github.com/cosmos/cosmos-sdk/x/ibc/02-client/types/errors" ) @@ -56,27 +55,31 @@ func (ev Evidence) GetHeight() int64 { func (ev Evidence) ValidateBasic() error { // ValidateBasic on both validators if err := ev.Header1.ValidateBasic(ev.ChainID); err != nil { - return errors.ErrInvalidEvidence(errors.DefaultCodespace, fmt.Sprintf("Header1 failed ValidateBasic: %v", err)) + return sdkerrors.Wrap( + errors.ErrInvalidEvidence, + sdkerrors.Wrap(err, "header 1 failed validation").Error(), + ) } if err := ev.Header2.ValidateBasic(ev.ChainID); err != nil { - return errors.ErrInvalidEvidence(errors.DefaultCodespace, fmt.Sprintf("Header2 failed ValidateBasic: %v", err)) + return sdkerrors.Wrap( + errors.ErrInvalidEvidence, + sdkerrors.Wrap(err, "header 2 failed validation").Error(), + ) } // Ensure that Heights are the same if ev.Header1.Height != ev.Header2.Height { - return errors.ErrInvalidEvidence(errors.DefaultCodespace, "headers in evidence are on different heights") + return sdkerrors.Wrapf(errors.ErrInvalidEvidence, "headers in evidence are on different heights (%d ≠ %d)", ev.Header1.Height, ev.Header2.Height) } // Ensure that Commit Hashes are different if ev.Header1.Commit.BlockID.Equals(ev.Header2.Commit.BlockID) { - return errors.ErrInvalidEvidence(errors.DefaultCodespace, "Headers commit to same blockID") + return sdkerrors.Wrap(errors.ErrInvalidEvidence, "headers commit to same blockID") } - - if err1 := ValidCommit(ev.ChainID, ev.Header1.Commit, ev.Header1.ValidatorSet); err1 != nil { - return err1 + if err := ValidCommit(ev.ChainID, ev.Header1.Commit, ev.Header1.ValidatorSet); err != nil { + return err } - if err2 := ValidCommit(ev.ChainID, ev.Header2.Commit, ev.Header2.ValidatorSet); err2 != nil { - return err2 + if err := ValidCommit(ev.ChainID, ev.Header2.Commit, ev.Header2.ValidatorSet); err != nil { + return err } - return nil } @@ -88,7 +91,7 @@ func (ev Evidence) ValidateBasic() error { func ValidCommit(chainID string, commit *tmtypes.Commit, valSet *tmtypes.ValidatorSet) (err error) { defer func() { if r := recover(); r != nil { - err = errors.ErrInvalidEvidence(errors.DefaultCodespace, fmt.Sprintf("invalid commit: %v", r)) + err = sdkerrors.Wrapf(errors.ErrInvalidEvidence, "invalid commit: %v", r) } }() @@ -99,7 +102,7 @@ func ValidCommit(chainID string, commit *tmtypes.Commit, valSet *tmtypes.Validat // Check that ValidatorSet did indeed commit to blockID in Commit if !ok || !blockID.Equals(commit.BlockID) { - return errors.ErrInvalidEvidence(errors.DefaultCodespace, "ValidatorSet did not commit to Header1") + return sdkerrors.Wrap(errors.ErrInvalidEvidence, "validator set did not commit to header 1") } return nil diff --git a/x/ibc/02-client/types/tendermint/header.go b/x/ibc/02-client/types/tendermint/header.go index 133c1741e56e..9509d6370019 100644 --- a/x/ibc/02-client/types/tendermint/header.go +++ b/x/ibc/02-client/types/tendermint/header.go @@ -42,13 +42,13 @@ func (h Header) GetHeight() uint64 { // and checks that validatorsets are not nil func (h Header) ValidateBasic(chainID string) error { if err := h.SignedHeader.ValidateBasic(chainID); err != nil { - return err + return sdkerrors.Wrap(clienterrors.ErrInvalidHeader, err.Error()) } if h.ValidatorSet == nil { - return sdkerrors.Wrap(clienterrors.ErrInvalidHeader(clienterrors.DefaultCodespace), "ValidatorSet is nil") + return sdkerrors.Wrap(clienterrors.ErrInvalidHeader, "validator set is nil") } if h.NextValidatorSet == nil { - return sdkerrors.Wrap(clienterrors.ErrInvalidHeader(clienterrors.DefaultCodespace), "NextValidatorSet is nil") + return sdkerrors.Wrap(clienterrors.ErrInvalidHeader, "next validator set is nil") } return nil } diff --git a/x/ibc/02-client/types/tendermint/misbehaviour.go b/x/ibc/02-client/types/tendermint/misbehaviour.go index 5b04b6e3ec0c..36c8e14ce8ab 100644 --- a/x/ibc/02-client/types/tendermint/misbehaviour.go +++ b/x/ibc/02-client/types/tendermint/misbehaviour.go @@ -1,8 +1,7 @@ package tendermint import ( - "fmt" - + sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" evidenceexported "github.com/cosmos/cosmos-sdk/x/evidence/exported" "github.com/cosmos/cosmos-sdk/x/ibc/02-client/exported" "github.com/cosmos/cosmos-sdk/x/ibc/02-client/types/errors" @@ -33,14 +32,15 @@ func (m Misbehaviour) GetEvidence() evidenceexported.Evidence { // client ID. func (m Misbehaviour) ValidateBasic() error { if m.Evidence == nil { - return errors.ErrInvalidEvidence(errors.DefaultCodespace, "empty evidence") + return sdkerrors.Wrap(errors.ErrInvalidEvidence, "evidence is empty") } - if err := m.Evidence.ValidateBasic(); err != nil { - return err + return sdkerrors.Wrap(errors.ErrInvalidEvidence, err.Error()) } - - return host.DefaultClientIdentifierValidator(m.ClientID) + if err := host.DefaultClientIdentifierValidator(m.ClientID); err != nil { + return sdkerrors.Wrap(errors.ErrInvalidEvidence, err.Error()) + } + return nil } // CheckMisbehaviour checks if the evidence provided is a valid light client misbehaviour @@ -54,13 +54,17 @@ func CheckMisbehaviour(trustedCommitter Committer, m Misbehaviour) error { // Evidence is within trusting period. ValidatorSet must have 2/3 similarity with trustedCommitter ValidatorSet // check that the validator sets on both headers are valid given the last trusted validatorset // less than or equal to evidence height - if err := trustedValSet.VerifyFutureCommit(m.Evidence.Header1.ValidatorSet, m.Evidence.ChainID, - m.Evidence.Header1.Commit.BlockID, m.Evidence.Header1.Height, m.Evidence.Header1.Commit); err != nil { - return errors.ErrInvalidEvidence(errors.DefaultCodespace, fmt.Sprintf("validator set in Header1 has too much change from last known committer: %v", err)) + if err := trustedValSet.VerifyFutureCommit( + m.Evidence.Header1.ValidatorSet, m.Evidence.ChainID, + m.Evidence.Header1.Commit.BlockID, m.Evidence.Header1.Height, m.Evidence.Header1.Commit, + ); err != nil { + return sdkerrors.Wrapf(errors.ErrInvalidEvidence, "validator set in header 1 has too much change from last known committer: %v", err) } - if err := trustedValSet.VerifyFutureCommit(m.Evidence.Header2.ValidatorSet, m.Evidence.ChainID, - m.Evidence.Header2.Commit.BlockID, m.Evidence.Header2.Height, m.Evidence.Header2.Commit); err != nil { - return errors.ErrInvalidEvidence(errors.DefaultCodespace, fmt.Sprintf("validator set in Header2 has too much change from last known committer: %v", err)) + if err := trustedValSet.VerifyFutureCommit( + m.Evidence.Header2.ValidatorSet, m.Evidence.ChainID, + m.Evidence.Header2.Commit.BlockID, m.Evidence.Header2.Height, m.Evidence.Header2.Commit, + ); err != nil { + return sdkerrors.Wrapf(errors.ErrInvalidEvidence, "validator set in header 2 has too much change from last known committer: %v", err) } return nil diff --git a/x/ibc/03-connection/alias.go b/x/ibc/03-connection/alias.go index 4d44e18048e8..2cb4faf887ff 100644 --- a/x/ibc/03-connection/alias.go +++ b/x/ibc/03-connection/alias.go @@ -12,33 +12,23 @@ import ( ) const ( - UNINITIALIZED = types.UNINITIALIZED - INIT = types.INIT - TRYOPEN = types.TRYOPEN - OPEN = types.OPEN - StateUninitialized = types.StateUninitialized - StateInit = types.StateInit - StateTryOpen = types.StateTryOpen - StateOpen = types.StateOpen - DefaultCodespace = types.DefaultCodespace - CodeConnectionExists = types.CodeConnectionExists - CodeConnectionNotFound = types.CodeConnectionNotFound - CodeClientConnectionPathsNotFound = types.CodeClientConnectionPathsNotFound - CodeConnectionPath = types.CodeConnectionPath - CodeInvalidCounterpartyConnection = types.CodeInvalidCounterpartyConnection - CodeInvalidVersion = types.CodeInvalidVersion - CodeInvalidHeight = types.CodeInvalidHeight - CodeInvalidConnectionState = types.CodeInvalidConnectionState - CodeInvalidCounterparty = types.CodeInvalidCounterparty - AttributeKeyConnectionID = types.AttributeKeyConnectionID - AttributeKeyCounterpartyClientID = types.AttributeKeyCounterpartyClientID - SubModuleName = types.SubModuleName - StoreKey = types.StoreKey - RouterKey = types.RouterKey - QuerierRoute = types.QuerierRoute - QueryAllConnections = types.QueryAllConnections - QueryConnection = types.QueryConnection - QueryClientConnections = types.QueryClientConnections + UNINITIALIZED = types.UNINITIALIZED + INIT = types.INIT + TRYOPEN = types.TRYOPEN + OPEN = types.OPEN + StateUninitialized = types.StateUninitialized + StateInit = types.StateInit + StateTryOpen = types.StateTryOpen + StateOpen = types.StateOpen + AttributeKeyConnectionID = types.AttributeKeyConnectionID + AttributeKeyCounterpartyClientID = types.AttributeKeyCounterpartyClientID + SubModuleName = types.SubModuleName + StoreKey = types.StoreKey + RouterKey = types.RouterKey + QuerierRoute = types.QuerierRoute + QueryAllConnections = types.QueryAllConnections + QueryConnection = types.QueryConnection + QueryClientConnections = types.QueryClientConnections ) var ( @@ -55,8 +45,6 @@ var ( ErrConnectionNotFound = types.ErrConnectionNotFound ErrClientConnectionPathsNotFound = types.ErrClientConnectionPathsNotFound ErrConnectionPath = types.ErrConnectionPath - ErrInvalidCounterpartyConnection = types.ErrInvalidCounterpartyConnection - ErrInvalidHeight = types.ErrInvalidHeight ErrInvalidConnectionState = types.ErrInvalidConnectionState ErrInvalidCounterparty = types.ErrInvalidCounterparty ConnectionPath = types.ConnectionPath diff --git a/x/ibc/03-connection/client/cli/cli.go b/x/ibc/03-connection/client/cli/cli.go index e0ea7c89880f..92c3fa8cc901 100644 --- a/x/ibc/03-connection/client/cli/cli.go +++ b/x/ibc/03-connection/client/cli/cli.go @@ -3,7 +3,7 @@ package cli import ( "github.com/spf13/cobra" - "github.com/cosmos/cosmos-sdk/client" + "github.com/cosmos/cosmos-sdk/client/flags" "github.com/cosmos/cosmos-sdk/codec" ) @@ -16,7 +16,7 @@ func GetQueryCmd(queryRoute string, cdc *codec.Codec) *cobra.Command { SuggestionsMinimumDistance: 2, } - ics03ConnectionQueryCmd.AddCommand(client.GetCommands( + ics03ConnectionQueryCmd.AddCommand(flags.GetCommands( GetCmdQueryConnections(queryRoute, cdc), GetCmdQueryConnection(queryRoute, cdc), )...) @@ -30,7 +30,7 @@ func GetTxCmd(storeKey string, cdc *codec.Codec) *cobra.Command { Short: "IBC connection transaction subcommands", } - ics03ConnectionTxCmd.AddCommand(client.PostCommands( + ics03ConnectionTxCmd.AddCommand(flags.PostCommands( GetCmdConnectionOpenInit(storeKey, cdc), GetCmdConnectionOpenTry(storeKey, cdc), GetCmdConnectionOpenAck(storeKey, cdc), diff --git a/x/ibc/03-connection/handler.go b/x/ibc/03-connection/handler.go index 854436eadd6a..b7c9eae08d3f 100644 --- a/x/ibc/03-connection/handler.go +++ b/x/ibc/03-connection/handler.go @@ -7,10 +7,10 @@ import ( ) // HandleMsgConnectionOpenInit defines the sdk.Handler for MsgConnectionOpenInit -func HandleMsgConnectionOpenInit(ctx sdk.Context, k keeper.Keeper, msg types.MsgConnectionOpenInit) sdk.Result { +func HandleMsgConnectionOpenInit(ctx sdk.Context, k keeper.Keeper, msg types.MsgConnectionOpenInit) (*sdk.Result, error) { err := k.ConnOpenInit(ctx, msg.ConnectionID, msg.ClientID, msg.Counterparty) if err != nil { - return sdk.ResultFromError(err) + return nil, err } ctx.EventManager().EmitEvents(sdk.Events{ @@ -26,16 +26,18 @@ func HandleMsgConnectionOpenInit(ctx sdk.Context, k keeper.Keeper, msg types.Msg ), }) - return sdk.Result{Events: ctx.EventManager().Events()} + return &sdk.Result{ + Events: ctx.EventManager().Events(), + }, nil } // HandleMsgConnectionOpenTry defines the sdk.Handler for MsgConnectionOpenTry -func HandleMsgConnectionOpenTry(ctx sdk.Context, k keeper.Keeper, msg types.MsgConnectionOpenTry) sdk.Result { +func HandleMsgConnectionOpenTry(ctx sdk.Context, k keeper.Keeper, msg types.MsgConnectionOpenTry) (*sdk.Result, error) { err := k.ConnOpenTry( ctx, msg.ConnectionID, msg.Counterparty, msg.ClientID, msg.CounterpartyVersions, msg.ProofInit, msg.ProofConsensus, msg.ProofHeight, msg.ConsensusHeight) if err != nil { - return sdk.ResultFromError(err) + return nil, err } ctx.EventManager().EmitEvents(sdk.Events{ @@ -51,17 +53,19 @@ func HandleMsgConnectionOpenTry(ctx sdk.Context, k keeper.Keeper, msg types.MsgC ), }) - return sdk.Result{Events: ctx.EventManager().Events()} + return &sdk.Result{ + Events: ctx.EventManager().Events(), + }, nil } // HandleMsgConnectionOpenAck defines the sdk.Handler for MsgConnectionOpenAck -func HandleMsgConnectionOpenAck(ctx sdk.Context, k keeper.Keeper, msg types.MsgConnectionOpenAck) sdk.Result { +func HandleMsgConnectionOpenAck(ctx sdk.Context, k keeper.Keeper, msg types.MsgConnectionOpenAck) (*sdk.Result, error) { err := k.ConnOpenAck( ctx, msg.ConnectionID, msg.Version, msg.ProofTry, msg.ProofConsensus, msg.ProofHeight, msg.ConsensusHeight, ) if err != nil { - return sdk.ResultFromError(err) + return nil, err } ctx.EventManager().EmitEvents(sdk.Events{ @@ -76,14 +80,16 @@ func HandleMsgConnectionOpenAck(ctx sdk.Context, k keeper.Keeper, msg types.MsgC ), }) - return sdk.Result{Events: ctx.EventManager().Events()} + return &sdk.Result{ + Events: ctx.EventManager().Events(), + }, nil } // HandleMsgConnectionOpenConfirm defines the sdk.Handler for MsgConnectionOpenConfirm -func HandleMsgConnectionOpenConfirm(ctx sdk.Context, k keeper.Keeper, msg types.MsgConnectionOpenConfirm) sdk.Result { +func HandleMsgConnectionOpenConfirm(ctx sdk.Context, k keeper.Keeper, msg types.MsgConnectionOpenConfirm) (*sdk.Result, error) { err := k.ConnOpenConfirm(ctx, msg.ConnectionID, msg.ProofAck, msg.ProofHeight) if err != nil { - return sdk.ResultFromError(err) + return nil, err } ctx.EventManager().EmitEvents(sdk.Events{ @@ -98,5 +104,7 @@ func HandleMsgConnectionOpenConfirm(ctx sdk.Context, k keeper.Keeper, msg types. ), }) - return sdk.Result{Events: ctx.EventManager().Events()} + return &sdk.Result{ + Events: ctx.EventManager().Events(), + }, nil } diff --git a/x/ibc/03-connection/keeper/handshake.go b/x/ibc/03-connection/keeper/handshake.go index e5a011a84b3a..8a40c427de52 100644 --- a/x/ibc/03-connection/keeper/handshake.go +++ b/x/ibc/03-connection/keeper/handshake.go @@ -22,7 +22,7 @@ func (k Keeper) ConnOpenInit( ) error { _, found := k.GetConnection(ctx, connectionID) if found { - return sdkerrors.Wrap(types.ErrConnectionExists(k.codespace, connectionID), "cannot initialize connection") + return sdkerrors.Wrap(types.ErrConnectionExists, "cannot initialize connection") } // connection defines chain A's ConnectionEnd @@ -58,7 +58,7 @@ func (k Keeper) ConnOpenTry( // XXX: blocked by #5078 /* if consensusHeight > uint64(ctx.BlockHeight()) { - return errors.New("invalid consensus height") // TODO: sdk.Error + return sdkerrors.Wrap(ibctypes.ErrInvalidHeight, "invalid consensus height") } expectedConsensusState, found := k.clientKeeper.GetConsensusState(ctx, clientID) @@ -112,7 +112,7 @@ func (k Keeper) ConnOpenTry( _, found := k.GetConnection(ctx, connectionID) if found { - return sdkerrors.Wrap(types.ErrConnectionExists(k.codespace, connectionID), "cannot relay connection attempt") + return sdkerrors.Wrap(types.ErrConnectionExists, "cannot relay connection attempt") } connection.State = types.TRYOPEN @@ -142,25 +142,25 @@ func (k Keeper) ConnOpenAck( // XXX: blocked by #5078 /* if consensusHeight > uint64(ctx.BlockHeight()) { - return errors.New("invalid consensus height") // TODO: sdk.Error + return sdkerrors.Wrap(ibctypes.ErrInvalidHeight, "invalid consensus height") } */ connection, found := k.GetConnection(ctx, connectionID) if !found { - return sdkerrors.Wrap(types.ErrConnectionNotFound(k.codespace, connectionID), "cannot relay ACK of open attempt") + return sdkerrors.Wrap(types.ErrConnectionNotFound, "cannot relay ACK of open attempt") } if connection.State != types.INIT { - return types.ErrInvalidConnectionState( - k.codespace, - fmt.Sprintf("connection state is not INIT (got %s)", connection.State.String()), + return sdkerrors.Wrapf( + types.ErrInvalidConnectionState, + "connection state is not INIT (got %s)", connection.State.String(), ) } if types.LatestVersion(connection.Versions) != version { - return ibctypes.ErrInvalidVersion( - k.codespace, - fmt.Sprintf("connection version does't match provided one (%s ≠ %s)", types.LatestVersion(connection.Versions), version), + return sdkerrors.Wrapf( + ibctypes.ErrInvalidVersion, + "connection version does't match provided one (%s ≠ %s)", types.LatestVersion(connection.Versions), version, ) } @@ -223,13 +223,13 @@ func (k Keeper) ConnOpenConfirm( ) error { connection, found := k.GetConnection(ctx, connectionID) if !found { - return sdkerrors.Wrap(types.ErrConnectionNotFound(k.codespace, connectionID), "cannot relay ACK of open attempt") + return sdkerrors.Wrap(types.ErrConnectionNotFound, "cannot relay ACK of open attempt") } if connection.State != types.TRYOPEN { - return types.ErrInvalidConnectionState( - k.codespace, - fmt.Sprintf("connection state is not TRYOPEN (got %s)", connection.State.String()), + return sdkerrors.Wrapf( + types.ErrInvalidConnectionState, + "connection state is not TRYOPEN (got %s)", connection.State.String(), ) } @@ -247,7 +247,7 @@ func (k Keeper) ConnOpenConfirm( types.ConnectionPath(connection.Counterparty.ConnectionID), expConnBz, ) if !ok { - return types.ErrInvalidCounterpartyConnection(k.codespace) + return errors.New("couldn't verify connection membership on counterparty's client") } connection.State = types.OPEN diff --git a/x/ibc/03-connection/keeper/keeper.go b/x/ibc/03-connection/keeper/keeper.go index c20720c17788..5edec4cdf32b 100644 --- a/x/ibc/03-connection/keeper/keeper.go +++ b/x/ibc/03-connection/keeper/keeper.go @@ -7,6 +7,7 @@ import ( "github.com/cosmos/cosmos-sdk/codec" sdk "github.com/cosmos/cosmos-sdk/types" + sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" "github.com/cosmos/cosmos-sdk/x/ibc/03-connection/types" commitment "github.com/cosmos/cosmos-sdk/x/ibc/23-commitment" host "github.com/cosmos/cosmos-sdk/x/ibc/24-host" @@ -17,16 +18,14 @@ import ( type Keeper struct { storeKey sdk.StoreKey cdc *codec.Codec - codespace sdk.CodespaceType clientKeeper types.ClientKeeper } // NewKeeper creates a new IBC connection Keeper instance -func NewKeeper(cdc *codec.Codec, key sdk.StoreKey, codespace sdk.CodespaceType, ck types.ClientKeeper) Keeper { +func NewKeeper(cdc *codec.Codec, key sdk.StoreKey, ck types.ClientKeeper) Keeper { return Keeper{ storeKey: key, cdc: cdc, - codespace: sdk.CodespaceType(fmt.Sprintf("%s/%s", codespace, types.DefaultCodespace)), // "ibc/connection", clientKeeper: ck, } } @@ -133,12 +132,12 @@ func (k Keeper) addConnectionToClient(ctx sdk.Context, clientID, connectionID st func (k Keeper) removeConnectionFromClient(ctx sdk.Context, clientID, connectionID string) error { conns, found := k.GetClientConnectionPaths(ctx, clientID) if !found { - return types.ErrClientConnectionPathsNotFound(k.codespace, clientID) + return sdkerrors.Wrap(types.ErrClientConnectionPathsNotFound, clientID) } conns, ok := host.RemovePath(conns, connectionID) if !ok { - return types.ErrConnectionPath(k.codespace) + return sdkerrors.Wrap(types.ErrConnectionPath, clientID) } k.SetClientConnectionPaths(ctx, clientID, conns) diff --git a/x/ibc/03-connection/keeper/querier.go b/x/ibc/03-connection/keeper/querier.go index f5c56834161f..c888e84e32b2 100644 --- a/x/ibc/03-connection/keeper/querier.go +++ b/x/ibc/03-connection/keeper/querier.go @@ -20,12 +20,12 @@ func QuerierConnection(ctx sdk.Context, req abci.RequestQuery, k Keeper) ([]byte connection, found := k.GetConnection(ctx, params.ConnectionID) if !found { - return nil, types.ErrConnectionNotFound(k.codespace, params.ConnectionID) + return nil, sdkerrors.Wrap(types.ErrConnectionNotFound, params.ConnectionID) } - bz, err := codec.MarshalJSONIndent(k.cdc, connection) + bz, err := types.SubModuleCdc.MarshalJSON(connection) if err != nil { - return nil, sdk.ErrInternal(sdk.AppendMsgToErr("could not marshal result to JSON", err.Error())) + return nil, sdkerrors.Wrap(sdkerrors.ErrJSONMarshal, err.Error()) } return bz, nil @@ -66,7 +66,7 @@ func QuerierClientConnections(ctx sdk.Context, req abci.RequestQuery, k Keeper) clientConnectionPaths, found := k.GetClientConnectionPaths(ctx, params.ClientID) if !found { - return nil, types.ErrClientConnectionPathsNotFound(k.codespace, params.ClientID) + return nil, sdkerrors.Wrap(types.ErrClientConnectionPathsNotFound, params.ClientID) } bz, err := types.SubModuleCdc.MarshalJSON(clientConnectionPaths) diff --git a/x/ibc/03-connection/types/connection.go b/x/ibc/03-connection/types/connection.go index 65806e9f5a9a..5a441c22eb26 100644 --- a/x/ibc/03-connection/types/connection.go +++ b/x/ibc/03-connection/types/connection.go @@ -54,13 +54,23 @@ func NewCounterparty(clientID, connectionID string, prefix commitment.PrefixI) C // ValidateBasic performs a basic validation check of the identifiers and prefix func (c Counterparty) ValidateBasic() error { if err := host.DefaultConnectionIdentifierValidator(c.ConnectionID); err != nil { - return sdkerrors.Wrap(err, "invalid counterparty connection ID") + return sdkerrors.Wrap(err, + sdkerrors.Wrapf( + ErrInvalidCounterparty, + "invalid counterparty connection ID %s", c.ConnectionID, + ).Error(), + ) } if err := host.DefaultClientIdentifierValidator(c.ClientID); err != nil { - return sdkerrors.Wrap(err, "invalid counterparty client ID") + return sdkerrors.Wrap(err, + sdkerrors.Wrapf( + ErrInvalidCounterparty, + "invalid counterparty client ID %s", c.ClientID, + ).Error(), + ) } if c.Prefix == nil || len(c.Prefix.Bytes()) == 0 { - return ErrInvalidCounterparty(DefaultCodespace, "invalid counterparty prefix") + return sdkerrors.Wrap(ErrInvalidCounterparty, "invalid counterparty prefix") } return nil } diff --git a/x/ibc/03-connection/types/errors.go b/x/ibc/03-connection/types/errors.go index d62e14a49218..41199efc4103 100644 --- a/x/ibc/03-connection/types/errors.go +++ b/x/ibc/03-connection/types/errors.go @@ -1,95 +1,15 @@ package types import ( - "fmt" - - sdk "github.com/cosmos/cosmos-sdk/types" sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" ) -// connection error codes -const ( - DefaultCodespace sdk.CodespaceType = SubModuleName - - CodeConnectionExists sdk.CodeType = 210 - CodeConnectionNotFound sdk.CodeType = 211 - CodeClientConnectionPathsNotFound sdk.CodeType = 212 - CodeConnectionPath sdk.CodeType = 213 - CodeInvalidCounterpartyConnection sdk.CodeType = 214 - CodeInvalidVersion sdk.CodeType = 215 - CodeInvalidHeight sdk.CodeType = 216 - CodeInvalidConnectionState sdk.CodeType = 217 - CodeInvalidCounterparty sdk.CodeType = 218 +// IBC connection sentinel errors +var ( + ErrConnectionExists = sdkerrors.Register(SubModuleName, 1, "connection already exists") + ErrConnectionNotFound = sdkerrors.Register(SubModuleName, 2, "connection not found") + ErrClientConnectionPathsNotFound = sdkerrors.Register(SubModuleName, 3, "light client connection paths not found") + ErrConnectionPath = sdkerrors.Register(SubModuleName, 4, "connection path is not associated to the given light client") + ErrInvalidConnectionState = sdkerrors.Register(SubModuleName, 5, "invalid connection state") + ErrInvalidCounterparty = sdkerrors.Register(SubModuleName, 6, "invalid counterparty connection") ) - -// ErrConnectionExists implements sdk.Error -func ErrConnectionExists(codespace sdk.CodespaceType, connectionID string) error { - return sdkerrors.New( - string(codespace), - uint32(CodeConnectionExists), - fmt.Sprintf("connection with ID %s already exists", connectionID), - ) -} - -// ErrConnectionNotFound implements sdk.Error -func ErrConnectionNotFound(codespace sdk.CodespaceType, connectionID string) error { - return sdkerrors.New( - string(codespace), - uint32(CodeConnectionNotFound), - fmt.Sprintf("connection with ID %s not found", connectionID), - ) -} - -// ErrClientConnectionPathsNotFound implements sdk.Error -func ErrClientConnectionPathsNotFound(codespace sdk.CodespaceType, clientID string) error { - return sdkerrors.New( - string(codespace), - uint32(CodeClientConnectionPathsNotFound), - fmt.Sprintf("client connection paths not found for ID %s", clientID), - ) -} - -// ErrConnectionPath implements sdk.Error -func ErrConnectionPath(codespace sdk.CodespaceType) error { - return sdkerrors.New( - string(codespace), - uint32(CodeConnectionPath), - "connection path is not associated to the client", - ) -} - -// ErrInvalidCounterpartyConnection implements sdk.Error -func ErrInvalidCounterpartyConnection(codespace sdk.CodespaceType) error { - return sdkerrors.New( - string(codespace), - uint32(CodeInvalidCounterpartyConnection), - "couldn't verify connection membership on counterparty's client", - ) -} - -// ErrInvalidHeight implements sdk.Error -func ErrInvalidHeight(codespace sdk.CodespaceType, msg string) error { - return sdkerrors.New( - string(codespace), - uint32(CodeInvalidHeight), - msg, - ) -} - -// ErrInvalidConnectionState implements sdk.Error -func ErrInvalidConnectionState(codespace sdk.CodespaceType, msg string) error { - return sdkerrors.New( - string(codespace), - uint32(CodeInvalidConnectionState), - msg, - ) -} - -// ErrInvalidCounterparty implements sdk.Error -func ErrInvalidCounterparty(codespace sdk.CodespaceType, msg string) error { - return sdkerrors.New( - string(codespace), - uint32(CodeInvalidCounterparty), - msg, - ) -} diff --git a/x/ibc/03-connection/types/msgs.go b/x/ibc/03-connection/types/msgs.go index e302badac9c4..bf0731c3bb66 100644 --- a/x/ibc/03-connection/types/msgs.go +++ b/x/ibc/03-connection/types/msgs.go @@ -47,17 +47,17 @@ func (msg MsgConnectionOpenInit) Type() string { } // ValidateBasic implements sdk.Msg -func (msg MsgConnectionOpenInit) ValidateBasic() sdk.Error { +func (msg MsgConnectionOpenInit) ValidateBasic() error { if err := host.DefaultConnectionIdentifierValidator(msg.ConnectionID); err != nil { - return sdk.ConvertError(sdkerrors.Wrap(err, "invalid connection ID")) + return sdkerrors.Wrapf(err, "invalid connection ID: %s", msg.ConnectionID) } if err := host.DefaultClientIdentifierValidator(msg.ClientID); err != nil { - return sdk.ConvertError(sdkerrors.Wrap(err, "invalid client ID")) + return sdkerrors.Wrapf(err, "invalid client ID: %s", msg.ClientID) } if msg.Signer.Empty() { - return sdk.ErrInvalidAddress("missing signer address") + return sdkerrors.ErrInvalidAddress } - return sdk.ConvertError(msg.Counterparty.ValidateBasic()) + return msg.Counterparty.ValidateBasic() } // GetSignBytes implements sdk.Msg @@ -118,37 +118,40 @@ func (msg MsgConnectionOpenTry) Type() string { } // ValidateBasic implements sdk.Msg -func (msg MsgConnectionOpenTry) ValidateBasic() sdk.Error { +func (msg MsgConnectionOpenTry) ValidateBasic() error { if err := host.DefaultConnectionIdentifierValidator(msg.ConnectionID); err != nil { - return sdk.ConvertError(sdkerrors.Wrap(err, "invalid connection ID")) + return sdkerrors.Wrapf(err, "invalid connection ID: %s", msg.ConnectionID) } if err := host.DefaultClientIdentifierValidator(msg.ClientID); err != nil { - return sdk.ConvertError(sdkerrors.Wrap(err, "invalid client ID")) + return sdkerrors.Wrapf(err, "invalid client ID: %s", msg.ClientID) } if len(msg.CounterpartyVersions) == 0 { - return sdk.ConvertError(ibctypes.ErrInvalidVersion(DefaultCodespace, "missing counterparty versions")) + return sdkerrors.Wrap(ibctypes.ErrInvalidVersion, "missing counterparty versions") } for _, version := range msg.CounterpartyVersions { if strings.TrimSpace(version) == "" { - return sdk.ConvertError(ibctypes.ErrInvalidVersion(DefaultCodespace, "version can't be blank")) + return sdkerrors.Wrap(ibctypes.ErrInvalidVersion, "version can't be blank") } } - if msg.ProofInit == nil { - return sdk.ConvertError(ibctypes.ErrInvalidProof(DefaultCodespace, "proof init cannot be nil")) + if msg.ProofInit == nil || msg.ProofConsensus == nil { + return sdkerrors.Wrap(commitment.ErrInvalidProof, "cannot submit an empty proof") } - if msg.ProofConsensus == nil { - return sdk.ConvertError(ibctypes.ErrInvalidProof(DefaultCodespace, "proof consensus cannot be nil")) + if err := msg.ProofInit.ValidateBasic(); err != nil { + return sdkerrors.Wrap(err, "proof init cannot be nil") + } + if err := msg.ProofConsensus.ValidateBasic(); err != nil { + return sdkerrors.Wrap(err, "proof consensus cannot be nil") } if msg.ProofHeight == 0 { - return sdk.ConvertError(ErrInvalidHeight(DefaultCodespace, "proof height must be > 0")) + return sdkerrors.Wrap(ibctypes.ErrInvalidHeight, "proof height must be > 0") } if msg.ConsensusHeight == 0 { - return sdk.ConvertError(ErrInvalidHeight(DefaultCodespace, "consensus height must be > 0")) + return sdkerrors.Wrap(ibctypes.ErrInvalidHeight, "consensus height must be > 0") } if msg.Signer.Empty() { - return sdk.ErrInvalidAddress("missing signer address") + return sdkerrors.ErrInvalidAddress } - return sdk.ConvertError(msg.Counterparty.ValidateBasic()) + return msg.Counterparty.ValidateBasic() } // GetSignBytes implements sdk.Msg @@ -203,27 +206,30 @@ func (msg MsgConnectionOpenAck) Type() string { } // ValidateBasic implements sdk.Msg -func (msg MsgConnectionOpenAck) ValidateBasic() sdk.Error { +func (msg MsgConnectionOpenAck) ValidateBasic() error { if err := host.DefaultConnectionIdentifierValidator(msg.ConnectionID); err != nil { - return sdk.ConvertError(sdkerrors.Wrap(err, "invalid connection ID")) + return sdkerrors.Wrap(err, "invalid connection ID") } if strings.TrimSpace(msg.Version) == "" { - return sdk.ConvertError(ibctypes.ErrInvalidVersion(DefaultCodespace, "version can't be blank")) + return sdkerrors.Wrap(ibctypes.ErrInvalidVersion, "version can't be blank") + } + if msg.ProofTry == nil || msg.ProofConsensus == nil { + return sdkerrors.Wrap(commitment.ErrInvalidProof, "cannot submit an empty proof") } - if msg.ProofTry == nil { - return sdk.ConvertError(ibctypes.ErrInvalidProof(DefaultCodespace, "proof try cannot be nil")) + if err := msg.ProofTry.ValidateBasic(); err != nil { + return sdkerrors.Wrap(err, "proof try cannot be nil") } - if msg.ProofConsensus == nil { - return sdk.ConvertError(ibctypes.ErrInvalidProof(DefaultCodespace, "proof consensus cannot be nil")) + if err := msg.ProofConsensus.ValidateBasic(); err != nil { + return sdkerrors.Wrap(err, "proof consensus cannot be nil") } if msg.ProofHeight == 0 { - return sdk.ConvertError(ErrInvalidHeight(DefaultCodespace, "proof height must be > 0")) + return sdkerrors.Wrap(ibctypes.ErrInvalidHeight, "proof height must be > 0") } if msg.ConsensusHeight == 0 { - return sdk.ConvertError(ErrInvalidHeight(DefaultCodespace, "consensus height must be > 0")) + return sdkerrors.Wrap(ibctypes.ErrInvalidHeight, "consensus height must be > 0") } if msg.Signer.Empty() { - return sdk.ErrInvalidAddress("missing signer address") + return sdkerrors.ErrInvalidAddress } return nil } @@ -272,18 +278,21 @@ func (msg MsgConnectionOpenConfirm) Type() string { } // ValidateBasic implements sdk.Msg -func (msg MsgConnectionOpenConfirm) ValidateBasic() sdk.Error { +func (msg MsgConnectionOpenConfirm) ValidateBasic() error { if err := host.DefaultConnectionIdentifierValidator(msg.ConnectionID); err != nil { - return sdk.ConvertError(sdkerrors.Wrap(err, "invalid connection ID")) + return sdkerrors.Wrap(err, "invalid connection ID") } if msg.ProofAck == nil { - return sdk.ConvertError(ibctypes.ErrInvalidProof(DefaultCodespace, "proof ack cannot be nil")) + return sdkerrors.Wrap(commitment.ErrInvalidProof, "cannot submit an empty proof") + } + if err := msg.ProofAck.ValidateBasic(); err != nil { + return sdkerrors.Wrap(err, "proof ack cannot be nil") } if msg.ProofHeight == 0 { - return sdk.ConvertError(ErrInvalidHeight(DefaultCodespace, "proof height must be > 0")) + return sdkerrors.Wrap(ibctypes.ErrInvalidHeight, "proof height must be > 0") } if msg.Signer.Empty() { - return sdk.ErrInvalidAddress("missing signer address") + return sdkerrors.ErrInvalidAddress } return nil } diff --git a/x/ibc/03-connection/types/msgs_test.go b/x/ibc/03-connection/types/msgs_test.go index 87fbae8b7276..8bca120769ba 100644 --- a/x/ibc/03-connection/types/msgs_test.go +++ b/x/ibc/03-connection/types/msgs_test.go @@ -4,20 +4,50 @@ import ( "fmt" "testing" - "github.com/stretchr/testify/require" + "github.com/stretchr/testify/suite" + abci "github.com/tendermint/tendermint/abci/types" + dbm "github.com/tendermint/tm-db" + + "github.com/cosmos/cosmos-sdk/store/iavl" + "github.com/cosmos/cosmos-sdk/store/rootmulti" + storetypes "github.com/cosmos/cosmos-sdk/store/types" sdk "github.com/cosmos/cosmos-sdk/types" commitment "github.com/cosmos/cosmos-sdk/x/ibc/23-commitment" ) -func TestNewMsgConnectionOpenInit(t *testing.T) { +type MsgTestSuite struct { + suite.Suite - type TestCase = struct { - msg MsgConnectionOpenInit - expected bool - errMsg string - } + proof commitment.Proof +} + +func (suite *MsgTestSuite) SetupTest() { + db := dbm.NewMemDB() + store := rootmulti.NewStore(db) + storeKey := storetypes.NewKVStoreKey("iavlStoreKey") + + store.MountStoreWithDB(storeKey, storetypes.StoreTypeIAVL, nil) + store.LoadVersion(0) + iavlStore := store.GetCommitStore(storeKey).(*iavl.Store) + + iavlStore.Set([]byte("KEY"), []byte("VALUE")) + _ = store.Commit() + + res := store.Query(abci.RequestQuery{ + Path: fmt.Sprintf("/%s/key", storeKey.Name()), // required path to get key/value+proof + Data: []byte("KEY"), + Prove: true, + }) + + suite.proof = commitment.Proof{Proof: res.Proof} +} + +func TestMsgTestSuite(t *testing.T) { + suite.Run(t, new(MsgTestSuite)) +} +func (suite *MsgTestSuite) TestNewMsgConnectionOpenInit() { prefix := commitment.NewPrefix([]byte("storePrefixKey")) signer, _ := sdk.AccAddressFromBech32("cosmos1ckgw5d7jfj7wwxjzs9fdrdev9vc8dzcw3n2lht") @@ -31,7 +61,11 @@ func TestNewMsgConnectionOpenInit(t *testing.T) { NewMsgConnectionOpenInit("ibcconntest", "clienttotest", "connectiontotest", "clienttotest", prefix, signer), } - var testCases = []TestCase{ + var testCases = []struct { + msg MsgConnectionOpenInit + expPass bool + errMsg string + }{ {testMsgs[0], false, "invalid connection ID"}, {testMsgs[1], false, "invalid client ID"}, {testMsgs[2], false, "invalid counterparty client ID"}, @@ -42,36 +76,41 @@ func TestNewMsgConnectionOpenInit(t *testing.T) { } for i, tc := range testCases { - require.Equal(t, tc.expected, tc.msg.ValidateBasic() == nil, fmt.Sprintf("case: %d,msg: %s,", i, tc.errMsg)) + err := tc.msg.ValidateBasic() + if tc.expPass { + suite.Require().NoError(err, "Msg %d failed: %v", i, err) + } else { + suite.Require().Error(err, "Invalid Msg %d passed: %s", i, tc.errMsg) + } } } -func TestNewMsgConnectionOpenTry(t *testing.T) { - type TestCase = struct { - msg MsgConnectionOpenTry - expected bool - errMsg string - } - +func (suite *MsgTestSuite) TestNewMsgConnectionOpenTry() { prefix := commitment.NewPrefix([]byte("storePrefixKey")) signer, _ := sdk.AccAddressFromBech32("cosmos1ckgw5d7jfj7wwxjzs9fdrdev9vc8dzcw3n2lht") testMsgs := []MsgConnectionOpenTry{ - NewMsgConnectionOpenTry("test/conn1", "clienttotesta", "connectiontotest", "clienttotest", prefix, []string{"1.0.0"}, commitment.Proof{}, commitment.Proof{}, 10, 10, signer), - NewMsgConnectionOpenTry("ibcconntest", "test/iris", "connectiontotest", "clienttotest", prefix, []string{"1.0.0"}, commitment.Proof{}, commitment.Proof{}, 10, 10, signer), - NewMsgConnectionOpenTry("ibcconntest", "clienttotesta", "ibc/test", "clienttotest", prefix, []string{"1.0.0"}, commitment.Proof{}, commitment.Proof{}, 10, 10, signer), - NewMsgConnectionOpenTry("ibcconntest", "clienttotesta", "connectiontotest", "test/conn1", prefix, []string{"1.0.0"}, commitment.Proof{}, commitment.Proof{}, 10, 10, signer), - NewMsgConnectionOpenTry("ibcconntest", "clienttotesta", "connectiontotest", "clienttotest", nil, []string{"1.0.0"}, commitment.Proof{}, commitment.Proof{}, 10, 10, signer), - NewMsgConnectionOpenTry("ibcconntest", "clienttotesta", "connectiontotest", "clienttotest", prefix, []string{}, commitment.Proof{}, commitment.Proof{}, 10, 10, signer), - NewMsgConnectionOpenTry("ibcconntest", "clienttotesta", "connectiontotest", "clienttotest", prefix, []string{"1.0.0"}, nil, commitment.Proof{}, 10, 10, signer), - NewMsgConnectionOpenTry("ibcconntest", "clienttotesta", "connectiontotest", "clienttotest", prefix, []string{"1.0.0"}, commitment.Proof{}, nil, 10, 10, signer), - NewMsgConnectionOpenTry("ibcconntest", "clienttotesta", "connectiontotest", "clienttotest", prefix, []string{"1.0.0"}, commitment.Proof{}, commitment.Proof{}, 0, 10, signer), - NewMsgConnectionOpenTry("ibcconntest", "clienttotesta", "connectiontotest", "clienttotest", prefix, []string{"1.0.0"}, commitment.Proof{}, commitment.Proof{}, 10, 0, signer), - NewMsgConnectionOpenTry("ibcconntest", "clienttotesta", "connectiontotest", "clienttotest", prefix, []string{"1.0.0"}, commitment.Proof{}, commitment.Proof{}, 10, 10, nil), - NewMsgConnectionOpenTry("ibcconntest", "clienttotesta", "connectiontotest", "clienttotest", prefix, []string{"1.0.0"}, commitment.Proof{}, commitment.Proof{}, 10, 10, signer), - } - - var testCases = []TestCase{ + NewMsgConnectionOpenTry("test/conn1", "clienttotesta", "connectiontotest", "clienttotest", prefix, []string{"1.0.0"}, suite.proof, suite.proof, 10, 10, signer), + NewMsgConnectionOpenTry("ibcconntest", "test/iris", "connectiontotest", "clienttotest", prefix, []string{"1.0.0"}, suite.proof, suite.proof, 10, 10, signer), + NewMsgConnectionOpenTry("ibcconntest", "clienttotesta", "ibc/test", "clienttotest", prefix, []string{"1.0.0"}, suite.proof, suite.proof, 10, 10, signer), + NewMsgConnectionOpenTry("ibcconntest", "clienttotesta", "connectiontotest", "test/conn1", prefix, []string{"1.0.0"}, suite.proof, suite.proof, 10, 10, signer), + NewMsgConnectionOpenTry("ibcconntest", "clienttotesta", "connectiontotest", "clienttotest", nil, []string{"1.0.0"}, suite.proof, suite.proof, 10, 10, signer), + NewMsgConnectionOpenTry("ibcconntest", "clienttotesta", "connectiontotest", "clienttotest", prefix, []string{}, suite.proof, suite.proof, 10, 10, signer), + NewMsgConnectionOpenTry("ibcconntest", "clienttotesta", "connectiontotest", "clienttotest", prefix, []string{"1.0.0"}, nil, suite.proof, 10, 10, signer), + NewMsgConnectionOpenTry("ibcconntest", "clienttotesta", "connectiontotest", "clienttotest", prefix, []string{"1.0.0"}, commitment.Proof{Proof: nil}, suite.proof, 10, 10, signer), + NewMsgConnectionOpenTry("ibcconntest", "clienttotesta", "connectiontotest", "clienttotest", prefix, []string{"1.0.0"}, suite.proof, nil, 10, 10, signer), + NewMsgConnectionOpenTry("ibcconntest", "clienttotesta", "connectiontotest", "clienttotest", prefix, []string{"1.0.0"}, suite.proof, commitment.Proof{Proof: nil}, 10, 10, signer), + NewMsgConnectionOpenTry("ibcconntest", "clienttotesta", "connectiontotest", "clienttotest", prefix, []string{"1.0.0"}, suite.proof, suite.proof, 0, 10, signer), + NewMsgConnectionOpenTry("ibcconntest", "clienttotesta", "connectiontotest", "clienttotest", prefix, []string{"1.0.0"}, suite.proof, suite.proof, 10, 0, signer), + NewMsgConnectionOpenTry("ibcconntest", "clienttotesta", "connectiontotest", "clienttotest", prefix, []string{"1.0.0"}, suite.proof, suite.proof, 10, 10, nil), + NewMsgConnectionOpenTry("ibcconntest", "clienttotesta", "connectiontotest", "clienttotest", prefix, []string{"1.0.0"}, suite.proof, suite.proof, 10, 10, signer), + } + + var testCases = []struct { + msg MsgConnectionOpenTry + expPass bool + errMsg string + }{ {testMsgs[0], false, "invalid connection ID"}, {testMsgs[1], false, "invalid client ID"}, {testMsgs[2], false, "invalid counterparty connection ID"}, @@ -79,79 +118,98 @@ func TestNewMsgConnectionOpenTry(t *testing.T) { {testMsgs[4], false, "empty counterparty prefix"}, {testMsgs[5], false, "empty counterpartyVersions"}, {testMsgs[6], false, "empty proofInit"}, - {testMsgs[7], false, "empty proofConsensus"}, - {testMsgs[8], false, "invalid proofHeight"}, - {testMsgs[9], false, "invalid consensusHeight"}, - {testMsgs[10], false, "empty singer"}, - {testMsgs[11], true, "success"}, + {testMsgs[7], false, "empty proofInit"}, + {testMsgs[8], false, "empty proofConsensus"}, + {testMsgs[9], false, "empty proofConsensus"}, + {testMsgs[10], false, "invalid proofHeight"}, + {testMsgs[11], false, "invalid consensusHeight"}, + {testMsgs[12], false, "empty singer"}, + {testMsgs[13], true, "success"}, } for i, tc := range testCases { - require.Equal(t, tc.expected, tc.msg.ValidateBasic() == nil, fmt.Sprintf("case: %d,msg: %s,", i, tc.errMsg)) + err := tc.msg.ValidateBasic() + if tc.expPass { + suite.Require().NoError(err, "Msg %d failed: %s", i, tc.errMsg) + } else { + suite.Require().Error(err, "Invalid Msg %d passed: %s", i, tc.errMsg) + } } } -func TestNewMsgConnectionOpenAck(t *testing.T) { - type TestCase = struct { - msg MsgConnectionOpenAck - expected bool - errMsg string - } - +func (suite *MsgTestSuite) TestNewMsgConnectionOpenAck() { signer, _ := sdk.AccAddressFromBech32("cosmos1ckgw5d7jfj7wwxjzs9fdrdev9vc8dzcw3n2lht") testMsgs := []MsgConnectionOpenAck{ - NewMsgConnectionOpenAck("test/conn1", commitment.Proof{}, commitment.Proof{}, 10, 10, "1.0.0", signer), - NewMsgConnectionOpenAck("ibcconntest", nil, commitment.Proof{}, 10, 10, "1.0.0", signer), - NewMsgConnectionOpenAck("ibcconntest", commitment.Proof{}, nil, 10, 10, "1.0.0", signer), - NewMsgConnectionOpenAck("ibcconntest", commitment.Proof{}, commitment.Proof{}, 0, 10, "1.0.0", signer), - NewMsgConnectionOpenAck("ibcconntest", commitment.Proof{}, commitment.Proof{}, 10, 0, "1.0.0", signer), - NewMsgConnectionOpenAck("ibcconntest", commitment.Proof{}, commitment.Proof{}, 10, 10, "", signer), - NewMsgConnectionOpenAck("ibcconntest", commitment.Proof{}, commitment.Proof{}, 10, 10, "1.0.0", nil), - NewMsgConnectionOpenAck("ibcconntest", commitment.Proof{}, commitment.Proof{}, 10, 10, "1.0.0", signer), - } - var testCases = []TestCase{ + NewMsgConnectionOpenAck("test/conn1", suite.proof, suite.proof, 10, 10, "1.0.0", signer), + NewMsgConnectionOpenAck("ibcconntest", nil, suite.proof, 10, 10, "1.0.0", signer), + NewMsgConnectionOpenAck("ibcconntest", commitment.Proof{Proof: nil}, suite.proof, 10, 10, "1.0.0", signer), + NewMsgConnectionOpenAck("ibcconntest", suite.proof, nil, 10, 10, "1.0.0", signer), + NewMsgConnectionOpenAck("ibcconntest", suite.proof, commitment.Proof{Proof: nil}, 10, 10, "1.0.0", signer), + NewMsgConnectionOpenAck("ibcconntest", suite.proof, suite.proof, 0, 10, "1.0.0", signer), + NewMsgConnectionOpenAck("ibcconntest", suite.proof, suite.proof, 10, 0, "1.0.0", signer), + NewMsgConnectionOpenAck("ibcconntest", suite.proof, suite.proof, 10, 10, "", signer), + NewMsgConnectionOpenAck("ibcconntest", suite.proof, suite.proof, 10, 10, "1.0.0", nil), + NewMsgConnectionOpenAck("ibcconntest", suite.proof, suite.proof, 10, 10, "1.0.0", signer), + } + var testCases = []struct { + msg MsgConnectionOpenAck + expPass bool + errMsg string + }{ {testMsgs[0], false, "invalid connection ID"}, {testMsgs[1], false, "empty proofTry"}, - {testMsgs[2], false, "empty proofConsensus"}, - {testMsgs[3], false, "invalid proofHeight"}, - {testMsgs[4], false, "invalid consensusHeight"}, - {testMsgs[5], false, "invalid version"}, - {testMsgs[6], false, "empty signer"}, - {testMsgs[7], true, "success"}, + {testMsgs[2], false, "empty proofTry"}, + {testMsgs[3], false, "empty proofConsensus"}, + {testMsgs[4], false, "empty proofConsensus"}, + {testMsgs[5], false, "invalid proofHeight"}, + {testMsgs[6], false, "invalid consensusHeight"}, + {testMsgs[7], false, "invalid version"}, + {testMsgs[8], false, "empty signer"}, + {testMsgs[9], true, "success"}, } for i, tc := range testCases { - require.Equal(t, tc.expected, tc.msg.ValidateBasic() == nil, fmt.Sprintf("case: %d,msg: %s,", i, tc.errMsg)) + err := tc.msg.ValidateBasic() + if tc.expPass { + suite.Require().NoError(err, "Msg %d failed: %s", i, tc.errMsg) + } else { + suite.Require().Error(err, "Invalid Msg %d passed: %s", i, tc.errMsg) + } } } -func TestNewMsgConnectionOpenConfirm(t *testing.T) { - type TestCase = struct { - msg MsgConnectionOpenConfirm - expected bool - errMsg string - } - +func (suite *MsgTestSuite) TestNewMsgConnectionOpenConfirm() { signer, _ := sdk.AccAddressFromBech32("cosmos1ckgw5d7jfj7wwxjzs9fdrdev9vc8dzcw3n2lht") testMsgs := []MsgConnectionOpenConfirm{ - NewMsgConnectionOpenConfirm("test/conn1", commitment.Proof{}, 10, signer), + NewMsgConnectionOpenConfirm("test/conn1", suite.proof, 10, signer), NewMsgConnectionOpenConfirm("ibcconntest", nil, 10, signer), - NewMsgConnectionOpenConfirm("ibcconntest", commitment.Proof{}, 0, signer), - NewMsgConnectionOpenConfirm("ibcconntest", commitment.Proof{}, 10, nil), - NewMsgConnectionOpenConfirm("ibcconntest", commitment.Proof{}, 10, signer), + NewMsgConnectionOpenConfirm("ibcconntest", commitment.Proof{Proof: nil}, 10, signer), + NewMsgConnectionOpenConfirm("ibcconntest", suite.proof, 0, signer), + NewMsgConnectionOpenConfirm("ibcconntest", suite.proof, 10, nil), + NewMsgConnectionOpenConfirm("ibcconntest", suite.proof, 10, signer), } - var testCases = []TestCase{ + var testCases = []struct { + msg MsgConnectionOpenConfirm + expPass bool + errMsg string + }{ {testMsgs[0], false, "invalid connection ID"}, {testMsgs[1], false, "empty proofTry"}, - {testMsgs[2], false, "invalid proofHeight"}, - {testMsgs[3], false, "empty signer"}, - {testMsgs[4], true, "success"}, + {testMsgs[2], false, "empty proofTry"}, + {testMsgs[3], false, "invalid proofHeight"}, + {testMsgs[4], false, "empty signer"}, + {testMsgs[5], true, "success"}, } for i, tc := range testCases { - require.Equal(t, tc.expected, tc.msg.ValidateBasic() == nil, fmt.Sprintf("case: %d,msg: %s,", i, tc.errMsg)) + err := tc.msg.ValidateBasic() + if tc.expPass { + suite.Require().NoError(err, "Msg %d failed: %s", i, tc.errMsg) + } else { + suite.Require().Error(err, "Invalid Msg %d passed: %s", i, tc.errMsg) + } } } diff --git a/x/ibc/04-channel/alias.go b/x/ibc/04-channel/alias.go index f2d6a7f49d24..73e18df48d0c 100644 --- a/x/ibc/04-channel/alias.go +++ b/x/ibc/04-channel/alias.go @@ -12,84 +12,75 @@ import ( ) const ( - UNINITIALIZED = types.UNINITIALIZED - UNORDERED = types.UNORDERED - ORDERED = types.ORDERED - OrderNone = types.OrderNone - OrderUnordered = types.OrderUnordered - OrderOrdered = types.OrderOrdered - CLOSED = types.CLOSED - INIT = types.INIT - TRYOPEN = types.TRYOPEN - OPEN = types.OPEN - StateUninitialized = types.StateUninitialized - StateInit = types.StateInit - StateTryOpen = types.StateTryOpen - StateOpen = types.StateOpen - StateClosed = types.StateClosed - DefaultCodespace = types.DefaultCodespace - CodeChannelExists = types.CodeChannelExists - CodeChannelNotFound = types.CodeChannelNotFound - CodeInvalidCounterpartyChannel = types.CodeInvalidCounterpartyChannel - CodeChannelCapabilityNotFound = types.CodeChannelCapabilityNotFound - CodeInvalidPacket = types.CodeInvalidPacket - CodeSequenceNotFound = types.CodeSequenceNotFound - CodePacketTimeout = types.CodePacketTimeout - CodeInvalidChannel = types.CodeInvalidChannel - CodeInvalidChannelState = types.CodeInvalidChannelState - AttributeKeySenderPort = types.AttributeKeySenderPort - AttributeKeyReceiverPort = types.AttributeKeyReceiverPort - AttributeKeyChannelID = types.AttributeKeyChannelID - AttributeKeySequence = types.AttributeKeySequence - SubModuleName = types.SubModuleName - StoreKey = types.StoreKey - RouterKey = types.RouterKey - QuerierRoute = types.QuerierRoute - QueryAllChannels = types.QueryAllChannels - QueryChannel = types.QueryChannel + UNINITIALIZED = types.UNINITIALIZED + UNORDERED = types.UNORDERED + ORDERED = types.ORDERED + OrderNone = types.OrderNone + OrderUnordered = types.OrderUnordered + OrderOrdered = types.OrderOrdered + CLOSED = types.CLOSED + INIT = types.INIT + TRYOPEN = types.TRYOPEN + OPEN = types.OPEN + StateUninitialized = types.StateUninitialized + StateInit = types.StateInit + StateTryOpen = types.StateTryOpen + StateOpen = types.StateOpen + StateClosed = types.StateClosed + AttributeKeySenderPort = types.AttributeKeySenderPort + AttributeKeyReceiverPort = types.AttributeKeyReceiverPort + AttributeKeyChannelID = types.AttributeKeyChannelID + AttributeKeySequence = types.AttributeKeySequence + SubModuleName = types.SubModuleName + StoreKey = types.StoreKey + RouterKey = types.RouterKey + QuerierRoute = types.QuerierRoute + QueryAllChannels = types.QueryAllChannels + QueryChannel = types.QueryChannel ) var ( // functions aliases - NewKeeper = keeper.NewKeeper - QuerierChannels = keeper.QuerierChannels - QuerierChannel = keeper.QuerierChannel - NewChannel = types.NewChannel - NewCounterparty = types.NewCounterparty - OrderFromString = types.OrderFromString - StateFromString = types.StateFromString - RegisterCodec = types.RegisterCodec - ErrChannelExists = types.ErrChannelExists - ErrChannelNotFound = types.ErrChannelNotFound - ErrInvalidCounterpartyChannel = types.ErrInvalidCounterpartyChannel - ErrChannelCapabilityNotFound = types.ErrChannelCapabilityNotFound - ErrInvalidPacket = types.ErrInvalidPacket - ErrSequenceNotFound = types.ErrSequenceNotFound - ErrPacketTimeout = types.ErrPacketTimeout - ErrInvalidChannel = types.ErrInvalidChannel - ErrInvalidChannelState = types.ErrInvalidChannelState - ChannelPath = types.ChannelPath - ChannelCapabilityPath = types.ChannelCapabilityPath - NextSequenceSendPath = types.NextSequenceSendPath - NextSequenceRecvPath = types.NextSequenceRecvPath - PacketCommitmentPath = types.PacketCommitmentPath - PacketAcknowledgementPath = types.PacketAcknowledgementPath - KeyChannel = types.KeyChannel - KeyChannelCapabilityPath = types.KeyChannelCapabilityPath - KeyNextSequenceSend = types.KeyNextSequenceSend - KeyNextSequenceRecv = types.KeyNextSequenceRecv - KeyPacketCommitment = types.KeyPacketCommitment - KeyPacketAcknowledgement = types.KeyPacketAcknowledgement - NewMsgChannelOpenInit = types.NewMsgChannelOpenInit - NewMsgChannelOpenTry = types.NewMsgChannelOpenTry - NewMsgChannelOpenAck = types.NewMsgChannelOpenAck - NewMsgChannelOpenConfirm = types.NewMsgChannelOpenConfirm - NewMsgChannelCloseInit = types.NewMsgChannelCloseInit - NewMsgChannelCloseConfirm = types.NewMsgChannelCloseConfirm - NewPacket = types.NewPacket - NewOpaquePacket = types.NewOpaquePacket - NewChannelResponse = types.NewChannelResponse - NewQueryChannelParams = types.NewQueryChannelParams + NewKeeper = keeper.NewKeeper + QuerierChannels = keeper.QuerierChannels + QuerierChannel = keeper.QuerierChannel + NewChannel = types.NewChannel + NewCounterparty = types.NewCounterparty + OrderFromString = types.OrderFromString + StateFromString = types.StateFromString + RegisterCodec = types.RegisterCodec + ErrChannelExists = types.ErrChannelExists + ErrChannelNotFound = types.ErrChannelNotFound + ErrInvalidCounterparty = types.ErrInvalidCounterparty + ErrChannelCapabilityNotFound = types.ErrChannelCapabilityNotFound + ErrInvalidPacket = types.ErrInvalidPacket + ErrSequenceSendNotFound = types.ErrSequenceSendNotFound + ErrSequenceReceiveNotFound = types.ErrSequenceReceiveNotFound + ErrPacketTimeout = types.ErrPacketTimeout + ErrInvalidChannel = types.ErrInvalidChannel + ErrInvalidChannelState = types.ErrInvalidChannelState + ChannelPath = types.ChannelPath + ChannelCapabilityPath = types.ChannelCapabilityPath + NextSequenceSendPath = types.NextSequenceSendPath + NextSequenceRecvPath = types.NextSequenceRecvPath + PacketCommitmentPath = types.PacketCommitmentPath + PacketAcknowledgementPath = types.PacketAcknowledgementPath + KeyChannel = types.KeyChannel + KeyChannelCapabilityPath = types.KeyChannelCapabilityPath + KeyNextSequenceSend = types.KeyNextSequenceSend + KeyNextSequenceRecv = types.KeyNextSequenceRecv + KeyPacketCommitment = types.KeyPacketCommitment + KeyPacketAcknowledgement = types.KeyPacketAcknowledgement + NewMsgChannelOpenInit = types.NewMsgChannelOpenInit + NewMsgChannelOpenTry = types.NewMsgChannelOpenTry + NewMsgChannelOpenAck = types.NewMsgChannelOpenAck + NewMsgChannelOpenConfirm = types.NewMsgChannelOpenConfirm + NewMsgChannelCloseInit = types.NewMsgChannelCloseInit + NewMsgChannelCloseConfirm = types.NewMsgChannelCloseConfirm + NewPacket = types.NewPacket + NewOpaquePacket = types.NewOpaquePacket + NewChannelResponse = types.NewChannelResponse + NewQueryChannelParams = types.NewQueryChannelParams // variable aliases SubModuleCdc = types.SubModuleCdc diff --git a/x/ibc/04-channel/client/cli/cli.go b/x/ibc/04-channel/client/cli/cli.go index 35bd02203a1d..7c24dff1e95f 100644 --- a/x/ibc/04-channel/client/cli/cli.go +++ b/x/ibc/04-channel/client/cli/cli.go @@ -3,7 +3,7 @@ package cli import ( "github.com/spf13/cobra" - "github.com/cosmos/cosmos-sdk/client" + "github.com/cosmos/cosmos-sdk/client/flags" "github.com/cosmos/cosmos-sdk/codec" ) @@ -15,7 +15,7 @@ func GetQueryCmd(storeKey string, cdc *codec.Codec) *cobra.Command { DisableFlagParsing: true, } - ics04ChannelQueryCmd.AddCommand(client.GetCommands( + ics04ChannelQueryCmd.AddCommand(flags.GetCommands( GetCmdQueryChannel(storeKey, cdc), )...) @@ -29,7 +29,7 @@ func GetTxCmd(storeKey string, cdc *codec.Codec) *cobra.Command { Short: "IBC channel transaction subcommands", } - ics04ChannelTxCmd.AddCommand(client.PostCommands( + ics04ChannelTxCmd.AddCommand(flags.PostCommands( GetMsgChannelOpenInitCmd(storeKey, cdc), GetMsgChannelOpenTryCmd(storeKey, cdc), GetMsgChannelOpenAckCmd(storeKey, cdc), diff --git a/x/ibc/04-channel/client/utils/utils.go b/x/ibc/04-channel/client/utils/utils.go index 0084f57376a1..e7e9568e4add 100644 --- a/x/ibc/04-channel/client/utils/utils.go +++ b/x/ibc/04-channel/client/utils/utils.go @@ -3,13 +3,13 @@ package utils import ( abci "github.com/tendermint/tendermint/abci/types" - "github.com/cosmos/cosmos-sdk/client" + "github.com/cosmos/cosmos-sdk/client/context" "github.com/cosmos/cosmos-sdk/x/ibc/04-channel/types" ) // QueryPacket returns a packet from the store func QueryPacket( - ctx client.CLIContext, portID, channelID string, sequence, timeout uint64, prove bool, + ctx context.CLIContext, portID, channelID string, sequence, timeout uint64, prove bool, ) (types.PacketResponse, error) { req := abci.RequestQuery{ Path: "store/ibc/key", @@ -46,7 +46,7 @@ func QueryPacket( // QueryChannel queries the store to get a channel and a merkle proof. func QueryChannel( - ctx client.CLIContext, portID, channelID string, prove bool, + ctx context.CLIContext, portID, channelID string, prove bool, ) (types.ChannelResponse, error) { req := abci.RequestQuery{ Path: "store/ibc/key", diff --git a/x/ibc/04-channel/handler.go b/x/ibc/04-channel/handler.go index 31c97b668e1a..fb35ef8e5fbe 100644 --- a/x/ibc/04-channel/handler.go +++ b/x/ibc/04-channel/handler.go @@ -7,13 +7,13 @@ import ( ) // HandleMsgChannelOpenInit defines the sdk.Handler for MsgChannelOpenInit -func HandleMsgChannelOpenInit(ctx sdk.Context, k keeper.Keeper, msg types.MsgChannelOpenInit) sdk.Result { +func HandleMsgChannelOpenInit(ctx sdk.Context, k keeper.Keeper, msg types.MsgChannelOpenInit) (*sdk.Result, error) { err := k.ChanOpenInit( ctx, msg.Channel.Ordering, msg.Channel.ConnectionHops, msg.PortID, msg.ChannelID, msg.Channel.Counterparty, msg.Channel.Version, ) if err != nil { - return sdk.ResultFromError(err) + return nil, err } ctx.EventManager().EmitEvents(sdk.Events{ @@ -29,16 +29,18 @@ func HandleMsgChannelOpenInit(ctx sdk.Context, k keeper.Keeper, msg types.MsgCha ), }) - return sdk.Result{Events: ctx.EventManager().Events()} + return &sdk.Result{ + Events: ctx.EventManager().Events(), + }, nil } // HandleMsgChannelOpenTry defines the sdk.Handler for MsgChannelOpenTry -func HandleMsgChannelOpenTry(ctx sdk.Context, k keeper.Keeper, msg types.MsgChannelOpenTry) sdk.Result { +func HandleMsgChannelOpenTry(ctx sdk.Context, k keeper.Keeper, msg types.MsgChannelOpenTry) (*sdk.Result, error) { err := k.ChanOpenTry(ctx, msg.Channel.Ordering, msg.Channel.ConnectionHops, msg.PortID, msg.ChannelID, msg.Channel.Counterparty, msg.Channel.Version, msg.CounterpartyVersion, msg.ProofInit, msg.ProofHeight, ) if err != nil { - return sdk.ResultFromError(err) + return nil, err } ctx.EventManager().EmitEvents(sdk.Events{ @@ -55,16 +57,18 @@ func HandleMsgChannelOpenTry(ctx sdk.Context, k keeper.Keeper, msg types.MsgChan ), }) - return sdk.Result{Events: ctx.EventManager().Events()} + return &sdk.Result{ + Events: ctx.EventManager().Events(), + }, nil } // HandleMsgChannelOpenAck defines the sdk.Handler for MsgChannelOpenAck -func HandleMsgChannelOpenAck(ctx sdk.Context, k keeper.Keeper, msg types.MsgChannelOpenAck) sdk.Result { +func HandleMsgChannelOpenAck(ctx sdk.Context, k keeper.Keeper, msg types.MsgChannelOpenAck) (*sdk.Result, error) { err := k.ChanOpenAck( ctx, msg.PortID, msg.ChannelID, msg.CounterpartyVersion, msg.ProofTry, msg.ProofHeight, ) if err != nil { - return sdk.ResultFromError(err) + return nil, err } ctx.EventManager().EmitEvents(sdk.Events{ @@ -80,14 +84,16 @@ func HandleMsgChannelOpenAck(ctx sdk.Context, k keeper.Keeper, msg types.MsgChan ), }) - return sdk.Result{Events: ctx.EventManager().Events()} + return &sdk.Result{ + Events: ctx.EventManager().Events(), + }, nil } // HandleMsgChannelOpenConfirm defines the sdk.Handler for MsgChannelOpenConfirm -func HandleMsgChannelOpenConfirm(ctx sdk.Context, k keeper.Keeper, msg types.MsgChannelOpenConfirm) sdk.Result { +func HandleMsgChannelOpenConfirm(ctx sdk.Context, k keeper.Keeper, msg types.MsgChannelOpenConfirm) (*sdk.Result, error) { err := k.ChanOpenConfirm(ctx, msg.PortID, msg.ChannelID, msg.ProofAck, msg.ProofHeight) if err != nil { - return sdk.ResultFromError(err) + return nil, err } ctx.EventManager().EmitEvents(sdk.Events{ @@ -103,14 +109,16 @@ func HandleMsgChannelOpenConfirm(ctx sdk.Context, k keeper.Keeper, msg types.Msg ), }) - return sdk.Result{Events: ctx.EventManager().Events()} + return &sdk.Result{ + Events: ctx.EventManager().Events(), + }, nil } // HandleMsgChannelCloseInit defines the sdk.Handler for MsgChannelCloseInit -func HandleMsgChannelCloseInit(ctx sdk.Context, k keeper.Keeper, msg types.MsgChannelCloseInit) sdk.Result { +func HandleMsgChannelCloseInit(ctx sdk.Context, k keeper.Keeper, msg types.MsgChannelCloseInit) (*sdk.Result, error) { err := k.ChanCloseInit(ctx, msg.PortID, msg.ChannelID) if err != nil { - return sdk.ResultFromError(err) + return nil, err } ctx.EventManager().EmitEvents(sdk.Events{ @@ -126,14 +134,16 @@ func HandleMsgChannelCloseInit(ctx sdk.Context, k keeper.Keeper, msg types.MsgCh ), }) - return sdk.Result{Events: ctx.EventManager().Events()} + return &sdk.Result{ + Events: ctx.EventManager().Events(), + }, nil } // HandleMsgChannelCloseConfirm defines the sdk.Handler for MsgChannelCloseConfirm -func HandleMsgChannelCloseConfirm(ctx sdk.Context, k keeper.Keeper, msg types.MsgChannelCloseConfirm) sdk.Result { +func HandleMsgChannelCloseConfirm(ctx sdk.Context, k keeper.Keeper, msg types.MsgChannelCloseConfirm) (*sdk.Result, error) { err := k.ChanCloseConfirm(ctx, msg.PortID, msg.ChannelID, msg.ProofInit, msg.ProofHeight) if err != nil { - return sdk.ResultFromError(err) + return nil, err } ctx.EventManager().EmitEvents(sdk.Events{ @@ -149,5 +159,7 @@ func HandleMsgChannelCloseConfirm(ctx sdk.Context, k keeper.Keeper, msg types.Ms ), }) - return sdk.Result{Events: ctx.EventManager().Events()} + return &sdk.Result{ + Events: ctx.EventManager().Events(), + }, nil } diff --git a/x/ibc/04-channel/keeper/handshake.go b/x/ibc/04-channel/keeper/handshake.go index 5deef767e415..c09dac9344f7 100644 --- a/x/ibc/04-channel/keeper/handshake.go +++ b/x/ibc/04-channel/keeper/handshake.go @@ -2,11 +2,12 @@ package keeper import ( "errors" - "fmt" sdk "github.com/cosmos/cosmos-sdk/types" + sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" connection "github.com/cosmos/cosmos-sdk/x/ibc/03-connection" "github.com/cosmos/cosmos-sdk/x/ibc/04-channel/types" + port "github.com/cosmos/cosmos-sdk/x/ibc/05-port" commitment "github.com/cosmos/cosmos-sdk/x/ibc/23-commitment" ) @@ -38,18 +39,18 @@ func (k Keeper) ChanOpenInit( // TODO: abortTransactionUnless(validateChannelIdentifier(portIdentifier, channelIdentifier)) _, found := k.GetChannel(ctx, portID, channelID) if found { - return types.ErrChannelExists(k.codespace, channelID) + return sdkerrors.Wrap(types.ErrChannelExists, channelID) } connectionEnd, found := k.connectionKeeper.GetConnection(ctx, connectionHops[0]) if !found { - return connection.ErrConnectionNotFound(k.codespace, connectionHops[0]) + return sdkerrors.Wrap(connection.ErrConnectionNotFound, connectionHops[0]) } if connectionEnd.State == connection.UNINITIALIZED { - return connection.ErrInvalidConnectionState( - k.codespace, - fmt.Sprintf("connection state cannot be NONE"), + return sdkerrors.Wrap( + connection.ErrInvalidConnectionState, + "connection state cannot be UNINITIALIZED", ) } @@ -58,7 +59,7 @@ func (k Keeper) ChanOpenInit( key := sdk.NewKVStoreKey(portID) if !k.portKeeper.Authenticate(key, portID) { - return errors.New("port is not valid") + return sdkerrors.Wrap(port.ErrInvalidPort, portID) } */ @@ -88,25 +89,25 @@ func (k Keeper) ChanOpenTry( ) error { _, found := k.GetChannel(ctx, portID, channelID) if found { - return types.ErrChannelExists(k.codespace, channelID) + return sdkerrors.Wrap(types.ErrChannelExists, channelID) } // TODO: Maybe not right key := sdk.NewKVStoreKey(portID) if !k.portKeeper.Authenticate(key, portID) { - return errors.New("port is not valid") + return sdkerrors.Wrap(port.ErrInvalidPort, portID) } connectionEnd, found := k.connectionKeeper.GetConnection(ctx, connectionHops[0]) if !found { - return connection.ErrConnectionNotFound(k.codespace, connectionHops[0]) + return sdkerrors.Wrap(connection.ErrConnectionNotFound, connectionHops[0]) } if connectionEnd.State != connection.OPEN { - return connection.ErrInvalidConnectionState( - k.codespace, - fmt.Sprintf("connection state is not OPEN (got %s)", connectionEnd.State.String()), + return sdkerrors.Wrapf( + connection.ErrInvalidConnectionState, + "connection state is not OPEN (got %s)", connectionEnd.State.String(), ) } @@ -130,7 +131,7 @@ func (k Keeper) ChanOpenTry( bz, err := k.cdc.MarshalBinaryLengthPrefixed(expectedChannel) if err != nil { - return errors.New("failed to marshal expected channel") + return err } if !k.connectionKeeper.VerifyMembership( @@ -138,7 +139,7 @@ func (k Keeper) ChanOpenTry( types.ChannelPath(counterparty.PortID, counterparty.ChannelID), bz, ) { - return types.ErrInvalidCounterpartyChannel(k.codespace, "channel membership verification failed") + return sdkerrors.Wrap(types.ErrInvalidCounterparty, "channel membership verification failed") } k.SetChannel(ctx, portID, channelID, channel) @@ -162,13 +163,13 @@ func (k Keeper) ChanOpenAck( ) error { channel, found := k.GetChannel(ctx, portID, channelID) if !found { - return types.ErrChannelNotFound(k.codespace, portID, channelID) + return sdkerrors.Wrap(types.ErrChannelNotFound, channelID) } if channel.State != types.INIT { - return types.ErrInvalidChannelState( - k.codespace, - fmt.Sprintf("channel state is not INIT (got %s)", channel.State.String()), + return sdkerrors.Wrapf( + types.ErrInvalidChannelState, + "channel state is not INIT (got %s)", channel.State.String(), ) } @@ -176,18 +177,18 @@ func (k Keeper) ChanOpenAck( key := sdk.NewKVStoreKey(portID) if !k.portKeeper.Authenticate(key, portID) { - return errors.New("port is not valid") + return sdkerrors.Wrap(port.ErrInvalidPort, portID) } connectionEnd, found := k.connectionKeeper.GetConnection(ctx, channel.ConnectionHops[0]) if !found { - return connection.ErrConnectionNotFound(k.codespace, channel.ConnectionHops[0]) + return sdkerrors.Wrap(connection.ErrConnectionNotFound, channel.ConnectionHops[0]) } if connectionEnd.State != connection.OPEN { - return connection.ErrInvalidConnectionState( - k.codespace, - fmt.Sprintf("connection state is not OPEN (got %s)", connectionEnd.State.String()), + return sdkerrors.Wrapf( + connection.ErrInvalidConnectionState, + "connection state is not OPEN (got %s)", connectionEnd.State.String(), ) } @@ -206,7 +207,7 @@ func (k Keeper) ChanOpenAck( bz, err := k.cdc.MarshalBinaryLengthPrefixed(expectedChannel) if err != nil { - return errors.New("failed to marshal expected channel") + return err } if !k.connectionKeeper.VerifyMembership( @@ -214,7 +215,9 @@ func (k Keeper) ChanOpenAck( types.ChannelPath(channel.Counterparty.PortID, channel.Counterparty.ChannelID), bz, ) { - return types.ErrInvalidCounterpartyChannel(k.codespace, "channel membership verification failed") + return sdkerrors.Wrap( + types.ErrInvalidCounterparty, "channel membership verification failed", + ) } channel.State = types.OPEN @@ -235,13 +238,13 @@ func (k Keeper) ChanOpenConfirm( ) error { channel, found := k.GetChannel(ctx, portID, channelID) if !found { - return types.ErrChannelNotFound(k.codespace, portID, channelID) + return sdkerrors.Wrap(types.ErrChannelNotFound, channelID) } if channel.State != types.TRYOPEN { - return types.ErrInvalidChannelState( - k.codespace, - fmt.Sprintf("channel state is not OPENTRY (got %s)", channel.State.String()), + return sdkerrors.Wrapf( + types.ErrInvalidChannelState, + "channel state is not OPENTRY (got %s)", channel.State.String(), ) } @@ -249,18 +252,18 @@ func (k Keeper) ChanOpenConfirm( key := sdk.NewKVStoreKey(portID) if !k.portKeeper.Authenticate(key, portID) { - return errors.New("port is not valid") + return sdkerrors.Wrap(port.ErrInvalidPort, portID) } connectionEnd, found := k.connectionKeeper.GetConnection(ctx, channel.ConnectionHops[0]) if !found { - return connection.ErrConnectionNotFound(k.codespace, channel.ConnectionHops[0]) + return sdkerrors.Wrap(connection.ErrConnectionNotFound, channel.ConnectionHops[0]) } if connectionEnd.State != connection.OPEN { - return connection.ErrInvalidConnectionState( - k.codespace, - fmt.Sprintf("connection state is not OPEN (got %s)", connectionEnd.State.String()), + return sdkerrors.Wrapf( + connection.ErrInvalidConnectionState, + "connection state is not OPEN (got %s)", connectionEnd.State.String(), ) } @@ -278,7 +281,7 @@ func (k Keeper) ChanOpenConfirm( bz, err := k.cdc.MarshalBinaryLengthPrefixed(expectedChannel) if err != nil { - return errors.New("failed to marshal expected channel") + return err } if !k.connectionKeeper.VerifyMembership( @@ -286,7 +289,7 @@ func (k Keeper) ChanOpenConfirm( types.ChannelPath(channel.Counterparty.PortID, channel.Counterparty.ChannelID), bz, ) { - return types.ErrInvalidCounterpartyChannel(k.codespace, "channel membership verification failed") + return sdkerrors.Wrap(types.ErrInvalidCounterparty, "channel membership verification failed") } channel.State = types.OPEN @@ -311,27 +314,27 @@ func (k Keeper) ChanCloseInit( key := sdk.NewKVStoreKey(portID) if !k.portKeeper.Authenticate(key, portID) { - return errors.New("port is not valid") + return sdkerrors.Wrap(port.ErrInvalidPort, portID) } channel, found := k.GetChannel(ctx, portID, channelID) if !found { - return types.ErrChannelNotFound(k.codespace, portID, channelID) + return sdkerrors.Wrap(types.ErrChannelNotFound, channelID) } if channel.State == types.CLOSED { - return types.ErrInvalidChannelState(k.codespace, "channel is already CLOSED") + return sdkerrors.Wrap(types.ErrInvalidChannelState, "channel is already CLOSED") } connectionEnd, found := k.connectionKeeper.GetConnection(ctx, channel.ConnectionHops[0]) if !found { - return connection.ErrConnectionNotFound(k.codespace, channel.ConnectionHops[0]) + return sdkerrors.Wrap(connection.ErrConnectionNotFound, channel.ConnectionHops[0]) } if connectionEnd.State != connection.OPEN { - return connection.ErrInvalidConnectionState( - k.codespace, - fmt.Sprintf("connection state is not OPEN (got %s)", connectionEnd.State.String()), + return sdkerrors.Wrapf( + connection.ErrInvalidConnectionState, + "connection state is not OPEN (got %s)", connectionEnd.State.String(), ) } @@ -354,27 +357,27 @@ func (k Keeper) ChanCloseConfirm( key := sdk.NewKVStoreKey(portID) if !k.portKeeper.Authenticate(key, portID) { - return errors.New("port is not valid") + return sdkerrors.Wrap(port.ErrInvalidPort, portID) } channel, found := k.GetChannel(ctx, portID, channelID) if !found { - return types.ErrChannelNotFound(k.codespace, portID, channelID) + return sdkerrors.Wrap(types.ErrChannelNotFound, channelID) } if channel.State == types.CLOSED { - return types.ErrInvalidChannelState(k.codespace, "channel is already CLOSED") + return sdkerrors.Wrap(types.ErrInvalidChannelState, "channel is already CLOSED") } connectionEnd, found := k.connectionKeeper.GetConnection(ctx, channel.ConnectionHops[0]) if !found { - return connection.ErrConnectionNotFound(k.codespace, channel.ConnectionHops[0]) + return sdkerrors.Wrap(connection.ErrConnectionNotFound, channel.ConnectionHops[0]) } if connectionEnd.State != connection.OPEN { - return connection.ErrInvalidConnectionState( - k.codespace, - fmt.Sprintf("connection state is not OPEN (got %s)", connectionEnd.State.String()), + return sdkerrors.Wrapf( + connection.ErrInvalidConnectionState, + "connection state is not OPEN (got %s)", connectionEnd.State.String(), ) } @@ -400,7 +403,7 @@ func (k Keeper) ChanCloseConfirm( types.ChannelPath(channel.Counterparty.PortID, channel.Counterparty.ChannelID), bz, ) { - return types.ErrInvalidCounterpartyChannel(k.codespace, "channel membership verification failed") + return sdkerrors.Wrap(types.ErrInvalidCounterparty, "channel membership verification failed") } channel.State = types.CLOSED diff --git a/x/ibc/04-channel/keeper/keeper.go b/x/ibc/04-channel/keeper/keeper.go index 5d72ab76cc60..92b1a3bca1f1 100644 --- a/x/ibc/04-channel/keeper/keeper.go +++ b/x/ibc/04-channel/keeper/keeper.go @@ -16,7 +16,6 @@ import ( type Keeper struct { storeKey sdk.StoreKey cdc *codec.Codec - codespace sdk.CodespaceType clientKeeper types.ClientKeeper connectionKeeper types.ConnectionKeeper portKeeper types.PortKeeper @@ -24,14 +23,13 @@ type Keeper struct { // NewKeeper creates a new IBC channel Keeper instance func NewKeeper( - cdc *codec.Codec, key sdk.StoreKey, codespace sdk.CodespaceType, + cdc *codec.Codec, key sdk.StoreKey, clientKeeper types.ClientKeeper, connectionKeeper types.ConnectionKeeper, portKeeper types.PortKeeper, ) Keeper { return Keeper{ storeKey: key, cdc: cdc, - codespace: sdk.CodespaceType(fmt.Sprintf("%s/%s", codespace, types.DefaultCodespace)), // "ibc/channel", clientKeeper: clientKeeper, connectionKeeper: connectionKeeper, portKeeper: portKeeper, diff --git a/x/ibc/04-channel/keeper/packet.go b/x/ibc/04-channel/keeper/packet.go index 515b7ecdf107..2703f283a814 100644 --- a/x/ibc/04-channel/keeper/packet.go +++ b/x/ibc/04-channel/keeper/packet.go @@ -3,13 +3,14 @@ package keeper import ( "bytes" "errors" - "fmt" sdk "github.com/cosmos/cosmos-sdk/types" + sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" client "github.com/cosmos/cosmos-sdk/x/ibc/02-client" connection "github.com/cosmos/cosmos-sdk/x/ibc/03-connection" "github.com/cosmos/cosmos-sdk/x/ibc/04-channel/exported" "github.com/cosmos/cosmos-sdk/x/ibc/04-channel/types" + port "github.com/cosmos/cosmos-sdk/x/ibc/05-port" commitment "github.com/cosmos/cosmos-sdk/x/ibc/23-commitment" ) @@ -34,51 +35,50 @@ func (k Keeper) CleanupPacket( ) (exported.PacketI, error) { channel, found := k.GetChannel(ctx, packet.GetSourcePort(), packet.GetSourceChannel()) if !found { - return nil, types.ErrChannelNotFound(k.codespace, packet.GetSourcePort(), packet.GetSourceChannel()) + return nil, sdkerrors.Wrap(types.ErrChannelNotFound, packet.GetSourceChannel()) } if channel.State != types.OPEN { - return nil, types.ErrInvalidChannelState( - k.codespace, - fmt.Sprintf("channel state is not OPEN (got %s)", channel.State.String()), + return nil, sdkerrors.Wrapf( + types.ErrInvalidChannelState, + "channel state is not OPEN (got %s)", channel.State.String(), ) } _, found = k.GetChannelCapability(ctx, packet.GetSourcePort(), packet.GetSourceChannel()) if !found { - return nil, types.ErrChannelCapabilityNotFound(k.codespace) + return nil, types.ErrChannelCapabilityNotFound } if !k.portKeeper.Authenticate(portCapability, packet.GetSourcePort()) { - return nil, errors.New("port is not valid") + return nil, sdkerrors.Wrapf(port.ErrInvalidPort, "invalid source port: %s", packet.GetSourcePort()) } if packet.GetDestChannel() != channel.Counterparty.ChannelID { - return nil, types.ErrInvalidPacket( - k.codespace, - fmt.Sprintf("packet destination channel doesn't match the counterparty's channel (%s ≠ %s)", packet.GetDestChannel(), channel.Counterparty.ChannelID), + return nil, sdkerrors.Wrapf( + types.ErrInvalidPacket, + "packet destination channel doesn't match the counterparty's channel (%s ≠ %s)", packet.GetDestChannel(), channel.Counterparty.ChannelID, ) } connectionEnd, found := k.connectionKeeper.GetConnection(ctx, channel.ConnectionHops[0]) if !found { - return nil, connection.ErrConnectionNotFound(k.codespace, channel.ConnectionHops[0]) + return nil, sdkerrors.Wrap(connection.ErrConnectionNotFound, channel.ConnectionHops[0]) } if packet.GetDestPort() != channel.Counterparty.PortID { - return nil, types.ErrInvalidPacket( - k.codespace, - fmt.Sprintf("packet destination port doesn't match the counterparty's port (%s ≠ %s)", packet.GetDestPort(), channel.Counterparty.PortID), + return nil, sdkerrors.Wrapf(types.ErrInvalidPacket, + "packet destination port doesn't match the counterparty's port (%s ≠ %s)", packet.GetDestPort(), channel.Counterparty.PortID, ) } if nextSequenceRecv >= packet.GetSequence() { - return nil, types.ErrInvalidPacket(k.codespace, "packet already received") + return nil, sdkerrors.Wrap(types.ErrInvalidPacket, "packet already received") } commitment := k.GetPacketCommitment(ctx, packet.GetSourcePort(), packet.GetSourceChannel(), packet.GetSequence()) if !bytes.Equal(commitment, packet.GetData()) { // TODO: hash packet data - return nil, types.ErrInvalidPacket(k.codespace, "packet hasn't been sent") + return nil, sdkerrors.Wrap(types.ErrInvalidPacket, "packet hasn't been sent") } var ok bool @@ -96,11 +96,11 @@ func (k Keeper) CleanupPacket( acknowledgement, ) default: - panic(fmt.Sprintf("invalid channel ordering type %v", channel.Ordering)) + panic(sdkerrors.Wrapf(types.ErrInvalidChannelOrdering, channel.Ordering.String())) } if !ok { - return nil, types.ErrInvalidPacket(k.codespace, "packet verification failed") + return nil, sdkerrors.Wrap(types.ErrInvalidPacket, "packet verification failed") } k.deletePacketCommitment(ctx, packet.GetSourcePort(), packet.GetSourceChannel(), packet.GetSequence()) @@ -121,64 +121,64 @@ func (k Keeper) SendPacket( channel, found := k.GetChannel(ctx, packet.GetSourcePort(), packet.GetSourceChannel()) if !found { - return types.ErrChannelNotFound(k.codespace, packet.GetSourcePort(), packet.GetSourceChannel()) + return sdkerrors.Wrap(types.ErrChannelNotFound, packet.GetSourceChannel()) } if channel.State == types.CLOSED { - return types.ErrInvalidChannelState( - k.codespace, - fmt.Sprintf("channel is CLOSED (got %s)", channel.State.String()), + return sdkerrors.Wrapf( + types.ErrInvalidChannelState, + "channel is CLOSED (got %s)", channel.State.String(), ) } if !k.portKeeper.Authenticate(portCapability, packet.GetSourcePort()) { - return errors.New("port is not valid") + return sdkerrors.Wrap(port.ErrInvalidPort, packet.GetSourcePort()) } if packet.GetDestPort() != channel.Counterparty.PortID { - return types.ErrInvalidPacket( - k.codespace, - fmt.Sprintf("packet destination port doesn't match the counterparty's port (%s ≠ %s)", packet.GetDestPort(), channel.Counterparty.PortID), + return sdkerrors.Wrapf( + types.ErrInvalidPacket, + "packet destination port doesn't match the counterparty's port (%s ≠ %s)", packet.GetDestPort(), channel.Counterparty.PortID, ) } if packet.GetDestChannel() != channel.Counterparty.ChannelID { - return types.ErrInvalidPacket( - k.codespace, - fmt.Sprintf("packet destination channel doesn't match the counterparty's channel (%s ≠ %s)", packet.GetDestChannel(), channel.Counterparty.ChannelID), + return sdkerrors.Wrapf( + types.ErrInvalidPacket, + "packet destination channel doesn't match the counterparty's channel (%s ≠ %s)", packet.GetDestChannel(), channel.Counterparty.ChannelID, ) } connectionEnd, found := k.connectionKeeper.GetConnection(ctx, channel.ConnectionHops[0]) if !found { - return connection.ErrConnectionNotFound(k.codespace, channel.ConnectionHops[0]) + return sdkerrors.Wrap(connection.ErrConnectionNotFound, channel.ConnectionHops[0]) } if connectionEnd.State == connection.UNINITIALIZED { - return connection.ErrInvalidConnectionState( - k.codespace, - fmt.Sprintf("connection is closed (i.e NONE)"), + return sdkerrors.Wrap( + connection.ErrInvalidConnectionState, + "connection is closed (i.e NONE)", ) } - consensusState, found := k.clientKeeper.GetConsensusState(ctx, connectionEnd.ClientID) + _, found = k.clientKeeper.GetConsensusState(ctx, connectionEnd.ClientID) if !found { - return client.ErrConsensusStateNotFound(k.codespace) + return client.ErrConsensusStateNotFound } - if consensusState.GetHeight() >= packet.GetTimeoutHeight() { - return types.ErrPacketTimeout(k.codespace) + if uint64(ctx.BlockHeight()) >= packet.GetTimeoutHeight() { + return types.ErrPacketTimeout } nextSequenceSend, found := k.GetNextSequenceSend(ctx, packet.GetSourcePort(), packet.GetSourceChannel()) if !found { - return types.ErrSequenceNotFound(k.codespace, "send") + return types.ErrSequenceSendNotFound } if packet.GetSequence() != nextSequenceSend { - return types.ErrInvalidPacket( - k.codespace, - fmt.Sprintf("packet sequence ≠ next send sequence (%d ≠ %d)", packet.GetSequence(), nextSequenceSend), + return sdkerrors.Wrapf( + types.ErrInvalidPacket, + "packet sequence ≠ next send sequence (%d ≠ %d)", packet.GetSequence(), nextSequenceSend, ) } @@ -202,49 +202,49 @@ func (k Keeper) RecvPacket( channel, found := k.GetChannel(ctx, packet.GetDestPort(), packet.GetDestChannel()) if !found { - return nil, types.ErrChannelNotFound(k.codespace, packet.GetDestPort(), packet.GetDestChannel()) + return nil, sdkerrors.Wrap(types.ErrChannelNotFound, packet.GetDestChannel()) } if channel.State != types.OPEN { - return nil, types.ErrInvalidChannelState( - k.codespace, - fmt.Sprintf("channel state is not OPEN (got %s)", channel.State.String()), + return nil, sdkerrors.Wrapf( + types.ErrInvalidChannelState, + "channel state is not OPEN (got %s)", channel.State.String(), ) } if !k.portKeeper.Authenticate(portCapability, packet.GetDestPort()) { - return nil, errors.New("port is not valid") + return nil, sdkerrors.Wrap(port.ErrInvalidPort, packet.GetDestPort()) } // packet must come from the channel's counterparty if packet.GetSourcePort() != channel.Counterparty.PortID { - return nil, types.ErrInvalidPacket( - k.codespace, - fmt.Sprintf("packet source port doesn't match the counterparty's port (%s ≠ %s)", packet.GetSourcePort(), channel.Counterparty.PortID), + return nil, sdkerrors.Wrapf( + types.ErrInvalidPacket, + "packet source port doesn't match the counterparty's port (%s ≠ %s)", packet.GetSourcePort(), channel.Counterparty.PortID, ) } if packet.GetSourceChannel() != channel.Counterparty.ChannelID { - return nil, types.ErrInvalidPacket( - k.codespace, - fmt.Sprintf("packet source channel doesn't match the counterparty's channel (%s ≠ %s)", packet.GetSourceChannel(), channel.Counterparty.ChannelID), + return nil, sdkerrors.Wrapf( + types.ErrInvalidPacket, + "packet source channel doesn't match the counterparty's channel (%s ≠ %s)", packet.GetSourceChannel(), channel.Counterparty.ChannelID, ) } connectionEnd, found := k.connectionKeeper.GetConnection(ctx, channel.ConnectionHops[0]) if !found { - return nil, connection.ErrConnectionNotFound(k.codespace, channel.ConnectionHops[0]) + return nil, sdkerrors.Wrap(connection.ErrConnectionNotFound, channel.ConnectionHops[0]) } if connectionEnd.State != connection.OPEN { - return nil, connection.ErrInvalidConnectionState( - k.codespace, - fmt.Sprintf("connection state is not OPEN (got %s)", connectionEnd.State.String()), + return nil, sdkerrors.Wrapf( + connection.ErrInvalidConnectionState, + "connection state is not OPEN (got %s)", connectionEnd.State.String(), ) } if uint64(ctx.BlockHeight()) >= packet.GetTimeoutHeight() { - return nil, types.ErrPacketTimeout(k.codespace) + return nil, types.ErrPacketTimeout } if !k.connectionKeeper.VerifyMembership( @@ -265,13 +265,13 @@ func (k Keeper) RecvPacket( if channel.Ordering == types.ORDERED { nextSequenceRecv, found := k.GetNextSequenceRecv(ctx, packet.GetDestPort(), packet.GetDestChannel()) if !found { - return nil, types.ErrSequenceNotFound(k.codespace, "receive") + return nil, types.ErrSequenceReceiveNotFound } if packet.GetSequence() != nextSequenceRecv { - return nil, types.ErrInvalidPacket( - k.codespace, - fmt.Sprintf("packet sequence ≠ next receive sequence (%d ≠ %d)", packet.GetSequence(), nextSequenceRecv), + return nil, sdkerrors.Wrapf( + types.ErrInvalidPacket, + "packet sequence ≠ next receive sequence (%d ≠ %d)", packet.GetSequence(), nextSequenceRecv, ) } @@ -298,13 +298,13 @@ func (k Keeper) AcknowledgePacket( ) (exported.PacketI, error) { channel, found := k.GetChannel(ctx, packet.GetSourcePort(), packet.GetSourceChannel()) if !found { - return nil, types.ErrChannelNotFound(k.codespace, packet.GetSourcePort(), packet.GetSourceChannel()) + return nil, sdkerrors.Wrap(types.ErrChannelNotFound, packet.GetSourceChannel()) } if channel.State != types.OPEN { - return nil, types.ErrInvalidChannelState( - k.codespace, - fmt.Sprintf("channel state is not OPEN (got %s)", channel.State.String()), + return nil, sdkerrors.Wrapf( + types.ErrInvalidChannelState, + "channel state is not OPEN (got %s)", channel.State.String(), ) } @@ -314,34 +314,34 @@ func (k Keeper) AcknowledgePacket( // packet must come from the channel's counterparty if packet.GetSourcePort() != channel.Counterparty.PortID { - return nil, types.ErrInvalidPacket( - k.codespace, - fmt.Sprintf("packet source port doesn't match the counterparty's port (%s ≠ %s)", packet.GetSourcePort(), channel.Counterparty.PortID), + return nil, sdkerrors.Wrapf( + types.ErrInvalidPacket, + "packet source port doesn't match the counterparty's port (%s ≠ %s)", packet.GetSourcePort(), channel.Counterparty.PortID, ) } if packet.GetSourceChannel() != channel.Counterparty.ChannelID { - return nil, types.ErrInvalidPacket( - k.codespace, - fmt.Sprintf("packet source channel doesn't match the counterparty's channel (%s ≠ %s)", packet.GetSourceChannel(), channel.Counterparty.ChannelID), + return nil, sdkerrors.Wrapf( + types.ErrInvalidPacket, + "packet source channel doesn't match the counterparty's channel (%s ≠ %s)", packet.GetSourceChannel(), channel.Counterparty.ChannelID, ) } connectionEnd, found := k.connectionKeeper.GetConnection(ctx, channel.ConnectionHops[0]) if !found { - return nil, connection.ErrConnectionNotFound(k.codespace, channel.ConnectionHops[0]) + return nil, sdkerrors.Wrap(connection.ErrConnectionNotFound, channel.ConnectionHops[0]) } if connectionEnd.State != connection.OPEN { - return nil, connection.ErrInvalidConnectionState( - k.codespace, - fmt.Sprintf("connection state is not OPEN (got %s)", connectionEnd.State.String()), + return nil, sdkerrors.Wrapf( + connection.ErrInvalidConnectionState, + "connection state is not OPEN (got %s)", connectionEnd.State.String(), ) } commitment := k.GetPacketCommitment(ctx, packet.GetSourcePort(), packet.GetSourceChannel(), packet.GetSequence()) if !bytes.Equal(commitment, packet.GetData()) { // TODO: hash packet data - return nil, types.ErrInvalidPacket(k.codespace, "packet hasn't been sent") + return nil, sdkerrors.Wrap(types.ErrInvalidPacket, "packet hasn't been sent") } if !k.connectionKeeper.VerifyMembership( diff --git a/x/ibc/04-channel/keeper/querier.go b/x/ibc/04-channel/keeper/querier.go index 8aef90c879ad..8c8cac783cec 100644 --- a/x/ibc/04-channel/keeper/querier.go +++ b/x/ibc/04-channel/keeper/querier.go @@ -20,7 +20,7 @@ func QuerierChannel(ctx sdk.Context, req abci.RequestQuery, k Keeper) ([]byte, e channel, found := k.GetChannel(ctx, params.PortID, params.ChannelID) if !found { - return nil, types.ErrChannelNotFound(k.codespace, params.PortID, params.ChannelID) + return nil, sdkerrors.Wrap(types.ErrChannelNotFound, params.ChannelID) } bz, err := codec.MarshalJSONIndent(k.cdc, channel) diff --git a/x/ibc/04-channel/keeper/timeout.go b/x/ibc/04-channel/keeper/timeout.go index 3ae481373de3..af54040dad2c 100644 --- a/x/ibc/04-channel/keeper/timeout.go +++ b/x/ibc/04-channel/keeper/timeout.go @@ -3,9 +3,9 @@ package keeper import ( "bytes" "errors" - "fmt" sdk "github.com/cosmos/cosmos-sdk/types" + sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" connection "github.com/cosmos/cosmos-sdk/x/ibc/03-connection" "github.com/cosmos/cosmos-sdk/x/ibc/04-channel/exported" "github.com/cosmos/cosmos-sdk/x/ibc/04-channel/types" @@ -27,19 +27,19 @@ func (k Keeper) TimeoutPacket( ) (exported.PacketI, error) { channel, found := k.GetChannel(ctx, packet.GetSourcePort(), packet.GetSourceChannel()) if !found { - return nil, types.ErrChannelNotFound(k.codespace, packet.GetSourcePort(), packet.GetSourceChannel()) + return nil, sdkerrors.Wrap(types.ErrChannelNotFound, packet.GetSourceChannel()) } if channel.State != types.OPEN { - return nil, types.ErrInvalidChannelState( - k.codespace, - fmt.Sprintf("channel state is not OPEN (got %s)", channel.State.String()), + return nil, sdkerrors.Wrapf( + types.ErrInvalidChannelState, + "channel state is not OPEN (got %s)", channel.State.String(), ) } _, found = k.GetChannelCapability(ctx, packet.GetSourcePort(), packet.GetSourceChannel()) if !found { - return nil, types.ErrChannelCapabilityNotFound(k.codespace) + return nil, types.ErrChannelCapabilityNotFound } if !k.portKeeper.Authenticate(portCapability, packet.GetSourcePort()) { @@ -47,35 +47,35 @@ func (k Keeper) TimeoutPacket( } if packet.GetDestChannel() != channel.Counterparty.ChannelID { - return nil, types.ErrInvalidPacket( - k.codespace, - fmt.Sprintf("packet destination channel doesn't match the counterparty's channel (%s ≠ %s)", packet.GetDestChannel(), channel.Counterparty.ChannelID), + return nil, sdkerrors.Wrapf( + types.ErrInvalidPacket, + "packet destination channel doesn't match the counterparty's channel (%s ≠ %s)", packet.GetDestChannel(), channel.Counterparty.ChannelID, ) } connectionEnd, found := k.connectionKeeper.GetConnection(ctx, channel.ConnectionHops[0]) if !found { - return nil, connection.ErrConnectionNotFound(k.codespace, channel.ConnectionHops[0]) + return nil, sdkerrors.Wrap(connection.ErrConnectionNotFound, channel.ConnectionHops[0]) } if packet.GetDestPort() != channel.Counterparty.PortID { - return nil, types.ErrInvalidPacket( - k.codespace, - fmt.Sprintf("packet destination port doesn't match the counterparty's port (%s ≠ %s)", packet.GetDestPort(), channel.Counterparty.PortID), + return nil, sdkerrors.Wrapf( + types.ErrInvalidPacket, + "packet destination port doesn't match the counterparty's port (%s ≠ %s)", packet.GetDestPort(), channel.Counterparty.PortID, ) } if proofHeight < packet.GetTimeoutHeight() { - return nil, types.ErrPacketTimeout(k.codespace) + return nil, types.ErrPacketTimeout } if nextSequenceRecv >= packet.GetSequence() { - return nil, types.ErrInvalidPacket(k.codespace, "packet already received") + return nil, sdkerrors.Wrap(types.ErrInvalidPacket, "packet already received") } commitment := k.GetPacketCommitment(ctx, packet.GetSourcePort(), packet.GetSourceChannel(), packet.GetSequence()) if !bytes.Equal(commitment, packet.GetData()) { // TODO: hash packet data - return nil, types.ErrInvalidPacket(k.codespace, "packet hasn't been sent") + return nil, sdkerrors.Wrap(types.ErrInvalidPacket, "packet hasn't been sent") } var ok bool @@ -92,11 +92,11 @@ func (k Keeper) TimeoutPacket( types.PacketAcknowledgementPath(packet.GetSourcePort(), packet.GetSourceChannel(), packet.GetSequence()), ) default: - panic(fmt.Sprintf("invalid channel ordering type %v", channel.Ordering)) + panic(sdkerrors.Wrapf(types.ErrInvalidChannelOrdering, channel.Ordering.String())) } if !ok { - return nil, types.ErrInvalidPacket(k.codespace, "packet verification failed") + return nil, sdkerrors.Wrap(types.ErrInvalidPacket, "packet verification failed") } k.deletePacketCommitment(ctx, packet.GetSourcePort(), packet.GetSourceChannel(), packet.GetSequence()) @@ -122,12 +122,12 @@ func (k Keeper) TimeoutOnClose( ) (exported.PacketI, error) { channel, found := k.GetChannel(ctx, packet.GetSourcePort(), packet.GetSourceChannel()) if !found { - return nil, types.ErrChannelNotFound(k.codespace, packet.GetSourcePort(), packet.GetSourceChannel()) + return nil, sdkerrors.Wrap(types.ErrChannelNotFound, packet.GetSourceChannel()) } _, found = k.GetChannelCapability(ctx, packet.GetSourcePort(), packet.GetSourceChannel()) if !found { - return nil, types.ErrChannelCapabilityNotFound(k.codespace) + return nil, types.ErrChannelCapabilityNotFound } if !k.portKeeper.Authenticate(portCapability, packet.GetSourcePort()) { @@ -135,27 +135,27 @@ func (k Keeper) TimeoutOnClose( } if packet.GetDestChannel() != channel.Counterparty.ChannelID { - return nil, types.ErrInvalidPacket( - k.codespace, - fmt.Sprintf("packet destination channel doesn't match the counterparty's channel (%s ≠ %s)", packet.GetDestChannel(), channel.Counterparty.ChannelID), + return nil, sdkerrors.Wrapf( + types.ErrInvalidPacket, + "packet destination channel doesn't match the counterparty's channel (%s ≠ %s)", packet.GetDestChannel(), channel.Counterparty.ChannelID, ) } connectionEnd, found := k.connectionKeeper.GetConnection(ctx, channel.ConnectionHops[0]) if !found { - return nil, connection.ErrConnectionNotFound(k.codespace, channel.ConnectionHops[0]) + return nil, sdkerrors.Wrap(connection.ErrConnectionNotFound, channel.ConnectionHops[0]) } if packet.GetDestPort() != channel.Counterparty.PortID { - return nil, types.ErrInvalidPacket( - k.codespace, - fmt.Sprintf("packet destination port doesn't match the counterparty's port (%s ≠ %s)", packet.GetDestPort(), channel.Counterparty.PortID), + return nil, sdkerrors.Wrapf( + types.ErrInvalidPacket, + "packet destination port doesn't match the counterparty's port (%s ≠ %s)", packet.GetDestPort(), channel.Counterparty.PortID, ) } commitment := k.GetPacketCommitment(ctx, packet.GetSourcePort(), packet.GetSourceChannel(), packet.GetSequence()) if !bytes.Equal(commitment, packet.GetData()) { // TODO: hash packet data - return nil, types.ErrInvalidPacket(k.codespace, "packet hasn't been sent") + return nil, sdkerrors.Wrap(types.ErrInvalidPacket, "packet hasn't been sent") } counterpartyHops, found := k.CounterpartyHops(ctx, channel) @@ -179,7 +179,10 @@ func (k Keeper) TimeoutOnClose( types.ChannelPath(channel.Counterparty.PortID, channel.Counterparty.ChannelID), bz, ) { - return nil, types.ErrInvalidCounterpartyChannel(k.codespace, "channel membership verification failed") + return nil, sdkerrors.Wrap( + types.ErrInvalidCounterparty, + "channel membership verification failed", + ) } if !k.connectionKeeper.VerifyNonMembership( diff --git a/x/ibc/04-channel/types/channel.go b/x/ibc/04-channel/types/channel.go index 1250d1208808..ae38cb2212df 100644 --- a/x/ibc/04-channel/types/channel.go +++ b/x/ibc/04-channel/types/channel.go @@ -2,11 +2,11 @@ package types import ( "encoding/json" - "fmt" "strings" sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" host "github.com/cosmos/cosmos-sdk/x/ibc/24-host" + ibctypes "github.com/cosmos/cosmos-sdk/x/ibc/types" ) type Channel struct { @@ -34,25 +34,25 @@ func NewChannel( // ValidateBasic performs a basic validation of the channel fields func (ch Channel) ValidateBasic() error { if ch.State.String() == "" { - return ErrInvalidChannelState( - DefaultCodespace, - "channel order should be either 'ORDERED' or 'UNORDERED'", - ) + return sdkerrors.Wrap(ErrInvalidChannel, ErrInvalidChannelState.Error()) } if ch.Ordering.String() == "" { - return ErrInvalidChannel( - DefaultCodespace, - "channel order should be either 'ORDERED' or 'UNORDERED'", - ) + return sdkerrors.Wrap(ErrInvalidChannel, ErrInvalidChannelOrdering.Error()) } if len(ch.ConnectionHops) != 1 { - return ErrInvalidChannel(DefaultCodespace, "IBC v1 only supports one connection hop") + return sdkerrors.Wrap(ErrInvalidChannel, "IBC v1 only supports one connection hop") } if err := host.DefaultConnectionIdentifierValidator(ch.ConnectionHops[0]); err != nil { - return sdkerrors.Wrap(err, "invalid connection hop ID") + return sdkerrors.Wrap( + ErrInvalidChannel, + sdkerrors.Wrap(err, "invalid connection hop ID").Error(), + ) } if strings.TrimSpace(ch.Version) == "" { - return ErrInvalidChannel(DefaultCodespace, "channel version can't be blank") + return sdkerrors.Wrap( + ErrInvalidChannel, + sdkerrors.Wrap(ibctypes.ErrInvalidVersion, "channel version can't be blank").Error(), + ) } return ch.Counterparty.ValidateBasic() } @@ -74,10 +74,16 @@ func NewCounterparty(portID, channelID string) Counterparty { // ValidateBasic performs a basic validation check of the identifiers func (c Counterparty) ValidateBasic() error { if err := host.DefaultPortIdentifierValidator(c.PortID); err != nil { - return sdkerrors.Wrap(err, "invalid counterparty connection ID") + return sdkerrors.Wrap( + ErrInvalidCounterparty, + sdkerrors.Wrap(err, "invalid counterparty connection ID").Error(), + ) } if err := host.DefaultChannelIdentifierValidator(c.ChannelID); err != nil { - return sdkerrors.Wrap(err, "invalid counterparty client ID") + return sdkerrors.Wrap( + ErrInvalidCounterparty, + sdkerrors.Wrap(err, "invalid counterparty client ID").Error(), + ) } return nil } @@ -126,7 +132,7 @@ func (o *Order) UnmarshalJSON(data []byte) error { order := OrderFromString(s) if order == 0 { - return fmt.Errorf("invalid channel ordering '%s'", s) + return sdkerrors.Wrap(ErrInvalidChannelOrdering, s) } *o = order diff --git a/x/ibc/04-channel/types/errors.go b/x/ibc/04-channel/types/errors.go index 318c78017d34..40e526476eae 100644 --- a/x/ibc/04-channel/types/errors.go +++ b/x/ibc/04-channel/types/errors.go @@ -1,104 +1,20 @@ package types import ( - "fmt" - - sdk "github.com/cosmos/cosmos-sdk/types" sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" ) -// channel error codes -const ( - DefaultCodespace sdk.CodespaceType = SubModuleName - - CodeChannelExists sdk.CodeType = 219 - CodeChannelNotFound sdk.CodeType = 220 - CodeInvalidCounterpartyChannel sdk.CodeType = 221 - CodeChannelCapabilityNotFound sdk.CodeType = 222 - CodeInvalidPacket sdk.CodeType = 223 - CodeSequenceNotFound sdk.CodeType = 224 - CodePacketTimeout sdk.CodeType = 225 - CodeInvalidChannel sdk.CodeType = 226 - CodeInvalidChannelState sdk.CodeType = 227 +// IBC channel sentinel errors +var ( + ErrChannelExists = sdkerrors.Register(SubModuleName, 1, "channel already exists") + ErrChannelNotFound = sdkerrors.Register(SubModuleName, 2, "channel not found") + ErrInvalidChannel = sdkerrors.Register(SubModuleName, 3, "invalid channel") + ErrInvalidChannelState = sdkerrors.Register(SubModuleName, 4, "invalid channel state") + ErrInvalidChannelOrdering = sdkerrors.Register(SubModuleName, 5, "invalid channel ordering") + ErrInvalidCounterparty = sdkerrors.Register(SubModuleName, 6, "invalid counterparty channel") + ErrChannelCapabilityNotFound = sdkerrors.Register(SubModuleName, 7, "channel capability not found") + ErrSequenceSendNotFound = sdkerrors.Register(SubModuleName, 8, "sequence send not found") + ErrSequenceReceiveNotFound = sdkerrors.Register(SubModuleName, 9, "sequence receive not found") + ErrInvalidPacket = sdkerrors.Register(SubModuleName, 10, "invalid packet") + ErrPacketTimeout = sdkerrors.Register(SubModuleName, 11, "packet timeout") ) - -// ErrChannelExists implements sdk.Error -func ErrChannelExists(codespace sdk.CodespaceType, channelID string) error { - return sdkerrors.New( - string(codespace), - uint32(CodeChannelExists), - fmt.Sprintf("channel with ID %s already exists", channelID), - ) -} - -// ErrChannelNotFound implements sdk.Error -func ErrChannelNotFound(codespace sdk.CodespaceType, portID, channelID string) error { - return sdkerrors.New( - string(codespace), - uint32(CodeChannelNotFound), - fmt.Sprintf("channel with ID %s on port %s not found", channelID, portID), - ) -} - -// ErrInvalidCounterpartyChannel implements sdk.Error -func ErrInvalidCounterpartyChannel(codespace sdk.CodespaceType, msg string) error { - return sdkerrors.New( - string(codespace), - uint32(CodeInvalidCounterpartyChannel), - msg, - ) -} - -// ErrChannelCapabilityNotFound implements sdk.Error -func ErrChannelCapabilityNotFound(codespace sdk.CodespaceType) error { - return sdkerrors.New( - string(codespace), - uint32(CodeChannelCapabilityNotFound), - "channel capability key not found", - ) -} - -// ErrInvalidPacket implements sdk.Error -func ErrInvalidPacket(codespace sdk.CodespaceType, msg string) error { - return sdkerrors.New( - string(codespace), - uint32(CodeInvalidPacket), - msg, - ) -} - -// ErrSequenceNotFound implements sdk.Error -func ErrSequenceNotFound(codespace sdk.CodespaceType, seqType string) error { - return sdkerrors.New( - string(codespace), - uint32(CodeSequenceNotFound), - fmt.Sprintf("next %s sequence counter not found", seqType), - ) -} - -// ErrPacketTimeout implements sdk.Error -func ErrPacketTimeout(codespace sdk.CodespaceType) error { - return sdkerrors.New( - string(codespace), - uint32(CodePacketTimeout), - "packet timeout", - ) -} - -// ErrInvalidChannel implements sdk.Error -func ErrInvalidChannel(codespace sdk.CodespaceType, msg string) error { - return sdkerrors.New( - string(codespace), - uint32(CodeInvalidChannel), - msg, - ) -} - -// ErrInvalidChannelState implements sdk.Error -func ErrInvalidChannelState(codespace sdk.CodespaceType, msg string) error { - return sdkerrors.New( - string(codespace), - uint32(CodeInvalidChannelState), - msg, - ) -} diff --git a/x/ibc/04-channel/types/msgs.go b/x/ibc/04-channel/types/msgs.go index 16a7a1943999..d0a9e71955ba 100644 --- a/x/ibc/04-channel/types/msgs.go +++ b/x/ibc/04-channel/types/msgs.go @@ -45,15 +45,15 @@ func (msg MsgChannelOpenInit) Type() string { } // ValidateBasic implements sdk.Msg -func (msg MsgChannelOpenInit) ValidateBasic() sdk.Error { +func (msg MsgChannelOpenInit) ValidateBasic() error { if err := host.DefaultPortIdentifierValidator(msg.PortID); err != nil { - return sdk.ConvertError(sdkerrors.Wrap(err, "invalid port ID")) + return sdkerrors.Wrap(err, "invalid port ID") } if err := host.DefaultChannelIdentifierValidator(msg.ChannelID); err != nil { - return sdk.ConvertError(sdkerrors.Wrap(err, "invalid channel ID")) + return sdkerrors.Wrap(err, "invalid channel ID") } // Signer can be empty - return sdk.ConvertError(msg.Channel.ValidateBasic()) + return msg.Channel.ValidateBasic() } // GetSignBytes implements sdk.Msg @@ -108,24 +108,27 @@ func (msg MsgChannelOpenTry) Type() string { } // ValidateBasic implements sdk.Msg -func (msg MsgChannelOpenTry) ValidateBasic() sdk.Error { +func (msg MsgChannelOpenTry) ValidateBasic() error { if err := host.DefaultPortIdentifierValidator(msg.PortID); err != nil { - return sdk.ConvertError(sdkerrors.Wrap(err, "invalid port ID")) + return sdkerrors.Wrap(err, "invalid port ID") } if err := host.DefaultChannelIdentifierValidator(msg.ChannelID); err != nil { - return sdk.ConvertError(sdkerrors.Wrap(err, "invalid channel ID")) + return sdkerrors.Wrap(err, "invalid channel ID") } if strings.TrimSpace(msg.CounterpartyVersion) == "" { - return sdk.ConvertError(ErrInvalidCounterpartyChannel(DefaultCodespace, "counterparty version cannot be blank")) + return sdkerrors.Wrap(ErrInvalidCounterparty, "counterparty version cannot be blank") } if msg.ProofInit == nil { - return sdk.ConvertError(ibctypes.ErrInvalidProof(DefaultCodespace, "cannot submit an empty proof")) + return sdkerrors.Wrap(commitment.ErrInvalidProof, "cannot submit an empty proof") + } + if err := msg.ProofInit.ValidateBasic(); err != nil { + return sdkerrors.Wrap(err, "proof init cannot be nil") } if msg.ProofHeight == 0 { - return sdk.ConvertError(ibctypes.ErrInvalidProof(DefaultCodespace, "proof height must be > 0")) + return sdkerrors.Wrap(ibctypes.ErrInvalidHeight, "proof height must be > 0") } // Signer can be empty - return sdk.ConvertError(msg.Channel.ValidateBasic()) + return msg.Channel.ValidateBasic() } // GetSignBytes implements sdk.Msg @@ -175,21 +178,24 @@ func (msg MsgChannelOpenAck) Type() string { } // ValidateBasic implements sdk.Msg -func (msg MsgChannelOpenAck) ValidateBasic() sdk.Error { +func (msg MsgChannelOpenAck) ValidateBasic() error { if err := host.DefaultPortIdentifierValidator(msg.PortID); err != nil { - return sdk.ConvertError(sdkerrors.Wrap(err, "invalid port ID")) + return sdkerrors.Wrap(err, "invalid port ID") } if err := host.DefaultChannelIdentifierValidator(msg.ChannelID); err != nil { - return sdk.ConvertError(sdkerrors.Wrap(err, "invalid channel ID")) + return sdkerrors.Wrap(err, "invalid channel ID") } if strings.TrimSpace(msg.CounterpartyVersion) == "" { - return sdk.ConvertError(ErrInvalidCounterpartyChannel(DefaultCodespace, "counterparty version cannot be blank")) + return sdkerrors.Wrap(ErrInvalidCounterparty, "counterparty version cannot be blank") } if msg.ProofTry == nil { - return sdk.ConvertError(ibctypes.ErrInvalidProof(DefaultCodespace, "cannot submit an empty proof")) + return sdkerrors.Wrap(commitment.ErrInvalidProof, "cannot submit an empty proof") + } + if err := msg.ProofTry.ValidateBasic(); err != nil { + return sdkerrors.Wrap(err, "proof try cannot be nil") } if msg.ProofHeight == 0 { - return sdk.ConvertError(ibctypes.ErrInvalidProof(DefaultCodespace, "proof height must be > 0")) + return sdkerrors.Wrap(ibctypes.ErrInvalidHeight, "proof height must be > 0") } // Signer can be empty return nil @@ -240,18 +246,21 @@ func (msg MsgChannelOpenConfirm) Type() string { } // ValidateBasic implements sdk.Msg -func (msg MsgChannelOpenConfirm) ValidateBasic() sdk.Error { +func (msg MsgChannelOpenConfirm) ValidateBasic() error { if err := host.DefaultPortIdentifierValidator(msg.PortID); err != nil { - return sdk.ConvertError(sdkerrors.Wrap(err, "invalid port ID")) + return sdkerrors.Wrap(err, "invalid port ID") } if err := host.DefaultChannelIdentifierValidator(msg.ChannelID); err != nil { - return sdk.ConvertError(sdkerrors.Wrap(err, "invalid channel ID")) + return sdkerrors.Wrap(err, "invalid channel ID") } if msg.ProofAck == nil { - return sdk.ConvertError(ibctypes.ErrInvalidProof(DefaultCodespace, "cannot submit an empty proof")) + return sdkerrors.Wrap(commitment.ErrInvalidProof, "cannot submit an empty proof") + } + if err := msg.ProofAck.ValidateBasic(); err != nil { + return sdkerrors.Wrap(err, "proof ack cannot be nil") } if msg.ProofHeight == 0 { - return sdk.ConvertError(ibctypes.ErrInvalidProof(DefaultCodespace, "proof height must be > 0")) + return sdkerrors.Wrap(ibctypes.ErrInvalidHeight, "proof height must be > 0") } // Signer can be empty return nil @@ -295,12 +304,12 @@ func (msg MsgChannelCloseInit) Type() string { } // ValidateBasic implements sdk.Msg -func (msg MsgChannelCloseInit) ValidateBasic() sdk.Error { +func (msg MsgChannelCloseInit) ValidateBasic() error { if err := host.DefaultPortIdentifierValidator(msg.PortID); err != nil { - return sdk.ConvertError(sdkerrors.Wrap(err, "invalid port ID")) + return sdkerrors.Wrap(err, "invalid port ID") } if err := host.DefaultChannelIdentifierValidator(msg.ChannelID); err != nil { - return sdk.ConvertError(sdkerrors.Wrap(err, "invalid channel ID")) + return sdkerrors.Wrap(err, "invalid channel ID") } // Signer can be empty return nil @@ -351,18 +360,21 @@ func (msg MsgChannelCloseConfirm) Type() string { } // ValidateBasic implements sdk.Msg -func (msg MsgChannelCloseConfirm) ValidateBasic() sdk.Error { +func (msg MsgChannelCloseConfirm) ValidateBasic() error { if err := host.DefaultPortIdentifierValidator(msg.PortID); err != nil { - return sdk.ConvertError(sdkerrors.Wrap(err, "invalid port ID")) + return sdkerrors.Wrap(err, "invalid port ID") } if err := host.DefaultChannelIdentifierValidator(msg.ChannelID); err != nil { - return sdk.ConvertError(sdkerrors.Wrap(err, "invalid channel ID")) + return sdkerrors.Wrap(err, "invalid channel ID") } if msg.ProofInit == nil { - return sdk.ConvertError(ibctypes.ErrInvalidProof(DefaultCodespace, "cannot submit an empty proof")) + return sdkerrors.Wrap(commitment.ErrInvalidProof, "cannot submit an empty proof") + } + if err := msg.ProofInit.ValidateBasic(); err != nil { + return sdkerrors.Wrap(err, "proof init cannot be nil") } if msg.ProofHeight == 0 { - return sdk.ConvertError(ibctypes.ErrInvalidProof(DefaultCodespace, "proof height must be > 0")) + return sdkerrors.Wrap(ibctypes.ErrInvalidHeight, "proof height must be > 0") } // Signer can be empty return nil diff --git a/x/ibc/04-channel/types/msgs_test.go b/x/ibc/04-channel/types/msgs_test.go index 3754ea4efa1a..2165f8c4eb40 100644 --- a/x/ibc/04-channel/types/msgs_test.go +++ b/x/ibc/04-channel/types/msgs_test.go @@ -1,10 +1,17 @@ package types import ( + "fmt" "testing" - "github.com/stretchr/testify/require" + "github.com/stretchr/testify/suite" + abci "github.com/tendermint/tendermint/abci/types" + dbm "github.com/tendermint/tm-db" + + "github.com/cosmos/cosmos-sdk/store/iavl" + "github.com/cosmos/cosmos-sdk/store/rootmulti" + storetypes "github.com/cosmos/cosmos-sdk/store/types" sdk "github.com/cosmos/cosmos-sdk/types" commitment "github.com/cosmos/cosmos-sdk/x/ibc/23-commitment" ) @@ -36,8 +43,39 @@ var ( addr = sdk.AccAddress("testaddr") ) +type MsgTestSuite struct { + suite.Suite + + proof commitment.Proof +} + +func (suite *MsgTestSuite) SetupTest() { + db := dbm.NewMemDB() + store := rootmulti.NewStore(db) + storeKey := storetypes.NewKVStoreKey("iavlStoreKey") + + store.MountStoreWithDB(storeKey, storetypes.StoreTypeIAVL, nil) + store.LoadVersion(0) + iavlStore := store.GetCommitStore(storeKey).(*iavl.Store) + + iavlStore.Set([]byte("KEY"), []byte("VALUE")) + _ = store.Commit() + + res := store.Query(abci.RequestQuery{ + Path: fmt.Sprintf("/%s/key", storeKey.Name()), // required path to get key/value+proof + Data: []byte("KEY"), + Prove: true, + }) + + suite.proof = commitment.Proof{Proof: res.Proof} +} + +func TestMsgTestSuite(t *testing.T) { + suite.Run(t, new(MsgTestSuite)) +} + // TestMsgChannelOpenInit tests ValidateBasic for MsgChannelOpenInit -func TestMsgChannelOpenInit(t *testing.T) { +func (suite *MsgTestSuite) TestMsgChannelOpenInit() { testMsgs := []MsgChannelOpenInit{ NewMsgChannelOpenInit("testportid", "testchannel", "1.0", ORDERED, connHops, "testcpport", "testcpchannel", addr), // valid msg NewMsgChannelOpenInit(invalidShortPort, "testchannel", "1.0", ORDERED, connHops, "testcpport", "testcpchannel", addr), // too short port id @@ -81,34 +119,34 @@ func TestMsgChannelOpenInit(t *testing.T) { for i, tc := range testCases { err := tc.msg.ValidateBasic() if tc.expPass { - require.Nil(t, err, "Msg %d failed: %v", i, err) + suite.Require().NoError(err, "Msg %d failed: %s", i, tc.errMsg) } else { - require.NotNil(t, err, "Invalid Msg %d passed: %s", i, tc.errMsg) + suite.Require().Error(err, "Invalid Msg %d passed: %s", i, tc.errMsg) } } } // TestMsgChannelOpenTry tests ValidateBasic for MsgChannelOpenTry -func TestMsgChannelOpenTry(t *testing.T) { +func (suite *MsgTestSuite) TestMsgChannelOpenTry() { testMsgs := []MsgChannelOpenTry{ - NewMsgChannelOpenTry("testportid", "testchannel", "1.0", ORDERED, connHops, "testcpport", "testcpchannel", "1.0", proof, 1, addr), // valid msg - NewMsgChannelOpenTry(invalidShortPort, "testchannel", "1.0", ORDERED, connHops, "testcpport", "testcpchannel", "1.0", proof, 1, addr), // too short port id - NewMsgChannelOpenTry(invalidLongPort, "testchannel", "1.0", ORDERED, connHops, "testcpport", "testcpchannel", "1.0", proof, 1, addr), // too long port id - NewMsgChannelOpenTry(invalidPort, "testchannel", "1.0", ORDERED, connHops, "testcpport", "testcpchannel", "1.0", proof, 1, addr), // port id contains non-alpha - NewMsgChannelOpenTry("testportid", invalidShortChannel, "1.0", ORDERED, connHops, "testcpport", "testcpchannel", "1.0", proof, 1, addr), // too short channel id - NewMsgChannelOpenTry("testportid", invalidLongChannel, "1.0", ORDERED, connHops, "testcpport", "testcpchannel", "1.0", proof, 1, addr), // too long channel id - NewMsgChannelOpenTry("testportid", invalidChannel, "1.0", ORDERED, connHops, "testcpport", "testcpchannel", "1.0", proof, 1, addr), // channel id contains non-alpha - NewMsgChannelOpenTry("testportid", "testchannel", "1.0", ORDERED, connHops, "testcpport", "testcpchannel", "", proof, 1, addr), // empty counterparty version - NewMsgChannelOpenTry("testportid", "testchannel", "1.0", ORDERED, connHops, "testcpport", "testcpchannel", "1.0", nil, 1, addr), // empty proof - NewMsgChannelOpenTry("testportid", "testchannel", "1.0", ORDERED, connHops, "testcpport", "testcpchannel", "1.0", proof, 0, addr), // proof height is zero - NewMsgChannelOpenTry("testportid", "testchannel", "1.0", Order(4), connHops, "testcpport", "testcpchannel", "1.0", proof, 1, addr), // invalid channel order - NewMsgChannelOpenTry("testportid", "testchannel", "1.0", UNORDERED, invalidConnHops, "testcpport", "testcpchannel", "1.0", proof, 1, addr), // connection hops more than 1 - NewMsgChannelOpenTry("testportid", "testchannel", "1.0", UNORDERED, invalidShortConnHops, "testcpport", "testcpchannel", "1.0", proof, 1, addr), // too short connection id - NewMsgChannelOpenTry("testportid", "testchannel", "1.0", UNORDERED, invalidLongConnHops, "testcpport", "testcpchannel", "1.0", proof, 1, addr), // too long connection id - NewMsgChannelOpenTry("testportid", "testchannel", "1.0", UNORDERED, []string{invalidConnection}, "testcpport", "testcpchannel", "1.0", proof, 1, addr), // connection id contains non-alpha - NewMsgChannelOpenTry("testportid", "testchannel", "", UNORDERED, connHops, "testcpport", "testcpchannel", "1.0", proof, 1, addr), // empty channel version - NewMsgChannelOpenTry("testportid", "testchannel", "1.0", UNORDERED, connHops, invalidPort, "testcpchannel", "1.0", proof, 1, addr), // invalid counterparty port id - NewMsgChannelOpenTry("testportid", "testchannel", "1.0", UNORDERED, connHops, "testcpport", invalidChannel, "1.0", proof, 1, addr), // invalid counterparty channel id + NewMsgChannelOpenTry("testportid", "testchannel", "1.0", ORDERED, connHops, "testcpport", "testcpchannel", "1.0", suite.proof, 1, addr), // valid msg + NewMsgChannelOpenTry(invalidShortPort, "testchannel", "1.0", ORDERED, connHops, "testcpport", "testcpchannel", "1.0", suite.proof, 1, addr), // too short port id + NewMsgChannelOpenTry(invalidLongPort, "testchannel", "1.0", ORDERED, connHops, "testcpport", "testcpchannel", "1.0", suite.proof, 1, addr), // too long port id + NewMsgChannelOpenTry(invalidPort, "testchannel", "1.0", ORDERED, connHops, "testcpport", "testcpchannel", "1.0", suite.proof, 1, addr), // port id contains non-alpha + NewMsgChannelOpenTry("testportid", invalidShortChannel, "1.0", ORDERED, connHops, "testcpport", "testcpchannel", "1.0", suite.proof, 1, addr), // too short channel id + NewMsgChannelOpenTry("testportid", invalidLongChannel, "1.0", ORDERED, connHops, "testcpport", "testcpchannel", "1.0", suite.proof, 1, addr), // too long channel id + NewMsgChannelOpenTry("testportid", invalidChannel, "1.0", ORDERED, connHops, "testcpport", "testcpchannel", "1.0", suite.proof, 1, addr), // channel id contains non-alpha + NewMsgChannelOpenTry("testportid", "testchannel", "1.0", ORDERED, connHops, "testcpport", "testcpchannel", "", suite.proof, 1, addr), // empty counterparty version + NewMsgChannelOpenTry("testportid", "testchannel", "1.0", ORDERED, connHops, "testcpport", "testcpchannel", "1.0", nil, 1, addr), // empty suite.proof + NewMsgChannelOpenTry("testportid", "testchannel", "1.0", ORDERED, connHops, "testcpport", "testcpchannel", "1.0", suite.proof, 0, addr), // suite.proof height is zero + NewMsgChannelOpenTry("testportid", "testchannel", "1.0", Order(4), connHops, "testcpport", "testcpchannel", "1.0", suite.proof, 1, addr), // invalid channel order + NewMsgChannelOpenTry("testportid", "testchannel", "1.0", UNORDERED, invalidConnHops, "testcpport", "testcpchannel", "1.0", suite.proof, 1, addr), // connection hops more than 1 + NewMsgChannelOpenTry("testportid", "testchannel", "1.0", UNORDERED, invalidShortConnHops, "testcpport", "testcpchannel", "1.0", suite.proof, 1, addr), // too short connection id + NewMsgChannelOpenTry("testportid", "testchannel", "1.0", UNORDERED, invalidLongConnHops, "testcpport", "testcpchannel", "1.0", suite.proof, 1, addr), // too long connection id + NewMsgChannelOpenTry("testportid", "testchannel", "1.0", UNORDERED, []string{invalidConnection}, "testcpport", "testcpchannel", "1.0", suite.proof, 1, addr), // connection id contains non-alpha + NewMsgChannelOpenTry("testportid", "testchannel", "", UNORDERED, connHops, "testcpport", "testcpchannel", "1.0", suite.proof, 1, addr), // empty channel version + NewMsgChannelOpenTry("testportid", "testchannel", "1.0", UNORDERED, connHops, invalidPort, "testcpchannel", "1.0", suite.proof, 1, addr), // invalid counterparty port id + NewMsgChannelOpenTry("testportid", "testchannel", "1.0", UNORDERED, connHops, "testcpport", invalidChannel, "1.0", suite.proof, 1, addr), // invalid counterparty channel id } testCases := []struct { @@ -139,26 +177,27 @@ func TestMsgChannelOpenTry(t *testing.T) { for i, tc := range testCases { err := tc.msg.ValidateBasic() if tc.expPass { - require.Nil(t, err, "Msg %d failed: %v", i, err) + suite.Require().NoError(err, "Msg %d failed: %s", i, tc.errMsg) } else { - require.NotNil(t, err, "Invalid Msg %d passed: %s", i, tc.errMsg) + suite.Require().Error(err, "Invalid Msg %d passed: %s", i, tc.errMsg) } } } // TestMsgChannelOpenAck tests ValidateBasic for MsgChannelOpenAck -func TestMsgChannelOpenAck(t *testing.T) { +func (suite *MsgTestSuite) TestMsgChannelOpenAck() { testMsgs := []MsgChannelOpenAck{ - NewMsgChannelOpenAck("testportid", "testchannel", "1.0", proof, 1, addr), // valid msg - NewMsgChannelOpenAck(invalidShortPort, "testchannel", "1.0", proof, 1, addr), // too short port id - NewMsgChannelOpenAck(invalidLongPort, "testchannel", "1.0", proof, 1, addr), // too long port id - NewMsgChannelOpenAck(invalidPort, "testchannel", "1.0", proof, 1, addr), // port id contains non-alpha - NewMsgChannelOpenAck("testportid", invalidShortChannel, "1.0", proof, 1, addr), // too short channel id - NewMsgChannelOpenAck("testportid", invalidLongChannel, "1.0", proof, 1, addr), // too long channel id - NewMsgChannelOpenAck("testportid", invalidChannel, "1.0", proof, 1, addr), // channel id contains non-alpha - NewMsgChannelOpenAck("testportid", "testchannel", "", proof, 1, addr), // empty counterparty version - NewMsgChannelOpenAck("testportid", "testchannel", "1.0", nil, 1, addr), // empty proof - NewMsgChannelOpenAck("testportid", "testchannel", "1.0", proof, 0, addr), // proof height is zero + NewMsgChannelOpenAck("testportid", "testchannel", "1.0", suite.proof, 1, addr), // valid msg + NewMsgChannelOpenAck(invalidShortPort, "testchannel", "1.0", suite.proof, 1, addr), // too short port id + NewMsgChannelOpenAck(invalidLongPort, "testchannel", "1.0", suite.proof, 1, addr), // too long port id + NewMsgChannelOpenAck(invalidPort, "testchannel", "1.0", suite.proof, 1, addr), // port id contains non-alpha + NewMsgChannelOpenAck("testportid", invalidShortChannel, "1.0", suite.proof, 1, addr), // too short channel id + NewMsgChannelOpenAck("testportid", invalidLongChannel, "1.0", suite.proof, 1, addr), // too long channel id + NewMsgChannelOpenAck("testportid", invalidChannel, "1.0", suite.proof, 1, addr), // channel id contains non-alpha + NewMsgChannelOpenAck("testportid", "testchannel", "", suite.proof, 1, addr), // empty counterparty version + NewMsgChannelOpenAck("testportid", "testchannel", "1.0", nil, 1, addr), // empty proof + NewMsgChannelOpenAck("testportid", "testchannel", "1.0", commitment.Proof{Proof: nil}, 1, addr), // empty proof + NewMsgChannelOpenAck("testportid", "testchannel", "1.0", suite.proof, 0, addr), // proof height is zero } testCases := []struct { @@ -175,31 +214,33 @@ func TestMsgChannelOpenAck(t *testing.T) { {testMsgs[6], false, "channel id contains non-alpha"}, {testMsgs[7], false, "empty counterparty version"}, {testMsgs[8], false, "empty proof"}, - {testMsgs[9], false, "proof height is zero"}, + {testMsgs[9], false, "empty proof"}, + {testMsgs[10], false, "proof height is zero"}, } for i, tc := range testCases { err := tc.msg.ValidateBasic() if tc.expPass { - require.Nil(t, err, "Msg %d failed: %v", i, err) + suite.Require().NoError(err, "Msg %d failed: %s", i, tc.errMsg) } else { - require.NotNil(t, err, "Invalid Msg %d passed: %s", i, tc.errMsg) + suite.Require().Error(err, "Invalid Msg %d passed: %s", i, tc.errMsg) } } } // TestMsgChannelOpenConfirm tests ValidateBasic for MsgChannelOpenConfirm -func TestMsgChannelOpenConfirm(t *testing.T) { +func (suite *MsgTestSuite) TestMsgChannelOpenConfirm() { testMsgs := []MsgChannelOpenConfirm{ - NewMsgChannelOpenConfirm("testportid", "testchannel", proof, 1, addr), // valid msg - NewMsgChannelOpenConfirm(invalidShortPort, "testchannel", proof, 1, addr), // too short port id - NewMsgChannelOpenConfirm(invalidLongPort, "testchannel", proof, 1, addr), // too long port id - NewMsgChannelOpenConfirm(invalidPort, "testchannel", proof, 1, addr), // port id contains non-alpha - NewMsgChannelOpenConfirm("testportid", invalidShortChannel, proof, 1, addr), // too short channel id - NewMsgChannelOpenConfirm("testportid", invalidLongChannel, proof, 1, addr), // too long channel id - NewMsgChannelOpenConfirm("testportid", invalidChannel, proof, 1, addr), // channel id contains non-alpha - NewMsgChannelOpenConfirm("testportid", "testchannel", nil, 1, addr), // empty proof - NewMsgChannelOpenConfirm("testportid", "testchannel", proof, 0, addr), // proof height is zero + NewMsgChannelOpenConfirm("testportid", "testchannel", suite.proof, 1, addr), // valid msg + NewMsgChannelOpenConfirm(invalidShortPort, "testchannel", suite.proof, 1, addr), // too short port id + NewMsgChannelOpenConfirm(invalidLongPort, "testchannel", suite.proof, 1, addr), // too long port id + NewMsgChannelOpenConfirm(invalidPort, "testchannel", suite.proof, 1, addr), // port id contains non-alpha + NewMsgChannelOpenConfirm("testportid", invalidShortChannel, suite.proof, 1, addr), // too short channel id + NewMsgChannelOpenConfirm("testportid", invalidLongChannel, suite.proof, 1, addr), // too long channel id + NewMsgChannelOpenConfirm("testportid", invalidChannel, suite.proof, 1, addr), // channel id contains non-alpha + NewMsgChannelOpenConfirm("testportid", "testchannel", nil, 1, addr), // empty proof + NewMsgChannelOpenConfirm("testportid", "testchannel", commitment.Proof{Proof: nil}, 1, addr), // empty proof + NewMsgChannelOpenConfirm("testportid", "testchannel", suite.proof, 0, addr), // proof height is zero } testCases := []struct { @@ -215,21 +256,22 @@ func TestMsgChannelOpenConfirm(t *testing.T) { {testMsgs[5], false, "too long channel id"}, {testMsgs[6], false, "channel id contains non-alpha"}, {testMsgs[7], false, "empty proof"}, - {testMsgs[8], false, "proof height is zero"}, + {testMsgs[8], false, "empty proof"}, + {testMsgs[9], false, "proof height is zero"}, } for i, tc := range testCases { err := tc.msg.ValidateBasic() if tc.expPass { - require.Nil(t, err, "Msg %d failed: %v", i, err) + suite.Require().NoError(err, "Msg %d failed: %s", i, tc.errMsg) } else { - require.NotNil(t, err, "Invalid Msg %d passed: %s", i, tc.errMsg) + suite.Require().Error(err, "Invalid Msg %d passed: %s", i, tc.errMsg) } } } // TestMsgChannelCloseInit tests ValidateBasic for MsgChannelCloseInit -func TestMsgChannelCloseInit(t *testing.T) { +func (suite *MsgTestSuite) TestMsgChannelCloseInit() { testMsgs := []MsgChannelCloseInit{ NewMsgChannelCloseInit("testportid", "testchannel", addr), // valid msg NewMsgChannelCloseInit(invalidShortPort, "testchannel", addr), // too short port id @@ -257,25 +299,26 @@ func TestMsgChannelCloseInit(t *testing.T) { for i, tc := range testCases { err := tc.msg.ValidateBasic() if tc.expPass { - require.Nil(t, err, "Msg %d failed: %v", i, err) + suite.Require().NoError(err, "Msg %d failed: %s", i, tc.errMsg) } else { - require.NotNil(t, err, "Invalid Msg %d passed: %s", i, tc.errMsg) + suite.Require().Error(err, "Invalid Msg %d passed: %s", i, tc.errMsg) } } } // TestMsgChannelCloseConfirm tests ValidateBasic for MsgChannelCloseConfirm -func TestMsgChannelCloseConfirm(t *testing.T) { +func (suite *MsgTestSuite) TestMsgChannelCloseConfirm() { testMsgs := []MsgChannelCloseConfirm{ - NewMsgChannelCloseConfirm("testportid", "testchannel", proof, 1, addr), // valid msg - NewMsgChannelCloseConfirm(invalidShortPort, "testchannel", proof, 1, addr), // too short port id - NewMsgChannelCloseConfirm(invalidLongPort, "testchannel", proof, 1, addr), // too long port id - NewMsgChannelCloseConfirm(invalidPort, "testchannel", proof, 1, addr), // port id contains non-alpha - NewMsgChannelCloseConfirm("testportid", invalidShortChannel, proof, 1, addr), // too short channel id - NewMsgChannelCloseConfirm("testportid", invalidLongChannel, proof, 1, addr), // too long channel id - NewMsgChannelCloseConfirm("testportid", invalidChannel, proof, 1, addr), // channel id contains non-alpha - NewMsgChannelCloseConfirm("testportid", "testchannel", nil, 1, addr), // empty proof - NewMsgChannelCloseConfirm("testportid", "testchannel", proof, 0, addr), // proof height is zero + NewMsgChannelCloseConfirm("testportid", "testchannel", suite.proof, 1, addr), // valid msg + NewMsgChannelCloseConfirm(invalidShortPort, "testchannel", suite.proof, 1, addr), // too short port id + NewMsgChannelCloseConfirm(invalidLongPort, "testchannel", suite.proof, 1, addr), // too long port id + NewMsgChannelCloseConfirm(invalidPort, "testchannel", suite.proof, 1, addr), // port id contains non-alpha + NewMsgChannelCloseConfirm("testportid", invalidShortChannel, suite.proof, 1, addr), // too short channel id + NewMsgChannelCloseConfirm("testportid", invalidLongChannel, suite.proof, 1, addr), // too long channel id + NewMsgChannelCloseConfirm("testportid", invalidChannel, suite.proof, 1, addr), // channel id contains non-alpha + NewMsgChannelCloseConfirm("testportid", "testchannel", nil, 1, addr), // empty proof + NewMsgChannelCloseConfirm("testportid", "testchannel", commitment.Proof{Proof: nil}, 1, addr), // empty proof + NewMsgChannelCloseConfirm("testportid", "testchannel", suite.proof, 0, addr), // proof height is zero } testCases := []struct { @@ -291,15 +334,16 @@ func TestMsgChannelCloseConfirm(t *testing.T) { {testMsgs[5], false, "too long channel id"}, {testMsgs[6], false, "channel id contains non-alpha"}, {testMsgs[7], false, "empty proof"}, - {testMsgs[8], false, "proof height is zero"}, + {testMsgs[8], false, "empty proof"}, + {testMsgs[9], false, "proof height is zero"}, } for i, tc := range testCases { err := tc.msg.ValidateBasic() if tc.expPass { - require.Nil(t, err, "Msg %d failed: %v", i, err) + suite.Require().NoError(err, "Msg %d failed: %s", i, tc.errMsg) } else { - require.NotNil(t, err, "Invalid Msg %d passed: %s", i, tc.errMsg) + suite.Require().Error(err, "Invalid Msg %d passed: %s", i, tc.errMsg) } } } diff --git a/x/ibc/04-channel/types/packet.go b/x/ibc/04-channel/types/packet.go index 8cfadf458487..7d8242d8db30 100644 --- a/x/ibc/04-channel/types/packet.go +++ b/x/ibc/04-channel/types/packet.go @@ -1,8 +1,7 @@ package types import ( - "fmt" - + sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" "github.com/cosmos/cosmos-sdk/x/ibc/04-channel/exported" host "github.com/cosmos/cosmos-sdk/x/ibc/24-host" ) @@ -11,13 +10,13 @@ var _ exported.PacketI = Packet{} // Packet defines a type that carries data across different chains through IBC type Packet struct { - Sequence uint64 `json:"sequence"` // number corresponds to the order of sends and receives, where a Packet with an earlier sequence number must be sent and received before a Packet with a later sequence number. - Timeout uint64 `json:"timeout"` // indicates a consensus height on the destination chain after which the Packet will no longer be processed, and will instead count as having timed-out. - SourcePort string `json:"source_port"` // identifies the port on the sending chain. - SourceChannel string `json:"source_channel"` // identifies the channel end on the sending chain. - DestinationPort string `json:"destination_port"` // identifies the port on the receiving chain. - DestinationChannel string `json:"destination_channel"` // identifies the channel end on the receiving chain. - Data []byte `json:"data"` // opaque value which can be defined by the application logic of the associated modules. + Sequence uint64 `json:"sequence" yaml:"sequence"` // number corresponds to the order of sends and receives, where a Packet with an earlier sequence number must be sent and received before a Packet with a later sequence number. + Timeout uint64 `json:"timeout" yaml:"timeout"` // indicates a consensus height on the destination chain after which the Packet will no longer be processed, and will instead count as having timed-out. + SourcePort string `json:"source_port" yaml:"source_port"` // identifies the port on the sending chain. + SourceChannel string `json:"source_channel" yaml:"source_channel"` // identifies the channel end on the sending chain. + DestinationPort string `json:"destination_port" yaml:"destination_port"` // identifies the port on the receiving chain. + DestinationChannel string `json:"destination_channel" yaml:"destination_channel"` // identifies the channel end on the receiving chain. + Data []byte `json:"data" yaml:"data"` // opaque value which can be defined by the application logic of the associated modules. } // NewPacket creates a new Packet instance @@ -26,13 +25,13 @@ func NewPacket( destinationPort, destinationChannel string, data []byte, ) Packet { return Packet{ - sequence, - timeout, - sourcePort, - sourceChannel, - destinationPort, - destinationChannel, - data, + Sequence: sequence, + Timeout: timeout, + SourcePort: sourcePort, + SourceChannel: sourceChannel, + DestinationPort: destinationPort, + DestinationChannel: destinationChannel, + Data: data, } } @@ -60,25 +59,37 @@ func (p Packet) GetData() []byte { return p.Data } // ValidateBasic implements PacketI interface func (p Packet) ValidateBasic() error { if err := host.DefaultPortIdentifierValidator(p.SourcePort); err != nil { - return ErrInvalidPacket(DefaultCodespace, fmt.Sprintf("invalid source port ID: %s", err.Error())) + return sdkerrors.Wrapf( + ErrInvalidPacket, + sdkerrors.Wrapf(err, "invalid source port ID: %s", p.SourcePort).Error(), + ) } if err := host.DefaultPortIdentifierValidator(p.DestinationPort); err != nil { - return ErrInvalidPacket(DefaultCodespace, fmt.Sprintf("invalid destination port ID: %s", err.Error())) + return sdkerrors.Wrapf( + ErrInvalidPacket, + sdkerrors.Wrapf(err, "invalid destination port ID: %s", p.DestinationPort).Error(), + ) } if err := host.DefaultChannelIdentifierValidator(p.SourceChannel); err != nil { - return ErrInvalidPacket(DefaultCodespace, fmt.Sprintf("invalid source channel ID: %s", err.Error())) + return sdkerrors.Wrapf( + ErrInvalidPacket, + sdkerrors.Wrapf(err, "invalid source channel ID: %s", p.SourceChannel).Error(), + ) } if err := host.DefaultChannelIdentifierValidator(p.DestinationChannel); err != nil { - return ErrInvalidPacket(DefaultCodespace, fmt.Sprintf("invalid destination channel ID: %s", err.Error())) + return sdkerrors.Wrapf( + ErrInvalidPacket, + sdkerrors.Wrapf(err, "invalid destination channel ID: %s", p.DestinationChannel).Error(), + ) } if p.Sequence == 0 { - return ErrInvalidPacket(DefaultCodespace, "packet sequence cannot be 0") + return sdkerrors.Wrap(ErrInvalidPacket, "packet sequence cannot be 0") } if p.Timeout == 0 { - return ErrPacketTimeout(DefaultCodespace) + return sdkerrors.Wrap(ErrInvalidPacket, "packet timeout cannot be 0") } if len(p.Data) == 0 { - return ErrInvalidPacket(DefaultCodespace, "packet data cannot be empty") + return sdkerrors.Wrap(ErrInvalidPacket, "packet data cannot be empty") } return nil } diff --git a/x/ibc/05-port/alias.go b/x/ibc/05-port/alias.go index ef3b6be60633..f53d7a41f9ee 100644 --- a/x/ibc/05-port/alias.go +++ b/x/ibc/05-port/alias.go @@ -12,13 +12,10 @@ import ( ) const ( - DefaultCodespace = types.DefaultCodespace - CodePortExists = types.CodePortExists - CodePortNotFound = types.CodePortNotFound - SubModuleName = types.SubModuleName - StoreKey = types.StoreKey - RouterKey = types.RouterKey - QuerierRoute = types.QuerierRoute + SubModuleName = types.SubModuleName + StoreKey = types.StoreKey + RouterKey = types.RouterKey + QuerierRoute = types.QuerierRoute ) var ( diff --git a/x/ibc/05-port/keeper/keeper.go b/x/ibc/05-port/keeper/keeper.go index 3d17a6881be8..45f0817f7702 100644 --- a/x/ibc/05-port/keeper/keeper.go +++ b/x/ibc/05-port/keeper/keeper.go @@ -5,25 +5,22 @@ import ( "github.com/cosmos/cosmos-sdk/codec" sdk "github.com/cosmos/cosmos-sdk/types" - "github.com/cosmos/cosmos-sdk/x/ibc/05-port/types" host "github.com/cosmos/cosmos-sdk/x/ibc/24-host" ) // Keeper defines the IBC connection keeper type Keeper struct { - storeKey sdk.StoreKey - cdc *codec.Codec - codespace sdk.CodespaceType - ports map[string]bool + storeKey sdk.StoreKey + cdc *codec.Codec + ports map[string]bool } // NewKeeper creates a new IBC connection Keeper instance -func NewKeeper(cdc *codec.Codec, key sdk.StoreKey, codespace sdk.CodespaceType) Keeper { +func NewKeeper(cdc *codec.Codec, key sdk.StoreKey) Keeper { return Keeper{ - storeKey: key, - cdc: cdc, - codespace: sdk.CodespaceType(fmt.Sprintf("%s/%s", codespace, types.DefaultCodespace)), // "ibc/port", - ports: make(map[string]bool), // map of capability key names to port ids + storeKey: key, + cdc: cdc, + ports: make(map[string]bool), // map of capability key names to port ids } } diff --git a/x/ibc/05-port/types/errors.go b/x/ibc/05-port/types/errors.go index d15b07bf0791..a0778ecd6b01 100644 --- a/x/ibc/05-port/types/errors.go +++ b/x/ibc/05-port/types/errors.go @@ -1,44 +1,12 @@ package types import ( - "fmt" - - sdk "github.com/cosmos/cosmos-sdk/types" sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" ) -// port error codes -const ( - DefaultCodespace sdk.CodespaceType = SubModuleName - - CodePortExists sdk.CodeType = 228 - CodePortNotFound sdk.CodeType = 229 - CodeInvalidPort sdk.CodeType = 230 +// IBC port sentinel errors +var ( + ErrPortExists = sdkerrors.Register(SubModuleName, 1, "port is already binded") + ErrPortNotFound = sdkerrors.Register(SubModuleName, 2, "port not found") + ErrInvalidPort = sdkerrors.Register(SubModuleName, 3, "invalid port") ) - -// ErrPortExists implements sdk.Error -func ErrPortExists(codespace sdk.CodespaceType, portID string) error { - return sdkerrors.New( - string(codespace), - uint32(CodePortExists), - fmt.Sprintf("port with ID %s is already binded", portID), - ) -} - -// ErrPortNotFound implements sdk.Error -func ErrPortNotFound(codespace sdk.CodespaceType, portID string) error { - return sdkerrors.New( - string(codespace), - uint32(CodePortNotFound), - fmt.Sprintf("port with ID %s not found", portID), - ) -} - -// ErrInvalidPort implements sdk.Error -func ErrInvalidPort(codespace sdk.CodespaceType, msg string) error { - return sdkerrors.New( - string(codespace), - uint32(CodePortNotFound), - msg, - ) -} diff --git a/x/ibc/20-transfer/alias.go b/x/ibc/20-transfer/alias.go index ee87c56d8b3e..00333d69f4b2 100644 --- a/x/ibc/20-transfer/alias.go +++ b/x/ibc/20-transfer/alias.go @@ -13,7 +13,6 @@ import ( const ( DefaultPacketTimeout = keeper.DefaultPacketTimeout - DefaultCodespace = types.DefaultCodespace AttributeKeyReceiver = types.AttributeKeyReceiver SubModuleName = types.SubModuleName StoreKey = types.StoreKey diff --git a/x/ibc/20-transfer/client/cli/cli.go b/x/ibc/20-transfer/client/cli/cli.go index 2007ed31908d..45a41239f974 100644 --- a/x/ibc/20-transfer/client/cli/cli.go +++ b/x/ibc/20-transfer/client/cli/cli.go @@ -3,7 +3,7 @@ package cli import ( "github.com/spf13/cobra" - "github.com/cosmos/cosmos-sdk/client" + "github.com/cosmos/cosmos-sdk/client/flags" "github.com/cosmos/cosmos-sdk/codec" ) @@ -14,7 +14,7 @@ func GetQueryCmd(cdc *codec.Codec, queryRoute string) *cobra.Command { Short: "IBC fungible token transfer query subcommands", } - ics20TransferQueryCmd.AddCommand(client.GetCommands( + ics20TransferQueryCmd.AddCommand(flags.GetCommands( GetCmdQueryNextSequence(cdc, queryRoute), )...) @@ -28,7 +28,7 @@ func GetTxCmd(cdc *codec.Codec) *cobra.Command { Short: "IBC fungible token transfer transaction subcommands", } - ics20TransferTxCmd.AddCommand(client.PostCommands( + ics20TransferTxCmd.AddCommand(flags.PostCommands( GetTransferTxCmd(cdc), // GetMsgRecvPacketCmd(cdc), )...) diff --git a/x/ibc/20-transfer/handler.go b/x/ibc/20-transfer/handler.go index 731a6c27e7f5..6dfcf0470e4d 100644 --- a/x/ibc/20-transfer/handler.go +++ b/x/ibc/20-transfer/handler.go @@ -6,10 +6,10 @@ import ( ) // HandleMsgTransfer defines the sdk.Handler for MsgTransfer -func HandleMsgTransfer(ctx sdk.Context, k Keeper, msg MsgTransfer) (res sdk.Result) { +func HandleMsgTransfer(ctx sdk.Context, k Keeper, msg MsgTransfer) (*sdk.Result, error) { err := k.SendTransfer(ctx, msg.SourcePort, msg.SourceChannel, msg.Amount, msg.Sender, msg.Receiver, msg.Source) if err != nil { - return sdk.ResultFromError(err) + return nil, err } ctx.EventManager().EmitEvent( @@ -21,14 +21,16 @@ func HandleMsgTransfer(ctx sdk.Context, k Keeper, msg MsgTransfer) (res sdk.Resu ), ) - return sdk.Result{Events: ctx.EventManager().Events()} + return &sdk.Result{ + Events: ctx.EventManager().Events(), + }, nil } // HandleMsgRecvPacket defines the sdk.Handler for MsgRecvPacket -func HandleMsgRecvPacket(ctx sdk.Context, k Keeper, msg MsgRecvPacket) (res sdk.Result) { +func HandleMsgRecvPacket(ctx sdk.Context, k Keeper, msg MsgRecvPacket) (*sdk.Result, error) { err := k.ReceivePacket(ctx, msg.Packet, msg.Proofs[0], msg.Height) if err != nil { - return sdk.ResultFromError(err) + return nil, err } ctx.EventManager().EmitEvent( @@ -39,5 +41,7 @@ func HandleMsgRecvPacket(ctx sdk.Context, k Keeper, msg MsgRecvPacket) (res sdk. ), ) - return sdk.Result{Events: ctx.EventManager().Events()} + return &sdk.Result{ + Events: ctx.EventManager().Events(), + }, nil } diff --git a/x/ibc/20-transfer/handler_test.go b/x/ibc/20-transfer/handler_test.go index 46ef6f08558b..d3db1ed739fc 100644 --- a/x/ibc/20-transfer/handler_test.go +++ b/x/ibc/20-transfer/handler_test.go @@ -160,35 +160,41 @@ func (suite *HandlerTestSuite) TestHandleMsgTransfer() { source := true msg := transfer.NewMsgTransfer(testPort1, testChannel1, testCoins, testAddr1, testAddr2, source) - res := transfer.HandleMsgTransfer(suite.ctx, suite.app.IBCKeeper.TransferKeeper, msg) - suite.False(res.Code.IsOK(), "%v", res) // channel does not exist + res, err := transfer.HandleMsgTransfer(suite.ctx, suite.app.IBCKeeper.TransferKeeper, msg) + suite.Require().Error(err) + suite.Require().Nil(res, "%v", res) // channel does not exist suite.createChannel(testPort1, testChannel1, testConnection, testPort2, testChannel2, channel.OPEN) - res = transfer.HandleMsgTransfer(suite.ctx, suite.app.IBCKeeper.TransferKeeper, msg) - suite.False(res.Code.IsOK(), "%v", res) // next send sequence not found + res, err = transfer.HandleMsgTransfer(suite.ctx, suite.app.IBCKeeper.TransferKeeper, msg) + suite.Require().Error(err) + suite.Require().Nil(res, "%v", res) // next send sequence not found nextSeqSend := uint64(1) suite.app.IBCKeeper.ChannelKeeper.SetNextSequenceSend(suite.ctx, testPort1, testChannel1, nextSeqSend) - res = transfer.HandleMsgTransfer(suite.ctx, suite.app.IBCKeeper.TransferKeeper, msg) - suite.False(res.Code.IsOK(), "%v", res) // sender has insufficient coins + res, err = transfer.HandleMsgTransfer(suite.ctx, suite.app.IBCKeeper.TransferKeeper, msg) + suite.Require().Error(err) + suite.Require().Nil(res, "%v", res) // sender has insufficient coins _ = suite.app.BankKeeper.SetCoins(suite.ctx, testAddr1, testCoins) - res = transfer.HandleMsgTransfer(suite.ctx, suite.app.IBCKeeper.TransferKeeper, msg) - suite.True(res.Code.IsOK(), "%v", res) // successfully executed + res, err = transfer.HandleMsgTransfer(suite.ctx, suite.app.IBCKeeper.TransferKeeper, msg) + suite.Require().NoError(err) + suite.Require().NotNil(res, "%v", res) // successfully executed // test when the source is false source = false msg = transfer.NewMsgTransfer(testPort1, testChannel1, testPrefixedCoins2, testAddr1, testAddr2, source) _ = suite.app.BankKeeper.SetCoins(suite.ctx, testAddr1, testPrefixedCoins2) - res = transfer.HandleMsgTransfer(suite.ctx, suite.app.IBCKeeper.TransferKeeper, msg) - suite.False(res.Code.IsOK(), "%v", res) // incorrect denom prefix + res, err = transfer.HandleMsgTransfer(suite.ctx, suite.app.IBCKeeper.TransferKeeper, msg) + suite.Require().Error(err) + suite.Require().Nil(res, "%v", res) // incorrect denom prefix msg = transfer.NewMsgTransfer(testPort1, testChannel1, testPrefixedCoins1, testAddr1, testAddr2, source) suite.app.SupplyKeeper.SetSupply(suite.ctx, supply.NewSupply(testPrefixedCoins1)) _ = suite.app.BankKeeper.SetCoins(suite.ctx, testAddr1, testPrefixedCoins1) - res = transfer.HandleMsgTransfer(suite.ctx, suite.app.IBCKeeper.TransferKeeper, msg) - suite.True(res.Code.IsOK(), "%v", res) // successfully executed + res, err = transfer.HandleMsgTransfer(suite.ctx, suite.app.IBCKeeper.TransferKeeper, msg) + suite.Require().NoError(err) + suite.Require().NotNil(res, "%v", res) // successfully executed } func (suite *HandlerTestSuite) TestHandleRecvPacket() { @@ -205,16 +211,18 @@ func (suite *HandlerTestSuite) TestHandleRecvPacket() { msg := types.NewMsgRecvPacket(packet, []commitment.Proof{proofPacket}, uint64(proofHeight), testAddr1) suite.createChannel(testPort1, testChannel1, testConnection, testPort2, testChannel2, channel.OPEN) - res := transfer.HandleMsgRecvPacket(suite.ctx, suite.app.IBCKeeper.TransferKeeper, msg) - suite.False(res.Code.IsOK(), "%v", res) // packet membership verification failed due to invalid counterparty packet commitment + res, err := transfer.HandleMsgRecvPacket(suite.ctx, suite.app.IBCKeeper.TransferKeeper, msg) + suite.Require().Error(err) + suite.Require().Nil(res, "%v", res) // packet membership verification failed due to invalid counterparty packet commitment suite.app.IBCKeeper.ChannelKeeper.SetPacketCommitment(suite.ctx, testPort2, testChannel2, packetSeq, packetDataBz) suite.updateClient() proofPacket, proofHeight = suite.queryProof(packetCommitmentPath) msg = types.NewMsgRecvPacket(packet, []commitment.Proof{proofPacket}, uint64(proofHeight), testAddr1) - res = transfer.HandleMsgRecvPacket(suite.ctx, suite.app.IBCKeeper.TransferKeeper, msg) - suite.False(res.Code.IsOK(), "%v", res) // invalid packet data + res, err = transfer.HandleMsgRecvPacket(suite.ctx, suite.app.IBCKeeper.TransferKeeper, msg) + suite.Require().Error(err) + suite.Require().Nil(res, "%v", res) // invalid packet data // test when the source is true source := true @@ -228,8 +236,9 @@ func (suite *HandlerTestSuite) TestHandleRecvPacket() { proofPacket, proofHeight = suite.queryProof(packetCommitmentPath) msg = types.NewMsgRecvPacket(packet, []commitment.Proof{proofPacket}, uint64(proofHeight), testAddr1) - res = transfer.HandleMsgRecvPacket(suite.ctx, suite.app.IBCKeeper.TransferKeeper, msg) - suite.False(res.Code.IsOK(), "%v", res) // invalid denom prefix + res, err = transfer.HandleMsgRecvPacket(suite.ctx, suite.app.IBCKeeper.TransferKeeper, msg) + suite.Require().Error(err) + suite.Require().Nil(res, "%v", res) // invalid denom prefix packetData = types.NewPacketData(testPrefixedCoins1, testAddr1, testAddr2, source) packetDataBz, _ = suite.cdc.MarshalBinaryBare(packetData) @@ -240,8 +249,9 @@ func (suite *HandlerTestSuite) TestHandleRecvPacket() { proofPacket, proofHeight = suite.queryProof(packetCommitmentPath) msg = types.NewMsgRecvPacket(packet, []commitment.Proof{proofPacket}, uint64(proofHeight), testAddr1) - res = transfer.HandleMsgRecvPacket(suite.ctx, suite.app.IBCKeeper.TransferKeeper, msg) - suite.True(res.Code.IsOK(), "%v", res) // successfully executed + res, err = transfer.HandleMsgRecvPacket(suite.ctx, suite.app.IBCKeeper.TransferKeeper, msg) + suite.Require().NoError(err) + suite.Require().NotNil(res, "%v", res) // successfully executed // test when the source is false source = false @@ -255,8 +265,9 @@ func (suite *HandlerTestSuite) TestHandleRecvPacket() { proofPacket, proofHeight = suite.queryProof(packetCommitmentPath) msg = types.NewMsgRecvPacket(packet, []commitment.Proof{proofPacket}, uint64(proofHeight), testAddr1) - res = transfer.HandleMsgRecvPacket(suite.ctx, suite.app.IBCKeeper.TransferKeeper, msg) - suite.False(res.Code.IsOK(), "%v", res) // invalid denom prefix + res, err = transfer.HandleMsgRecvPacket(suite.ctx, suite.app.IBCKeeper.TransferKeeper, msg) + suite.Require().Error(err) + suite.Require().Nil(res, "%v", res) // invalid denom prefix packetData = types.NewPacketData(testPrefixedCoins2, testAddr1, testAddr2, source) packetDataBz, _ = suite.cdc.MarshalBinaryBare(packetData) @@ -267,13 +278,15 @@ func (suite *HandlerTestSuite) TestHandleRecvPacket() { proofPacket, proofHeight = suite.queryProof(packetCommitmentPath) msg = types.NewMsgRecvPacket(packet, []commitment.Proof{proofPacket}, uint64(proofHeight), testAddr1) - res = transfer.HandleMsgRecvPacket(suite.ctx, suite.app.IBCKeeper.TransferKeeper, msg) - suite.False(res.Code.IsOK(), "%v", res) // insufficient coins in the corresponding escrow account + res, err = transfer.HandleMsgRecvPacket(suite.ctx, suite.app.IBCKeeper.TransferKeeper, msg) + suite.Require().Error(err) + suite.Require().Nil(res, "%v", res) // insufficient coins in the corresponding escrow account escrowAddress := types.GetEscrowAddress(testPort1, testChannel1) _ = suite.app.BankKeeper.SetCoins(suite.ctx, escrowAddress, testCoins) - res = transfer.HandleMsgRecvPacket(suite.ctx, suite.app.IBCKeeper.TransferKeeper, msg) - suite.True(res.Code.IsOK(), "%v", res) // successfully executed + res, err = transfer.HandleMsgRecvPacket(suite.ctx, suite.app.IBCKeeper.TransferKeeper, msg) + suite.Require().NoError(err) + suite.Require().NotNil(res, "%v", res) // successfully executed } func TestHandlerTestSuite(t *testing.T) { diff --git a/x/ibc/20-transfer/keeper/callbacks.go b/x/ibc/20-transfer/keeper/callbacks.go index 57c772e67b2f..b4c0675bed78 100644 --- a/x/ibc/20-transfer/keeper/callbacks.go +++ b/x/ibc/20-transfer/keeper/callbacks.go @@ -1,7 +1,6 @@ package keeper import ( - "fmt" "strings" sdk "github.com/cosmos/cosmos-sdk/types" @@ -24,18 +23,19 @@ func (k Keeper) OnChanOpenInit( version string, ) error { if order != channel.UNORDERED { - return channel.ErrInvalidChannel(k.codespace, "channel must be UNORDERED") + return sdkerrors.Wrap(channel.ErrInvalidChannel, "channel must be UNORDERED") } // NOTE: here the capability key name defines the port ID of the counterparty if counterparty.PortID != k.boundedCapability.Name() { - return port.ErrInvalidPort( - k.codespace, - fmt.Sprintf("counterparty port ID doesn't match the capability key (%s ≠ %s)", counterparty.PortID, k.boundedCapability.Name())) + return sdkerrors.Wrapf( + port.ErrInvalidPort, + "counterparty port ID doesn't match the capability key (%s ≠ %s)", counterparty.PortID, k.boundedCapability.Name(), + ) } if strings.TrimSpace(version) != "" { - return ibctypes.ErrInvalidVersion(k.codespace, "version must be blank") + return sdkerrors.Wrap(ibctypes.ErrInvalidVersion, "version must be blank") } // NOTE: as the escrow address is generated from both the port and channel IDs @@ -55,22 +55,23 @@ func (k Keeper) OnChanOpenTry( counterpartyVersion string, ) error { if order != channel.UNORDERED { - return channel.ErrInvalidChannel(k.codespace, "channel must be UNORDERED") + return sdkerrors.Wrap(channel.ErrInvalidChannel, "channel must be UNORDERED") } // NOTE: here the capability key name defines the port ID of the counterparty if counterparty.PortID != k.boundedCapability.Name() { - return port.ErrInvalidPort( - k.codespace, - fmt.Sprintf("counterparty port ID doesn't match the capability key (%s ≠ %s)", counterparty.PortID, k.boundedCapability.Name())) + return sdkerrors.Wrapf( + port.ErrInvalidPort, + "counterparty port ID doesn't match the capability key (%s ≠ %s)", counterparty.PortID, k.boundedCapability.Name(), + ) } if strings.TrimSpace(version) != "" { - return ibctypes.ErrInvalidVersion(k.codespace, "version must be blank") + return sdkerrors.Wrap(ibctypes.ErrInvalidVersion, "version must be blank") } if strings.TrimSpace(counterpartyVersion) != "" { - return ibctypes.ErrInvalidVersion(k.codespace, "counterparty version must be blank") + return sdkerrors.Wrap(ibctypes.ErrInvalidVersion, "counterparty version must be blank") } // NOTE: as the escrow address is generated from both the port and channel IDs @@ -86,7 +87,7 @@ func (k Keeper) OnChanOpenAck( version string, ) error { if strings.TrimSpace(version) != "" { - return ibctypes.ErrInvalidVersion(k.codespace, "version must be blank") + return sdkerrors.Wrap(ibctypes.ErrInvalidVersion, "version must be blank") } return nil @@ -169,7 +170,10 @@ func (k Keeper) OnTimeoutPacket( for i, coin := range data.Amount { coin := coin if !strings.HasPrefix(coin.Denom, prefix) { - return sdk.ErrInvalidCoins(fmt.Sprintf("%s doesn't contain the prefix '%s'", coin.Denom, prefix)) + return sdkerrors.Wrapf( + sdkerrors.ErrInvalidCoins, + "%s doesn't contain the prefix '%s'", coin.Denom, prefix, + ) } coins[i] = sdk.NewCoin(coin.Denom[len(prefix):], coin.Amount) } diff --git a/x/ibc/20-transfer/keeper/keeper.go b/x/ibc/20-transfer/keeper/keeper.go index c42786f42741..341f75374881 100644 --- a/x/ibc/20-transfer/keeper/keeper.go +++ b/x/ibc/20-transfer/keeper/keeper.go @@ -19,9 +19,8 @@ const ( // Keeper defines the IBC transfer keeper type Keeper struct { - storeKey sdk.StoreKey - cdc *codec.Codec - codespace sdk.CodespaceType + storeKey sdk.StoreKey + cdc *codec.Codec // Capability key and port to which ICS20 is binded. Used for packet relaying. boundedCapability sdk.CapabilityKey @@ -35,7 +34,7 @@ type Keeper struct { // NewKeeper creates a new IBC transfer Keeper instance func NewKeeper( - cdc *codec.Codec, key sdk.StoreKey, codespace sdk.CodespaceType, + cdc *codec.Codec, key sdk.StoreKey, capKey sdk.CapabilityKey, clientKeeper types.ClientKeeper, connnectionKeeper types.ConnectionKeeper, channelKeeper types.ChannelKeeper, bankKeeper types.BankKeeper, supplyKeeper types.SupplyKeeper, @@ -49,7 +48,6 @@ func NewKeeper( return Keeper{ storeKey: key, cdc: cdc, - codespace: sdk.CodespaceType(fmt.Sprintf("%s/%s", codespace, types.DefaultCodespace)), // "ibc/transfer", boundedCapability: capKey, clientKeeper: clientKeeper, connectionKeeper: connnectionKeeper, diff --git a/x/ibc/20-transfer/keeper/relay.go b/x/ibc/20-transfer/keeper/relay.go index 8c3a6bb2ea5b..f30d59de04fb 100644 --- a/x/ibc/20-transfer/keeper/relay.go +++ b/x/ibc/20-transfer/keeper/relay.go @@ -1,7 +1,6 @@ package keeper import ( - "fmt" "strings" sdk "github.com/cosmos/cosmos-sdk/types" @@ -25,7 +24,7 @@ func (k Keeper) SendTransfer( // get the port and channel of the counterparty sourceChan, found := k.channelKeeper.GetChannel(ctx, sourcePort, sourceChannel) if !found { - return channel.ErrChannelNotFound(k.codespace, sourcePort, sourceChannel) + return sdkerrors.Wrap(channel.ErrChannelNotFound, sourceChannel) } destinationPort := sourceChan.Counterparty.PortID @@ -34,7 +33,7 @@ func (k Keeper) SendTransfer( // get the next sequence sequence, found := k.channelKeeper.GetNextSequenceSend(ctx, sourcePort, sourceChannel) if !found { - return channel.ErrSequenceNotFound(k.codespace, "send") + return channel.ErrSequenceSendNotFound } coins := make(sdk.Coins, len(amount)) @@ -81,7 +80,10 @@ func (k Keeper) ReceiveTransfer( prefix := types.GetDenomPrefix(destinationPort, destinationChannel) for _, coin := range data.Amount { if !strings.HasPrefix(coin.Denom, prefix) { - return sdk.ErrInvalidCoins(fmt.Sprintf("%s doesn't contain the prefix '%s'", coin.Denom, prefix)) + return sdkerrors.Wrapf( + sdkerrors.ErrInvalidCoins, + "%s doesn't contain the prefix '%s'", coin.Denom, prefix, + ) } } @@ -102,7 +104,10 @@ func (k Keeper) ReceiveTransfer( coins := make(sdk.Coins, len(data.Amount)) for i, coin := range data.Amount { if !strings.HasPrefix(coin.Denom, prefix) { - return sdk.ErrInvalidCoins(fmt.Sprintf("%s doesn't contain the prefix '%s'", coin.Denom, prefix)) + return sdkerrors.Wrapf( + sdkerrors.ErrInvalidCoins, + "%s doesn't contain the prefix '%s'", coin.Denom, prefix, + ) } coins[i] = sdk.NewCoin(coin.Denom[len(prefix):], coin.Amount) } @@ -132,7 +137,10 @@ func (k Keeper) createOutgoingPacket( coins := make(sdk.Coins, len(amount)) for i, coin := range amount { if !strings.HasPrefix(coin.Denom, prefix) { - return sdk.ErrInvalidCoins(fmt.Sprintf("%s doesn't contain the prefix '%s'", coin.Denom, prefix)) + return sdkerrors.Wrapf( + sdkerrors.ErrInvalidCoins, + "%s doesn't contain the prefix '%s'", coin.Denom, prefix, + ) } coins[i] = sdk.NewCoin(coin.Denom[len(prefix):], coin.Amount) } @@ -147,7 +155,10 @@ func (k Keeper) createOutgoingPacket( prefix := types.GetDenomPrefix(sourcePort, sourceChannel) for _, coin := range amount { if !strings.HasPrefix(coin.Denom, prefix) { - return sdk.ErrInvalidCoins(fmt.Sprintf("%s doesn't contain the prefix '%s'", coin.Denom, prefix)) + return sdkerrors.Wrapf( + sdkerrors.ErrInvalidCoins, + "%s doesn't contain the prefix '%s'", coin.Denom, prefix, + ) } } diff --git a/x/ibc/20-transfer/types/expected_keepers.go b/x/ibc/20-transfer/types/expected_keepers.go index 252eb8060645..e7c709306228 100644 --- a/x/ibc/20-transfer/types/expected_keepers.go +++ b/x/ibc/20-transfer/types/expected_keepers.go @@ -12,7 +12,7 @@ import ( // BankKeeper defines the expected bank keeper type BankKeeper interface { - SendCoins(ctx sdk.Context, fromAddr sdk.AccAddress, toAddr sdk.AccAddress, amt sdk.Coins) sdk.Error + SendCoins(ctx sdk.Context, fromAddr sdk.AccAddress, toAddr sdk.AccAddress, amt sdk.Coins) error } // ChannelKeeper defines the expected IBC channel keeper @@ -37,8 +37,8 @@ type ConnectionKeeper interface { type SupplyKeeper interface { GetModuleAddress(name string) sdk.AccAddress GetModuleAccount(ctx sdk.Context, name string) supplyexported.ModuleAccountI - MintCoins(ctx sdk.Context, moduleName string, amt sdk.Coins) sdk.Error - BurnCoins(ctx sdk.Context, moduleName string, amt sdk.Coins) sdk.Error - SendCoinsFromModuleToAccount(ctx sdk.Context, senderModule string, recipientAddr sdk.AccAddress, amt sdk.Coins) sdk.Error - SendCoinsFromAccountToModule(ctx sdk.Context, senderAddr sdk.AccAddress, recipientModule string, amt sdk.Coins) sdk.Error + MintCoins(ctx sdk.Context, moduleName string, amt sdk.Coins) error + BurnCoins(ctx sdk.Context, moduleName string, amt sdk.Coins) error + SendCoinsFromModuleToAccount(ctx sdk.Context, senderModule string, recipientAddr sdk.AccAddress, amt sdk.Coins) error + SendCoinsFromAccountToModule(ctx sdk.Context, senderAddr sdk.AccAddress, recipientModule string, amt sdk.Coins) error } diff --git a/x/ibc/20-transfer/types/keys.go b/x/ibc/20-transfer/types/keys.go index 469456bbd946..1a3a8458ae53 100644 --- a/x/ibc/20-transfer/types/keys.go +++ b/x/ibc/20-transfer/types/keys.go @@ -21,9 +21,6 @@ const ( // QuerierRoute is the querier route for IBC transfer QuerierRoute = SubModuleName - - // DefaultCodespace is the default error codespace for the ibc transfers - DefaultCodespace sdk.CodespaceType = SubModuleName ) // GetEscrowAddress returns the escrow address for the specified channel diff --git a/x/ibc/20-transfer/types/msgs.go b/x/ibc/20-transfer/types/msgs.go index 2a353de56cff..42a56e0f30a6 100644 --- a/x/ibc/20-transfer/types/msgs.go +++ b/x/ibc/20-transfer/types/msgs.go @@ -3,7 +3,6 @@ package types import ( sdk "github.com/cosmos/cosmos-sdk/types" sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" - connectiontypes "github.com/cosmos/cosmos-sdk/x/ibc/03-connection/types" channelexported "github.com/cosmos/cosmos-sdk/x/ibc/04-channel/exported" commitment "github.com/cosmos/cosmos-sdk/x/ibc/23-commitment" host "github.com/cosmos/cosmos-sdk/x/ibc/24-host" @@ -44,24 +43,24 @@ func (MsgTransfer) Type() string { } // ValidateBasic implements sdk.Msg -func (msg MsgTransfer) ValidateBasic() sdk.Error { +func (msg MsgTransfer) ValidateBasic() error { if err := host.DefaultPortIdentifierValidator(msg.SourcePort); err != nil { - return sdk.ConvertError(sdkerrors.Wrap(err, "invalid source port ID")) + return sdkerrors.Wrap(err, "invalid source port ID") } if err := host.DefaultChannelIdentifierValidator(msg.SourceChannel); err != nil { - return sdk.ConvertError(sdkerrors.Wrap(err, "invalid source channel ID")) + return sdkerrors.Wrap(err, "invalid source channel ID") } if !msg.Amount.IsAllPositive() { - return sdk.ErrInsufficientCoins("transfer amount must be positive") + return sdkerrors.ErrInsufficientFunds } if !msg.Amount.IsValid() { - return sdk.ErrInvalidCoins("transfer amount is invalid") + return sdkerrors.ErrInvalidCoins } if msg.Sender.Empty() { - return sdk.ErrInvalidAddress("missing sender address") + return sdkerrors.Wrap(sdkerrors.ErrInvalidAddress, "missing sender address") } if msg.Receiver.Empty() { - return sdk.ErrInvalidAddress("missing recipient address") + return sdkerrors.Wrap(sdkerrors.ErrInvalidAddress, "missing recipient address") } return nil } @@ -104,26 +103,22 @@ func (MsgRecvPacket) Type() string { } // ValidateBasic implements sdk.Msg -func (msg MsgRecvPacket) ValidateBasic() sdk.Error { +func (msg MsgRecvPacket) ValidateBasic() error { if msg.Height == 0 { - return sdk.ConvertError(connectiontypes.ErrInvalidHeight(DefaultCodespace, "height must be > 0")) + return sdkerrors.Wrap(ibctypes.ErrInvalidHeight, "height must be > 0") } - if msg.Proofs == nil || len(msg.Proofs) == 0 { - return sdk.ConvertError(ibctypes.ErrInvalidProof(DefaultCodespace, "missing proofs")) + return sdkerrors.Wrap(commitment.ErrInvalidProof, "missing proof") } - for _, proof := range msg.Proofs { - if proof.Proof == nil { - return sdk.ConvertError(ibctypes.ErrInvalidProof(DefaultCodespace, "cannot submit an empty proof")) + if err := proof.ValidateBasic(); err != nil { + return err } } - if msg.Signer.Empty() { - return sdk.ErrInvalidAddress("missing signer address") + return sdkerrors.Wrap(sdkerrors.ErrInvalidAddress, "missing sender address") } - - return sdk.ConvertError(msg.Packet.ValidateBasic()) + return msg.Packet.ValidateBasic() } // GetSignBytes implements sdk.Msg diff --git a/x/ibc/20-transfer/types/packet.go b/x/ibc/20-transfer/types/packet.go index f7c79b9be07e..19aed7c60343 100644 --- a/x/ibc/20-transfer/types/packet.go +++ b/x/ibc/20-transfer/types/packet.go @@ -4,6 +4,7 @@ import ( "fmt" sdk "github.com/cosmos/cosmos-sdk/types" + sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" ) // PacketData defines a struct for the packet payload @@ -38,18 +39,18 @@ func (pd PacketData) String() string { } // ValidateBasic performs a basic check of the packet fields -func (pd PacketData) ValidateBasic() sdk.Error { +func (pd PacketData) ValidateBasic() error { if !pd.Amount.IsAllPositive() { - return sdk.ErrInsufficientCoins("transfer amount must be positive") + return sdkerrors.ErrInsufficientFunds } if !pd.Amount.IsValid() { - return sdk.ErrInvalidCoins("transfer amount is invalid") + return sdkerrors.ErrInvalidCoins } if pd.Sender.Empty() { - return sdk.ErrInvalidAddress("missing sender address") + return sdkerrors.Wrap(sdkerrors.ErrInvalidAddress, "missing sender address") } if pd.Receiver.Empty() { - return sdk.ErrInvalidAddress("missing recipient address") + return sdkerrors.Wrap(sdkerrors.ErrInvalidAddress, "missing receiver address") } return nil } diff --git a/x/ibc/23-commitment/errors.go b/x/ibc/23-commitment/errors.go new file mode 100644 index 000000000000..89b2bf0b0ad7 --- /dev/null +++ b/x/ibc/23-commitment/errors.go @@ -0,0 +1,14 @@ +package commitment + +import ( + sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" +) + +// SubModuleName is the error codespace +const SubModuleName string = "ibc/commitment" + +// IBC connection sentinel errors +var ( + ErrInvalidProof = sdkerrors.Register(SubModuleName, 1, "invalid proof") + ErrInvalidPrefix = sdkerrors.Register(SubModuleName, 2, "invalid prefix") +) diff --git a/x/ibc/23-commitment/merkle.go b/x/ibc/23-commitment/merkle.go index 33d84408f997..39a355fc9ce8 100644 --- a/x/ibc/23-commitment/merkle.go +++ b/x/ibc/23-commitment/merkle.go @@ -151,3 +151,11 @@ func (proof Proof) VerifyNonMembership(root RootI, path PathI) bool { err := runtime.VerifyAbsence(proof.Proof, root.GetHash(), path.String()) return err == nil } + +// ValidateBasic checks if the proof is empty. +func (proof Proof) ValidateBasic() error { + if (proof == Proof{}) || proof.Proof == nil { + return ErrInvalidProof + } + return nil +} diff --git a/x/ibc/23-commitment/merkle_test.go b/x/ibc/23-commitment/merkle_test.go index 01dc9f2edcb4..7dcb5cbfd0fc 100644 --- a/x/ibc/23-commitment/merkle_test.go +++ b/x/ibc/23-commitment/merkle_test.go @@ -25,6 +25,8 @@ func (suite *MerkleTestSuite) TestVerifyMembership() { proof := commitment.Proof{ Proof: res.Proof, } + suite.Require().NoError(proof.ValidateBasic()) + suite.Require().Error(commitment.Proof{}.ValidateBasic()) cases := []struct { name string @@ -73,6 +75,7 @@ func (suite *MerkleTestSuite) TestVerifyNonMembership() { proof := commitment.Proof{ Proof: res.Proof, } + suite.Require().NoError(proof.ValidateBasic()) cases := []struct { name string diff --git a/x/ibc/23-commitment/types.go b/x/ibc/23-commitment/types.go index 1b70f4f04d9c..bd2968da88dc 100644 --- a/x/ibc/23-commitment/types.go +++ b/x/ibc/23-commitment/types.go @@ -38,6 +38,8 @@ type ProofI interface { GetCommitmentType() Type VerifyMembership(RootI, PathI, []byte) bool VerifyNonMembership(RootI, PathI) bool + + ValidateBasic() error } // Type defines the type of the commitment diff --git a/x/ibc/24-host/errors.go b/x/ibc/24-host/errors.go index 0ff6ad59d896..26b7919e6cb5 100644 --- a/x/ibc/24-host/errors.go +++ b/x/ibc/24-host/errors.go @@ -1,47 +1,15 @@ package host import ( - "fmt" - - sdk "github.com/cosmos/cosmos-sdk/types" sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" ) // SubModuleName defines the ICS 24 host const SubModuleName = "host" -// Error codes specific to the ibc host submodule -const ( - DefaultCodespace sdk.CodespaceType = SubModuleName - - CodeInvalidID sdk.CodeType = 231 - CodeInvalidPath sdk.CodeType = 232 - CodeInvalidPacket sdk.CodeType = 233 +// IBC client sentinel errors +var ( + ErrInvalidID = sdkerrors.Register(SubModuleName, 1, "invalid identifier") + ErrInvalidPath = sdkerrors.Register(SubModuleName, 2, "invalid path") + ErrInvalidPacket = sdkerrors.Register(SubModuleName, 3, "invalid packet") ) - -// ErrInvalidID returns a typed ABCI error for an invalid identifier -func ErrInvalidID(codespace sdk.CodespaceType, id string) error { - return sdkerrors.New( - string(codespace), - uint32(CodeInvalidID), - fmt.Sprintf("invalid identifier '%s'", id), - ) -} - -// ErrInvalidPath returns a typed ABCI error for an invalid path -func ErrInvalidPath(codespace sdk.CodespaceType, path string) error { - return sdkerrors.New( - string(codespace), - uint32(CodeInvalidPath), - fmt.Sprintf("invalid path '%s'", path), - ) -} - -// ErrInvalidPacket returns a typed ABCI error for an invalid identifier -func ErrInvalidPacket(codespace sdk.CodespaceType, msg string) error { - return sdkerrors.New( - string(codespace), - uint32(CodeInvalidPacket), - fmt.Sprintf("invalid packet: '%s'", msg), - ) -} diff --git a/x/ibc/24-host/validate.go b/x/ibc/24-host/validate.go index f6b3d14751e7..c360abf8616f 100644 --- a/x/ibc/24-host/validate.go +++ b/x/ibc/24-host/validate.go @@ -25,15 +25,15 @@ type ValidateFn func(string) error func defaultIdentifierValidator(id string, min, max int) error { // valid id MUST NOT contain "/" separator if strings.Contains(id, "/") { - return sdkerrors.Wrap(ErrInvalidID(DefaultCodespace, id), "identifier cannot contain separator: /") + return sdkerrors.Wrapf(ErrInvalidID, "identifier %s cannot contain separator '/'", id) } // valid id must be between 10 and 20 characters if len(id) < min || len(id) > max { - return sdkerrors.Wrapf(ErrInvalidID(DefaultCodespace, id), "identifier has invalid length: %d, must be between %d-%d characters", len(id), min, max) + return sdkerrors.Wrapf(ErrInvalidID, "identifier %s has invalid length: %d, must be between %d-%d characters", id, len(id), min, max) } // valid id must contain only lower alphabetic characters if !isAlphaLower(id) { - return sdkerrors.Wrap(ErrInvalidID(DefaultCodespace, id), "identifier must contain only lowercase alphabetic characters") + return sdkerrors.Wrapf(ErrInvalidID, "identifier %s must contain only lowercase alphabetic characters", id) } return nil } @@ -76,7 +76,7 @@ func NewPathValidator(idValidator ValidateFn) ValidateFn { // Each path element must either be valid identifier or alphanumeric err := idValidator(p) if err != nil && !isAlphaNumeric(p) { - return sdkerrors.Wrapf(ErrInvalidPath(DefaultCodespace, path), "path contains invalid identifier or non-alphanumeric path element: %s", p) + return sdkerrors.Wrapf(ErrInvalidPath, "path %s contains invalid identifier or non-alphanumeric path element: %s", path, p) } } return nil @@ -89,13 +89,13 @@ func NewPathValidator(idValidator ValidateFn) ValidateFn { func DefaultPathValidator(path string) error { pathArr := strings.Split(path, "/") if pathArr[0] == path { - return sdkerrors.Wrap(ErrInvalidPath(DefaultCodespace, path), "path doesn't contain any separator '/'") + return sdkerrors.Wrapf(ErrInvalidPath, "path %s doesn't contain any separator '/'", path) } for _, p := range pathArr { // Each path element must be alphanumeric and non-blank if strings.TrimSpace(p) == "" || !isAlphaNumeric(p) { - return sdkerrors.Wrapf(ErrInvalidPath(DefaultCodespace, path), "invalid path element containing non-alphanumeric characters: '%s'", p) + return sdkerrors.Wrapf(ErrInvalidPath, "path %s contains an invalid non-alphanumeric character: '%s'", path, p) } } return nil diff --git a/x/ibc/alias.go b/x/ibc/alias.go index abb2aae3c59a..7c1ad02349e2 100644 --- a/x/ibc/alias.go +++ b/x/ibc/alias.go @@ -12,11 +12,10 @@ import ( ) const ( - ModuleName = types.ModuleName - StoreKey = types.StoreKey - QuerierRoute = types.QuerierRoute - RouterKey = types.RouterKey - DefaultCodespace = types.DefaultCodespace + ModuleName = types.ModuleName + StoreKey = types.StoreKey + QuerierRoute = types.QuerierRoute + RouterKey = types.RouterKey ) var ( diff --git a/x/ibc/client/cli/cli.go b/x/ibc/client/cli/cli.go index 4818d68008d6..cb095b788a52 100644 --- a/x/ibc/client/cli/cli.go +++ b/x/ibc/client/cli/cli.go @@ -4,6 +4,7 @@ import ( "github.com/spf13/cobra" "github.com/cosmos/cosmos-sdk/client" + "github.com/cosmos/cosmos-sdk/client/flags" "github.com/cosmos/cosmos-sdk/codec" ibcclient "github.com/cosmos/cosmos-sdk/x/ibc/02-client" connection "github.com/cosmos/cosmos-sdk/x/ibc/03-connection" @@ -22,7 +23,7 @@ func GetTxCmd(storeKey string, cdc *codec.Codec) *cobra.Command { RunE: client.ValidateCmd, } - ibcTxCmd.AddCommand(client.PostCommands( + ibcTxCmd.AddCommand(flags.PostCommands( ibcclient.GetTxCmd(cdc, storeKey), connection.GetTxCmd(cdc, storeKey), channel.GetTxCmd(cdc, storeKey), @@ -42,7 +43,7 @@ func GetQueryCmd(queryRoute string, cdc *codec.Codec) *cobra.Command { RunE: client.ValidateCmd, } - ibcQueryCmd.AddCommand(client.GetCommands( + ibcQueryCmd.AddCommand(flags.GetCommands( ibcclient.GetQueryCmd(cdc, queryRoute), connection.GetQueryCmd(cdc, queryRoute), channel.GetQueryCmd(cdc, queryRoute), diff --git a/x/ibc/handler.go b/x/ibc/handler.go index 1a1e2d0189be..d7d7262a165e 100644 --- a/x/ibc/handler.go +++ b/x/ibc/handler.go @@ -1,9 +1,8 @@ package ibc import ( - "fmt" - sdk "github.com/cosmos/cosmos-sdk/types" + sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" client "github.com/cosmos/cosmos-sdk/x/ibc/02-client" connection "github.com/cosmos/cosmos-sdk/x/ibc/03-connection" channel "github.com/cosmos/cosmos-sdk/x/ibc/04-channel" @@ -12,7 +11,7 @@ import ( // NewHandler defines the IBC handler func NewHandler(k Keeper) sdk.Handler { - return func(ctx sdk.Context, msg sdk.Msg) sdk.Result { + return func(ctx sdk.Context, msg sdk.Msg) (*sdk.Result, error) { ctx = ctx.WithEventManager(sdk.NewEventManager()) switch msg := msg.(type) { @@ -63,8 +62,7 @@ func NewHandler(k Keeper) sdk.Handler { return transfer.HandleMsgRecvPacket(ctx, k.TransferKeeper, msg) default: - errMsg := fmt.Sprintf("unrecognized IBC message type: %T", msg) - return sdk.ErrUnknownRequest(errMsg).Result() + return nil, sdkerrors.Wrapf(sdkerrors.ErrUnknownRequest, "unrecognized IBC message type: %T", msg) } } } diff --git a/x/ibc/keeper/keeper.go b/x/ibc/keeper/keeper.go index 2c28b5c9dd51..694dae13b9ec 100644 --- a/x/ibc/keeper/keeper.go +++ b/x/ibc/keeper/keeper.go @@ -22,18 +22,18 @@ type Keeper struct { // NewKeeper creates a new ibc Keeper func NewKeeper( - cdc *codec.Codec, key sdk.StoreKey, codespace sdk.CodespaceType, + cdc *codec.Codec, key sdk.StoreKey, bk transfer.BankKeeper, sk transfer.SupplyKeeper, ) Keeper { - clientKeeper := client.NewKeeper(cdc, key, codespace) - connectionKeeper := connection.NewKeeper(cdc, key, codespace, clientKeeper) - portKeeper := port.NewKeeper(cdc, key, codespace) - channelKeeper := channel.NewKeeper(cdc, key, codespace, clientKeeper, connectionKeeper, portKeeper) + clientKeeper := client.NewKeeper(cdc, key) + connectionKeeper := connection.NewKeeper(cdc, key, clientKeeper) + portKeeper := port.NewKeeper(cdc, key) + channelKeeper := channel.NewKeeper(cdc, key, clientKeeper, connectionKeeper, portKeeper) // TODO: move out of IBC keeper. Blocked on ADR15 capKey := portKeeper.BindPort(bank.ModuleName) transferKeeper := transfer.NewKeeper( - cdc, key, codespace, capKey, + cdc, key, capKey, clientKeeper, connectionKeeper, channelKeeper, bk, sk, ) diff --git a/x/ibc/keeper/querier.go b/x/ibc/keeper/querier.go index 02b468cdb031..68447885bbd1 100644 --- a/x/ibc/keeper/querier.go +++ b/x/ibc/keeper/querier.go @@ -12,7 +12,7 @@ import ( // NewQuerier creates a querier for the IBC module func NewQuerier(k Keeper) sdk.Querier { - return func(ctx sdk.Context, path []string, req abci.RequestQuery) ([]byte, sdk.Error) { + return func(ctx sdk.Context, path []string, req abci.RequestQuery) ([]byte, error) { var ( res []byte err error @@ -56,6 +56,6 @@ func NewQuerier(k Keeper) sdk.Querier { err = sdkerrors.Wrapf(sdkerrors.ErrUnknownRequest, "unknown IBC query endpoint") } - return res, sdk.ConvertError(err) + return res, err } } diff --git a/x/ibc/types/errors.go b/x/ibc/types/errors.go index 086851321b6a..5246b3c5a206 100644 --- a/x/ibc/types/errors.go +++ b/x/ibc/types/errors.go @@ -1,33 +1,11 @@ package types import ( - sdk "github.com/cosmos/cosmos-sdk/types" sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" ) -// common IBC error codes -const ( - // DefaultCodespace of the IBC module - DefaultCodespace sdk.CodespaceType = ModuleName - - CodeInvalidProof sdk.CodeType = 234 - CodeInvalidVersion sdk.CodeType = 235 +// ibc module common sentinel errors +var ( + ErrInvalidHeight = sdkerrors.Register(ModuleName, 1, "invalid height") + ErrInvalidVersion = sdkerrors.Register(ModuleName, 2, "invalid version") ) - -// ErrInvalidProof implements sdk.Error -func ErrInvalidProof(codespace sdk.CodespaceType, msg string) error { - return sdkerrors.New( - string(codespace), - uint32(CodeInvalidProof), - msg, - ) -} - -// ErrInvalidVersion implements sdk.Error -func ErrInvalidVersion(codespace sdk.CodespaceType, msg string) error { - return sdkerrors.New( - string(codespace), - uint32(CodeInvalidVersion), - msg, - ) -} diff --git a/x/mint/alias.go b/x/mint/alias.go index 9572d077b458..c6d2330f9a8b 100644 --- a/x/mint/alias.go +++ b/x/mint/alias.go @@ -1,10 +1,7 @@ -// nolint -// autogenerated code using github.com/rigelrozanski/multitool -// aliases generated for the following subdirectories: -// ALIASGEN: github.com/cosmos/cosmos-sdk/x/mint/internal/keeper -// ALIASGEN: github.com/cosmos/cosmos-sdk/x/mint/internal/types package mint +// nolint + import ( "github.com/cosmos/cosmos-sdk/x/mint/internal/keeper" "github.com/cosmos/cosmos-sdk/x/mint/internal/types" diff --git a/x/mint/client/cli/query.go b/x/mint/client/cli/query.go index 3350706362f3..ec37cde40cf6 100644 --- a/x/mint/client/cli/query.go +++ b/x/mint/client/cli/query.go @@ -7,6 +7,7 @@ import ( "github.com/cosmos/cosmos-sdk/client" "github.com/cosmos/cosmos-sdk/client/context" + "github.com/cosmos/cosmos-sdk/client/flags" "github.com/cosmos/cosmos-sdk/codec" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/x/mint/internal/types" @@ -23,7 +24,7 @@ func GetQueryCmd(cdc *codec.Codec) *cobra.Command { } mintingQueryCmd.AddCommand( - client.GetCommands( + flags.GetCommands( GetCmdQueryParams(cdc), GetCmdQueryInflation(cdc), GetCmdQueryAnnualProvisions(cdc), diff --git a/x/mint/internal/keeper/keeper.go b/x/mint/internal/keeper/keeper.go index ff4bd029dfda..3be3146fdf68 100644 --- a/x/mint/internal/keeper/keeper.go +++ b/x/mint/internal/keeper/keeper.go @@ -24,7 +24,8 @@ type Keeper struct { // NewKeeper creates a new mint Keeper instance func NewKeeper( cdc *codec.Codec, key sdk.StoreKey, paramSpace params.Subspace, - sk types.StakingKeeper, supplyKeeper types.SupplyKeeper, feeCollectorName string) Keeper { + sk types.StakingKeeper, supplyKeeper types.SupplyKeeper, feeCollectorName string, +) Keeper { // ensure mint module account is set if addr := supplyKeeper.GetModuleAddress(types.ModuleName); addr == nil { @@ -96,16 +97,17 @@ func (k Keeper) BondedRatio(ctx sdk.Context) sdk.Dec { // MintCoins implements an alias call to the underlying supply keeper's // MintCoins to be used in BeginBlocker. -func (k Keeper) MintCoins(ctx sdk.Context, newCoins sdk.Coins) sdk.Error { +func (k Keeper) MintCoins(ctx sdk.Context, newCoins sdk.Coins) error { if newCoins.Empty() { // skip as no coins need to be minted return nil } + return k.supplyKeeper.MintCoins(ctx, types.ModuleName, newCoins) } // AddCollectedFees implements an alias call to the underlying supply keeper's // AddCollectedFees to be used in BeginBlocker. -func (k Keeper) AddCollectedFees(ctx sdk.Context, fees sdk.Coins) sdk.Error { +func (k Keeper) AddCollectedFees(ctx sdk.Context, fees sdk.Coins) error { return k.supplyKeeper.SendCoinsFromModuleToModule(ctx, types.ModuleName, k.feeCollectorName, fees) } diff --git a/x/mint/internal/keeper/querier.go b/x/mint/internal/keeper/querier.go index fe3943f0896a..258d1b111ed2 100644 --- a/x/mint/internal/keeper/querier.go +++ b/x/mint/internal/keeper/querier.go @@ -1,18 +1,17 @@ package keeper import ( - "fmt" - abci "github.com/tendermint/tendermint/abci/types" "github.com/cosmos/cosmos-sdk/codec" sdk "github.com/cosmos/cosmos-sdk/types" + sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" "github.com/cosmos/cosmos-sdk/x/mint/internal/types" ) // NewQuerier returns a minting Querier handler. func NewQuerier(k Keeper) sdk.Querier { - return func(ctx sdk.Context, path []string, _ abci.RequestQuery) ([]byte, sdk.Error) { + return func(ctx sdk.Context, path []string, _ abci.RequestQuery) ([]byte, error) { switch path[0] { case types.QueryParameters: return queryParams(ctx, k) @@ -24,39 +23,39 @@ func NewQuerier(k Keeper) sdk.Querier { return queryAnnualProvisions(ctx, k) default: - return nil, sdk.ErrUnknownRequest(fmt.Sprintf("unknown minting query endpoint: %s", path[0])) + return nil, sdkerrors.Wrapf(sdkerrors.ErrUnknownRequest, "unknown query path: %s", path[0]) } } } -func queryParams(ctx sdk.Context, k Keeper) ([]byte, sdk.Error) { +func queryParams(ctx sdk.Context, k Keeper) ([]byte, error) { params := k.GetParams(ctx) res, err := codec.MarshalJSONIndent(k.cdc, params) if err != nil { - return nil, sdk.ErrInternal(sdk.AppendMsgToErr("failed to marshal JSON", err.Error())) + return nil, sdkerrors.Wrap(sdkerrors.ErrJSONMarshal, err.Error()) } return res, nil } -func queryInflation(ctx sdk.Context, k Keeper) ([]byte, sdk.Error) { +func queryInflation(ctx sdk.Context, k Keeper) ([]byte, error) { minter := k.GetMinter(ctx) res, err := codec.MarshalJSONIndent(k.cdc, minter.Inflation) if err != nil { - return nil, sdk.ErrInternal(sdk.AppendMsgToErr("failed to marshal JSON", err.Error())) + return nil, sdkerrors.Wrap(sdkerrors.ErrJSONMarshal, err.Error()) } return res, nil } -func queryAnnualProvisions(ctx sdk.Context, k Keeper) ([]byte, sdk.Error) { +func queryAnnualProvisions(ctx sdk.Context, k Keeper) ([]byte, error) { minter := k.GetMinter(ctx) res, err := codec.MarshalJSONIndent(k.cdc, minter.AnnualProvisions) if err != nil { - return nil, sdk.ErrInternal(sdk.AppendMsgToErr("failed to marshal JSON", err.Error())) + return nil, sdkerrors.Wrap(sdkerrors.ErrJSONMarshal, err.Error()) } return res, nil diff --git a/x/mint/internal/types/expected_keepers.go b/x/mint/internal/types/expected_keepers.go index 564a0136b5c7..ea20619164d3 100644 --- a/x/mint/internal/types/expected_keepers.go +++ b/x/mint/internal/types/expected_keepers.go @@ -18,7 +18,7 @@ type SupplyKeeper interface { // TODO remove with genesis 2-phases refactor https://github.com/cosmos/cosmos-sdk/issues/2862 SetModuleAccount(sdk.Context, exported.ModuleAccountI) - SendCoinsFromModuleToAccount(ctx sdk.Context, senderModule string, recipientAddr sdk.AccAddress, amt sdk.Coins) sdk.Error - SendCoinsFromModuleToModule(ctx sdk.Context, senderModule, recipientModule string, amt sdk.Coins) sdk.Error - MintCoins(ctx sdk.Context, name string, amt sdk.Coins) sdk.Error + SendCoinsFromModuleToAccount(ctx sdk.Context, senderModule string, recipientAddr sdk.AccAddress, amt sdk.Coins) error + SendCoinsFromModuleToModule(ctx sdk.Context, senderModule, recipientModule string, amt sdk.Coins) error + MintCoins(ctx sdk.Context, name string, amt sdk.Coins) error } diff --git a/x/mock/app.go b/x/mock/app.go index 1e59e050507b..d0cee9f592af 100644 --- a/x/mock/app.go +++ b/x/mock/app.go @@ -64,7 +64,7 @@ func NewApp() *App { } // define keepers - app.ParamsKeeper = params.NewKeeper(app.Cdc, app.KeyParams, app.TKeyParams, params.DefaultCodespace) + app.ParamsKeeper = params.NewKeeper(app.Cdc, app.KeyParams, app.TKeyParams) app.AccountKeeper = auth.NewAccountKeeper( app.Cdc, diff --git a/x/mock/app_test.go b/x/mock/app_test.go index db5e29522539..95bed4fda085 100644 --- a/x/mock/app_test.go +++ b/x/mock/app_test.go @@ -7,6 +7,7 @@ import ( abci "github.com/tendermint/tendermint/abci/types" sdk "github.com/cosmos/cosmos-sdk/types" + sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" "github.com/cosmos/cosmos-sdk/x/auth" "github.com/cosmos/cosmos-sdk/x/supply/exported" ) @@ -32,18 +33,20 @@ func (tx testMsg) GetMemo() string { return "" } func (tx testMsg) GetSignBytes() []byte { return nil } func (tx testMsg) GetSigners() []sdk.AccAddress { return tx.signers } func (tx testMsg) GetSignatures() []auth.StdSignature { return nil } -func (tx testMsg) ValidateBasic() sdk.Error { +func (tx testMsg) ValidateBasic() error { if tx.positiveNum >= 0 { return nil } - return sdk.ErrTxDecode("positiveNum should be a non-negative integer.") + return sdkerrors.Wrap(sdkerrors.ErrTxDecode, "positiveNum should be a non-negative integer") } // getMockApp returns an initialized mock application. func getMockApp(t *testing.T) *App { mApp := NewApp() - mApp.Router().AddRoute(msgRoute, func(ctx sdk.Context, msg sdk.Msg) (res sdk.Result) { return }) + mApp.Router().AddRoute(msgRoute, func(ctx sdk.Context, msg sdk.Msg) (*sdk.Result, error) { + return &sdk.Result{}, nil + }) require.NoError(t, mApp.CompleteSetup()) return mApp @@ -71,15 +74,16 @@ func TestCheckAndDeliverGenTx(t *testing.T) { // Signing a tx with the wrong privKey should result in an auth error header = abci.Header{Height: mApp.LastBlockHeight() + 1} - res := SignCheckDeliver( + _, _, err := SignCheckDeliver( t, mApp.Cdc, mApp.BaseApp, header, []sdk.Msg{msg}, []uint64{accs[1].GetAccountNumber()}, []uint64{accs[1].GetSequence() + 1}, true, false, privKeys[1], ) // Will fail on SetPubKey decorator - require.Equal(t, sdk.CodeInvalidPubKey, res.Code, res.Log) - require.Equal(t, sdk.CodespaceRoot, res.Codespace) + space, code, log := sdkerrors.ABCIInfo(err, false) + require.Equal(t, sdkerrors.ErrInvalidPubKey.ABCICode(), code, log) + require.Equal(t, sdkerrors.ErrInvalidPubKey.Codespace(), space) // Resigning the tx with the correct privKey should result in an OK result header = abci.Header{Height: mApp.LastBlockHeight() + 1} diff --git a/x/mock/test_utils.go b/x/mock/test_utils.go index 2b5978823363..11073e64f413 100644 --- a/x/mock/test_utils.go +++ b/x/mock/test_utils.go @@ -55,17 +55,19 @@ func CheckBalance(t *testing.T, app *App, addr sdk.AccAddress, exp sdk.Coins) { func CheckGenTx( t *testing.T, app *baseapp.BaseApp, msgs []sdk.Msg, accNums []uint64, seq []uint64, expPass bool, priv ...crypto.PrivKey, -) sdk.Result { +) (sdk.GasInfo, *sdk.Result, error) { tx := GenTx(msgs, accNums, seq, priv...) - res := app.Check(tx) + gInfo, res, err := app.Check(tx) if expPass { - require.Equal(t, sdk.CodeOK, res.Code, res.Log) + require.NoError(t, err) + require.NotNil(t, res) } else { - require.NotEqual(t, sdk.CodeOK, res.Code, res.Log) + require.Error(t, err) + require.Nil(t, res) } - return res + return gInfo, res, err } // SignCheckDeliver checks a generated signed transaction and simulates a @@ -75,7 +77,7 @@ func CheckGenTx( func SignCheckDeliver( t *testing.T, cdc *codec.Codec, app *baseapp.BaseApp, header abci.Header, msgs []sdk.Msg, accNums, seq []uint64, expSimPass, expPass bool, priv ...crypto.PrivKey, -) sdk.Result { +) (sdk.GasInfo, *sdk.Result, error) { tx := GenTx(msgs, accNums, seq, priv...) @@ -83,26 +85,31 @@ func SignCheckDeliver( require.Nil(t, err) // Must simulate now as CheckTx doesn't run Msgs anymore - res := app.Simulate(txBytes, tx) + _, res, err := app.Simulate(txBytes, tx) if expSimPass { - require.Equal(t, sdk.CodeOK, res.Code, res.Log) + require.NoError(t, err) + require.NotNil(t, res) } else { - require.NotEqual(t, sdk.CodeOK, res.Code, res.Log) + require.Error(t, err) + require.Nil(t, res) } // Simulate a sending a transaction and committing a block app.BeginBlock(abci.RequestBeginBlock{Header: header}) - res = app.Deliver(tx) + + gInfo, res, err := app.Deliver(tx) if expPass { - require.Equal(t, sdk.CodeOK, res.Code, res.Log) + require.NoError(t, err) + require.NotNil(t, res) } else { - require.NotEqual(t, sdk.CodeOK, res.Code, res.Log) + require.Error(t, err) + require.Nil(t, res) } app.EndBlock(abci.RequestEndBlock{}) app.Commit() - return res + return gInfo, res, err } diff --git a/x/mock/types.go b/x/mock/types.go index 14ec10772006..56912780dac1 100644 --- a/x/mock/types.go +++ b/x/mock/types.go @@ -4,7 +4,7 @@ import ( "github.com/tendermint/tendermint/crypto" sdk "github.com/cosmos/cosmos-sdk/types" - + sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" "github.com/cosmos/cosmos-sdk/x/auth" "github.com/cosmos/cosmos-sdk/x/supply" "github.com/cosmos/cosmos-sdk/x/supply/exported" @@ -22,24 +22,23 @@ func NewDummySupplyKeeper(ak auth.AccountKeeper) DummySupplyKeeper { } // SendCoinsFromAccountToModule for the dummy supply keeper -func (sk DummySupplyKeeper) SendCoinsFromAccountToModule(ctx sdk.Context, fromAddr sdk.AccAddress, recipientModule string, amt sdk.Coins) sdk.Error { - +func (sk DummySupplyKeeper) SendCoinsFromAccountToModule(ctx sdk.Context, fromAddr sdk.AccAddress, recipientModule string, amt sdk.Coins) error { fromAcc := sk.ak.GetAccount(ctx, fromAddr) moduleAcc := sk.GetModuleAccount(ctx, recipientModule) newFromCoins, hasNeg := fromAcc.GetCoins().SafeSub(amt) if hasNeg { - return sdk.ErrInsufficientCoins(fromAcc.GetCoins().String()) + return sdkerrors.Wrap(sdkerrors.ErrInsufficientFunds, fromAcc.GetCoins().String()) } newToCoins := moduleAcc.GetCoins().Add(amt) if err := fromAcc.SetCoins(newFromCoins); err != nil { - return sdk.ErrInternal(err.Error()) + return err } if err := moduleAcc.SetCoins(newToCoins); err != nil { - return sdk.ErrInternal(err.Error()) + return err } sk.ak.SetAccount(ctx, fromAcc) diff --git a/x/params/alias.go b/x/params/alias.go index ace601c219dc..1198e93cede3 100644 --- a/x/params/alias.go +++ b/x/params/alias.go @@ -1,10 +1,6 @@ package params // nolint -// autogenerated code using github.com/rigelrozanski/multitool -// aliases generated for the following subdirectories: -// ALIASGEN: github.com/cosmos/cosmos-sdk/x/params/subspace -// ALIASGEN: github.com/cosmos/cosmos-sdk/x/params/types import ( "github.com/cosmos/cosmos-sdk/x/params/subspace" @@ -12,15 +8,11 @@ import ( ) const ( - StoreKey = subspace.StoreKey - TStoreKey = subspace.TStoreKey - DefaultCodespace = types.DefaultCodespace - CodeUnknownSubspace = types.CodeUnknownSubspace - CodeSettingParameter = types.CodeSettingParameter - CodeEmptyData = types.CodeEmptyData - ModuleName = types.ModuleName - RouterKey = types.RouterKey - ProposalTypeChange = types.ProposalTypeChange + StoreKey = subspace.StoreKey + TStoreKey = subspace.TStoreKey + ModuleName = types.ModuleName + RouterKey = types.RouterKey + ProposalTypeChange = types.ProposalTypeChange ) var ( diff --git a/x/params/commmon_test.go b/x/params/commmon_test.go index 5ca01ad98d40..ecebf8eb2e60 100644 --- a/x/params/commmon_test.go +++ b/x/params/commmon_test.go @@ -43,7 +43,7 @@ func testComponents() (*codec.Codec, sdk.Context, sdk.StoreKey, sdk.StoreKey, Ke mkey := sdk.NewKVStoreKey("test") tkey := sdk.NewTransientStoreKey("transient_test") ctx := defaultContext(mkey, tkey) - keeper := NewKeeper(cdc, mkey, tkey, DefaultCodespace) + keeper := NewKeeper(cdc, mkey, tkey) return cdc, ctx, mkey, tkey, keeper } diff --git a/x/params/keeper.go b/x/params/keeper.go index 9e91259df656..c3532f32834f 100644 --- a/x/params/keeper.go +++ b/x/params/keeper.go @@ -13,21 +13,19 @@ import ( // Keeper of the global paramstore type Keeper struct { - cdc *codec.Codec - key sdk.StoreKey - tkey sdk.StoreKey - codespace sdk.CodespaceType - spaces map[string]*Subspace + cdc *codec.Codec + key sdk.StoreKey + tkey sdk.StoreKey + spaces map[string]*Subspace } // NewKeeper constructs a params keeper -func NewKeeper(cdc *codec.Codec, key, tkey sdk.StoreKey, codespace sdk.CodespaceType) Keeper { +func NewKeeper(cdc *codec.Codec, key, tkey sdk.StoreKey) Keeper { return Keeper{ - cdc: cdc, - key: key, - tkey: tkey, - codespace: codespace, - spaces: make(map[string]*Subspace), + cdc: cdc, + key: key, + tkey: tkey, + spaces: make(map[string]*Subspace), } } diff --git a/x/params/proposal_handler.go b/x/params/proposal_handler.go index e2e976454275..339cfd7410ce 100644 --- a/x/params/proposal_handler.go +++ b/x/params/proposal_handler.go @@ -4,28 +4,28 @@ import ( "fmt" sdk "github.com/cosmos/cosmos-sdk/types" + sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" govtypes "github.com/cosmos/cosmos-sdk/x/gov/types" ) // NewParamChangeProposalHandler creates a new governance Handler for a ParamChangeProposal func NewParamChangeProposalHandler(k Keeper) govtypes.Handler { - return func(ctx sdk.Context, content govtypes.Content) sdk.Error { + return func(ctx sdk.Context, content govtypes.Content) error { switch c := content.(type) { case ParameterChangeProposal: return handleParameterChangeProposal(ctx, k, c) default: - errMsg := fmt.Sprintf("unrecognized param proposal content type: %T", c) - return sdk.ErrUnknownRequest(errMsg) + return sdkerrors.Wrapf(sdkerrors.ErrUnknownRequest, "unrecognized param proposal content type: %T", c) } } } -func handleParameterChangeProposal(ctx sdk.Context, k Keeper, p ParameterChangeProposal) sdk.Error { +func handleParameterChangeProposal(ctx sdk.Context, k Keeper, p ParameterChangeProposal) error { for _, c := range p.Changes { ss, ok := k.GetSubspace(c.Subspace) if !ok { - return ErrUnknownSubspace(k.codespace, c.Subspace) + return sdkerrors.Wrap(ErrUnknownSubspace, c.Subspace) } k.Logger(ctx).Info( @@ -33,7 +33,7 @@ func handleParameterChangeProposal(ctx sdk.Context, k Keeper, p ParameterChangeP ) if err := ss.Update(ctx, []byte(c.Key), []byte(c.Value)); err != nil { - return ErrSettingParameter(k.codespace, c.Key, c.Value, err.Error()) + return sdkerrors.Wrapf(ErrSettingParameter, "key: %s, value: %s, err: %s", c.Key, c.Value, err.Error()) } } diff --git a/x/params/proposal_handler_test.go b/x/params/proposal_handler_test.go index 841f832160c5..9d83975c1020 100644 --- a/x/params/proposal_handler_test.go +++ b/x/params/proposal_handler_test.go @@ -74,7 +74,7 @@ func newTestInput(t *testing.T) testInput { err := cms.LoadLatestVersion() require.Nil(t, err) - keeper := params.NewKeeper(cdc, keyParams, tKeyParams, params.DefaultCodespace) + keeper := params.NewKeeper(cdc, keyParams, tKeyParams) ctx := sdk.NewContext(cms, abci.Header{}, false, log.NewNopLogger()) return testInput{ctx, cdc, keeper} diff --git a/x/params/types/errors.go b/x/params/types/errors.go index 12726b0322f5..4b218d9444ee 100644 --- a/x/params/types/errors.go +++ b/x/params/types/errors.go @@ -1,46 +1,15 @@ package types import ( - "fmt" - - sdk "github.com/cosmos/cosmos-sdk/types" + sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" ) -// Param module codespace constants -const ( - DefaultCodespace sdk.CodespaceType = "params" - - CodeUnknownSubspace sdk.CodeType = 1 - CodeSettingParameter sdk.CodeType = 2 - CodeEmptyData sdk.CodeType = 3 +// x/params module sentinel errors +var ( + ErrUnknownSubspace = sdkerrors.Register(ModuleName, 1, "unknown subspace") + ErrSettingParameter = sdkerrors.Register(ModuleName, 2, "failed to set parameter") + ErrEmptyChanges = sdkerrors.Register(ModuleName, 3, "submitted parameter changes are empty") + ErrEmptySubspace = sdkerrors.Register(ModuleName, 4, "parameter subspace is empty") + ErrEmptyKey = sdkerrors.Register(ModuleName, 5, "parameter key is empty") + ErrEmptyValue = sdkerrors.Register(ModuleName, 6, "parameter value is empty") ) - -// ErrUnknownSubspace returns an unknown subspace error. -func ErrUnknownSubspace(codespace sdk.CodespaceType, space string) sdk.Error { - return sdk.NewError(codespace, CodeUnknownSubspace, fmt.Sprintf("unknown subspace %s", space)) -} - -// ErrSettingParameter returns an error for failing to set a parameter. -func ErrSettingParameter(codespace sdk.CodespaceType, key, value, msg string) sdk.Error { - return sdk.NewError(codespace, CodeSettingParameter, fmt.Sprintf("error setting parameter %s on %s: %s", value, key, msg)) -} - -// ErrEmptyChanges returns an error for empty parameter changes. -func ErrEmptyChanges(codespace sdk.CodespaceType) sdk.Error { - return sdk.NewError(codespace, CodeEmptyData, "submitted parameter changes are empty") -} - -// ErrEmptySubspace returns an error for an empty subspace. -func ErrEmptySubspace(codespace sdk.CodespaceType) sdk.Error { - return sdk.NewError(codespace, CodeEmptyData, "parameter subspace is empty") -} - -// ErrEmptyKey returns an error for when an empty key is given. -func ErrEmptyKey(codespace sdk.CodespaceType) sdk.Error { - return sdk.NewError(codespace, CodeEmptyData, "parameter key is empty") -} - -// ErrEmptyValue returns an error for when an empty key is given. -func ErrEmptyValue(codespace sdk.CodespaceType) sdk.Error { - return sdk.NewError(codespace, CodeEmptyData, "parameter value is empty") -} diff --git a/x/params/types/proposal.go b/x/params/types/proposal.go index a4bcefab2df6..78f200d143e9 100644 --- a/x/params/types/proposal.go +++ b/x/params/types/proposal.go @@ -4,7 +4,6 @@ import ( "fmt" "strings" - sdk "github.com/cosmos/cosmos-sdk/types" govtypes "github.com/cosmos/cosmos-sdk/x/gov/types" ) @@ -46,8 +45,8 @@ func (pcp ParameterChangeProposal) ProposalRoute() string { return RouterKey } func (pcp ParameterChangeProposal) ProposalType() string { return ProposalTypeChange } // ValidateBasic validates the parameter change proposal -func (pcp ParameterChangeProposal) ValidateBasic() sdk.Error { - err := govtypes.ValidateAbstract(DefaultCodespace, pcp) +func (pcp ParameterChangeProposal) ValidateBasic() error { + err := govtypes.ValidateAbstract(pcp) if err != nil { return err } @@ -98,20 +97,20 @@ func (pc ParamChange) String() string { // ValidateChanges performs basic validation checks over a set of ParamChange. It // returns an error if any ParamChange is invalid. -func ValidateChanges(changes []ParamChange) sdk.Error { +func ValidateChanges(changes []ParamChange) error { if len(changes) == 0 { - return ErrEmptyChanges(DefaultCodespace) + return ErrEmptyChanges } for _, pc := range changes { if len(pc.Subspace) == 0 { - return ErrEmptySubspace(DefaultCodespace) + return ErrEmptySubspace } if len(pc.Key) == 0 { - return ErrEmptyKey(DefaultCodespace) + return ErrEmptyKey } if len(pc.Value) == 0 { - return ErrEmptyValue(DefaultCodespace) + return ErrEmptyValue } } diff --git a/x/slashing/abci_test.go b/x/slashing/abci_test.go index 84d36c6ee083..bcd1ee7ce8a2 100644 --- a/x/slashing/abci_test.go +++ b/x/slashing/abci_test.go @@ -20,8 +20,10 @@ func TestBeginBlocker(t *testing.T) { addr, pk := slashingkeeper.Addrs[2], slashingkeeper.Pks[2] // bond the validator - got := staking.NewHandler(sk)(ctx, slashingkeeper.NewTestMsgCreateValidator(addr, pk, amt)) - require.True(t, got.IsOK()) + res, err := staking.NewHandler(sk)(ctx, slashingkeeper.NewTestMsgCreateValidator(addr, pk, amt)) + require.NoError(t, err) + require.NotNil(t, res) + staking.EndBlocker(ctx, sk) require.Equal( t, ck.GetCoins(ctx, sdk.AccAddress(addr)), diff --git a/x/slashing/alias.go b/x/slashing/alias.go index 677228182c0d..38d556a6e492 100644 --- a/x/slashing/alias.go +++ b/x/slashing/alias.go @@ -1,23 +1,13 @@ -// nolint -// autogenerated code using github.com/rigelrozanski/multitool -// aliases generated for the following subdirectories: -// ALIASGEN: github.com/cosmos/cosmos-sdk/x/slashing/internal/keeper -// ALIASGEN: github.com/cosmos/cosmos-sdk/x/slashing/internal/types package slashing +// nolint + import ( "github.com/cosmos/cosmos-sdk/x/slashing/internal/keeper" "github.com/cosmos/cosmos-sdk/x/slashing/internal/types" ) const ( - DefaultCodespace = types.DefaultCodespace - CodeInvalidValidator = types.CodeInvalidValidator - CodeValidatorJailed = types.CodeValidatorJailed - CodeValidatorNotJailed = types.CodeValidatorNotJailed - CodeMissingSelfDelegation = types.CodeMissingSelfDelegation - CodeSelfDelegationTooLow = types.CodeSelfDelegationTooLow - CodeMissingSigningInfo = types.CodeMissingSigningInfo ModuleName = types.ModuleName StoreKey = types.StoreKey RouterKey = types.RouterKey @@ -89,7 +79,6 @@ var ( type ( Hooks = keeper.Hooks Keeper = keeper.Keeper - CodeType = types.CodeType GenesisState = types.GenesisState MissedBlock = types.MissedBlock MsgUnjail = types.MsgUnjail diff --git a/x/slashing/app_test.go b/x/slashing/app_test.go index 8704333b75b8..23dd43e590bf 100644 --- a/x/slashing/app_test.go +++ b/x/slashing/app_test.go @@ -3,6 +3,7 @@ package slashing import ( + "errors" "testing" "github.com/stretchr/testify/require" @@ -47,15 +48,15 @@ func getMockApp(t *testing.T) (*mock.App, staking.Keeper, Keeper) { blacklistedAddrs[notBondedPool.GetAddress().String()] = true blacklistedAddrs[bondPool.GetAddress().String()] = true - bankKeeper := bank.NewBaseKeeper(mapp.AccountKeeper, mapp.ParamsKeeper.Subspace(bank.DefaultParamspace), bank.DefaultCodespace, blacklistedAddrs) + bankKeeper := bank.NewBaseKeeper(mapp.AccountKeeper, mapp.ParamsKeeper.Subspace(bank.DefaultParamspace), blacklistedAddrs) maccPerms := map[string][]string{ auth.FeeCollectorName: nil, staking.NotBondedPoolName: {supply.Burner, supply.Staking}, staking.BondedPoolName: {supply.Burner, supply.Staking}, } supplyKeeper := supply.NewKeeper(mapp.Cdc, keySupply, mapp.AccountKeeper, bankKeeper, maccPerms) - stakingKeeper := staking.NewKeeper(mapp.Cdc, keyStaking, supplyKeeper, mapp.ParamsKeeper.Subspace(staking.DefaultParamspace), staking.DefaultCodespace) - keeper := NewKeeper(mapp.Cdc, keySlashing, stakingKeeper, mapp.ParamsKeeper.Subspace(DefaultParamspace), DefaultCodespace) + stakingKeeper := staking.NewKeeper(mapp.Cdc, keyStaking, supplyKeeper, mapp.ParamsKeeper.Subspace(staking.DefaultParamspace)) + keeper := NewKeeper(mapp.Cdc, keySlashing, stakingKeeper, mapp.ParamsKeeper.Subspace(DefaultParamspace)) mapp.Router().AddRoute(staking.RouterKey, staking.NewHandler(stakingKeeper)) mapp.Router().AddRoute(RouterKey, NewHandler(keeper)) @@ -152,7 +153,8 @@ func TestSlashingMsgs(t *testing.T) { // unjail should fail with unknown validator header = abci.Header{Height: mapp.LastBlockHeight() + 1} - res := mock.SignCheckDeliver(t, mapp.Cdc, mapp.BaseApp, header, []sdk.Msg{unjailMsg}, []uint64{0}, []uint64{1}, false, false, priv1) - require.EqualValues(t, CodeValidatorNotJailed, res.Code) - require.EqualValues(t, DefaultCodespace, res.Codespace) + _, res, err := mock.SignCheckDeliver(t, mapp.Cdc, mapp.BaseApp, header, []sdk.Msg{unjailMsg}, []uint64{0}, []uint64{1}, false, false, priv1) + require.Error(t, err) + require.Nil(t, res) + require.True(t, errors.Is(ErrValidatorNotJailed, err)) } diff --git a/x/slashing/client/cli/query.go b/x/slashing/client/cli/query.go index 836d2bcb1f3d..a5b0cd1be524 100644 --- a/x/slashing/client/cli/query.go +++ b/x/slashing/client/cli/query.go @@ -8,6 +8,7 @@ import ( "github.com/cosmos/cosmos-sdk/client" "github.com/cosmos/cosmos-sdk/client/context" + "github.com/cosmos/cosmos-sdk/client/flags" "github.com/cosmos/cosmos-sdk/codec" sdk "github.com/cosmos/cosmos-sdk/types" @@ -26,7 +27,7 @@ func GetQueryCmd(queryRoute string, cdc *codec.Codec) *cobra.Command { } slashingQueryCmd.AddCommand( - client.GetCommands( + flags.GetCommands( GetCmdQuerySigningInfo(queryRoute, cdc), GetCmdQueryParams(cdc), )..., diff --git a/x/slashing/client/cli/tx.go b/x/slashing/client/cli/tx.go index e6bb0b44e9b8..5aa262568d54 100644 --- a/x/slashing/client/cli/tx.go +++ b/x/slashing/client/cli/tx.go @@ -7,6 +7,7 @@ import ( "github.com/cosmos/cosmos-sdk/client" "github.com/cosmos/cosmos-sdk/client/context" + "github.com/cosmos/cosmos-sdk/client/flags" "github.com/cosmos/cosmos-sdk/codec" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/x/auth" @@ -24,7 +25,7 @@ func GetTxCmd(cdc *codec.Codec) *cobra.Command { RunE: client.ValidateCmd, } - slashingTxCmd.AddCommand(client.PostCommands( + slashingTxCmd.AddCommand(flags.PostCommands( GetCmdUnjail(cdc), )...) diff --git a/x/slashing/handler.go b/x/slashing/handler.go index 3c338d0bc7b2..fe4ef7cb7c2e 100644 --- a/x/slashing/handler.go +++ b/x/slashing/handler.go @@ -1,15 +1,14 @@ package slashing import ( - "fmt" - sdk "github.com/cosmos/cosmos-sdk/types" + sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" "github.com/cosmos/cosmos-sdk/x/slashing/internal/types" ) // NewHandler creates an sdk.Handler for all the slashing type messages func NewHandler(k Keeper) sdk.Handler { - return func(ctx sdk.Context, msg sdk.Msg) sdk.Result { + return func(ctx sdk.Context, msg sdk.Msg) (*sdk.Result, error) { ctx = ctx.WithEventManager(sdk.NewEventManager()) switch msg := msg.(type) { @@ -17,19 +16,17 @@ func NewHandler(k Keeper) sdk.Handler { return handleMsgUnjail(ctx, msg, k) default: - errMsg := fmt.Sprintf("unrecognized slashing message type: %T", msg) - return sdk.ErrUnknownRequest(errMsg).Result() + return nil, sdkerrors.Wrapf(sdkerrors.ErrUnknownRequest, "unrecognized %s message type: %T", ModuleName, msg) } } } // Validators must submit a transaction to unjail itself after // having been jailed (and thus unbonded) for downtime -func handleMsgUnjail(ctx sdk.Context, msg MsgUnjail, k Keeper) sdk.Result { - +func handleMsgUnjail(ctx sdk.Context, msg MsgUnjail, k Keeper) (*sdk.Result, error) { err := k.Unjail(ctx, msg.ValidatorAddr) if err != nil { - return err.Result() + return nil, err } ctx.EventManager().EmitEvent( @@ -40,5 +37,5 @@ func handleMsgUnjail(ctx sdk.Context, msg MsgUnjail, k Keeper) sdk.Result { ), ) - return sdk.Result{Events: ctx.EventManager().Events()} + return &sdk.Result{Events: ctx.EventManager().Events()}, nil } diff --git a/x/slashing/handler_test.go b/x/slashing/handler_test.go index e0d5228326da..a137ff8d0d08 100644 --- a/x/slashing/handler_test.go +++ b/x/slashing/handler_test.go @@ -1,6 +1,7 @@ package slashing import ( + "errors" "strings" "testing" "time" @@ -20,9 +21,12 @@ func TestCannotUnjailUnlessJailed(t *testing.T) { slh := NewHandler(keeper) amt := sdk.TokensFromConsensusPower(100) addr, val := slashingkeeper.Addrs[0], slashingkeeper.Pks[0] + msg := slashingkeeper.NewTestMsgCreateValidator(addr, val, amt) - got := staking.NewHandler(sk)(ctx, msg) - require.True(t, got.IsOK(), "%v", got) + res, err := staking.NewHandler(sk)(ctx, msg) + require.NoError(t, err) + require.NotNil(t, res) + staking.EndBlocker(ctx, sk) require.Equal( @@ -32,10 +36,10 @@ func TestCannotUnjailUnlessJailed(t *testing.T) { require.Equal(t, amt, sk.Validator(ctx, addr).GetBondedTokens()) // assert non-jailed validator can't be unjailed - got = slh(ctx, NewMsgUnjail(addr)) - require.False(t, got.IsOK(), "allowed unjail of non-jailed validator") - require.EqualValues(t, CodeValidatorNotJailed, got.Code) - require.EqualValues(t, DefaultCodespace, got.Codespace) + res, err = slh(ctx, NewMsgUnjail(addr)) + require.Error(t, err) + require.Nil(t, res) + require.True(t, errors.Is(ErrValidatorNotJailed, err)) } func TestCannotUnjailUnlessMeetMinSelfDelegation(t *testing.T) { @@ -46,8 +50,11 @@ func TestCannotUnjailUnlessMeetMinSelfDelegation(t *testing.T) { addr, val, amt := slashingkeeper.Addrs[0], slashingkeeper.Pks[0], sdk.TokensFromConsensusPower(amtInt) msg := slashingkeeper.NewTestMsgCreateValidator(addr, val, amt) msg.MinSelfDelegation = amt - got := staking.NewHandler(sk)(ctx, msg) - require.True(t, got.IsOK()) + + res, err := staking.NewHandler(sk)(ctx, msg) + require.NoError(t, err) + require.NotNil(t, res) + staking.EndBlocker(ctx, sk) require.Equal( @@ -57,15 +64,17 @@ func TestCannotUnjailUnlessMeetMinSelfDelegation(t *testing.T) { unbondAmt := sdk.NewCoin(sk.GetParams(ctx).BondDenom, sdk.OneInt()) undelegateMsg := staking.NewMsgUndelegate(sdk.AccAddress(addr), addr, unbondAmt) - got = staking.NewHandler(sk)(ctx, undelegateMsg) + res, err = staking.NewHandler(sk)(ctx, undelegateMsg) + require.NoError(t, err) + require.NotNil(t, res) require.True(t, sk.Validator(ctx, addr).IsJailed()) // assert non-jailed validator can't be unjailed - got = slh(ctx, NewMsgUnjail(addr)) - require.False(t, got.IsOK(), "allowed unjail of validator with less than MinSelfDelegation") - require.EqualValues(t, CodeValidatorNotJailed, got.Code) - require.EqualValues(t, DefaultCodespace, got.Codespace) + res, err = slh(ctx, NewMsgUnjail(addr)) + require.Error(t, err) + require.Nil(t, res) + require.True(t, errors.Is(ErrSelfDelegationTooLowToUnjail, err)) } func TestJailedValidatorDelegations(t *testing.T) { @@ -80,8 +89,9 @@ func TestJailedValidatorDelegations(t *testing.T) { valAddr, consAddr := slashingkeeper.Addrs[1], sdk.ConsAddress(slashingkeeper.Addrs[0]) msgCreateVal := slashingkeeper.NewTestMsgCreateValidator(valAddr, valPubKey, bondAmount) - got := staking.NewHandler(stakingKeeper)(ctx, msgCreateVal) - require.True(t, got.IsOK(), "expected create validator msg to be ok, got: %v", got) + res, err := staking.NewHandler(stakingKeeper)(ctx, msgCreateVal) + require.NoError(t, err) + require.NotNil(t, res) // end block staking.EndBlocker(ctx, stakingKeeper) @@ -93,17 +103,19 @@ func TestJailedValidatorDelegations(t *testing.T) { // delegate tokens to the validator delAddr := sdk.AccAddress(slashingkeeper.Addrs[2]) msgDelegate := slashingkeeper.NewTestMsgDelegate(delAddr, valAddr, bondAmount) - got = staking.NewHandler(stakingKeeper)(ctx, msgDelegate) - require.True(t, got.IsOK(), "expected delegation to be ok, got %v", got) + res, err = staking.NewHandler(stakingKeeper)(ctx, msgDelegate) + require.NoError(t, err) + require.NotNil(t, res) unbondAmt := sdk.NewCoin(stakingKeeper.GetParams(ctx).BondDenom, bondAmount) // unbond validator total self-delegations (which should jail the validator) msgUndelegate := staking.NewMsgUndelegate(sdk.AccAddress(valAddr), valAddr, unbondAmt) - got = staking.NewHandler(stakingKeeper)(ctx, msgUndelegate) - require.True(t, got.IsOK(), "expected begin unbonding validator msg to be ok, got: %v", got) + res, err = staking.NewHandler(stakingKeeper)(ctx, msgUndelegate) + require.NoError(t, err) + require.NotNil(t, res) - err := stakingKeeper.CompleteUnbonding(ctx, sdk.AccAddress(valAddr), valAddr) + err = stakingKeeper.CompleteUnbonding(ctx, sdk.AccAddress(valAddr), valAddr) require.Nil(t, err, "expected complete unbonding validator to be ok, got: %v", err) // verify validator still exists and is jailed @@ -112,26 +124,30 @@ func TestJailedValidatorDelegations(t *testing.T) { require.True(t, validator.IsJailed()) // verify the validator cannot unjail itself - got = NewHandler(slashingKeeper)(ctx, NewMsgUnjail(valAddr)) - require.False(t, got.IsOK(), "expected jailed validator to not be able to unjail, got: %v", got) + res, err = NewHandler(slashingKeeper)(ctx, NewMsgUnjail(valAddr)) + require.Error(t, err) + require.Nil(t, res) // self-delegate to validator msgSelfDelegate := slashingkeeper.NewTestMsgDelegate(sdk.AccAddress(valAddr), valAddr, bondAmount) - got = staking.NewHandler(stakingKeeper)(ctx, msgSelfDelegate) - require.True(t, got.IsOK(), "expected delegation to not be ok, got %v", got) + res, err = staking.NewHandler(stakingKeeper)(ctx, msgSelfDelegate) + require.NoError(t, err) + require.NotNil(t, res) // verify the validator can now unjail itself - got = NewHandler(slashingKeeper)(ctx, NewMsgUnjail(valAddr)) - require.True(t, got.IsOK(), "expected jailed validator to be able to unjail, got: %v", got) + res, err = NewHandler(slashingKeeper)(ctx, NewMsgUnjail(valAddr)) + require.NoError(t, err) + require.NotNil(t, res) } func TestInvalidMsg(t *testing.T) { k := Keeper{} h := NewHandler(k) - res := h(sdk.NewContext(nil, abci.Header{}, false, nil), sdk.NewTestMsg()) - require.False(t, res.IsOK()) - require.True(t, strings.Contains(res.Log, "unrecognized slashing message type")) + res, err := h(sdk.NewContext(nil, abci.Header{}, false, nil), sdk.NewTestMsg()) + require.Error(t, err) + require.Nil(t, res) + require.True(t, strings.Contains(err.Error(), "unrecognized slashing message type")) } // Test a validator through uptime, downtime, revocation, @@ -145,8 +161,11 @@ func TestHandleAbsentValidator(t *testing.T) { addr, val := slashingkeeper.Addrs[0], slashingkeeper.Pks[0] sh := staking.NewHandler(sk) slh := NewHandler(keeper) - got := sh(ctx, slashingkeeper.NewTestMsgCreateValidator(addr, val, amt)) - require.True(t, got.IsOK()) + + res, err := sh(ctx, slashingkeeper.NewTestMsgCreateValidator(addr, val, amt)) + require.NoError(t, err) + require.NotNil(t, res) + staking.EndBlocker(ctx, sk) require.Equal( @@ -228,13 +247,15 @@ func TestHandleAbsentValidator(t *testing.T) { require.Equal(t, amt.Int64()-slashAmt, validator.GetTokens().Int64()) // unrevocation should fail prior to jail expiration - got = slh(ctx, types.NewMsgUnjail(addr)) - require.False(t, got.IsOK()) + res, err = slh(ctx, types.NewMsgUnjail(addr)) + require.Error(t, err) + require.Nil(t, res) // unrevocation should succeed after jail expiration ctx = ctx.WithBlockHeader(abci.Header{Time: time.Unix(1, 0).Add(keeper.DowntimeJailDuration(ctx))}) - got = slh(ctx, types.NewMsgUnjail(addr)) - require.True(t, got.IsOK()) + res, err = slh(ctx, types.NewMsgUnjail(addr)) + require.NoError(t, err) + require.NotNil(t, res) // end block staking.EndBlocker(ctx, sk) diff --git a/x/slashing/internal/keeper/keeper.go b/x/slashing/internal/keeper/keeper.go index b7a3706369f9..e725519314d1 100644 --- a/x/slashing/internal/keeper/keeper.go +++ b/x/slashing/internal/keeper/keeper.go @@ -17,19 +17,16 @@ type Keeper struct { cdc *codec.Codec sk types.StakingKeeper paramspace types.ParamSubspace - codespace sdk.CodespaceType } // NewKeeper creates a slashing keeper -func NewKeeper(cdc *codec.Codec, key sdk.StoreKey, sk types.StakingKeeper, paramspace types.ParamSubspace, codespace sdk.CodespaceType) Keeper { - keeper := Keeper{ +func NewKeeper(cdc *codec.Codec, key sdk.StoreKey, sk types.StakingKeeper, paramspace types.ParamSubspace) Keeper { + return Keeper{ storeKey: key, cdc: cdc, sk: sk, paramspace: paramspace.WithKeyTable(types.ParamKeyTable()), - codespace: codespace, } - return keeper } // Logger returns a module-specific logger. diff --git a/x/slashing/internal/keeper/keeper_test.go b/x/slashing/internal/keeper/keeper_test.go index 54b77848a043..52eb6b59b77a 100644 --- a/x/slashing/internal/keeper/keeper_test.go +++ b/x/slashing/internal/keeper/keeper_test.go @@ -25,8 +25,10 @@ func TestHandleNewValidator(t *testing.T) { ctx = ctx.WithBlockHeight(keeper.SignedBlocksWindow(ctx) + 1) // Validator created - got := sh(ctx, NewTestMsgCreateValidator(addr, val, amt)) - require.True(t, got.IsOK()) + res, err := sh(ctx, NewTestMsgCreateValidator(addr, val, amt)) + require.NoError(t, err) + require.NotNil(t, res) + staking.EndBlocker(ctx, sk) require.Equal( @@ -65,8 +67,10 @@ func TestHandleAlreadyJailed(t *testing.T) { amt := sdk.TokensFromConsensusPower(power) addr, val := Addrs[0], Pks[0] sh := staking.NewHandler(sk) - got := sh(ctx, NewTestMsgCreateValidator(addr, val, amt)) - require.True(t, got.IsOK()) + res, err := sh(ctx, NewTestMsgCreateValidator(addr, val, amt)) + require.NoError(t, err) + require.NotNil(t, res) + staking.EndBlocker(ctx, sk) // 1000 first blocks OK @@ -119,8 +123,10 @@ func TestValidatorDippingInAndOut(t *testing.T) { addr, val := Addrs[0], Pks[0] consAddr := sdk.ConsAddress(addr) sh := staking.NewHandler(sk) - got := sh(ctx, NewTestMsgCreateValidator(addr, val, amt)) - require.True(t, got.IsOK()) + res, err := sh(ctx, NewTestMsgCreateValidator(addr, val, amt)) + require.NoError(t, err) + require.NotNil(t, res) + staking.EndBlocker(ctx, sk) // 100 first blocks OK @@ -132,8 +138,10 @@ func TestValidatorDippingInAndOut(t *testing.T) { // kick first validator out of validator set newAmt := sdk.TokensFromConsensusPower(101) - got = sh(ctx, NewTestMsgCreateValidator(Addrs[1], Pks[1], newAmt)) - require.True(t, got.IsOK()) + res, err = sh(ctx, NewTestMsgCreateValidator(Addrs[1], Pks[1], newAmt)) + require.NoError(t, err) + require.NotNil(t, res) + validatorUpdates := staking.EndBlocker(ctx, sk) require.Equal(t, 2, len(validatorUpdates)) validator, _ := sk.GetValidator(ctx, addr) @@ -145,8 +153,10 @@ func TestValidatorDippingInAndOut(t *testing.T) { // validator added back in delTokens := sdk.TokensFromConsensusPower(50) - got = sh(ctx, NewTestMsgDelegate(sdk.AccAddress(Addrs[2]), Addrs[0], delTokens)) - require.True(t, got.IsOK()) + res, err = sh(ctx, NewTestMsgDelegate(sdk.AccAddress(Addrs[2]), Addrs[0], delTokens)) + require.NoError(t, err) + require.NotNil(t, res) + validatorUpdates = staking.EndBlocker(ctx, sk) require.Equal(t, 2, len(validatorUpdates)) validator, _ = sk.GetValidator(ctx, addr) diff --git a/x/slashing/internal/keeper/querier.go b/x/slashing/internal/keeper/querier.go index 4633d8ba50e9..11b365e1ee1b 100644 --- a/x/slashing/internal/keeper/querier.go +++ b/x/slashing/internal/keeper/querier.go @@ -1,70 +1,72 @@ package keeper import ( - "fmt" - abci "github.com/tendermint/tendermint/abci/types" "github.com/cosmos/cosmos-sdk/client" "github.com/cosmos/cosmos-sdk/codec" sdk "github.com/cosmos/cosmos-sdk/types" + sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" "github.com/cosmos/cosmos-sdk/x/slashing/internal/types" ) // NewQuerier creates a new querier for slashing clients. func NewQuerier(k Keeper) sdk.Querier { - return func(ctx sdk.Context, path []string, req abci.RequestQuery) ([]byte, sdk.Error) { + return func(ctx sdk.Context, path []string, req abci.RequestQuery) ([]byte, error) { switch path[0] { case types.QueryParameters: return queryParams(ctx, k) + case types.QuerySigningInfo: return querySigningInfo(ctx, req, k) + case types.QuerySigningInfos: return querySigningInfos(ctx, req, k) + default: - return nil, sdk.ErrUnknownRequest("unknown staking query endpoint") + return nil, sdkerrors.Wrapf(sdkerrors.ErrUnknownRequest, "unknown %s query endpoint: %s", types.ModuleName, path[0]) } } } -func queryParams(ctx sdk.Context, k Keeper) ([]byte, sdk.Error) { +func queryParams(ctx sdk.Context, k Keeper) ([]byte, error) { params := k.GetParams(ctx) res, err := codec.MarshalJSONIndent(types.ModuleCdc, params) if err != nil { - return nil, sdk.ErrInternal(sdk.AppendMsgToErr("failed to marshal JSON", err.Error())) + return nil, sdkerrors.Wrap(sdkerrors.ErrJSONMarshal, err.Error()) } return res, nil } -func querySigningInfo(ctx sdk.Context, req abci.RequestQuery, k Keeper) ([]byte, sdk.Error) { +func querySigningInfo(ctx sdk.Context, req abci.RequestQuery, k Keeper) ([]byte, error) { var params types.QuerySigningInfoParams err := types.ModuleCdc.UnmarshalJSON(req.Data, ¶ms) if err != nil { - return nil, sdk.ErrInternal(fmt.Sprintf("failed to parse params: %s", err)) + return nil, sdkerrors.Wrap(sdkerrors.ErrJSONUnmarshal, err.Error()) } signingInfo, found := k.GetValidatorSigningInfo(ctx, params.ConsAddress) if !found { - return nil, types.ErrNoSigningInfoFound(types.DefaultCodespace, params.ConsAddress) + return nil, sdkerrors.Wrap(types.ErrNoSigningInfoFound, params.ConsAddress.String()) } res, err := codec.MarshalJSONIndent(types.ModuleCdc, signingInfo) if err != nil { - return nil, sdk.ErrInternal(sdk.AppendMsgToErr("failed to JSON marshal result: %s", err.Error())) + return nil, sdkerrors.Wrap(sdkerrors.ErrJSONMarshal, err.Error()) } return res, nil } -func querySigningInfos(ctx sdk.Context, req abci.RequestQuery, k Keeper) ([]byte, sdk.Error) { +func querySigningInfos(ctx sdk.Context, req abci.RequestQuery, k Keeper) ([]byte, error) { var params types.QuerySigningInfosParams err := types.ModuleCdc.UnmarshalJSON(req.Data, ¶ms) if err != nil { - return nil, sdk.ErrInternal(fmt.Sprintf("failed to parse params: %s", err)) + return nil, sdkerrors.Wrap(sdkerrors.ErrJSONUnmarshal, err.Error()) } var signingInfos []types.ValidatorSigningInfo @@ -83,7 +85,7 @@ func querySigningInfos(ctx sdk.Context, req abci.RequestQuery, k Keeper) ([]byte res, err := codec.MarshalJSONIndent(types.ModuleCdc, signingInfos) if err != nil { - return nil, sdk.ErrInternal(sdk.AppendMsgToErr("failed to JSON marshal result: %s", err.Error())) + return nil, sdkerrors.Wrap(sdkerrors.ErrJSONMarshal, err.Error()) } return res, nil diff --git a/x/slashing/internal/keeper/test_common.go b/x/slashing/internal/keeper/test_common.go index 721967ca88c4..eb8870c1d199 100644 --- a/x/slashing/internal/keeper/test_common.go +++ b/x/slashing/internal/keeper/test_common.go @@ -88,10 +88,10 @@ func CreateTestInput(t *testing.T, defaults types.Params) (sdk.Context, bank.Kee blacklistedAddrs[notBondedPool.GetAddress().String()] = true blacklistedAddrs[bondPool.GetAddress().String()] = true - paramsKeeper := params.NewKeeper(cdc, keyParams, tkeyParams, params.DefaultCodespace) + paramsKeeper := params.NewKeeper(cdc, keyParams, tkeyParams) accountKeeper := auth.NewAccountKeeper(cdc, keyAcc, paramsKeeper.Subspace(auth.DefaultParamspace), auth.ProtoBaseAccount) - bk := bank.NewBaseKeeper(accountKeeper, paramsKeeper.Subspace(bank.DefaultParamspace), bank.DefaultCodespace, blacklistedAddrs) + bk := bank.NewBaseKeeper(accountKeeper, paramsKeeper.Subspace(bank.DefaultParamspace), blacklistedAddrs) maccPerms := map[string][]string{ auth.FeeCollectorName: nil, staking.NotBondedPoolName: {supply.Burner, supply.Staking}, @@ -102,7 +102,7 @@ func CreateTestInput(t *testing.T, defaults types.Params) (sdk.Context, bank.Kee totalSupply := sdk.NewCoins(sdk.NewCoin(sdk.DefaultBondDenom, InitTokens.MulRaw(int64(len(Addrs))))) supplyKeeper.SetSupply(ctx, supply.NewSupply(totalSupply)) - sk := staking.NewKeeper(cdc, keyStaking, supplyKeeper, paramsKeeper.Subspace(staking.DefaultParamspace), staking.DefaultCodespace) + sk := staking.NewKeeper(cdc, keyStaking, supplyKeeper, paramsKeeper.Subspace(staking.DefaultParamspace)) genesis := staking.DefaultGenesisState() // set module accounts @@ -117,7 +117,7 @@ func CreateTestInput(t *testing.T, defaults types.Params) (sdk.Context, bank.Kee } require.Nil(t, err) paramstore := paramsKeeper.Subspace(types.DefaultParamspace) - keeper := NewKeeper(cdc, keySlashing, &sk, paramstore, types.DefaultCodespace) + keeper := NewKeeper(cdc, keySlashing, &sk, paramstore) keeper.SetParams(ctx, defaults) sk.SetHooks(keeper.Hooks()) diff --git a/x/slashing/internal/keeper/unjail.go b/x/slashing/internal/keeper/unjail.go index 3fdab405eb91..51fda4855382 100644 --- a/x/slashing/internal/keeper/unjail.go +++ b/x/slashing/internal/keeper/unjail.go @@ -7,42 +7,42 @@ import ( // Unjail calls the staking Unjail function to unjail a validator if the // jailed period has concluded -func (k Keeper) Unjail(ctx sdk.Context, validatorAddr sdk.ValAddress) sdk.Error { +func (k Keeper) Unjail(ctx sdk.Context, validatorAddr sdk.ValAddress) error { validator := k.sk.Validator(ctx, validatorAddr) if validator == nil { - return types.ErrNoValidatorForAddress(k.codespace) + return types.ErrNoValidatorForAddress } // cannot be unjailed if no self-delegation exists selfDel := k.sk.Delegation(ctx, sdk.AccAddress(validatorAddr), validatorAddr) if selfDel == nil { - return types.ErrMissingSelfDelegation(k.codespace) + return types.ErrMissingSelfDelegation } if validator.TokensFromShares(selfDel.GetShares()).TruncateInt().LT(validator.GetMinSelfDelegation()) { - return types.ErrSelfDelegationTooLowToUnjail(k.codespace) + return types.ErrSelfDelegationTooLowToUnjail } // cannot be unjailed if not jailed if !validator.IsJailed() { - return types.ErrValidatorNotJailed(k.codespace) + return types.ErrValidatorNotJailed } consAddr := sdk.ConsAddress(validator.GetConsPubKey().Address()) info, found := k.GetValidatorSigningInfo(ctx, consAddr) if !found { - return types.ErrNoValidatorForAddress(k.codespace) + return types.ErrNoValidatorForAddress } // cannot be unjailed if tombstoned if info.Tombstoned { - return types.ErrValidatorJailed(k.codespace) + return types.ErrValidatorJailed } // cannot be unjailed until out of jail if ctx.BlockHeader().Time.Before(info.JailedUntil) { - return types.ErrValidatorJailed(k.codespace) + return types.ErrValidatorJailed } k.sk.Unjail(ctx, consAddr) diff --git a/x/slashing/internal/types/errors.go b/x/slashing/internal/types/errors.go index b00e6e4f94ab..290ed36cad66 100644 --- a/x/slashing/internal/types/errors.go +++ b/x/slashing/internal/types/errors.go @@ -1,53 +1,16 @@ -//nolint package types import ( - "fmt" - - sdk "github.com/cosmos/cosmos-sdk/types" + sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" ) -// DONTCOVER - -// Local code type -type CodeType = sdk.CodeType - -const ( - // Default slashing codespace - DefaultCodespace sdk.CodespaceType = ModuleName - - CodeInvalidValidator CodeType = 101 - CodeValidatorJailed CodeType = 102 - CodeValidatorNotJailed CodeType = 103 - CodeMissingSelfDelegation CodeType = 104 - CodeSelfDelegationTooLow CodeType = 105 - CodeMissingSigningInfo CodeType = 106 +// x/slashing module sentinel errors +var ( + ErrNoValidatorForAddress = sdkerrors.Register(ModuleName, 1, "address is not associated with any known validator") + ErrBadValidatorAddr = sdkerrors.Register(ModuleName, 2, "validator does not exist for that address") + ErrValidatorJailed = sdkerrors.Register(ModuleName, 3, "validator still jailed; cannot be unjailed") + ErrValidatorNotJailed = sdkerrors.Register(ModuleName, 4, "validator not jailed; cannot be unjailed") + ErrMissingSelfDelegation = sdkerrors.Register(ModuleName, 5, "validator has no self-delegation; cannot be unjailed") + ErrSelfDelegationTooLowToUnjail = sdkerrors.Register(ModuleName, 6, "validator's self delegation less than minimum; cannot be unjailed") + ErrNoSigningInfoFound = sdkerrors.Register(ModuleName, 7, "no validator signing info found") ) - -func ErrNoValidatorForAddress(codespace sdk.CodespaceType) sdk.Error { - return sdk.NewError(codespace, CodeInvalidValidator, "that address is not associated with any known validator") -} - -func ErrBadValidatorAddr(codespace sdk.CodespaceType) sdk.Error { - return sdk.NewError(codespace, CodeInvalidValidator, "validator does not exist for that address") -} - -func ErrValidatorJailed(codespace sdk.CodespaceType) sdk.Error { - return sdk.NewError(codespace, CodeValidatorJailed, "validator still jailed, cannot yet be unjailed") -} - -func ErrValidatorNotJailed(codespace sdk.CodespaceType) sdk.Error { - return sdk.NewError(codespace, CodeValidatorNotJailed, "validator not jailed, cannot be unjailed") -} - -func ErrMissingSelfDelegation(codespace sdk.CodespaceType) sdk.Error { - return sdk.NewError(codespace, CodeMissingSelfDelegation, "validator has no self-delegation; cannot be unjailed") -} - -func ErrSelfDelegationTooLowToUnjail(codespace sdk.CodespaceType) sdk.Error { - return sdk.NewError(codespace, CodeValidatorNotJailed, "validator's self delegation less than MinSelfDelegation, cannot be unjailed") -} - -func ErrNoSigningInfoFound(codespace sdk.CodespaceType, consAddr sdk.ConsAddress) sdk.Error { - return sdk.NewError(codespace, CodeMissingSigningInfo, fmt.Sprintf("no signing info found for address: %s", consAddr)) -} diff --git a/x/slashing/internal/types/msg.go b/x/slashing/internal/types/msg.go index 3513d3b6c12b..b2ccdce173ba 100644 --- a/x/slashing/internal/types/msg.go +++ b/x/slashing/internal/types/msg.go @@ -33,9 +33,9 @@ func (msg MsgUnjail) GetSignBytes() []byte { } // ValidateBasic validity check for the AnteHandler -func (msg MsgUnjail) ValidateBasic() sdk.Error { +func (msg MsgUnjail) ValidateBasic() error { if msg.ValidatorAddr.Empty() { - return ErrBadValidatorAddr(DefaultCodespace) + return ErrBadValidatorAddr } return nil } diff --git a/x/slashing/simulation/operations.go b/x/slashing/simulation/operations.go index 3e2a3bc78bad..f5e263b778dc 100644 --- a/x/slashing/simulation/operations.go +++ b/x/slashing/simulation/operations.go @@ -93,7 +93,7 @@ func SimulateMsgUnjail(ak types.AccountKeeper, k keeper.Keeper, sk stakingkeeper simAccount.PrivKey, ) - res := app.Deliver(tx) + _, res, err := app.Deliver(tx) // result should fail if: // - validator cannot be unjailed due to tombstone @@ -102,7 +102,7 @@ func SimulateMsgUnjail(ak types.AccountKeeper, k keeper.Keeper, sk stakingkeeper if info.Tombstoned || ctx.BlockHeader().Time.Before(info.JailedUntil) || validator.TokensFromShares(selfDel.GetShares()).TruncateInt().LT(validator.GetMinSelfDelegation()) { - if res.IsOK() { + if res != nil && err == nil { if info.Tombstoned { return simulation.NewOperationMsg(msg, true, ""), nil, errors.New("validator should not have been unjailed if validator tombstoned") } @@ -117,7 +117,7 @@ func SimulateMsgUnjail(ak types.AccountKeeper, k keeper.Keeper, sk stakingkeeper return simulation.NewOperationMsg(msg, false, ""), nil, nil } - if !res.IsOK() { + if err != nil { return simulation.NoOpMsg(types.ModuleName), nil, errors.New(res.Log) } diff --git a/x/staking/alias.go b/x/staking/alias.go index 887b9b7bf690..51c7eecc7087 100644 --- a/x/staking/alias.go +++ b/x/staking/alias.go @@ -1,11 +1,7 @@ -// nolint -// autogenerated code using github.com/rigelrozanski/multitool -// aliases generated for the following subdirectories: -// ALIASGEN: github.com/cosmos/cosmos-sdk/x/staking/keeper -// ALIASGEN: github.com/cosmos/cosmos-sdk/x/staking/types -// ALIASGEN: github.com/cosmos/cosmos-sdk/x/staking/exported package staking +// nolint + import ( "github.com/cosmos/cosmos-sdk/x/staking/exported" "github.com/cosmos/cosmos-sdk/x/staking/keeper" @@ -14,16 +10,6 @@ import ( const ( DefaultParamspace = keeper.DefaultParamspace - DefaultCodespace = types.DefaultCodespace - CodeInvalidValidator = types.CodeInvalidValidator - CodeInvalidDelegation = types.CodeInvalidDelegation - CodeInvalidInput = types.CodeInvalidInput - CodeValidatorJailed = types.CodeValidatorJailed - CodeInvalidHistoricalInfo = types.CodeInvalidHistoricalInfo - CodeInvalidAddress = types.CodeInvalidAddress - CodeUnauthorized = types.CodeUnauthorized - CodeInternal = types.CodeInternal - CodeUnknownRequest = types.CodeUnknownRequest ModuleName = types.ModuleName StoreKey = types.StoreKey TStoreKey = types.TStoreKey @@ -92,7 +78,7 @@ var ( MustMarshalHistoricalInfo = types.MustMarshalHistoricalInfo MustUnmarshalHistoricalInfo = types.MustUnmarshalHistoricalInfo UnmarshalHistoricalInfo = types.UnmarshalHistoricalInfo - ErrNilValidatorAddr = types.ErrNilValidatorAddr + ErrEmptyValidatorAddr = types.ErrEmptyValidatorAddr ErrBadValidatorAddr = types.ErrBadValidatorAddr ErrNoValidatorFound = types.ErrNoValidatorFound ErrValidatorOwnerExists = types.ErrValidatorOwnerExists @@ -100,7 +86,6 @@ var ( ErrValidatorPubKeyTypeNotSupported = types.ErrValidatorPubKeyTypeNotSupported ErrValidatorJailed = types.ErrValidatorJailed ErrBadRemoveValidator = types.ErrBadRemoveValidator - ErrDescriptionLength = types.ErrDescriptionLength ErrCommissionNegative = types.ErrCommissionNegative ErrCommissionHuge = types.ErrCommissionHuge ErrCommissionGTMaxRate = types.ErrCommissionGTMaxRate @@ -111,7 +96,7 @@ var ( ErrSelfDelegationBelowMinimum = types.ErrSelfDelegationBelowMinimum ErrMinSelfDelegationInvalid = types.ErrMinSelfDelegationInvalid ErrMinSelfDelegationDecreased = types.ErrMinSelfDelegationDecreased - ErrNilDelegatorAddr = types.ErrNilDelegatorAddr + ErrEmptyDelegatorAddr = types.ErrEmptyDelegatorAddr ErrBadDenom = types.ErrBadDenom ErrBadDelegationAddr = types.ErrBadDelegationAddr ErrBadDelegationAmount = types.ErrBadDelegationAmount @@ -129,14 +114,13 @@ var ( ErrBadRedelegationAddr = types.ErrBadRedelegationAddr ErrNoRedelegation = types.ErrNoRedelegation ErrSelfRedelegation = types.ErrSelfRedelegation - ErrVerySmallRedelegation = types.ErrVerySmallRedelegation + ErrTinyRedelegationAmount = types.ErrTinyRedelegationAmount ErrBadRedelegationDst = types.ErrBadRedelegationDst ErrTransitiveRedelegation = types.ErrTransitiveRedelegation ErrMaxRedelegationEntries = types.ErrMaxRedelegationEntries ErrDelegatorShareExRateInvalid = types.ErrDelegatorShareExRateInvalid ErrBothShareMsgsGiven = types.ErrBothShareMsgsGiven ErrNeitherShareMsgsGiven = types.ErrNeitherShareMsgsGiven - ErrMissingSignature = types.ErrMissingSignature ErrInvalidHistoricalInfo = types.ErrInvalidHistoricalInfo ErrNoHistoricalInfo = types.ErrNoHistoricalInfo NewGenesisState = types.NewGenesisState @@ -233,7 +217,6 @@ type ( RedelegationResponse = types.RedelegationResponse RedelegationEntryResponse = types.RedelegationEntryResponse RedelegationResponses = types.RedelegationResponses - CodeType = types.CodeType GenesisState = types.GenesisState LastValidatorPower = types.LastValidatorPower MultiStakingHooks = types.MultiStakingHooks diff --git a/x/staking/app_test.go b/x/staking/app_test.go index 0c2615d7a3ea..a56923113380 100644 --- a/x/staking/app_test.go +++ b/x/staking/app_test.go @@ -35,14 +35,14 @@ func getMockApp(t *testing.T) (*mock.App, Keeper) { blacklistedAddrs[notBondedPool.GetAddress().String()] = true blacklistedAddrs[bondPool.GetAddress().String()] = true - bankKeeper := bank.NewBaseKeeper(mApp.AccountKeeper, mApp.ParamsKeeper.Subspace(bank.DefaultParamspace), bank.DefaultCodespace, blacklistedAddrs) + bankKeeper := bank.NewBaseKeeper(mApp.AccountKeeper, mApp.ParamsKeeper.Subspace(bank.DefaultParamspace), blacklistedAddrs) maccPerms := map[string][]string{ auth.FeeCollectorName: nil, types.NotBondedPoolName: {supply.Burner, supply.Staking}, types.BondedPoolName: {supply.Burner, supply.Staking}, } supplyKeeper := supply.NewKeeper(mApp.Cdc, keySupply, mApp.AccountKeeper, bankKeeper, maccPerms) - keeper := NewKeeper(mApp.Cdc, keyStaking, supplyKeeper, mApp.ParamsKeeper.Subspace(DefaultParamspace), DefaultCodespace) + keeper := NewKeeper(mApp.Cdc, keyStaking, supplyKeeper, mApp.ParamsKeeper.Subspace(DefaultParamspace)) mApp.Router().AddRoute(RouterKey, NewHandler(keeper)) mApp.SetEndBlocker(getEndBlocker(keeper)) diff --git a/x/staking/client/cli/query.go b/x/staking/client/cli/query.go index 632237c1d915..14a60c49bc04 100644 --- a/x/staking/client/cli/query.go +++ b/x/staking/client/cli/query.go @@ -9,6 +9,7 @@ import ( "github.com/cosmos/cosmos-sdk/client" "github.com/cosmos/cosmos-sdk/client/context" + "github.com/cosmos/cosmos-sdk/client/flags" "github.com/cosmos/cosmos-sdk/codec" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/version" @@ -24,7 +25,7 @@ func GetQueryCmd(queryRoute string, cdc *codec.Codec) *cobra.Command { SuggestionsMinimumDistance: 2, RunE: client.ValidateCmd, } - stakingQueryCmd.AddCommand(client.GetCommands( + stakingQueryCmd.AddCommand(flags.GetCommands( GetCmdQueryDelegation(queryRoute, cdc), GetCmdQueryDelegations(queryRoute, cdc), GetCmdQueryUnbondingDelegation(queryRoute, cdc), diff --git a/x/staking/client/cli/tx.go b/x/staking/client/cli/tx.go index 5898a25933f1..374d061e070a 100644 --- a/x/staking/client/cli/tx.go +++ b/x/staking/client/cli/tx.go @@ -15,6 +15,7 @@ import ( "github.com/cosmos/cosmos-sdk/client" "github.com/cosmos/cosmos-sdk/client/context" + "github.com/cosmos/cosmos-sdk/client/flags" "github.com/cosmos/cosmos-sdk/codec" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/version" @@ -33,7 +34,7 @@ func GetTxCmd(storeKey string, cdc *codec.Codec) *cobra.Command { RunE: client.ValidateCmd, } - stakingTxCmd.AddCommand(client.PostCommands( + stakingTxCmd.AddCommand(flags.PostCommands( GetCmdCreateValidator(cdc), GetCmdEditValidator(cdc), GetCmdDelegate(cdc), @@ -69,10 +70,10 @@ func GetCmdCreateValidator(cdc *codec.Codec) *cobra.Command { cmd.Flags().AddFlagSet(FsCommissionCreate) cmd.Flags().AddFlagSet(FsMinSelfDelegation) - cmd.Flags().String(FlagIP, "", fmt.Sprintf("The node's public IP. It takes effect only when used in combination with --%s", client.FlagGenerateOnly)) + cmd.Flags().String(FlagIP, "", fmt.Sprintf("The node's public IP. It takes effect only when used in combination with --%s", flags.FlagGenerateOnly)) cmd.Flags().String(FlagNodeID, "", "The node's ID") - cmd.MarkFlagRequired(client.FlagFrom) + cmd.MarkFlagRequired(flags.FlagFrom) cmd.MarkFlagRequired(FlagAmount) cmd.MarkFlagRequired(FlagPubKey) cmd.MarkFlagRequired(FlagMoniker) @@ -118,8 +119,9 @@ func GetCmdEditValidator(cdc *codec.Codec) *cobra.Command { if minSelfDelegationString != "" { msb, ok := sdk.NewIntFromString(minSelfDelegationString) if !ok { - return fmt.Errorf(types.ErrMinSelfDelegationInvalid(types.DefaultCodespace).Error()) + return types.ErrMinSelfDelegationInvalid } + newMinSelfDelegation = &msb } @@ -309,8 +311,8 @@ func PrepareFlagsForTxCreateValidator( details := viper.GetString(FlagDetails) identity := viper.GetString(FlagIdentity) - viper.Set(client.FlagChainID, chainID) - viper.Set(client.FlagFrom, viper.GetString(client.FlagName)) + viper.Set(flags.FlagChainID, chainID) + viper.Set(flags.FlagFrom, viper.GetString(flags.FlagName)) viper.Set(FlagNodeID, nodeID) viper.Set(FlagIP, ip) viper.Set(FlagPubKey, sdk.MustBech32ifyConsPub(valPubKey)) @@ -321,7 +323,7 @@ func PrepareFlagsForTxCreateValidator( viper.Set(FlagIdentity, identity) if config.Moniker == "" { - viper.Set(FlagMoniker, viper.GetString(client.FlagName)) + viper.Set(FlagMoniker, viper.GetString(flags.FlagName)) } if viper.GetString(FlagAmount) == "" { viper.Set(FlagAmount, defaultAmount) @@ -377,14 +379,14 @@ func BuildCreateValidatorMsg(cliCtx context.CLIContext, txBldr auth.TxBuilder) ( msbStr := viper.GetString(FlagMinSelfDelegation) minSelfDelegation, ok := sdk.NewIntFromString(msbStr) if !ok { - return txBldr, nil, fmt.Errorf(types.ErrMinSelfDelegationInvalid(types.DefaultCodespace).Error()) + return txBldr, nil, types.ErrMinSelfDelegationInvalid } msg := types.NewMsgCreateValidator( sdk.ValAddress(valAddr), pk, amount, description, commissionRates, minSelfDelegation, ) - if viper.GetBool(client.FlagGenerateOnly) { + if viper.GetBool(flags.FlagGenerateOnly) { ip := viper.GetString(FlagIP) nodeID := viper.GetString(FlagNodeID) if nodeID != "" && ip != "" { diff --git a/x/staking/exported/exported.go b/x/staking/exported/exported.go index eae33c8ee105..7c8a257cd342 100644 --- a/x/staking/exported/exported.go +++ b/x/staking/exported/exported.go @@ -15,24 +15,24 @@ type DelegationI interface { // ValidatorI expected validator functions type ValidatorI interface { - IsJailed() bool // whether the validator is jailed - GetMoniker() string // moniker of the validator - GetStatus() sdk.BondStatus // status of the validator - IsBonded() bool // check if has a bonded status - IsUnbonded() bool // check if has status unbonded - IsUnbonding() bool // check if has status unbonding - GetOperator() sdk.ValAddress // operator address to receive/return validators coins - GetConsPubKey() crypto.PubKey // validation consensus pubkey - GetConsAddr() sdk.ConsAddress // validation consensus address - GetTokens() sdk.Int // validation tokens - GetBondedTokens() sdk.Int // validator bonded tokens - GetConsensusPower() int64 // validation power in tendermint - GetCommission() sdk.Dec // validator commission rate - GetMinSelfDelegation() sdk.Int // validator minimum self delegation - GetDelegatorShares() sdk.Dec // total outstanding delegator shares - TokensFromShares(sdk.Dec) sdk.Dec // token worth of provided delegator shares - TokensFromSharesTruncated(sdk.Dec) sdk.Dec // token worth of provided delegator shares, truncated - TokensFromSharesRoundUp(sdk.Dec) sdk.Dec // token worth of provided delegator shares, rounded up - SharesFromTokens(amt sdk.Int) (sdk.Dec, sdk.Error) // shares worth of delegator's bond - SharesFromTokensTruncated(amt sdk.Int) (sdk.Dec, sdk.Error) // truncated shares worth of delegator's bond + IsJailed() bool // whether the validator is jailed + GetMoniker() string // moniker of the validator + GetStatus() sdk.BondStatus // status of the validator + IsBonded() bool // check if has a bonded status + IsUnbonded() bool // check if has status unbonded + IsUnbonding() bool // check if has status unbonding + GetOperator() sdk.ValAddress // operator address to receive/return validators coins + GetConsPubKey() crypto.PubKey // validation consensus pubkey + GetConsAddr() sdk.ConsAddress // validation consensus address + GetTokens() sdk.Int // validation tokens + GetBondedTokens() sdk.Int // validator bonded tokens + GetConsensusPower() int64 // validation power in tendermint + GetCommission() sdk.Dec // validator commission rate + GetMinSelfDelegation() sdk.Int // validator minimum self delegation + GetDelegatorShares() sdk.Dec // total outstanding delegator shares + TokensFromShares(sdk.Dec) sdk.Dec // token worth of provided delegator shares + TokensFromSharesTruncated(sdk.Dec) sdk.Dec // token worth of provided delegator shares, truncated + TokensFromSharesRoundUp(sdk.Dec) sdk.Dec // token worth of provided delegator shares, rounded up + SharesFromTokens(amt sdk.Int) (sdk.Dec, error) // shares worth of delegator's bond + SharesFromTokensTruncated(amt sdk.Int) (sdk.Dec, error) // truncated shares worth of delegator's bond } diff --git a/x/staking/handler.go b/x/staking/handler.go index 376da255ea1c..da5933930382 100644 --- a/x/staking/handler.go +++ b/x/staking/handler.go @@ -1,19 +1,19 @@ package staking import ( - "fmt" "time" "github.com/tendermint/tendermint/libs/common" tmtypes "github.com/tendermint/tendermint/types" sdk "github.com/cosmos/cosmos-sdk/types" + sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" "github.com/cosmos/cosmos-sdk/x/staking/keeper" "github.com/cosmos/cosmos-sdk/x/staking/types" ) func NewHandler(k keeper.Keeper) sdk.Handler { - return func(ctx sdk.Context, msg sdk.Msg) sdk.Result { + return func(ctx sdk.Context, msg sdk.Msg) (*sdk.Result, error) { ctx = ctx.WithEventManager(sdk.NewEventManager()) switch msg := msg.(type) { @@ -33,8 +33,7 @@ func NewHandler(k keeper.Keeper) sdk.Handler { return handleMsgUndelegate(ctx, msg, k) default: - errMsg := fmt.Sprintf("unrecognized staking message type: %T", msg) - return sdk.ErrUnknownRequest(errMsg).Result() + return nil, sdkerrors.Wrapf(sdkerrors.ErrUnknownRequest, "unrecognized %s message type: %T", ModuleName, msg) } } } @@ -42,30 +41,31 @@ func NewHandler(k keeper.Keeper) sdk.Handler { // These functions assume everything has been authenticated, // now we just perform action and save -func handleMsgCreateValidator(ctx sdk.Context, msg types.MsgCreateValidator, k keeper.Keeper) sdk.Result { +func handleMsgCreateValidator(ctx sdk.Context, msg types.MsgCreateValidator, k keeper.Keeper) (*sdk.Result, error) { // check to see if the pubkey or sender has been registered before if _, found := k.GetValidator(ctx, msg.ValidatorAddress); found { - return ErrValidatorOwnerExists(k.Codespace()).Result() + return nil, ErrValidatorOwnerExists } if _, found := k.GetValidatorByConsAddr(ctx, sdk.GetConsAddress(msg.PubKey)); found { - return ErrValidatorPubKeyExists(k.Codespace()).Result() + return nil, ErrValidatorPubKeyExists } if msg.Value.Denom != k.BondDenom(ctx) { - return ErrBadDenom(k.Codespace()).Result() + return nil, ErrBadDenom } if _, err := msg.Description.EnsureLength(); err != nil { - return err.Result() + return nil, err } if ctx.ConsensusParams() != nil { tmPubKey := tmtypes.TM2PB.PubKey(msg.PubKey) if !common.StringInSlice(tmPubKey.Type, ctx.ConsensusParams().Validator.PubKeyTypes) { - return ErrValidatorPubKeyTypeNotSupported(k.Codespace(), - tmPubKey.Type, - ctx.ConsensusParams().Validator.PubKeyTypes).Result() + return nil, sdkerrors.Wrapf( + ErrValidatorPubKeyTypeNotSupported, + "got: %s, valid: %s", tmPubKey.Type, ctx.ConsensusParams().Validator.PubKeyTypes, + ) } } @@ -76,7 +76,7 @@ func handleMsgCreateValidator(ctx sdk.Context, msg types.MsgCreateValidator, k k ) validator, err := validator.SetInitialCommission(commission) if err != nil { - return err.Result() + return nil, err } validator.MinSelfDelegation = msg.MinSelfDelegation @@ -93,7 +93,7 @@ func handleMsgCreateValidator(ctx sdk.Context, msg types.MsgCreateValidator, k k // NOTE source will always be from a wallet which are unbonded _, err = k.Delegate(ctx, msg.DelegatorAddress, msg.Value.Amount, sdk.Unbonded, validator, true) if err != nil { - return err.Result() + return nil, err } ctx.EventManager().EmitEvents(sdk.Events{ @@ -109,20 +109,20 @@ func handleMsgCreateValidator(ctx sdk.Context, msg types.MsgCreateValidator, k k ), }) - return sdk.Result{Events: ctx.EventManager().Events()} + return &sdk.Result{Events: ctx.EventManager().Events()}, nil } -func handleMsgEditValidator(ctx sdk.Context, msg types.MsgEditValidator, k keeper.Keeper) sdk.Result { +func handleMsgEditValidator(ctx sdk.Context, msg types.MsgEditValidator, k keeper.Keeper) (*sdk.Result, error) { // validator must already be registered validator, found := k.GetValidator(ctx, msg.ValidatorAddress) if !found { - return ErrNoValidatorFound(k.Codespace()).Result() + return nil, ErrNoValidatorFound } // replace all editable fields (clients should autofill existing values) description, err := validator.Description.UpdateDescription(msg.Description) if err != nil { - return err.Result() + return nil, err } validator.Description = description @@ -130,7 +130,7 @@ func handleMsgEditValidator(ctx sdk.Context, msg types.MsgEditValidator, k keepe if msg.CommissionRate != nil { commission, err := k.UpdateValidatorCommission(ctx, validator, *msg.CommissionRate) if err != nil { - return err.Result() + return nil, err } // call the before-modification hook since we're about to update the commission @@ -141,11 +141,12 @@ func handleMsgEditValidator(ctx sdk.Context, msg types.MsgEditValidator, k keepe if msg.MinSelfDelegation != nil { if !msg.MinSelfDelegation.GT(validator.MinSelfDelegation) { - return ErrMinSelfDelegationDecreased(k.Codespace()).Result() + return nil, ErrMinSelfDelegationDecreased } if msg.MinSelfDelegation.GT(validator.Tokens) { - return ErrSelfDelegationBelowMinimum(k.Codespace()).Result() + return nil, ErrSelfDelegationBelowMinimum } + validator.MinSelfDelegation = (*msg.MinSelfDelegation) } @@ -164,23 +165,23 @@ func handleMsgEditValidator(ctx sdk.Context, msg types.MsgEditValidator, k keepe ), }) - return sdk.Result{Events: ctx.EventManager().Events()} + return &sdk.Result{Events: ctx.EventManager().Events()}, nil } -func handleMsgDelegate(ctx sdk.Context, msg types.MsgDelegate, k keeper.Keeper) sdk.Result { +func handleMsgDelegate(ctx sdk.Context, msg types.MsgDelegate, k keeper.Keeper) (*sdk.Result, error) { validator, found := k.GetValidator(ctx, msg.ValidatorAddress) if !found { - return ErrNoValidatorFound(k.Codespace()).Result() + return nil, ErrNoValidatorFound } if msg.Amount.Denom != k.BondDenom(ctx) { - return ErrBadDenom(k.Codespace()).Result() + return nil, ErrBadDenom } // NOTE: source funds are always unbonded _, err := k.Delegate(ctx, msg.DelegatorAddress, msg.Amount.Amount, sdk.Unbonded, validator, true) if err != nil { - return err.Result() + return nil, err } ctx.EventManager().EmitEvents(sdk.Events{ @@ -196,24 +197,24 @@ func handleMsgDelegate(ctx sdk.Context, msg types.MsgDelegate, k keeper.Keeper) ), }) - return sdk.Result{Events: ctx.EventManager().Events()} + return &sdk.Result{Events: ctx.EventManager().Events()}, nil } -func handleMsgUndelegate(ctx sdk.Context, msg types.MsgUndelegate, k keeper.Keeper) sdk.Result { +func handleMsgUndelegate(ctx sdk.Context, msg types.MsgUndelegate, k keeper.Keeper) (*sdk.Result, error) { shares, err := k.ValidateUnbondAmount( ctx, msg.DelegatorAddress, msg.ValidatorAddress, msg.Amount.Amount, ) if err != nil { - return err.Result() + return nil, err } if msg.Amount.Denom != k.BondDenom(ctx) { - return ErrBadDenom(k.Codespace()).Result() + return nil, ErrBadDenom } completionTime, err := k.Undelegate(ctx, msg.DelegatorAddress, msg.ValidatorAddress, shares) if err != nil { - return err.Result() + return nil, err } completionTimeBz := types.ModuleCdc.MustMarshalBinaryLengthPrefixed(completionTime) @@ -231,26 +232,26 @@ func handleMsgUndelegate(ctx sdk.Context, msg types.MsgUndelegate, k keeper.Keep ), }) - return sdk.Result{Data: completionTimeBz, Events: ctx.EventManager().Events()} + return &sdk.Result{Data: completionTimeBz, Events: ctx.EventManager().Events()}, nil } -func handleMsgBeginRedelegate(ctx sdk.Context, msg types.MsgBeginRedelegate, k keeper.Keeper) sdk.Result { +func handleMsgBeginRedelegate(ctx sdk.Context, msg types.MsgBeginRedelegate, k keeper.Keeper) (*sdk.Result, error) { shares, err := k.ValidateUnbondAmount( ctx, msg.DelegatorAddress, msg.ValidatorSrcAddress, msg.Amount.Amount, ) if err != nil { - return err.Result() + return nil, err } if msg.Amount.Denom != k.BondDenom(ctx) { - return ErrBadDenom(k.Codespace()).Result() + return nil, ErrBadDenom } completionTime, err := k.BeginRedelegation( ctx, msg.DelegatorAddress, msg.ValidatorSrcAddress, msg.ValidatorDstAddress, shares, ) if err != nil { - return err.Result() + return nil, err } completionTimeBz := types.ModuleCdc.MustMarshalBinaryLengthPrefixed(completionTime) @@ -269,5 +270,5 @@ func handleMsgBeginRedelegate(ctx sdk.Context, msg types.MsgBeginRedelegate, k k ), }) - return sdk.Result{Data: completionTimeBz, Events: ctx.EventManager().Events()} + return &sdk.Result{Data: completionTimeBz, Events: ctx.EventManager().Events()}, nil } diff --git a/x/staking/handler_test.go b/x/staking/handler_test.go index 0e999ba9b43b..92147eabb097 100644 --- a/x/staking/handler_test.go +++ b/x/staking/handler_test.go @@ -26,8 +26,9 @@ func TestValidatorByPowerIndex(t *testing.T) { // create validator msgCreateValidator := NewTestMsgCreateValidator(validatorAddr, keep.PKs[0], initBond) - got := handleMsgCreateValidator(ctx, msgCreateValidator, keeper) - require.True(t, got.IsOK(), "expected create-validator to be ok, got %v", got) + res, err := handleMsgCreateValidator(ctx, msgCreateValidator, keeper) + require.NoError(t, err) + require.NotNil(t, res) // must end-block updates := keeper.ApplyAndReturnValidatorSetUpdates(ctx) @@ -47,8 +48,9 @@ func TestValidatorByPowerIndex(t *testing.T) { // create a second validator keep it bonded msgCreateValidator = NewTestMsgCreateValidator(validatorAddr3, keep.PKs[2], initBond) - got = handleMsgCreateValidator(ctx, msgCreateValidator, keeper) - require.True(t, got.IsOK(), "expected create-validator to be ok, got %v", got) + res, err = handleMsgCreateValidator(ctx, msgCreateValidator, keeper) + require.NoError(t, err) + require.NotNil(t, res) // must end-block updates = keeper.ApplyAndReturnValidatorSetUpdates(ctx) @@ -84,11 +86,12 @@ func TestValidatorByPowerIndex(t *testing.T) { unbondAmt := sdk.NewCoin(sdk.DefaultBondDenom, totalBond) msgUndelegate := NewMsgUndelegate(sdk.AccAddress(validatorAddr), validatorAddr, unbondAmt) - got = handleMsgUndelegate(ctx, msgUndelegate, keeper) - require.True(t, got.IsOK(), "expected msg to be ok, got %v", got) + res, err = handleMsgUndelegate(ctx, msgUndelegate, keeper) + require.NoError(t, err) + require.NotNil(t, res) var finishTime time.Time - types.ModuleCdc.MustUnmarshalBinaryLengthPrefixed(got.Data, &finishTime) + types.ModuleCdc.MustUnmarshalBinaryLengthPrefixed(res.Data, &finishTime) ctx = ctx.WithBlockTime(finishTime) EndBlocker(ctx, keeper) @@ -108,8 +111,9 @@ func TestDuplicatesMsgCreateValidator(t *testing.T) { valTokens := sdk.TokensFromConsensusPower(10) msgCreateValidator1 := NewTestMsgCreateValidator(addr1, pk1, valTokens) - got := handleMsgCreateValidator(ctx, msgCreateValidator1, keeper) - require.True(t, got.IsOK(), "%v", got) + res, err := handleMsgCreateValidator(ctx, msgCreateValidator1, keeper) + require.NoError(t, err) + require.NotNil(t, res) keeper.ApplyAndReturnValidatorSetUpdates(ctx) @@ -124,18 +128,21 @@ func TestDuplicatesMsgCreateValidator(t *testing.T) { // two validators can't have the same operator address msgCreateValidator2 := NewTestMsgCreateValidator(addr1, pk2, valTokens) - got = handleMsgCreateValidator(ctx, msgCreateValidator2, keeper) - require.False(t, got.IsOK(), "%v", got) + res, err = handleMsgCreateValidator(ctx, msgCreateValidator2, keeper) + require.Error(t, err) + require.Nil(t, res) // two validators can't have the same pubkey msgCreateValidator3 := NewTestMsgCreateValidator(addr2, pk1, valTokens) - got = handleMsgCreateValidator(ctx, msgCreateValidator3, keeper) - require.False(t, got.IsOK(), "%v", got) + res, err = handleMsgCreateValidator(ctx, msgCreateValidator3, keeper) + require.Error(t, err) + require.Nil(t, res) // must have different pubkey and operator msgCreateValidator4 := NewTestMsgCreateValidator(addr2, pk2, valTokens) - got = handleMsgCreateValidator(ctx, msgCreateValidator4, keeper) - require.True(t, got.IsOK(), "%v", got) + res, err = handleMsgCreateValidator(ctx, msgCreateValidator4, keeper) + require.NoError(t, err) + require.NotNil(t, res) // must end-block updates := keeper.ApplyAndReturnValidatorSetUpdates(ctx) @@ -160,15 +167,17 @@ func TestInvalidPubKeyTypeMsgCreateValidator(t *testing.T) { // invalid pukKey type should not be allowed msgCreateValidator := NewTestMsgCreateValidator(addr, invalidPk, sdk.NewInt(10)) - got := handleMsgCreateValidator(ctx, msgCreateValidator, keeper) - require.False(t, got.IsOK(), "%v", got) + res, err := handleMsgCreateValidator(ctx, msgCreateValidator, keeper) + require.Error(t, err) + require.Nil(t, res) ctx = ctx.WithConsensusParams(&abci.ConsensusParams{ Validator: &abci.ValidatorParams{PubKeyTypes: []string{tmtypes.ABCIPubKeyTypeSecp256k1}}, }) - got = handleMsgCreateValidator(ctx, msgCreateValidator, keeper) - require.True(t, got.IsOK(), "%v", got) + res, err = handleMsgCreateValidator(ctx, msgCreateValidator, keeper) + require.NoError(t, err) + require.NotNil(t, res) } func TestLegacyValidatorDelegations(t *testing.T) { @@ -181,8 +190,9 @@ func TestLegacyValidatorDelegations(t *testing.T) { // create validator msgCreateVal := NewTestMsgCreateValidator(valAddr, valConsPubKey, bondAmount) - got := handleMsgCreateValidator(ctx, msgCreateVal, keeper) - require.True(t, got.IsOK(), "expected create validator msg to be ok, got %v", got) + res, err := handleMsgCreateValidator(ctx, msgCreateVal, keeper) + require.NoError(t, err) + require.NotNil(t, res) // must end-block updates := keeper.ApplyAndReturnValidatorSetUpdates(ctx) @@ -197,8 +207,9 @@ func TestLegacyValidatorDelegations(t *testing.T) { // delegate tokens to the validator msgDelegate := NewTestMsgDelegate(delAddr, valAddr, bondAmount) - got = handleMsgDelegate(ctx, msgDelegate, keeper) - require.True(t, got.IsOK(), "expected delegation to be ok, got %v", got) + res, err = handleMsgDelegate(ctx, msgDelegate, keeper) + require.NoError(t, err) + require.NotNil(t, res) // verify validator bonded shares validator, found = keeper.GetValidator(ctx, valAddr) @@ -210,11 +221,12 @@ func TestLegacyValidatorDelegations(t *testing.T) { unbondAmt := sdk.NewCoin(sdk.DefaultBondDenom, bondAmount) msgUndelegate := NewMsgUndelegate(sdk.AccAddress(valAddr), valAddr, unbondAmt) - got = handleMsgUndelegate(ctx, msgUndelegate, keeper) - require.True(t, got.IsOK(), "expected begin unbonding validator msg to be ok, got %v", got) + res, err = handleMsgUndelegate(ctx, msgUndelegate, keeper) + require.NoError(t, err) + require.NotNil(t, res) var finishTime time.Time - types.ModuleCdc.MustUnmarshalBinaryLengthPrefixed(got.Data, &finishTime) + types.ModuleCdc.MustUnmarshalBinaryLengthPrefixed(res.Data, &finishTime) ctx = ctx.WithBlockTime(finishTime) EndBlocker(ctx, keeper) @@ -232,8 +244,9 @@ func TestLegacyValidatorDelegations(t *testing.T) { // verify the validator can still self-delegate msgSelfDelegate := NewTestMsgDelegate(sdk.AccAddress(valAddr), valAddr, bondAmount) - got = handleMsgDelegate(ctx, msgSelfDelegate, keeper) - require.True(t, got.IsOK(), "expected delegation to be ok, got %v", got) + res, err = handleMsgDelegate(ctx, msgSelfDelegate, keeper) + require.NoError(t, err) + require.NotNil(t, res) // verify validator bonded shares validator, found = keeper.GetValidator(ctx, valAddr) @@ -246,8 +259,9 @@ func TestLegacyValidatorDelegations(t *testing.T) { // verify the validator can now accept delegations msgDelegate = NewTestMsgDelegate(delAddr, valAddr, bondAmount) - got = handleMsgDelegate(ctx, msgDelegate, keeper) - require.True(t, got.IsOK(), "expected delegation to be ok, got %v", got) + res, err = handleMsgDelegate(ctx, msgDelegate, keeper) + require.NoError(t, err) + require.NotNil(t, res) // verify validator bonded shares validator, found = keeper.GetValidator(ctx, valAddr) @@ -273,8 +287,9 @@ func TestIncrementsMsgDelegate(t *testing.T) { // first create validator msgCreateValidator := NewTestMsgCreateValidator(validatorAddr, keep.PKs[0], bondAmount) - got := handleMsgCreateValidator(ctx, msgCreateValidator, keeper) - require.True(t, got.IsOK(), "expected create validator msg to be ok, got %v", got) + res, err := handleMsgCreateValidator(ctx, msgCreateValidator, keeper) + require.NoError(t, err) + require.NotNil(t, res) // apply TM updates keeper.ApplyAndReturnValidatorSetUpdates(ctx) @@ -301,8 +316,9 @@ func TestIncrementsMsgDelegate(t *testing.T) { for i := int64(0); i < 5; i++ { ctx = ctx.WithBlockHeight(i) - got := handleMsgDelegate(ctx, msgDelegate, keeper) - require.True(t, got.IsOK(), "expected msg %d to be ok, got %v", i, got) + res, err := handleMsgDelegate(ctx, msgDelegate, keeper) + require.NoError(t, err) + require.NotNil(t, res) //Check that the accounts and the bond account have the appropriate values validator, found := keeper.GetValidator(ctx, validatorAddr) @@ -340,8 +356,9 @@ func TestEditValidatorDecreaseMinSelfDelegation(t *testing.T) { // create validator msgCreateValidator := NewTestMsgCreateValidator(validatorAddr, keep.PKs[0], initBond) msgCreateValidator.MinSelfDelegation = sdk.NewInt(2) - got := handleMsgCreateValidator(ctx, msgCreateValidator, keeper) - require.True(t, got.IsOK(), "expected create-validator to be ok, got %v", got) + res, err := handleMsgCreateValidator(ctx, msgCreateValidator, keeper) + require.NoError(t, err) + require.NotNil(t, res) // must end-block updates := keeper.ApplyAndReturnValidatorSetUpdates(ctx) @@ -357,8 +374,9 @@ func TestEditValidatorDecreaseMinSelfDelegation(t *testing.T) { newMinSelfDelegation := sdk.OneInt() msgEditValidator := NewMsgEditValidator(validatorAddr, Description{}, nil, &newMinSelfDelegation) - got = handleMsgEditValidator(ctx, msgEditValidator, keeper) - require.False(t, got.IsOK(), "should not be able to decrease minSelfDelegation") + res, err = handleMsgEditValidator(ctx, msgEditValidator, keeper) + require.Error(t, err) + require.Nil(t, res) } func TestEditValidatorIncreaseMinSelfDelegationBeyondCurrentBond(t *testing.T) { @@ -371,8 +389,9 @@ func TestEditValidatorIncreaseMinSelfDelegationBeyondCurrentBond(t *testing.T) { // create validator msgCreateValidator := NewTestMsgCreateValidator(validatorAddr, keep.PKs[0], initBond) msgCreateValidator.MinSelfDelegation = sdk.NewInt(2) - got := handleMsgCreateValidator(ctx, msgCreateValidator, keeper) - require.True(t, got.IsOK(), "expected create-validator to be ok, got %v", got) + res, err := handleMsgCreateValidator(ctx, msgCreateValidator, keeper) + require.NoError(t, err) + require.NotNil(t, res) // must end-block updates := keeper.ApplyAndReturnValidatorSetUpdates(ctx) @@ -388,8 +407,9 @@ func TestEditValidatorIncreaseMinSelfDelegationBeyondCurrentBond(t *testing.T) { newMinSelfDelegation := initBond.Add(sdk.OneInt()) msgEditValidator := NewMsgEditValidator(validatorAddr, Description{}, nil, &newMinSelfDelegation) - got = handleMsgEditValidator(ctx, msgEditValidator, keeper) - require.False(t, got.IsOK(), "should not be able to increase minSelfDelegation above current self delegation") + res, err = handleMsgEditValidator(ctx, msgEditValidator, keeper) + require.Error(t, err) + require.Nil(t, res) } func TestIncrementsMsgUnbond(t *testing.T) { @@ -404,15 +424,17 @@ func TestIncrementsMsgUnbond(t *testing.T) { validatorAddr, delegatorAddr := sdk.ValAddress(keep.Addrs[0]), keep.Addrs[1] msgCreateValidator := NewTestMsgCreateValidator(validatorAddr, keep.PKs[0], initBond) - got := handleMsgCreateValidator(ctx, msgCreateValidator, keeper) - require.True(t, got.IsOK(), "expected create-validator to be ok, got %v", got) + res, err := handleMsgCreateValidator(ctx, msgCreateValidator, keeper) + require.NoError(t, err) + require.NotNil(t, res) // initial balance amt1 := accMapper.GetAccount(ctx, delegatorAddr).GetCoins().AmountOf(denom) msgDelegate := NewTestMsgDelegate(delegatorAddr, validatorAddr, initBond) - got = handleMsgDelegate(ctx, msgDelegate, keeper) - require.True(t, got.IsOK(), "expected delegation to be ok, got %v", got) + res, err = handleMsgDelegate(ctx, msgDelegate, keeper) + require.NoError(t, err) + require.NotNil(t, res) // balance should have been subtracted after delegation amt2 := accMapper.GetAccount(ctx, delegatorAddr).GetCoins().AmountOf(denom) @@ -431,12 +453,15 @@ func TestIncrementsMsgUnbond(t *testing.T) { unbondAmt := sdk.NewCoin(sdk.DefaultBondDenom, sdk.NewInt(10)) msgUndelegate := NewMsgUndelegate(delegatorAddr, validatorAddr, unbondAmt) numUnbonds := int64(5) + for i := int64(0); i < numUnbonds; i++ { + res, err := handleMsgUndelegate(ctx, msgUndelegate, keeper) + require.NoError(t, err) + require.NotNil(t, res) - got := handleMsgUndelegate(ctx, msgUndelegate, keeper) - require.True(t, got.IsOK(), "expected msg %d to be ok, got %v", i, got) var finishTime time.Time - types.ModuleCdc.MustUnmarshalBinaryLengthPrefixed(got.Data, &finishTime) + types.ModuleCdc.MustUnmarshalBinaryLengthPrefixed(res.Data, &finishTime) + ctx = ctx.WithBlockTime(finishTime) EndBlocker(ctx, keeper) @@ -474,11 +499,12 @@ func TestIncrementsMsgUnbond(t *testing.T) { initBond, } - for i, c := range errorCases { + for _, c := range errorCases { unbondAmt := sdk.NewCoin(sdk.DefaultBondDenom, c) msgUndelegate := NewMsgUndelegate(delegatorAddr, validatorAddr, unbondAmt) - got = handleMsgUndelegate(ctx, msgUndelegate, keeper) - require.False(t, got.IsOK(), "expected unbond msg to fail, index: %v", i) + res, err = handleMsgUndelegate(ctx, msgUndelegate, keeper) + require.Error(t, err) + require.Nil(t, res) } leftBonded := initBond.Sub(unbondAmt.Amount.Mul(sdk.NewInt(numUnbonds))) @@ -486,9 +512,9 @@ func TestIncrementsMsgUnbond(t *testing.T) { // should be able to unbond remaining unbondAmt = sdk.NewCoin(sdk.DefaultBondDenom, leftBonded) msgUndelegate = NewMsgUndelegate(delegatorAddr, validatorAddr, unbondAmt) - got = handleMsgUndelegate(ctx, msgUndelegate, keeper) - require.True(t, got.IsOK(), - "got: %v\nmsgUnbond: %v\nshares: %s\nleftBonded: %s\n", got.Log, msgUndelegate, unbondAmt, leftBonded) + res, err = handleMsgUndelegate(ctx, msgUndelegate, keeper) + require.NoError(t, err, "msgUnbond: %v\nshares: %s\nleftBonded: %s\n", msgUndelegate, unbondAmt, leftBonded) + require.NotNil(t, res, "msgUnbond: %v\nshares: %s\nleftBonded: %s\n", msgUndelegate, unbondAmt, leftBonded) } func TestMultipleMsgCreateValidator(t *testing.T) { @@ -516,8 +542,9 @@ func TestMultipleMsgCreateValidator(t *testing.T) { valTokens := sdk.TokensFromConsensusPower(10) msgCreateValidatorOnBehalfOf := NewTestMsgCreateValidator(validatorAddr, keep.PKs[i], valTokens) - got := handleMsgCreateValidator(ctx, msgCreateValidatorOnBehalfOf, keeper) - require.True(t, got.IsOK(), "expected msg %d to be ok, got %v", i, got) + res, err := handleMsgCreateValidator(ctx, msgCreateValidatorOnBehalfOf, keeper) + require.NoError(t, err) + require.NotNil(t, res) // verify that the account is bonded validators := keeper.GetValidators(ctx, 100) @@ -541,11 +568,12 @@ func TestMultipleMsgCreateValidator(t *testing.T) { unbondAmt := sdk.NewCoin(sdk.DefaultBondDenom, sdk.TokensFromConsensusPower(10)) msgUndelegate := NewMsgUndelegate(delegatorAddrs[i], validatorAddr, unbondAmt) // remove delegation - got := handleMsgUndelegate(ctx, msgUndelegate, keeper) - require.True(t, got.IsOK(), "expected msg %d to be ok, got %v", i, got) + res, err := handleMsgUndelegate(ctx, msgUndelegate, keeper) + require.NoError(t, err) + require.NotNil(t, res) var finishTime time.Time - types.ModuleCdc.MustUnmarshalBinaryLengthPrefixed(got.Data, &finishTime) + types.ModuleCdc.MustUnmarshalBinaryLengthPrefixed(res.Data, &finishTime) // adds validator into unbonding queue EndBlocker(ctx, keeper) @@ -572,14 +600,16 @@ func TestMultipleMsgDelegate(t *testing.T) { // first make a validator msgCreateValidator := NewTestMsgCreateValidator(validatorAddr, keep.PKs[0], sdk.NewInt(10)) - got := handleMsgCreateValidator(ctx, msgCreateValidator, keeper) - require.True(t, got.IsOK(), "expected msg to be ok, got %v", got) + res, err := handleMsgCreateValidator(ctx, msgCreateValidator, keeper) + require.NoError(t, err) + require.NotNil(t, res) // delegate multiple parties - for i, delegatorAddr := range delegatorAddrs { + for _, delegatorAddr := range delegatorAddrs { msgDelegate := NewTestMsgDelegate(delegatorAddr, validatorAddr, sdk.NewInt(10)) - got := handleMsgDelegate(ctx, msgDelegate, keeper) - require.True(t, got.IsOK(), "expected msg %d to be ok, got %v", i, got) + res, err := handleMsgDelegate(ctx, msgDelegate, keeper) + require.NoError(t, err) + require.NotNil(t, res) // check that the account is bonded bond, found := keeper.GetDelegation(ctx, delegatorAddr, validatorAddr) @@ -588,15 +618,16 @@ func TestMultipleMsgDelegate(t *testing.T) { } // unbond them all - for i, delegatorAddr := range delegatorAddrs { + for _, delegatorAddr := range delegatorAddrs { unbondAmt := sdk.NewCoin(sdk.DefaultBondDenom, sdk.NewInt(10)) msgUndelegate := NewMsgUndelegate(delegatorAddr, validatorAddr, unbondAmt) - got := handleMsgUndelegate(ctx, msgUndelegate, keeper) - require.True(t, got.IsOK(), "expected msg %d to be ok, got %v", i, got) + res, err := handleMsgUndelegate(ctx, msgUndelegate, keeper) + require.NoError(t, err) + require.NotNil(t, res) var finishTime time.Time - types.ModuleCdc.MustUnmarshalBinaryLengthPrefixed(got.Data, &finishTime) + types.ModuleCdc.MustUnmarshalBinaryLengthPrefixed(res.Data, &finishTime) ctx = ctx.WithBlockTime(finishTime) EndBlocker(ctx, keeper) @@ -613,22 +644,25 @@ func TestJailValidator(t *testing.T) { // create the validator msgCreateValidator := NewTestMsgCreateValidator(validatorAddr, keep.PKs[0], sdk.NewInt(10)) - got := handleMsgCreateValidator(ctx, msgCreateValidator, keeper) - require.True(t, got.IsOK(), "expected no error on runMsgCreateValidator") + res, err := handleMsgCreateValidator(ctx, msgCreateValidator, keeper) + require.NoError(t, err) + require.NotNil(t, res) // bond a delegator msgDelegate := NewTestMsgDelegate(delegatorAddr, validatorAddr, sdk.NewInt(10)) - got = handleMsgDelegate(ctx, msgDelegate, keeper) - require.True(t, got.IsOK(), "expected ok, got %v", got) + res, err = handleMsgDelegate(ctx, msgDelegate, keeper) + require.NoError(t, err) + require.NotNil(t, res) // unbond the validators bond portion unbondAmt := sdk.NewCoin(sdk.DefaultBondDenom, sdk.NewInt(10)) msgUndelegateValidator := NewMsgUndelegate(sdk.AccAddress(validatorAddr), validatorAddr, unbondAmt) - got = handleMsgUndelegate(ctx, msgUndelegateValidator, keeper) - require.True(t, got.IsOK(), "expected no error: %v", got) + res, err = handleMsgUndelegate(ctx, msgUndelegateValidator, keeper) + require.NoError(t, err) + require.NotNil(t, res) var finishTime time.Time - types.ModuleCdc.MustUnmarshalBinaryLengthPrefixed(got.Data, &finishTime) + types.ModuleCdc.MustUnmarshalBinaryLengthPrefixed(res.Data, &finishTime) ctx = ctx.WithBlockTime(finishTime) EndBlocker(ctx, keeper) @@ -640,16 +674,18 @@ func TestJailValidator(t *testing.T) { // test that the delegator can still withdraw their bonds msgUndelegateDelegator := NewMsgUndelegate(delegatorAddr, validatorAddr, unbondAmt) - got = handleMsgUndelegate(ctx, msgUndelegateDelegator, keeper) - require.True(t, got.IsOK(), "expected no error") - types.ModuleCdc.MustUnmarshalBinaryLengthPrefixed(got.Data, &finishTime) + res, err = handleMsgUndelegate(ctx, msgUndelegateDelegator, keeper) + require.NoError(t, err) + require.NotNil(t, res) + types.ModuleCdc.MustUnmarshalBinaryLengthPrefixed(res.Data, &finishTime) ctx = ctx.WithBlockTime(finishTime) EndBlocker(ctx, keeper) // verify that the pubkey can now be reused - got = handleMsgCreateValidator(ctx, msgCreateValidator, keeper) - require.True(t, got.IsOK(), "expected ok, got %v", got) + res, err = handleMsgCreateValidator(ctx, msgCreateValidator, keeper) + require.NoError(t, err) + require.NotNil(t, res) } func TestValidatorQueue(t *testing.T) { @@ -664,25 +700,28 @@ func TestValidatorQueue(t *testing.T) { // create the validator valTokens := sdk.TokensFromConsensusPower(10) msgCreateValidator := NewTestMsgCreateValidator(validatorAddr, keep.PKs[0], valTokens) - got := handleMsgCreateValidator(ctx, msgCreateValidator, keeper) - require.True(t, got.IsOK(), "expected no error on runMsgCreateValidator") + res, err := handleMsgCreateValidator(ctx, msgCreateValidator, keeper) + require.NoError(t, err) + require.NotNil(t, res) // bond a delegator delTokens := sdk.TokensFromConsensusPower(10) msgDelegate := NewTestMsgDelegate(delegatorAddr, validatorAddr, delTokens) - got = handleMsgDelegate(ctx, msgDelegate, keeper) - require.True(t, got.IsOK(), "expected ok, got %v", got) + res, err = handleMsgDelegate(ctx, msgDelegate, keeper) + require.NoError(t, err) + require.NotNil(t, res) EndBlocker(ctx, keeper) // unbond the all self-delegation to put validator in unbonding state unbondAmt := sdk.NewCoin(sdk.DefaultBondDenom, delTokens) msgUndelegateValidator := NewMsgUndelegate(sdk.AccAddress(validatorAddr), validatorAddr, unbondAmt) - got = handleMsgUndelegate(ctx, msgUndelegateValidator, keeper) - require.True(t, got.IsOK(), "expected no error: %v", got) + res, err = handleMsgUndelegate(ctx, msgUndelegateValidator, keeper) + require.NoError(t, err) + require.NotNil(t, res) var finishTime time.Time - types.ModuleCdc.MustUnmarshalBinaryLengthPrefixed(got.Data, &finishTime) + types.ModuleCdc.MustUnmarshalBinaryLengthPrefixed(res.Data, &finishTime) ctx = ctx.WithBlockTime(finishTime) EndBlocker(ctx, keeper) @@ -722,16 +761,18 @@ func TestUnbondingPeriod(t *testing.T) { // create the validator valTokens := sdk.TokensFromConsensusPower(10) msgCreateValidator := NewTestMsgCreateValidator(validatorAddr, keep.PKs[0], valTokens) - got := handleMsgCreateValidator(ctx, msgCreateValidator, keeper) - require.True(t, got.IsOK(), "expected no error on runMsgCreateValidator") + res, err := handleMsgCreateValidator(ctx, msgCreateValidator, keeper) + require.NoError(t, err) + require.NotNil(t, res) EndBlocker(ctx, keeper) // begin unbonding unbondAmt := sdk.NewCoin(sdk.DefaultBondDenom, sdk.TokensFromConsensusPower(10)) msgUndelegate := NewMsgUndelegate(sdk.AccAddress(validatorAddr), validatorAddr, unbondAmt) - got = handleMsgUndelegate(ctx, msgUndelegate, keeper) - require.True(t, got.IsOK(), "expected no error") + res, err = handleMsgUndelegate(ctx, msgUndelegate, keeper) + require.NoError(t, err) + require.NotNil(t, res) origHeader := ctx.BlockHeader() @@ -762,29 +803,33 @@ func TestUnbondingFromUnbondingValidator(t *testing.T) { // create the validator msgCreateValidator := NewTestMsgCreateValidator(validatorAddr, keep.PKs[0], sdk.NewInt(10)) - got := handleMsgCreateValidator(ctx, msgCreateValidator, keeper) - require.True(t, got.IsOK(), "expected no error on runMsgCreateValidator") + res, err := handleMsgCreateValidator(ctx, msgCreateValidator, keeper) + require.NoError(t, err) + require.NotNil(t, res) // bond a delegator msgDelegate := NewTestMsgDelegate(delegatorAddr, validatorAddr, sdk.NewInt(10)) - got = handleMsgDelegate(ctx, msgDelegate, keeper) - require.True(t, got.IsOK(), "expected ok, got %v", got) + res, err = handleMsgDelegate(ctx, msgDelegate, keeper) + require.NoError(t, err) + require.NotNil(t, res) // unbond the validators bond portion unbondAmt := sdk.NewCoin(sdk.DefaultBondDenom, sdk.NewInt(10)) msgUndelegateValidator := NewMsgUndelegate(sdk.AccAddress(validatorAddr), validatorAddr, unbondAmt) - got = handleMsgUndelegate(ctx, msgUndelegateValidator, keeper) - require.True(t, got.IsOK(), "expected no error") + res, err = handleMsgUndelegate(ctx, msgUndelegateValidator, keeper) + require.NoError(t, err) + require.NotNil(t, res) // change the ctx to Block Time one second before the validator would have unbonded var finishTime time.Time - types.ModuleCdc.MustUnmarshalBinaryLengthPrefixed(got.Data, &finishTime) + types.ModuleCdc.MustUnmarshalBinaryLengthPrefixed(res.Data, &finishTime) ctx = ctx.WithBlockTime(finishTime.Add(time.Second * -1)) // unbond the delegator from the validator msgUndelegateDelegator := NewMsgUndelegate(delegatorAddr, validatorAddr, unbondAmt) - got = handleMsgUndelegate(ctx, msgUndelegateDelegator, keeper) - require.True(t, got.IsOK(), "expected no error") + res, err = handleMsgUndelegate(ctx, msgUndelegateDelegator, keeper) + require.NoError(t, err) + require.NotNil(t, res) ctx = ctx.WithBlockTime(ctx.BlockHeader().Time.Add(keeper.UnbondingTime(ctx))) @@ -813,24 +858,27 @@ func TestRedelegationPeriod(t *testing.T) { // initial balance amt1 := AccMapper.GetAccount(ctx, sdk.AccAddress(validatorAddr)).GetCoins().AmountOf(denom) - got := handleMsgCreateValidator(ctx, msgCreateValidator, keeper) - require.True(t, got.IsOK(), "expected no error on runMsgCreateValidator") + res, err := handleMsgCreateValidator(ctx, msgCreateValidator, keeper) + require.NoError(t, err) + require.NotNil(t, res) // balance should have been subtracted after creation amt2 := AccMapper.GetAccount(ctx, sdk.AccAddress(validatorAddr)).GetCoins().AmountOf(denom) require.Equal(t, amt1.Sub(sdk.NewInt(10)).Int64(), amt2.Int64(), "expected coins to be subtracted") msgCreateValidator = NewTestMsgCreateValidator(validatorAddr2, keep.PKs[1], sdk.NewInt(10)) - got = handleMsgCreateValidator(ctx, msgCreateValidator, keeper) - require.True(t, got.IsOK(), "expected no error on runMsgCreateValidator") + res, err = handleMsgCreateValidator(ctx, msgCreateValidator, keeper) + require.NoError(t, err) + require.NotNil(t, res) bal1 := AccMapper.GetAccount(ctx, sdk.AccAddress(validatorAddr)).GetCoins() // begin redelegate redAmt := sdk.NewCoin(sdk.DefaultBondDenom, sdk.NewInt(10)) msgBeginRedelegate := NewMsgBeginRedelegate(sdk.AccAddress(validatorAddr), validatorAddr, validatorAddr2, redAmt) - got = handleMsgBeginRedelegate(ctx, msgBeginRedelegate, keeper) - require.True(t, got.IsOK(), "expected no error, %v", got) + res, err = handleMsgBeginRedelegate(ctx, msgBeginRedelegate, keeper) + require.NoError(t, err) + require.NotNil(t, res) // origin account should not lose tokens as with a regular delegation bal2 := AccMapper.GetAccount(ctx, sdk.AccAddress(validatorAddr)).GetCoins() @@ -867,27 +915,32 @@ func TestTransitiveRedelegation(t *testing.T) { // create the validators msgCreateValidator := NewTestMsgCreateValidator(validatorAddr, keep.PKs[0], sdk.NewInt(10)) - got := handleMsgCreateValidator(ctx, msgCreateValidator, keeper) - require.True(t, got.IsOK(), "expected no error on runMsgCreateValidator") + res, err := handleMsgCreateValidator(ctx, msgCreateValidator, keeper) + require.NoError(t, err) + require.NotNil(t, res) msgCreateValidator = NewTestMsgCreateValidator(validatorAddr2, keep.PKs[1], sdk.NewInt(10)) - got = handleMsgCreateValidator(ctx, msgCreateValidator, keeper) - require.True(t, got.IsOK(), "expected no error on runMsgCreateValidator") + res, err = handleMsgCreateValidator(ctx, msgCreateValidator, keeper) + require.NoError(t, err) + require.NotNil(t, res) msgCreateValidator = NewTestMsgCreateValidator(validatorAddr3, keep.PKs[2], sdk.NewInt(10)) - got = handleMsgCreateValidator(ctx, msgCreateValidator, keeper) - require.True(t, got.IsOK(), "expected no error on runMsgCreateValidator") + res, err = handleMsgCreateValidator(ctx, msgCreateValidator, keeper) + require.NoError(t, err) + require.NotNil(t, res) // begin redelegate redAmt := sdk.NewCoin(sdk.DefaultBondDenom, sdk.NewInt(10)) msgBeginRedelegate := NewMsgBeginRedelegate(sdk.AccAddress(validatorAddr), validatorAddr, validatorAddr2, redAmt) - got = handleMsgBeginRedelegate(ctx, msgBeginRedelegate, keeper) - require.True(t, got.IsOK(), "expected no error, %v", got) + res, err = handleMsgBeginRedelegate(ctx, msgBeginRedelegate, keeper) + require.NoError(t, err) + require.NotNil(t, res) // cannot redelegation to next validator while first delegation exists msgBeginRedelegate = NewMsgBeginRedelegate(sdk.AccAddress(validatorAddr), validatorAddr2, validatorAddr3, redAmt) - got = handleMsgBeginRedelegate(ctx, msgBeginRedelegate, keeper) - require.True(t, !got.IsOK(), "expected an error, msg: %v", msgBeginRedelegate) + res, err = handleMsgBeginRedelegate(ctx, msgBeginRedelegate, keeper) + require.Error(t, err) + require.Nil(t, res) params := keeper.GetParams(ctx) ctx = ctx.WithBlockTime(blockTime.Add(params.UnbondingTime)) @@ -896,8 +949,9 @@ func TestTransitiveRedelegation(t *testing.T) { EndBlocker(ctx, keeper) // now should be able to redelegate from the second validator to the third - got = handleMsgBeginRedelegate(ctx, msgBeginRedelegate, keeper) - require.True(t, got.IsOK(), "expected no error", got.Log) + res, err = handleMsgBeginRedelegate(ctx, msgBeginRedelegate, keeper) + require.NoError(t, err) + require.NotNil(t, res) } func TestMultipleRedelegationAtSameTime(t *testing.T) { @@ -913,12 +967,14 @@ func TestMultipleRedelegationAtSameTime(t *testing.T) { // create the validators valTokens := sdk.TokensFromConsensusPower(10) msgCreateValidator := NewTestMsgCreateValidator(valAddr, keep.PKs[0], valTokens) - got := handleMsgCreateValidator(ctx, msgCreateValidator, keeper) - require.True(t, got.IsOK(), "expected no error on runMsgCreateValidator") + res, err := handleMsgCreateValidator(ctx, msgCreateValidator, keeper) + require.NoError(t, err) + require.NotNil(t, res) msgCreateValidator = NewTestMsgCreateValidator(valAddr2, keep.PKs[1], valTokens) - got = handleMsgCreateValidator(ctx, msgCreateValidator, keeper) - require.True(t, got.IsOK(), "expected no error on runMsgCreateValidator") + res, err = handleMsgCreateValidator(ctx, msgCreateValidator, keeper) + require.NoError(t, err) + require.NotNil(t, res) // end block to bond them EndBlocker(ctx, keeper) @@ -927,8 +983,9 @@ func TestMultipleRedelegationAtSameTime(t *testing.T) { selfDelAddr := sdk.AccAddress(valAddr) // (the validator is it's own delegator) redAmt := sdk.NewCoin(sdk.DefaultBondDenom, valTokens.QuoRaw(2)) msgBeginRedelegate := NewMsgBeginRedelegate(selfDelAddr, valAddr, valAddr2, redAmt) - got = handleMsgBeginRedelegate(ctx, msgBeginRedelegate, keeper) - require.True(t, got.IsOK(), "expected no error, %v", got) + res, err = handleMsgBeginRedelegate(ctx, msgBeginRedelegate, keeper) + require.NoError(t, err) + require.NotNil(t, res) // there should only be one entry in the redelegation object rd, found := keeper.GetRedelegation(ctx, selfDelAddr, valAddr, valAddr2) @@ -936,8 +993,9 @@ func TestMultipleRedelegationAtSameTime(t *testing.T) { require.Len(t, rd.Entries, 1) // start a second redelegation at this same time as the first - got = handleMsgBeginRedelegate(ctx, msgBeginRedelegate, keeper) - require.True(t, got.IsOK(), "expected no error, msg: %v", msgBeginRedelegate) + res, err = handleMsgBeginRedelegate(ctx, msgBeginRedelegate, keeper) + require.NoError(t, err) + require.NotNil(t, res) // now there should be two entries rd, found = keeper.GetRedelegation(ctx, selfDelAddr, valAddr, valAddr2) @@ -965,12 +1023,14 @@ func TestMultipleRedelegationAtUniqueTimes(t *testing.T) { // create the validators valTokens := sdk.TokensFromConsensusPower(10) msgCreateValidator := NewTestMsgCreateValidator(valAddr, keep.PKs[0], valTokens) - got := handleMsgCreateValidator(ctx, msgCreateValidator, keeper) - require.True(t, got.IsOK(), "expected no error on runMsgCreateValidator") + res, err := handleMsgCreateValidator(ctx, msgCreateValidator, keeper) + require.NoError(t, err) + require.NotNil(t, res) msgCreateValidator = NewTestMsgCreateValidator(valAddr2, keep.PKs[1], valTokens) - got = handleMsgCreateValidator(ctx, msgCreateValidator, keeper) - require.True(t, got.IsOK(), "expected no error on runMsgCreateValidator") + res, err = handleMsgCreateValidator(ctx, msgCreateValidator, keeper) + require.NoError(t, err) + require.NotNil(t, res) // end block to bond them EndBlocker(ctx, keeper) @@ -979,13 +1039,15 @@ func TestMultipleRedelegationAtUniqueTimes(t *testing.T) { selfDelAddr := sdk.AccAddress(valAddr) // (the validator is it's own delegator) redAmt := sdk.NewCoin(sdk.DefaultBondDenom, valTokens.QuoRaw(2)) msgBeginRedelegate := NewMsgBeginRedelegate(selfDelAddr, valAddr, valAddr2, redAmt) - got = handleMsgBeginRedelegate(ctx, msgBeginRedelegate, keeper) - require.True(t, got.IsOK(), "expected no error, %v", got) + res, err = handleMsgBeginRedelegate(ctx, msgBeginRedelegate, keeper) + require.NoError(t, err) + require.NotNil(t, res) // move forward in time and start a second redelegation ctx = ctx.WithBlockTime(ctx.BlockHeader().Time.Add(5 * time.Second)) - got = handleMsgBeginRedelegate(ctx, msgBeginRedelegate, keeper) - require.True(t, got.IsOK(), "expected no error, msg: %v", msgBeginRedelegate) + res, err = handleMsgBeginRedelegate(ctx, msgBeginRedelegate, keeper) + require.NoError(t, err) + require.NotNil(t, res) // now there should be two entries rd, found := keeper.GetRedelegation(ctx, selfDelAddr, valAddr, valAddr2) @@ -1018,8 +1080,9 @@ func TestMultipleUnbondingDelegationAtSameTime(t *testing.T) { // create the validator valTokens := sdk.TokensFromConsensusPower(10) msgCreateValidator := NewTestMsgCreateValidator(valAddr, keep.PKs[0], valTokens) - got := handleMsgCreateValidator(ctx, msgCreateValidator, keeper) - require.True(t, got.IsOK(), "expected no error on runMsgCreateValidator") + res, err := handleMsgCreateValidator(ctx, msgCreateValidator, keeper) + require.NoError(t, err) + require.NotNil(t, res) // end block to bond EndBlocker(ctx, keeper) @@ -1028,8 +1091,9 @@ func TestMultipleUnbondingDelegationAtSameTime(t *testing.T) { selfDelAddr := sdk.AccAddress(valAddr) // (the validator is it's own delegator) unbondAmt := sdk.NewCoin(sdk.DefaultBondDenom, valTokens.QuoRaw(2)) msgUndelegate := NewMsgUndelegate(selfDelAddr, valAddr, unbondAmt) - got = handleMsgUndelegate(ctx, msgUndelegate, keeper) - require.True(t, got.IsOK(), "expected no error, %v", got) + res, err = handleMsgUndelegate(ctx, msgUndelegate, keeper) + require.NoError(t, err) + require.NotNil(t, res) // there should only be one entry in the ubd object ubd, found := keeper.GetUnbondingDelegation(ctx, selfDelAddr, valAddr) @@ -1037,8 +1101,9 @@ func TestMultipleUnbondingDelegationAtSameTime(t *testing.T) { require.Len(t, ubd.Entries, 1) // start a second ubd at this same time as the first - got = handleMsgUndelegate(ctx, msgUndelegate, keeper) - require.True(t, got.IsOK(), "expected no error, msg: %v", msgUndelegate) + res, err = handleMsgUndelegate(ctx, msgUndelegate, keeper) + require.NoError(t, err) + require.NotNil(t, res) // now there should be two entries ubd, found = keeper.GetUnbondingDelegation(ctx, selfDelAddr, valAddr) @@ -1065,8 +1130,9 @@ func TestMultipleUnbondingDelegationAtUniqueTimes(t *testing.T) { // create the validator valTokens := sdk.TokensFromConsensusPower(10) msgCreateValidator := NewTestMsgCreateValidator(valAddr, keep.PKs[0], valTokens) - got := handleMsgCreateValidator(ctx, msgCreateValidator, keeper) - require.True(t, got.IsOK(), "expected no error on runMsgCreateValidator") + res, err := handleMsgCreateValidator(ctx, msgCreateValidator, keeper) + require.NoError(t, err) + require.NotNil(t, res) // end block to bond EndBlocker(ctx, keeper) @@ -1075,8 +1141,9 @@ func TestMultipleUnbondingDelegationAtUniqueTimes(t *testing.T) { selfDelAddr := sdk.AccAddress(valAddr) // (the validator is it's own delegator) unbondAmt := sdk.NewCoin(sdk.DefaultBondDenom, valTokens.QuoRaw(2)) msgUndelegate := NewMsgUndelegate(selfDelAddr, valAddr, unbondAmt) - got = handleMsgUndelegate(ctx, msgUndelegate, keeper) - require.True(t, got.IsOK(), "expected no error, %v", got) + res, err = handleMsgUndelegate(ctx, msgUndelegate, keeper) + require.NoError(t, err) + require.NotNil(t, res) // there should only be one entry in the ubd object ubd, found := keeper.GetUnbondingDelegation(ctx, selfDelAddr, valAddr) @@ -1085,8 +1152,9 @@ func TestMultipleUnbondingDelegationAtUniqueTimes(t *testing.T) { // move forwaubd in time and start a second redelegation ctx = ctx.WithBlockTime(ctx.BlockHeader().Time.Add(5 * time.Second)) - got = handleMsgUndelegate(ctx, msgUndelegate, keeper) - require.True(t, got.IsOK(), "expected no error, msg: %v", msgUndelegate) + res, err = handleMsgUndelegate(ctx, msgUndelegate, keeper) + require.NoError(t, err) + require.NotNil(t, res) // now there should be two entries ubd, found = keeper.GetUnbondingDelegation(ctx, selfDelAddr, valAddr) @@ -1121,24 +1189,30 @@ func TestUnbondingWhenExcessValidators(t *testing.T) { // add three validators valTokens1 := sdk.TokensFromConsensusPower(50) msgCreateValidator := NewTestMsgCreateValidator(validatorAddr1, keep.PKs[0], valTokens1) - got := handleMsgCreateValidator(ctx, msgCreateValidator, keeper) - require.True(t, got.IsOK(), "expected no error on runMsgCreateValidator") + res, err := handleMsgCreateValidator(ctx, msgCreateValidator, keeper) + require.NoError(t, err) + require.NotNil(t, res) + // apply TM updates keeper.ApplyAndReturnValidatorSetUpdates(ctx) require.Equal(t, 1, len(keeper.GetLastValidators(ctx))) valTokens2 := sdk.TokensFromConsensusPower(30) msgCreateValidator = NewTestMsgCreateValidator(validatorAddr2, keep.PKs[1], valTokens2) - got = handleMsgCreateValidator(ctx, msgCreateValidator, keeper) - require.True(t, got.IsOK(), "expected no error on runMsgCreateValidator") + res, err = handleMsgCreateValidator(ctx, msgCreateValidator, keeper) + require.NoError(t, err) + require.NotNil(t, res) + // apply TM updates keeper.ApplyAndReturnValidatorSetUpdates(ctx) require.Equal(t, 2, len(keeper.GetLastValidators(ctx))) valTokens3 := sdk.TokensFromConsensusPower(10) msgCreateValidator = NewTestMsgCreateValidator(validatorAddr3, keep.PKs[2], valTokens3) - got = handleMsgCreateValidator(ctx, msgCreateValidator, keeper) - require.True(t, got.IsOK(), "expected no error on runMsgCreateValidator") + res, err = handleMsgCreateValidator(ctx, msgCreateValidator, keeper) + require.NoError(t, err) + require.NotNil(t, res) + // apply TM updates keeper.ApplyAndReturnValidatorSetUpdates(ctx) require.Equal(t, 2, len(keeper.GetLastValidators(ctx))) @@ -1146,8 +1220,9 @@ func TestUnbondingWhenExcessValidators(t *testing.T) { // unbond the validator-2 unbondAmt := sdk.NewCoin(sdk.DefaultBondDenom, valTokens2) msgUndelegate := NewMsgUndelegate(sdk.AccAddress(validatorAddr2), validatorAddr2, unbondAmt) - got = handleMsgUndelegate(ctx, msgUndelegate, keeper) - require.True(t, got.IsOK(), "expected no error on runMsgUndelegate") + res, err = handleMsgUndelegate(ctx, msgUndelegate, keeper) + require.NoError(t, err) + require.NotNil(t, res) // apply TM updates keeper.ApplyAndReturnValidatorSetUpdates(ctx) @@ -1169,17 +1244,20 @@ func TestBondUnbondRedelegateSlashTwice(t *testing.T) { valTokens := sdk.TokensFromConsensusPower(10) msgCreateValidator := NewTestMsgCreateValidator(valA, keep.PKs[0], valTokens) - got := handleMsgCreateValidator(ctx, msgCreateValidator, keeper) - require.True(t, got.IsOK(), "expected no error on runMsgCreateValidator") + res, err := handleMsgCreateValidator(ctx, msgCreateValidator, keeper) + require.NoError(t, err) + require.NotNil(t, res) msgCreateValidator = NewTestMsgCreateValidator(valB, keep.PKs[1], valTokens) - got = handleMsgCreateValidator(ctx, msgCreateValidator, keeper) - require.True(t, got.IsOK(), "expected no error on runMsgCreateValidator") + res, err = handleMsgCreateValidator(ctx, msgCreateValidator, keeper) + require.NoError(t, err) + require.NotNil(t, res) // delegate 10 stake msgDelegate := NewTestMsgDelegate(del, valA, valTokens) - got = handleMsgDelegate(ctx, msgDelegate, keeper) - require.True(t, got.IsOK(), "expected no error on runMsgDelegate") + res, err = handleMsgDelegate(ctx, msgDelegate, keeper) + require.NoError(t, err) + require.NotNil(t, res) // apply Tendermint updates updates := keeper.ApplyAndReturnValidatorSetUpdates(ctx) @@ -1191,14 +1269,16 @@ func TestBondUnbondRedelegateSlashTwice(t *testing.T) { // begin unbonding 4 stake unbondAmt := sdk.NewCoin(sdk.DefaultBondDenom, sdk.TokensFromConsensusPower(4)) msgUndelegate := NewMsgUndelegate(del, valA, unbondAmt) - got = handleMsgUndelegate(ctx, msgUndelegate, keeper) - require.True(t, got.IsOK(), "expected no error on runMsgUndelegate") + res, err = handleMsgUndelegate(ctx, msgUndelegate, keeper) + require.NoError(t, err) + require.NotNil(t, res) // begin redelegate 6 stake redAmt := sdk.NewCoin(sdk.DefaultBondDenom, sdk.TokensFromConsensusPower(6)) msgBeginRedelegate := NewMsgBeginRedelegate(del, valA, valB, redAmt) - got = handleMsgBeginRedelegate(ctx, msgBeginRedelegate, keeper) - require.True(t, got.IsOK(), "expected no error on runMsgBeginRedelegate") + res, err = handleMsgBeginRedelegate(ctx, msgBeginRedelegate, keeper) + require.NoError(t, err) + require.NotNil(t, res) // destination delegation should have 6 shares delegation, found := keeper.GetDelegation(ctx, del, valB) @@ -1266,9 +1346,10 @@ func TestInvalidMsg(t *testing.T) { k := keep.Keeper{} h := NewHandler(k) - res := h(sdk.NewContext(nil, abci.Header{}, false, nil), sdk.NewTestMsg()) - require.False(t, res.IsOK()) - require.True(t, strings.Contains(res.Log, "unrecognized staking message type")) + res, err := h(sdk.NewContext(nil, abci.Header{}, false, nil), sdk.NewTestMsg()) + require.Error(t, err) + require.Nil(t, res) + require.True(t, strings.Contains(err.Error(), "unrecognized staking message type")) } func TestInvalidCoinDenom(t *testing.T) { @@ -1283,33 +1364,47 @@ func TestInvalidCoinDenom(t *testing.T) { commission := types.NewCommissionRates(sdk.OneDec(), sdk.OneDec(), sdk.ZeroDec()) msgCreate := types.NewMsgCreateValidator(valA, keep.PKs[0], invalidCoin, Description{}, commission, sdk.OneInt()) - got := handleMsgCreateValidator(ctx, msgCreate, keeper) - require.False(t, got.IsOK()) + res, err := handleMsgCreateValidator(ctx, msgCreate, keeper) + require.Error(t, err) + require.Nil(t, res) + msgCreate = types.NewMsgCreateValidator(valA, keep.PKs[0], validCoin, Description{}, commission, sdk.OneInt()) - got = handleMsgCreateValidator(ctx, msgCreate, keeper) - require.True(t, got.IsOK()) + res, err = handleMsgCreateValidator(ctx, msgCreate, keeper) + require.NoError(t, err) + require.NotNil(t, res) + msgCreate = types.NewMsgCreateValidator(valB, keep.PKs[1], validCoin, Description{}, commission, sdk.OneInt()) - got = handleMsgCreateValidator(ctx, msgCreate, keeper) - require.True(t, got.IsOK()) + res, err = handleMsgCreateValidator(ctx, msgCreate, keeper) + require.NoError(t, err) + require.NotNil(t, res) msgDelegate := types.NewMsgDelegate(delAddr, valA, invalidCoin) - got = handleMsgDelegate(ctx, msgDelegate, keeper) - require.False(t, got.IsOK()) + res, err = handleMsgDelegate(ctx, msgDelegate, keeper) + require.Error(t, err) + require.Nil(t, res) + msgDelegate = types.NewMsgDelegate(delAddr, valA, validCoin) - got = handleMsgDelegate(ctx, msgDelegate, keeper) - require.True(t, got.IsOK()) + res, err = handleMsgDelegate(ctx, msgDelegate, keeper) + require.NoError(t, err) + require.NotNil(t, res) msgUndelegate := types.NewMsgUndelegate(delAddr, valA, invalidCoin) - got = handleMsgUndelegate(ctx, msgUndelegate, keeper) - require.False(t, got.IsOK()) + res, err = handleMsgUndelegate(ctx, msgUndelegate, keeper) + require.Error(t, err) + require.Nil(t, res) + msgUndelegate = types.NewMsgUndelegate(delAddr, valA, oneCoin) - got = handleMsgUndelegate(ctx, msgUndelegate, keeper) - require.True(t, got.IsOK()) + res, err = handleMsgUndelegate(ctx, msgUndelegate, keeper) + require.NoError(t, err) + require.NotNil(t, res) msgRedelegate := types.NewMsgBeginRedelegate(delAddr, valA, valB, invalidCoin) - got = handleMsgBeginRedelegate(ctx, msgRedelegate, keeper) - require.False(t, got.IsOK()) + res, err = handleMsgBeginRedelegate(ctx, msgRedelegate, keeper) + require.Error(t, err) + require.Nil(t, res) + msgRedelegate = types.NewMsgBeginRedelegate(delAddr, valA, valB, oneCoin) - got = handleMsgBeginRedelegate(ctx, msgRedelegate, keeper) - require.True(t, got.IsOK()) + res, err = handleMsgBeginRedelegate(ctx, msgRedelegate, keeper) + require.NoError(t, err) + require.NotNil(t, res) } diff --git a/x/staking/keeper/delegation.go b/x/staking/keeper/delegation.go index 3aa244b3b3c9..faf8ba415ef7 100644 --- a/x/staking/keeper/delegation.go +++ b/x/staking/keeper/delegation.go @@ -6,6 +6,7 @@ import ( "time" sdk "github.com/cosmos/cosmos-sdk/types" + sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" "github.com/cosmos/cosmos-sdk/x/staking/types" ) @@ -456,14 +457,16 @@ func (k Keeper) DequeueAllMatureRedelegationQueue(ctx sdk.Context, currTime time // Perform a delegation, set/update everything necessary within the store. // tokenSrc indicates the bond status of the incoming funds. -func (k Keeper) Delegate(ctx sdk.Context, delAddr sdk.AccAddress, bondAmt sdk.Int, tokenSrc sdk.BondStatus, - validator types.Validator, subtractAccount bool) (newShares sdk.Dec, err sdk.Error) { +func (k Keeper) Delegate( + ctx sdk.Context, delAddr sdk.AccAddress, bondAmt sdk.Int, tokenSrc sdk.BondStatus, + validator types.Validator, subtractAccount bool, +) (newShares sdk.Dec, err error) { // In some situations, the exchange rate becomes invalid, e.g. if // Validator loses all tokens due to slashing. In this case, // make all future delegations invalid. if validator.InvalidExRate() { - return sdk.ZeroDec(), types.ErrDelegatorShareExRateInvalid(k.Codespace()) + return sdk.ZeroDec(), types.ErrDelegatorShareExRateInvalid } // Get or create the delegation object @@ -534,13 +537,14 @@ func (k Keeper) Delegate(ctx sdk.Context, delAddr sdk.AccAddress, bondAmt sdk.In } // unbond a particular delegation and perform associated store operations -func (k Keeper) unbond(ctx sdk.Context, delAddr sdk.AccAddress, valAddr sdk.ValAddress, - shares sdk.Dec) (amount sdk.Int, err sdk.Error) { +func (k Keeper) unbond( + ctx sdk.Context, delAddr sdk.AccAddress, valAddr sdk.ValAddress, shares sdk.Dec, +) (amount sdk.Int, err error) { // check if a delegation object exists in the store delegation, found := k.GetDelegation(ctx, delAddr, valAddr) if !found { - return amount, types.ErrNoDelegatorForAddress(k.Codespace()) + return amount, types.ErrNoDelegatorForAddress } // call the before-delegation-modified hook @@ -548,13 +552,13 @@ func (k Keeper) unbond(ctx sdk.Context, delAddr sdk.AccAddress, valAddr sdk.ValA // ensure that we have enough shares to remove if delegation.Shares.LT(shares) { - return amount, types.ErrNotEnoughDelegationShares(k.Codespace(), delegation.Shares.String()) + return amount, sdkerrors.Wrap(types.ErrNotEnoughDelegationShares, delegation.Shares.String()) } // get validator validator, found := k.GetValidator(ctx, valAddr) if !found { - return amount, types.ErrNoValidatorFound(k.Codespace()) + return amount, types.ErrNoValidatorFound } // subtract shares from delegation @@ -628,15 +632,15 @@ func (k Keeper) getBeginInfo( // processed during the staking EndBlocker. func (k Keeper) Undelegate( ctx sdk.Context, delAddr sdk.AccAddress, valAddr sdk.ValAddress, sharesAmount sdk.Dec, -) (time.Time, sdk.Error) { +) (time.Time, error) { validator, found := k.GetValidator(ctx, valAddr) if !found { - return time.Time{}, types.ErrNoDelegatorForAddress(k.Codespace()) + return time.Time{}, types.ErrNoDelegatorForAddress } if k.HasMaxUnbondingDelegationEntries(ctx, delAddr, valAddr) { - return time.Time{}, types.ErrMaxUnbondingDelegationEntries(k.Codespace()) + return time.Time{}, types.ErrMaxUnbondingDelegationEntries } returnAmount, err := k.unbond(ctx, delAddr, valAddr, sharesAmount) @@ -658,12 +662,10 @@ func (k Keeper) Undelegate( // CompleteUnbonding completes the unbonding of all mature entries in the // retrieved unbonding delegation object. -func (k Keeper) CompleteUnbonding(ctx sdk.Context, delAddr sdk.AccAddress, - valAddr sdk.ValAddress) sdk.Error { - +func (k Keeper) CompleteUnbonding(ctx sdk.Context, delAddr sdk.AccAddress, valAddr sdk.ValAddress) error { ubd, found := k.GetUnbondingDelegation(ctx, delAddr, valAddr) if !found { - return types.ErrNoUnbondingDelegation(k.Codespace()) + return types.ErrNoUnbondingDelegation } ctxTime := ctx.BlockHeader().Time @@ -697,31 +699,31 @@ func (k Keeper) CompleteUnbonding(ctx sdk.Context, delAddr sdk.AccAddress, } // begin unbonding / redelegation; create a redelegation record -func (k Keeper) BeginRedelegation(ctx sdk.Context, delAddr sdk.AccAddress, - valSrcAddr, valDstAddr sdk.ValAddress, sharesAmount sdk.Dec) ( - completionTime time.Time, errSdk sdk.Error) { +func (k Keeper) BeginRedelegation( + ctx sdk.Context, delAddr sdk.AccAddress, valSrcAddr, valDstAddr sdk.ValAddress, sharesAmount sdk.Dec, +) (completionTime time.Time, err error) { if bytes.Equal(valSrcAddr, valDstAddr) { - return time.Time{}, types.ErrSelfRedelegation(k.Codespace()) + return time.Time{}, types.ErrSelfRedelegation } dstValidator, found := k.GetValidator(ctx, valDstAddr) if !found { - return time.Time{}, types.ErrBadRedelegationDst(k.Codespace()) + return time.Time{}, types.ErrBadRedelegationDst } srcValidator, found := k.GetValidator(ctx, valSrcAddr) if !found { - return time.Time{}, types.ErrBadRedelegationDst(k.Codespace()) + return time.Time{}, types.ErrBadRedelegationDst } // check if this is a transitive redelegation if k.HasReceivingRedelegation(ctx, delAddr, valSrcAddr) { - return time.Time{}, types.ErrTransitiveRedelegation(k.Codespace()) + return time.Time{}, types.ErrTransitiveRedelegation } if k.HasMaxRedelegationEntries(ctx, delAddr, valSrcAddr, valDstAddr) { - return time.Time{}, types.ErrMaxRedelegationEntries(k.Codespace()) + return time.Time{}, types.ErrMaxRedelegationEntries } returnAmount, err := k.unbond(ctx, delAddr, valSrcAddr, sharesAmount) @@ -730,7 +732,7 @@ func (k Keeper) BeginRedelegation(ctx sdk.Context, delAddr sdk.AccAddress, } if returnAmount.IsZero() { - return time.Time{}, types.ErrVerySmallRedelegation(k.Codespace()) + return time.Time{}, types.ErrTinyRedelegationAmount } sharesCreated, err := k.Delegate(ctx, delAddr, returnAmount, srcValidator.GetStatus(), dstValidator, false) @@ -745,20 +747,23 @@ func (k Keeper) BeginRedelegation(ctx sdk.Context, delAddr sdk.AccAddress, return completionTime, nil } - red := k.SetRedelegationEntry(ctx, delAddr, valSrcAddr, valDstAddr, - height, completionTime, returnAmount, sharesAmount, sharesCreated) + red := k.SetRedelegationEntry( + ctx, delAddr, valSrcAddr, valDstAddr, + height, completionTime, returnAmount, sharesAmount, sharesCreated, + ) k.InsertRedelegationQueue(ctx, red, completionTime) return completionTime, nil } // CompleteRedelegation completes the unbonding of all mature entries in the // retrieved unbonding delegation object. -func (k Keeper) CompleteRedelegation(ctx sdk.Context, delAddr sdk.AccAddress, - valSrcAddr, valDstAddr sdk.ValAddress) sdk.Error { +func (k Keeper) CompleteRedelegation( + ctx sdk.Context, delAddr sdk.AccAddress, valSrcAddr, valDstAddr sdk.ValAddress, +) error { red, found := k.GetRedelegation(ctx, delAddr, valSrcAddr, valDstAddr) if !found { - return types.ErrNoRedelegation(k.Codespace()) + return types.ErrNoRedelegation } ctxTime := ctx.BlockHeader().Time @@ -787,16 +792,16 @@ func (k Keeper) CompleteRedelegation(ctx sdk.Context, delAddr sdk.AccAddress, // amount of respective shares is returned, otherwise an error is returned. func (k Keeper) ValidateUnbondAmount( ctx sdk.Context, delAddr sdk.AccAddress, valAddr sdk.ValAddress, amt sdk.Int, -) (shares sdk.Dec, err sdk.Error) { +) (shares sdk.Dec, err error) { validator, found := k.GetValidator(ctx, valAddr) if !found { - return shares, types.ErrNoValidatorFound(k.Codespace()) + return shares, types.ErrNoValidatorFound } del, found := k.GetDelegation(ctx, delAddr, valAddr) if !found { - return shares, types.ErrNoDelegation(k.Codespace()) + return shares, types.ErrNoDelegation } shares, err = validator.SharesFromTokens(amt) @@ -811,7 +816,7 @@ func (k Keeper) ValidateUnbondAmount( delShares := del.GetShares() if sharesTruncated.GT(delShares) { - return shares, types.ErrBadSharesAmount(k.Codespace()) + return shares, types.ErrBadSharesAmount } // Cap the shares at the delegation's shares. Shares being greater could occur diff --git a/x/staking/keeper/keeper.go b/x/staking/keeper/keeper.go index a63f5cf1ed68..fd51603115b7 100644 --- a/x/staking/keeper/keeper.go +++ b/x/staking/keeper/keeper.go @@ -29,14 +29,12 @@ type Keeper struct { paramstore params.Subspace validatorCache map[string]cachedValidator validatorCacheList *list.List - - // codespace - codespace sdk.CodespaceType } // NewKeeper creates a new staking Keeper instance -func NewKeeper(cdc *codec.Codec, key sdk.StoreKey, supplyKeeper types.SupplyKeeper, - paramstore params.Subspace, codespace sdk.CodespaceType) Keeper { +func NewKeeper( + cdc *codec.Codec, key sdk.StoreKey, supplyKeeper types.SupplyKeeper, paramstore params.Subspace, +) Keeper { // ensure bonded and not bonded module accounts are set if addr := supplyKeeper.GetModuleAddress(types.BondedPoolName); addr == nil { @@ -55,7 +53,6 @@ func NewKeeper(cdc *codec.Codec, key sdk.StoreKey, supplyKeeper types.SupplyKeep hooks: nil, validatorCache: make(map[string]cachedValidator, aminoCacheSize), validatorCacheList: list.New(), - codespace: codespace, } } @@ -73,11 +70,6 @@ func (k *Keeper) SetHooks(sh types.StakingHooks) *Keeper { return k } -// return the codespace -func (k Keeper) Codespace() sdk.CodespaceType { - return k.codespace -} - // Load the last total validator power. func (k Keeper) GetLastTotalPower(ctx sdk.Context) (power sdk.Int) { store := ctx.KVStore(k.storeKey) diff --git a/x/staking/keeper/pool.go b/x/staking/keeper/pool.go index 4ceb02446d93..004013ed8fe4 100644 --- a/x/staking/keeper/pool.go +++ b/x/staking/keeper/pool.go @@ -35,7 +35,7 @@ func (k Keeper) notBondedTokensToBonded(ctx sdk.Context, tokens sdk.Int) { } // burnBondedTokens removes coins from the bonded pool module account -func (k Keeper) burnBondedTokens(ctx sdk.Context, amt sdk.Int) sdk.Error { +func (k Keeper) burnBondedTokens(ctx sdk.Context, amt sdk.Int) error { if !amt.IsPositive() { // skip as no coins need to be burned return nil @@ -45,7 +45,7 @@ func (k Keeper) burnBondedTokens(ctx sdk.Context, amt sdk.Int) sdk.Error { } // burnNotBondedTokens removes coins from the not bonded pool module account -func (k Keeper) burnNotBondedTokens(ctx sdk.Context, amt sdk.Int) sdk.Error { +func (k Keeper) burnNotBondedTokens(ctx sdk.Context, amt sdk.Int) error { if !amt.IsPositive() { // skip as no coins need to be burned return nil diff --git a/x/staking/keeper/querier.go b/x/staking/keeper/querier.go index 15bc59ee5ff6..bc8a5b5b7fc0 100644 --- a/x/staking/keeper/querier.go +++ b/x/staking/keeper/querier.go @@ -1,7 +1,7 @@ package keeper import ( - "fmt" + "errors" "strings" abci "github.com/tendermint/tendermint/abci/types" @@ -9,53 +9,68 @@ import ( "github.com/cosmos/cosmos-sdk/client" "github.com/cosmos/cosmos-sdk/codec" sdk "github.com/cosmos/cosmos-sdk/types" + sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" "github.com/cosmos/cosmos-sdk/x/staking/types" ) // creates a querier for staking REST endpoints func NewQuerier(k Keeper) sdk.Querier { - return func(ctx sdk.Context, path []string, req abci.RequestQuery) (res []byte, err sdk.Error) { + return func(ctx sdk.Context, path []string, req abci.RequestQuery) ([]byte, error) { switch path[0] { case types.QueryValidators: return queryValidators(ctx, req, k) + case types.QueryValidator: return queryValidator(ctx, req, k) + case types.QueryValidatorDelegations: return queryValidatorDelegations(ctx, req, k) + case types.QueryValidatorUnbondingDelegations: return queryValidatorUnbondingDelegations(ctx, req, k) + case types.QueryDelegation: return queryDelegation(ctx, req, k) + case types.QueryUnbondingDelegation: return queryUnbondingDelegation(ctx, req, k) + case types.QueryDelegatorDelegations: return queryDelegatorDelegations(ctx, req, k) + case types.QueryDelegatorUnbondingDelegations: return queryDelegatorUnbondingDelegations(ctx, req, k) + case types.QueryRedelegations: return queryRedelegations(ctx, req, k) + case types.QueryDelegatorValidators: return queryDelegatorValidators(ctx, req, k) + case types.QueryDelegatorValidator: return queryDelegatorValidator(ctx, req, k) + case types.QueryHistoricalInfo: return queryHistoricalInfo(ctx, req, k) + case types.QueryPool: return queryPool(ctx, k) + case types.QueryParameters: return queryParameters(ctx, k) + default: - return nil, sdk.ErrUnknownRequest("unknown staking query endpoint") + return nil, sdkerrors.Wrapf(sdkerrors.ErrUnknownRequest, "unknown %s query endpoint: %s", types.ModuleName, path[0]) } } } -func queryValidators(ctx sdk.Context, req abci.RequestQuery, k Keeper) ([]byte, sdk.Error) { +func queryValidators(ctx sdk.Context, req abci.RequestQuery, k Keeper) ([]byte, error) { var params types.QueryValidatorsParams err := types.ModuleCdc.UnmarshalJSON(req.Data, ¶ms) if err != nil { - return nil, sdk.ErrInternal(fmt.Sprintf("failed to parse params: %s", err)) + return nil, sdkerrors.Wrap(sdkerrors.ErrJSONUnmarshal, err.Error()) } validators := k.GetAllValidators(ctx) @@ -76,45 +91,45 @@ func queryValidators(ctx sdk.Context, req abci.RequestQuery, k Keeper) ([]byte, res, err := codec.MarshalJSONIndent(types.ModuleCdc, filteredVals) if err != nil { - return nil, sdk.ErrInternal(sdk.AppendMsgToErr("failed to JSON marshal result: %s", err.Error())) + return nil, sdkerrors.Wrap(sdkerrors.ErrJSONMarshal, err.Error()) } return res, nil } -func queryValidator(ctx sdk.Context, req abci.RequestQuery, k Keeper) ([]byte, sdk.Error) { +func queryValidator(ctx sdk.Context, req abci.RequestQuery, k Keeper) ([]byte, error) { var params types.QueryValidatorParams err := types.ModuleCdc.UnmarshalJSON(req.Data, ¶ms) if err != nil { - return nil, sdk.ErrInternal(fmt.Sprintf("failed to parse params: %s", err)) + return nil, sdkerrors.Wrap(sdkerrors.ErrJSONUnmarshal, err.Error()) } validator, found := k.GetValidator(ctx, params.ValidatorAddr) if !found { - return nil, types.ErrNoValidatorFound(types.DefaultCodespace) + return nil, types.ErrNoValidatorFound } res, err := codec.MarshalJSONIndent(types.ModuleCdc, validator) if err != nil { - return nil, sdk.ErrInternal(sdk.AppendMsgToErr("could not marshal result to JSON", err.Error())) + return nil, sdkerrors.Wrap(sdkerrors.ErrJSONMarshal, err.Error()) } return res, nil } -func queryValidatorDelegations(ctx sdk.Context, req abci.RequestQuery, k Keeper) ([]byte, sdk.Error) { +func queryValidatorDelegations(ctx sdk.Context, req abci.RequestQuery, k Keeper) ([]byte, error) { var params types.QueryValidatorParams err := types.ModuleCdc.UnmarshalJSON(req.Data, ¶ms) if err != nil { - return nil, sdk.ErrInternal(fmt.Sprintf("failed to parse params: %s", err)) + return nil, sdkerrors.Wrap(sdkerrors.ErrJSONUnmarshal, err.Error()) } delegations := k.GetValidatorDelegations(ctx, params.ValidatorAddr) delegationResps, err := delegationsToDelegationResponses(ctx, k, delegations) if err != nil { - return nil, sdk.ErrInternal(err.Error()) + return nil, err } if delegationResps == nil { @@ -123,18 +138,18 @@ func queryValidatorDelegations(ctx sdk.Context, req abci.RequestQuery, k Keeper) res, err := codec.MarshalJSONIndent(types.ModuleCdc, delegationResps) if err != nil { - return nil, sdk.ErrInternal(sdk.AppendMsgToErr("failed to marshal result to JSON", err.Error())) + return nil, sdkerrors.Wrap(sdkerrors.ErrJSONMarshal, err.Error()) } return res, nil } -func queryValidatorUnbondingDelegations(ctx sdk.Context, req abci.RequestQuery, k Keeper) ([]byte, sdk.Error) { +func queryValidatorUnbondingDelegations(ctx sdk.Context, req abci.RequestQuery, k Keeper) ([]byte, error) { var params types.QueryValidatorParams err := types.ModuleCdc.UnmarshalJSON(req.Data, ¶ms) if err != nil { - return nil, sdk.ErrInternal(fmt.Sprintf("failed to parse params: %s", err)) + return nil, sdkerrors.Wrap(sdkerrors.ErrJSONUnmarshal, err.Error()) } unbonds := k.GetUnbondingDelegationsFromValidator(ctx, params.ValidatorAddr) @@ -144,24 +159,24 @@ func queryValidatorUnbondingDelegations(ctx sdk.Context, req abci.RequestQuery, res, err := codec.MarshalJSONIndent(types.ModuleCdc, unbonds) if err != nil { - return nil, sdk.ErrInternal(sdk.AppendMsgToErr("could not marshal result to JSON", err.Error())) + return nil, sdkerrors.Wrap(sdkerrors.ErrJSONMarshal, err.Error()) } return res, nil } -func queryDelegatorDelegations(ctx sdk.Context, req abci.RequestQuery, k Keeper) ([]byte, sdk.Error) { +func queryDelegatorDelegations(ctx sdk.Context, req abci.RequestQuery, k Keeper) ([]byte, error) { var params types.QueryDelegatorParams err := types.ModuleCdc.UnmarshalJSON(req.Data, ¶ms) if err != nil { - return nil, sdk.ErrInternal(fmt.Sprintf("failed to parse params: %s", err)) + return nil, sdkerrors.Wrap(sdkerrors.ErrJSONUnmarshal, err.Error()) } delegations := k.GetAllDelegatorDelegations(ctx, params.DelegatorAddr) delegationResps, err := delegationsToDelegationResponses(ctx, k, delegations) if err != nil { - return nil, sdk.ErrInternal(err.Error()) + return nil, err } if delegationResps == nil { @@ -170,18 +185,18 @@ func queryDelegatorDelegations(ctx sdk.Context, req abci.RequestQuery, k Keeper) res, err := codec.MarshalJSONIndent(types.ModuleCdc, delegationResps) if err != nil { - return nil, sdk.ErrInternal(sdk.AppendMsgToErr("failed to marshal result to JSON", err.Error())) + return nil, sdkerrors.Wrap(sdkerrors.ErrJSONMarshal, err.Error()) } return res, nil } -func queryDelegatorUnbondingDelegations(ctx sdk.Context, req abci.RequestQuery, k Keeper) ([]byte, sdk.Error) { +func queryDelegatorUnbondingDelegations(ctx sdk.Context, req abci.RequestQuery, k Keeper) ([]byte, error) { var params types.QueryDelegatorParams err := types.ModuleCdc.UnmarshalJSON(req.Data, ¶ms) if err != nil { - return nil, sdk.ErrInternal(fmt.Sprintf("failed to parse params: %s", err)) + return nil, sdkerrors.Wrap(sdkerrors.ErrJSONUnmarshal, err.Error()) } unbondingDelegations := k.GetAllUnbondingDelegations(ctx, params.DelegatorAddr) @@ -191,20 +206,20 @@ func queryDelegatorUnbondingDelegations(ctx sdk.Context, req abci.RequestQuery, res, err := codec.MarshalJSONIndent(types.ModuleCdc, unbondingDelegations) if err != nil { - return nil, sdk.ErrInternal(sdk.AppendMsgToErr("could not marshal result to JSON", err.Error())) + return nil, sdkerrors.Wrap(sdkerrors.ErrJSONMarshal, err.Error()) } return res, nil } -func queryDelegatorValidators(ctx sdk.Context, req abci.RequestQuery, k Keeper) ([]byte, sdk.Error) { +func queryDelegatorValidators(ctx sdk.Context, req abci.RequestQuery, k Keeper) ([]byte, error) { var params types.QueryDelegatorParams stakingParams := k.GetParams(ctx) err := types.ModuleCdc.UnmarshalJSON(req.Data, ¶ms) if err != nil { - return nil, sdk.ErrInternal(fmt.Sprintf("failed to parse params: %s", err)) + return nil, sdkerrors.Wrap(sdkerrors.ErrJSONUnmarshal, err.Error()) } validators := k.GetDelegatorValidators(ctx, params.DelegatorAddr, stakingParams.MaxValidators) @@ -214,86 +229,86 @@ func queryDelegatorValidators(ctx sdk.Context, req abci.RequestQuery, k Keeper) res, err := codec.MarshalJSONIndent(types.ModuleCdc, validators) if err != nil { - return nil, sdk.ErrInternal(sdk.AppendMsgToErr("could not marshal result to JSON", err.Error())) + return nil, sdkerrors.Wrap(sdkerrors.ErrJSONMarshal, err.Error()) } return res, nil } -func queryDelegatorValidator(ctx sdk.Context, req abci.RequestQuery, k Keeper) ([]byte, sdk.Error) { +func queryDelegatorValidator(ctx sdk.Context, req abci.RequestQuery, k Keeper) ([]byte, error) { var params types.QueryBondsParams err := types.ModuleCdc.UnmarshalJSON(req.Data, ¶ms) if err != nil { - return nil, sdk.ErrInternal(fmt.Sprintf("failed to parse params: %s", err)) + return nil, sdkerrors.Wrap(sdkerrors.ErrJSONUnmarshal, err.Error()) } validator, err := k.GetDelegatorValidator(ctx, params.DelegatorAddr, params.ValidatorAddr) if err != nil { - return nil, sdk.ErrInternal(err.Error()) + return nil, err } res, err := codec.MarshalJSONIndent(types.ModuleCdc, validator) if err != nil { - return nil, sdk.ErrInternal(sdk.AppendMsgToErr("could not marshal result to JSON", err.Error())) + return nil, sdkerrors.Wrap(sdkerrors.ErrJSONMarshal, err.Error()) } return res, nil } -func queryDelegation(ctx sdk.Context, req abci.RequestQuery, k Keeper) ([]byte, sdk.Error) { +func queryDelegation(ctx sdk.Context, req abci.RequestQuery, k Keeper) ([]byte, error) { var params types.QueryBondsParams err := types.ModuleCdc.UnmarshalJSON(req.Data, ¶ms) if err != nil { - return nil, sdk.ErrInternal(fmt.Sprintf("failed to parse params: %s", err)) + return nil, sdkerrors.Wrap(sdkerrors.ErrJSONUnmarshal, err.Error()) } delegation, found := k.GetDelegation(ctx, params.DelegatorAddr, params.ValidatorAddr) if !found { - return nil, types.ErrNoDelegation(types.DefaultCodespace) + return nil, types.ErrNoDelegation } delegationResp, err := delegationToDelegationResponse(ctx, k, delegation) if err != nil { - return nil, sdk.ErrInternal(err.Error()) + return nil, err } res, err := codec.MarshalJSONIndent(types.ModuleCdc, delegationResp) if err != nil { - return nil, sdk.ErrInternal(sdk.AppendMsgToErr("failed to marshal result to JSON", err.Error())) + return nil, sdkerrors.Wrap(sdkerrors.ErrJSONMarshal, err.Error()) } return res, nil } -func queryUnbondingDelegation(ctx sdk.Context, req abci.RequestQuery, k Keeper) ([]byte, sdk.Error) { +func queryUnbondingDelegation(ctx sdk.Context, req abci.RequestQuery, k Keeper) ([]byte, error) { var params types.QueryBondsParams err := types.ModuleCdc.UnmarshalJSON(req.Data, ¶ms) if err != nil { - return nil, sdk.ErrInternal(fmt.Sprintf("failed to parse params: %s", err)) + return nil, sdkerrors.Wrap(sdkerrors.ErrJSONUnmarshal, err.Error()) } unbond, found := k.GetUnbondingDelegation(ctx, params.DelegatorAddr, params.ValidatorAddr) if !found { - return nil, types.ErrNoUnbondingDelegation(types.DefaultCodespace) + return nil, types.ErrNoUnbondingDelegation } res, err := codec.MarshalJSONIndent(types.ModuleCdc, unbond) if err != nil { - return nil, sdk.ErrInternal(sdk.AppendMsgToErr("could not marshal result to JSON", err.Error())) + return nil, sdkerrors.Wrap(sdkerrors.ErrJSONMarshal, err.Error()) } return res, nil } -func queryRedelegations(ctx sdk.Context, req abci.RequestQuery, k Keeper) ([]byte, sdk.Error) { +func queryRedelegations(ctx sdk.Context, req abci.RequestQuery, k Keeper) ([]byte, error) { var params types.QueryRedelegationParams err := types.ModuleCdc.UnmarshalJSON(req.Data, ¶ms) if err != nil { - return nil, sdk.ErrUnknownRequest(string(req.Data)) + return nil, sdkerrors.Wrap(sdkerrors.ErrJSONUnmarshal, err.Error()) } var redels []types.Redelegation @@ -302,7 +317,7 @@ func queryRedelegations(ctx sdk.Context, req abci.RequestQuery, k Keeper) ([]byt case !params.DelegatorAddr.Empty() && !params.SrcValidatorAddr.Empty() && !params.DstValidatorAddr.Empty(): redel, found := k.GetRedelegation(ctx, params.DelegatorAddr, params.SrcValidatorAddr, params.DstValidatorAddr) if !found { - return nil, types.ErrNoRedelegation(types.DefaultCodespace) + return nil, types.ErrNoRedelegation } redels = []types.Redelegation{redel} @@ -314,7 +329,7 @@ func queryRedelegations(ctx sdk.Context, req abci.RequestQuery, k Keeper) ([]byt redelResponses, err := redelegationsToRedelegationResponses(ctx, k, redels) if err != nil { - return nil, sdk.ErrInternal(err.Error()) + return nil, err } if redelResponses == nil { @@ -323,39 +338,40 @@ func queryRedelegations(ctx sdk.Context, req abci.RequestQuery, k Keeper) ([]byt res, err := codec.MarshalJSONIndent(types.ModuleCdc, redelResponses) if err != nil { - return nil, sdk.ErrInternal(sdk.AppendMsgToErr("failed to marshal result to JSON", err.Error())) + return nil, sdkerrors.Wrap(sdkerrors.ErrJSONMarshal, err.Error()) } return res, nil } -func queryHistoricalInfo(ctx sdk.Context, req abci.RequestQuery, k Keeper) ([]byte, sdk.Error) { +func queryHistoricalInfo(ctx sdk.Context, req abci.RequestQuery, k Keeper) ([]byte, error) { var params types.QueryHistoricalInfoParams err := types.ModuleCdc.UnmarshalJSON(req.Data, ¶ms) if err != nil { - return nil, sdk.ErrUnknownRequest(string(req.Data)) + return nil, sdkerrors.Wrap(sdkerrors.ErrJSONUnmarshal, err.Error()) } hi, found := k.GetHistoricalInfo(ctx, params.Height) if !found { - return nil, types.ErrNoHistoricalInfo(types.DefaultCodespace) + return nil, types.ErrNoHistoricalInfo } res, err := codec.MarshalJSONIndent(types.ModuleCdc, hi) if err != nil { - return nil, sdk.ErrInternal(sdk.AppendMsgToErr("could not marshal result to JSON", err.Error())) + return nil, sdkerrors.Wrap(sdkerrors.ErrJSONMarshal, err.Error()) } return res, nil } -func queryPool(ctx sdk.Context, k Keeper) ([]byte, sdk.Error) { +func queryPool(ctx sdk.Context, k Keeper) ([]byte, error) { bondDenom := k.BondDenom(ctx) + bondedPool := k.GetBondedPool(ctx) notBondedPool := k.GetNotBondedPool(ctx) if bondedPool == nil || notBondedPool == nil { - return nil, sdk.ErrInternal("pool accounts haven't been set") + return nil, errors.New("pool accounts haven't been set") } pool := types.NewPool( @@ -365,18 +381,18 @@ func queryPool(ctx sdk.Context, k Keeper) ([]byte, sdk.Error) { res, err := codec.MarshalJSONIndent(types.ModuleCdc, pool) if err != nil { - return nil, sdk.ErrInternal(sdk.AppendMsgToErr("could not marshal result to JSON", err.Error())) + return nil, sdkerrors.Wrap(sdkerrors.ErrJSONMarshal, err.Error()) } return res, nil } -func queryParameters(ctx sdk.Context, k Keeper) ([]byte, sdk.Error) { +func queryParameters(ctx sdk.Context, k Keeper) ([]byte, error) { params := k.GetParams(ctx) res, err := codec.MarshalJSONIndent(types.ModuleCdc, params) if err != nil { - return nil, sdk.ErrInternal(sdk.AppendMsgToErr("could not marshal result to JSON", err.Error())) + return nil, sdkerrors.Wrap(sdkerrors.ErrJSONMarshal, err.Error()) } return res, nil @@ -385,10 +401,10 @@ func queryParameters(ctx sdk.Context, k Keeper) ([]byte, sdk.Error) { //______________________________________________________ // util -func delegationToDelegationResponse(ctx sdk.Context, k Keeper, del types.Delegation) (types.DelegationResponse, sdk.Error) { +func delegationToDelegationResponse(ctx sdk.Context, k Keeper, del types.Delegation) (types.DelegationResponse, error) { val, found := k.GetValidator(ctx, del.ValidatorAddress) if !found { - return types.DelegationResponse{}, types.ErrNoValidatorFound(types.DefaultCodespace) + return types.DelegationResponse{}, types.ErrNoValidatorFound } return types.NewDelegationResp( @@ -401,7 +417,7 @@ func delegationToDelegationResponse(ctx sdk.Context, k Keeper, del types.Delegat func delegationsToDelegationResponses( ctx sdk.Context, k Keeper, delegations types.Delegations, -) (types.DelegationResponses, sdk.Error) { +) (types.DelegationResponses, error) { resp := make(types.DelegationResponses, len(delegations)) for i, del := range delegations { @@ -418,13 +434,13 @@ func delegationsToDelegationResponses( func redelegationsToRedelegationResponses( ctx sdk.Context, k Keeper, redels types.Redelegations, -) (types.RedelegationResponses, sdk.Error) { +) (types.RedelegationResponses, error) { resp := make(types.RedelegationResponses, len(redels)) for i, redel := range redels { val, found := k.GetValidator(ctx, redel.ValidatorDstAddress) if !found { - return nil, types.ErrNoValidatorFound(types.DefaultCodespace) + return nil, types.ErrNoValidatorFound } entryResponses := make([]types.RedelegationEntryResponse, len(redel.Entries)) diff --git a/x/staking/keeper/query_utils.go b/x/staking/keeper/query_utils.go index 6bde68f5df6e..336bb842ab9e 100644 --- a/x/staking/keeper/query_utils.go +++ b/x/staking/keeper/query_utils.go @@ -21,7 +21,7 @@ func (k Keeper) GetDelegatorValidators(ctx sdk.Context, delegatorAddr sdk.AccAdd validator, found := k.GetValidator(ctx, delegation.ValidatorAddress) if !found { - panic(types.ErrNoValidatorFound(types.DefaultCodespace)) + panic(types.ErrNoValidatorFound) } validators[i] = validator i++ @@ -31,16 +31,16 @@ func (k Keeper) GetDelegatorValidators(ctx sdk.Context, delegatorAddr sdk.AccAdd // return a validator that a delegator is bonded to func (k Keeper) GetDelegatorValidator(ctx sdk.Context, delegatorAddr sdk.AccAddress, - validatorAddr sdk.ValAddress) (validator types.Validator, err sdk.Error) { + validatorAddr sdk.ValAddress) (validator types.Validator, err error) { delegation, found := k.GetDelegation(ctx, delegatorAddr, validatorAddr) if !found { - return validator, types.ErrNoDelegation(types.DefaultCodespace) + return validator, types.ErrNoDelegation } validator, found = k.GetValidator(ctx, delegation.ValidatorAddress) if !found { - panic(types.ErrNoValidatorFound(types.DefaultCodespace)) + panic(types.ErrNoValidatorFound) } return } diff --git a/x/staking/keeper/test_common.go b/x/staking/keeper/test_common.go index 51d7f71ae9d6..0d730b48b3ca 100644 --- a/x/staking/keeper/test_common.go +++ b/x/staking/keeper/test_common.go @@ -115,7 +115,7 @@ func CreateTestInput(t *testing.T, isCheckTx bool, initPower int64) (sdk.Context blacklistedAddrs[notBondedPool.GetAddress().String()] = true blacklistedAddrs[bondPool.GetAddress().String()] = true - pk := params.NewKeeper(cdc, keyParams, tkeyParams, params.DefaultCodespace) + pk := params.NewKeeper(cdc, keyParams, tkeyParams) accountKeeper := auth.NewAccountKeeper( cdc, // amino codec @@ -127,7 +127,6 @@ func CreateTestInput(t *testing.T, isCheckTx bool, initPower int64) (sdk.Context bk := bank.NewBaseKeeper( accountKeeper, pk.Subspace(bank.DefaultParamspace), - bank.DefaultCodespace, blacklistedAddrs, ) @@ -144,7 +143,7 @@ func CreateTestInput(t *testing.T, isCheckTx bool, initPower int64) (sdk.Context supplyKeeper.SetSupply(ctx, supply.NewSupply(totalSupply)) - keeper := NewKeeper(cdc, keyStaking, supplyKeeper, pk.Subspace(DefaultParamspace), types.DefaultCodespace) + keeper := NewKeeper(cdc, keyStaking, supplyKeeper, pk.Subspace(DefaultParamspace)) keeper.SetParams(ctx, types.DefaultParams()) // set module accounts diff --git a/x/staking/keeper/validator.go b/x/staking/keeper/validator.go index cd5e912ca92a..48ecbb384313 100644 --- a/x/staking/keeper/validator.go +++ b/x/staking/keeper/validator.go @@ -156,7 +156,7 @@ func (k Keeper) RemoveValidatorTokens(ctx sdk.Context, // UpdateValidatorCommission attempts to update a validator's commission rate. // An error is returned if the new commission rate is invalid. func (k Keeper) UpdateValidatorCommission(ctx sdk.Context, - validator types.Validator, newRate sdk.Dec) (types.Commission, sdk.Error) { + validator types.Validator, newRate sdk.Dec) (types.Commission, error) { commission := validator.Commission blockTime := ctx.BlockHeader().Time diff --git a/x/staking/simulation/operations.go b/x/staking/simulation/operations.go index 8ddea88aa7c6..b1a932270641 100644 --- a/x/staking/simulation/operations.go +++ b/x/staking/simulation/operations.go @@ -1,7 +1,6 @@ package simulation import ( - "errors" "fmt" "math/rand" @@ -161,9 +160,9 @@ func SimulateMsgCreateValidator(ak types.AccountKeeper, k keeper.Keeper) simulat simAccount.PrivKey, ) - res := app.Deliver(tx) - if !res.IsOK() { - return simulation.NoOpMsg(types.ModuleName), nil, errors.New(res.Log) + _, _, err = app.Deliver(tx) + if err != nil { + return simulation.NoOpMsg(types.ModuleName), nil, err } return simulation.NewOperationMsg(msg, true, ""), nil, nil @@ -226,9 +225,9 @@ func SimulateMsgEditValidator(ak types.AccountKeeper, k keeper.Keeper) simulatio simAccount.PrivKey, ) - res := app.Deliver(tx) - if !res.IsOK() { - return simulation.NoOpMsg(types.ModuleName), nil, errors.New(res.Log) + _, _, err = app.Deliver(tx) + if err != nil { + return simulation.NoOpMsg(types.ModuleName), nil, err } return simulation.NewOperationMsg(msg, true, ""), nil, nil @@ -293,9 +292,9 @@ func SimulateMsgDelegate(ak types.AccountKeeper, k keeper.Keeper) simulation.Ope simAccount.PrivKey, ) - res := app.Deliver(tx) - if !res.IsOK() { - return simulation.NoOpMsg(types.ModuleName), nil, errors.New(res.Log) + _, _, err = app.Deliver(tx) + if err != nil { + return simulation.NoOpMsg(types.ModuleName), nil, err } return simulation.NewOperationMsg(msg, true, ""), nil, nil @@ -373,9 +372,9 @@ func SimulateMsgUndelegate(ak types.AccountKeeper, k keeper.Keeper) simulation.O simAccount.PrivKey, ) - res := app.Deliver(tx) - if !res.IsOK() { - return simulation.NoOpMsg(types.ModuleName), nil, errors.New(res.Log) + _, _, err = app.Deliver(tx) + if err != nil { + return simulation.NoOpMsg(types.ModuleName), nil, err } return simulation.NewOperationMsg(msg, true, ""), nil, nil @@ -479,9 +478,9 @@ func SimulateMsgBeginRedelegate(ak types.AccountKeeper, k keeper.Keeper) simulat simAccount.PrivKey, ) - res := app.Deliver(tx) - if !res.IsOK() { - return simulation.NoOpMsg(types.ModuleName), nil, errors.New(res.Log) + _, _, err = app.Deliver(tx) + if err != nil { + return simulation.NoOpMsg(types.ModuleName), nil, err } return simulation.NewOperationMsg(msg, true, ""), nil, nil diff --git a/x/staking/types/commission.go b/x/staking/types/commission.go index f447c452822f..38ab8e06a703 100644 --- a/x/staking/types/commission.go +++ b/x/staking/types/commission.go @@ -67,31 +67,31 @@ func (c Commission) String() string { // Validate performs basic sanity validation checks of initial commission // parameters. If validation fails, an SDK error is returned. -func (c CommissionRates) Validate() sdk.Error { +func (c CommissionRates) Validate() error { switch { case c.MaxRate.IsNegative(): // max rate cannot be negative - return ErrCommissionNegative(DefaultCodespace) + return ErrCommissionNegative case c.MaxRate.GT(sdk.OneDec()): // max rate cannot be greater than 1 - return ErrCommissionHuge(DefaultCodespace) + return ErrCommissionHuge case c.Rate.IsNegative(): // rate cannot be negative - return ErrCommissionNegative(DefaultCodespace) + return ErrCommissionNegative case c.Rate.GT(c.MaxRate): // rate cannot be greater than the max rate - return ErrCommissionGTMaxRate(DefaultCodespace) + return ErrCommissionGTMaxRate case c.MaxChangeRate.IsNegative(): // change rate cannot be negative - return ErrCommissionChangeRateNegative(DefaultCodespace) + return ErrCommissionChangeRateNegative case c.MaxChangeRate.GT(c.MaxRate): // change rate cannot be greater than the max rate - return ErrCommissionChangeRateGTMaxRate(DefaultCodespace) + return ErrCommissionChangeRateGTMaxRate } return nil @@ -99,23 +99,23 @@ func (c CommissionRates) Validate() sdk.Error { // ValidateNewRate performs basic sanity validation checks of a new commission // rate. If validation fails, an SDK error is returned. -func (c Commission) ValidateNewRate(newRate sdk.Dec, blockTime time.Time) sdk.Error { +func (c Commission) ValidateNewRate(newRate sdk.Dec, blockTime time.Time) error { switch { case blockTime.Sub(c.UpdateTime).Hours() < 24: // new rate cannot be changed more than once within 24 hours - return ErrCommissionUpdateTime(DefaultCodespace) + return ErrCommissionUpdateTime case newRate.IsNegative(): // new rate cannot be negative - return ErrCommissionNegative(DefaultCodespace) + return ErrCommissionNegative case newRate.GT(c.MaxRate): // new rate cannot be greater than the max rate - return ErrCommissionGTMaxRate(DefaultCodespace) + return ErrCommissionGTMaxRate case newRate.Sub(c.Rate).GT(c.MaxChangeRate): // new rate % points change cannot be greater than the max change rate - return ErrCommissionGTMaxChangeRate(DefaultCodespace) + return ErrCommissionGTMaxChangeRate } return nil diff --git a/x/staking/types/errors.go b/x/staking/types/errors.go index 523e720e2d98..d3ccf0a9dac2 100644 --- a/x/staking/types/errors.go +++ b/x/staking/types/errors.go @@ -1,223 +1,59 @@ -// nolint package types import ( - "fmt" - "strings" - "time" - - sdk "github.com/cosmos/cosmos-sdk/types" + sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" ) -type CodeType = sdk.CodeType - -const ( - DefaultCodespace sdk.CodespaceType = ModuleName - - CodeInvalidValidator CodeType = 101 - CodeInvalidDelegation CodeType = 102 - CodeInvalidInput CodeType = 103 - CodeValidatorJailed CodeType = 104 - CodeInvalidHistoricalInfo CodeType = 105 - CodeInvalidAddress CodeType = sdk.CodeInvalidAddress - CodeUnauthorized CodeType = sdk.CodeUnauthorized - CodeInternal CodeType = sdk.CodeInternal - CodeUnknownRequest CodeType = sdk.CodeUnknownRequest +// x/staking module sentinel errors +// +// TODO: Many of these errors are redundant. They should be removed and replaced +// by sdkerrors.ErrInvalidRequest. +// +// REF: https://github.com/cosmos/cosmos-sdk/issues/5450 +var ( + ErrEmptyValidatorAddr = sdkerrors.Register(ModuleName, 1, "empty validator address") + ErrBadValidatorAddr = sdkerrors.Register(ModuleName, 2, "validator address is invalid") + ErrNoValidatorFound = sdkerrors.Register(ModuleName, 3, "validator does not exist") + ErrValidatorOwnerExists = sdkerrors.Register(ModuleName, 4, "validator already exist for this operator address; must use new validator operator address") + ErrValidatorPubKeyExists = sdkerrors.Register(ModuleName, 5, "validator already exist for this pubkey; must use new validator pubkey") + ErrValidatorPubKeyTypeNotSupported = sdkerrors.Register(ModuleName, 6, "validator pubkey type is not supported") + ErrValidatorJailed = sdkerrors.Register(ModuleName, 7, "validator for this address is currently jailed") + ErrBadRemoveValidator = sdkerrors.Register(ModuleName, 8, "failed to remove validator") + ErrCommissionNegative = sdkerrors.Register(ModuleName, 9, "commission must be positive") + ErrCommissionHuge = sdkerrors.Register(ModuleName, 10, "commission cannot be more than 100%") + ErrCommissionGTMaxRate = sdkerrors.Register(ModuleName, 11, "commission cannot be more than the max rate") + ErrCommissionUpdateTime = sdkerrors.Register(ModuleName, 12, "commission cannot be changed more than once in 24h") + ErrCommissionChangeRateNegative = sdkerrors.Register(ModuleName, 13, "commission change rate must be positive") + ErrCommissionChangeRateGTMaxRate = sdkerrors.Register(ModuleName, 14, "commission change rate cannot be more than the max rate") + ErrCommissionGTMaxChangeRate = sdkerrors.Register(ModuleName, 15, "commission cannot be changed more than max change rate") + ErrSelfDelegationBelowMinimum = sdkerrors.Register(ModuleName, 16, "validator's self delegation must be greater than their minimum self delegation") + ErrMinSelfDelegationInvalid = sdkerrors.Register(ModuleName, 17, "minimum self delegation must be a positive integer") + ErrMinSelfDelegationDecreased = sdkerrors.Register(ModuleName, 18, "minimum self delegation cannot be decrease") + ErrEmptyDelegatorAddr = sdkerrors.Register(ModuleName, 19, "empty delegator address") + ErrBadDenom = sdkerrors.Register(ModuleName, 20, "invalid coin denomination") + ErrBadDelegationAddr = sdkerrors.Register(ModuleName, 21, "invalid address for (address, validator) tuple") + ErrBadDelegationAmount = sdkerrors.Register(ModuleName, 22, "invalid delegation amount") + ErrNoDelegation = sdkerrors.Register(ModuleName, 23, "no delegation for (address, validator) tuple") + ErrBadDelegatorAddr = sdkerrors.Register(ModuleName, 24, "delegator does not exist with address") + ErrNoDelegatorForAddress = sdkerrors.Register(ModuleName, 25, "delegator does not contain delegation") + ErrInsufficientShares = sdkerrors.Register(ModuleName, 26, "insufficient delegation shares") + ErrDelegationValidatorEmpty = sdkerrors.Register(ModuleName, 27, "cannot delegate to an empty validator") + ErrNotEnoughDelegationShares = sdkerrors.Register(ModuleName, 28, "not enough delegation shares") + ErrBadSharesAmount = sdkerrors.Register(ModuleName, 29, "invalid shares amount") + ErrBadSharesPercent = sdkerrors.Register(ModuleName, 30, "Invalid shares percent") + ErrNotMature = sdkerrors.Register(ModuleName, 31, "entry not mature") + ErrNoUnbondingDelegation = sdkerrors.Register(ModuleName, 32, "no unbonding delegation found") + ErrMaxUnbondingDelegationEntries = sdkerrors.Register(ModuleName, 33, "too many unbonding delegation entries for (delegator, validator) tuple") + ErrBadRedelegationAddr = sdkerrors.Register(ModuleName, 34, "invalid address for (address, src-validator, dst-validator) tuple") + ErrNoRedelegation = sdkerrors.Register(ModuleName, 35, "no redelegation found") + ErrSelfRedelegation = sdkerrors.Register(ModuleName, 36, "cannot redelegate to the same validator") + ErrTinyRedelegationAmount = sdkerrors.Register(ModuleName, 37, "too few tokens to redelegate (truncates to zero tokens)") + ErrBadRedelegationDst = sdkerrors.Register(ModuleName, 38, "redelegation destination validator not found") + ErrTransitiveRedelegation = sdkerrors.Register(ModuleName, 39, "redelegation to this validator already in progress; first redelegation to this validator must complete before next redelegation") + ErrMaxRedelegationEntries = sdkerrors.Register(ModuleName, 40, "too many redelegation entries for (delegator, src-validator, dst-validator) tuple") + ErrDelegatorShareExRateInvalid = sdkerrors.Register(ModuleName, 41, "cannot delegate to validators with invalid (zero) ex-rate") + ErrBothShareMsgsGiven = sdkerrors.Register(ModuleName, 42, "both shares amount and shares percent provided") + ErrNeitherShareMsgsGiven = sdkerrors.Register(ModuleName, 43, "neither shares amount nor shares percent provided") + ErrInvalidHistoricalInfo = sdkerrors.Register(ModuleName, 44, "invalid historical info") + ErrNoHistoricalInfo = sdkerrors.Register(ModuleName, 45, "no historical info found") ) - -//validator -func ErrNilValidatorAddr(codespace sdk.CodespaceType) sdk.Error { - return sdk.NewError(codespace, CodeInvalidInput, "validator address is nil") -} - -func ErrBadValidatorAddr(codespace sdk.CodespaceType) sdk.Error { - return sdk.NewError(codespace, CodeInvalidAddress, "validator address is invalid") -} - -func ErrNoValidatorFound(codespace sdk.CodespaceType) sdk.Error { - return sdk.NewError(codespace, CodeInvalidValidator, "validator does not exist for that address") -} - -func ErrValidatorOwnerExists(codespace sdk.CodespaceType) sdk.Error { - return sdk.NewError(codespace, CodeInvalidValidator, "validator already exist for this operator address, must use new validator operator address") -} - -func ErrValidatorPubKeyExists(codespace sdk.CodespaceType) sdk.Error { - return sdk.NewError(codespace, CodeInvalidValidator, "validator already exist for this pubkey, must use new validator pubkey") -} - -func ErrValidatorPubKeyTypeNotSupported(codespace sdk.CodespaceType, keyType string, supportedTypes []string) sdk.Error { - msg := fmt.Sprintf("validator pubkey type %s is not supported, must use %s", keyType, strings.Join(supportedTypes, ",")) - return sdk.NewError(codespace, CodeInvalidValidator, msg) -} - -func ErrValidatorJailed(codespace sdk.CodespaceType) sdk.Error { - return sdk.NewError(codespace, CodeInvalidValidator, "validator for this address is currently jailed") -} - -func ErrBadRemoveValidator(codespace sdk.CodespaceType) sdk.Error { - return sdk.NewError(codespace, CodeInvalidValidator, "error removing validator") -} - -func ErrDescriptionLength(codespace sdk.CodespaceType, descriptor string, got, max int) sdk.Error { - msg := fmt.Sprintf("bad description length for %v, got length %v, max is %v", descriptor, got, max) - return sdk.NewError(codespace, CodeInvalidValidator, msg) -} - -func ErrCommissionNegative(codespace sdk.CodespaceType) sdk.Error { - return sdk.NewError(codespace, CodeInvalidValidator, "commission must be positive") -} - -func ErrCommissionHuge(codespace sdk.CodespaceType) sdk.Error { - return sdk.NewError(codespace, CodeInvalidValidator, "commission cannot be more than 100%") -} - -func ErrCommissionGTMaxRate(codespace sdk.CodespaceType) sdk.Error { - return sdk.NewError(codespace, CodeInvalidValidator, "commission cannot be more than the max rate") -} - -func ErrCommissionUpdateTime(codespace sdk.CodespaceType) sdk.Error { - return sdk.NewError(codespace, CodeInvalidValidator, "commission cannot be changed more than once in 24h") -} - -func ErrCommissionChangeRateNegative(codespace sdk.CodespaceType) sdk.Error { - return sdk.NewError(codespace, CodeInvalidValidator, "commission change rate must be positive") -} - -func ErrCommissionChangeRateGTMaxRate(codespace sdk.CodespaceType) sdk.Error { - return sdk.NewError(codespace, CodeInvalidValidator, "commission change rate cannot be more than the max rate") -} - -func ErrCommissionGTMaxChangeRate(codespace sdk.CodespaceType) sdk.Error { - return sdk.NewError(codespace, CodeInvalidValidator, "commission cannot be changed more than max change rate") -} - -func ErrSelfDelegationBelowMinimum(codespace sdk.CodespaceType) sdk.Error { - return sdk.NewError(codespace, CodeInvalidValidator, "validator's self delegation must be greater than their minimum self delegation") -} - -func ErrMinSelfDelegationInvalid(codespace sdk.CodespaceType) sdk.Error { - return sdk.NewError(codespace, CodeInvalidValidator, "minimum self delegation must be a positive integer") -} - -func ErrMinSelfDelegationDecreased(codespace sdk.CodespaceType) sdk.Error { - return sdk.NewError(codespace, CodeInvalidValidator, "minimum self delegation cannot be decrease") -} - -func ErrNilDelegatorAddr(codespace sdk.CodespaceType) sdk.Error { - return sdk.NewError(codespace, CodeInvalidInput, "delegator address is nil") -} - -func ErrBadDenom(codespace sdk.CodespaceType) sdk.Error { - return sdk.NewError(codespace, CodeInvalidDelegation, "invalid coin denomination") -} - -func ErrBadDelegationAddr(codespace sdk.CodespaceType) sdk.Error { - return sdk.NewError(codespace, CodeInvalidInput, "unexpected address length for this (address, validator) pair") -} - -func ErrBadDelegationAmount(codespace sdk.CodespaceType) sdk.Error { - return sdk.NewError(codespace, CodeInvalidDelegation, "amount must be > 0") -} - -func ErrNoDelegation(codespace sdk.CodespaceType) sdk.Error { - return sdk.NewError(codespace, CodeInvalidDelegation, "no delegation for this (address, validator) pair") -} - -func ErrBadDelegatorAddr(codespace sdk.CodespaceType) sdk.Error { - return sdk.NewError(codespace, CodeInvalidDelegation, "delegator does not exist for that address") -} - -func ErrNoDelegatorForAddress(codespace sdk.CodespaceType) sdk.Error { - return sdk.NewError(codespace, CodeInvalidDelegation, "delegator does not contain this delegation") -} - -func ErrInsufficientShares(codespace sdk.CodespaceType) sdk.Error { - return sdk.NewError(codespace, CodeInvalidDelegation, "insufficient delegation shares") -} - -func ErrDelegationValidatorEmpty(codespace sdk.CodespaceType) sdk.Error { - return sdk.NewError(codespace, CodeInvalidDelegation, "cannot delegate to an empty validator") -} - -func ErrNotEnoughDelegationShares(codespace sdk.CodespaceType, shares string) sdk.Error { - return sdk.NewError(codespace, CodeInvalidDelegation, fmt.Sprintf("not enough shares only have %v", shares)) -} - -func ErrBadSharesAmount(codespace sdk.CodespaceType) sdk.Error { - return sdk.NewError(codespace, CodeInvalidDelegation, "shares must be > 0") -} - -func ErrBadSharesPercent(codespace sdk.CodespaceType) sdk.Error { - return sdk.NewError(codespace, CodeInvalidDelegation, "shares percent must be >0 and <=1") -} - -func ErrNotMature(codespace sdk.CodespaceType, operation, descriptor string, got, min time.Time) sdk.Error { - msg := fmt.Sprintf("%v is not mature requires a min %v of %v, currently it is %v", - operation, descriptor, got, min) - return sdk.NewError(codespace, CodeUnauthorized, msg) -} - -func ErrNoUnbondingDelegation(codespace sdk.CodespaceType) sdk.Error { - return sdk.NewError(codespace, CodeInvalidDelegation, "no unbonding delegation found") -} - -func ErrMaxUnbondingDelegationEntries(codespace sdk.CodespaceType) sdk.Error { - return sdk.NewError(codespace, CodeInvalidDelegation, - "too many unbonding delegation entries in this delegator/validator duo, please wait for some entries to mature") -} - -func ErrBadRedelegationAddr(codespace sdk.CodespaceType) sdk.Error { - return sdk.NewError(codespace, CodeInvalidInput, "unexpected address length for this (address, srcValidator, dstValidator) tuple") -} - -func ErrNoRedelegation(codespace sdk.CodespaceType) sdk.Error { - return sdk.NewError(codespace, CodeInvalidDelegation, "no redelegation found") -} - -func ErrSelfRedelegation(codespace sdk.CodespaceType) sdk.Error { - return sdk.NewError(codespace, CodeInvalidDelegation, "cannot redelegate to the same validator") -} - -func ErrVerySmallRedelegation(codespace sdk.CodespaceType) sdk.Error { - return sdk.NewError(codespace, CodeInvalidDelegation, "too few tokens to redelegate, truncates to zero tokens") -} - -func ErrBadRedelegationDst(codespace sdk.CodespaceType) sdk.Error { - return sdk.NewError(codespace, CodeInvalidDelegation, "redelegation validator not found") -} - -func ErrTransitiveRedelegation(codespace sdk.CodespaceType) sdk.Error { - return sdk.NewError(codespace, CodeInvalidDelegation, - "redelegation to this validator already in progress, first redelegation to this validator must complete before next redelegation") -} - -func ErrMaxRedelegationEntries(codespace sdk.CodespaceType) sdk.Error { - return sdk.NewError(codespace, CodeInvalidDelegation, - "too many redelegation entries in this delegator/src-validator/dst-validator trio, please wait for some entries to mature") -} - -func ErrDelegatorShareExRateInvalid(codespace sdk.CodespaceType) sdk.Error { - return sdk.NewError(codespace, CodeInvalidDelegation, - "cannot delegate to validators with invalid (zero) ex-rate") -} - -func ErrBothShareMsgsGiven(codespace sdk.CodespaceType) sdk.Error { - return sdk.NewError(codespace, CodeInvalidInput, "both shares amount and shares percent provided") -} - -func ErrNeitherShareMsgsGiven(codespace sdk.CodespaceType) sdk.Error { - return sdk.NewError(codespace, CodeInvalidInput, "neither shares amount nor shares percent provided") -} - -func ErrMissingSignature(codespace sdk.CodespaceType) sdk.Error { - return sdk.NewError(codespace, CodeInvalidValidator, "missing signature") -} - -func ErrInvalidHistoricalInfo(codespace sdk.CodespaceType) sdk.Error { - return sdk.NewError(codespace, CodeInvalidHistoricalInfo, "invalid historical info") -} - -func ErrNoHistoricalInfo(codespace sdk.CodespaceType) sdk.Error { - return sdk.NewError(codespace, CodeInvalidHistoricalInfo, "no historical info found") -} diff --git a/x/staking/types/expected_keepers.go b/x/staking/types/expected_keepers.go index 8f346a71c4cb..5e98f0abbed0 100644 --- a/x/staking/types/expected_keepers.go +++ b/x/staking/types/expected_keepers.go @@ -29,11 +29,11 @@ type SupplyKeeper interface { // TODO remove with genesis 2-phases refactor https://github.com/cosmos/cosmos-sdk/issues/2862 SetModuleAccount(sdk.Context, supplyexported.ModuleAccountI) - SendCoinsFromModuleToModule(ctx sdk.Context, senderPool, recipientPool string, amt sdk.Coins) sdk.Error - UndelegateCoinsFromModuleToAccount(ctx sdk.Context, senderModule string, recipientAddr sdk.AccAddress, amt sdk.Coins) sdk.Error - DelegateCoinsFromAccountToModule(ctx sdk.Context, senderAddr sdk.AccAddress, recipientModule string, amt sdk.Coins) sdk.Error + SendCoinsFromModuleToModule(ctx sdk.Context, senderPool, recipientPool string, amt sdk.Coins) error + UndelegateCoinsFromModuleToAccount(ctx sdk.Context, senderModule string, recipientAddr sdk.AccAddress, amt sdk.Coins) error + DelegateCoinsFromAccountToModule(ctx sdk.Context, senderAddr sdk.AccAddress, recipientModule string, amt sdk.Coins) error - BurnCoins(ctx sdk.Context, name string, amt sdk.Coins) sdk.Error + BurnCoins(ctx sdk.Context, name string, amt sdk.Coins) error } // ValidatorSet expected properties for the set of all validators (noalias) diff --git a/x/staking/types/historical_info.go b/x/staking/types/historical_info.go index 8fae88f07f4e..78db1e7dd4a9 100644 --- a/x/staking/types/historical_info.go +++ b/x/staking/types/historical_info.go @@ -48,10 +48,10 @@ func UnmarshalHistoricalInfo(cdc *codec.Codec, value []byte) (hi HistoricalInfo, // ValidateBasic will ensure HistoricalInfo is not nil and sorted func ValidateBasic(hi HistoricalInfo) error { if len(hi.ValSet) == 0 { - return sdkerrors.Wrap(ErrInvalidHistoricalInfo(DefaultCodespace), "ValidatorSer is nil") + return sdkerrors.Wrap(ErrInvalidHistoricalInfo, "validator set is empty") } if !sort.IsSorted(Validators(hi.ValSet)) { - return sdkerrors.Wrap(ErrInvalidHistoricalInfo(DefaultCodespace), "ValidatorSet is not sorted by address") + return sdkerrors.Wrap(ErrInvalidHistoricalInfo, "validator set is not sorted by address") } return nil } diff --git a/x/staking/types/msg.go b/x/staking/types/msg.go index fa44090ac747..8b47cfec443c 100644 --- a/x/staking/types/msg.go +++ b/x/staking/types/msg.go @@ -8,6 +8,7 @@ import ( yaml "gopkg.in/yaml.v2" sdk "github.com/cosmos/cosmos-sdk/types" + sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" ) // ensure Msg interface compliance at compile time @@ -151,34 +152,34 @@ func (msg MsgCreateValidator) GetSignBytes() []byte { } // ValidateBasic implements the sdk.Msg interface. -func (msg MsgCreateValidator) ValidateBasic() sdk.Error { +func (msg MsgCreateValidator) ValidateBasic() error { // note that unmarshaling from bech32 ensures either empty or valid if msg.DelegatorAddress.Empty() { - return ErrNilDelegatorAddr(DefaultCodespace) + return ErrEmptyDelegatorAddr } if msg.ValidatorAddress.Empty() { - return ErrNilValidatorAddr(DefaultCodespace) + return ErrEmptyValidatorAddr } if !sdk.AccAddress(msg.ValidatorAddress).Equals(msg.DelegatorAddress) { - return ErrBadValidatorAddr(DefaultCodespace) + return ErrBadValidatorAddr } if !msg.Value.Amount.IsPositive() { - return ErrBadDelegationAmount(DefaultCodespace) + return ErrBadDelegationAmount } if msg.Description == (Description{}) { - return sdk.NewError(DefaultCodespace, CodeInvalidInput, "description must be included") + return sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "empty description") } if msg.Commission == (CommissionRates{}) { - return sdk.NewError(DefaultCodespace, CodeInvalidInput, "commission must be included") + return sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "empty commission") } if err := msg.Commission.Validate(); err != nil { return err } if !msg.MinSelfDelegation.IsPositive() { - return ErrMinSelfDelegationInvalid(DefaultCodespace) + return ErrMinSelfDelegationInvalid } if msg.Value.Amount.LT(msg.MinSelfDelegation) { - return ErrSelfDelegationBelowMinimum(DefaultCodespace) + return ErrSelfDelegationBelowMinimum } return nil @@ -226,22 +227,19 @@ func (msg MsgEditValidator) GetSignBytes() []byte { } // ValidateBasic implements the sdk.Msg interface. -func (msg MsgEditValidator) ValidateBasic() sdk.Error { +func (msg MsgEditValidator) ValidateBasic() error { if msg.ValidatorAddress.Empty() { - return sdk.NewError(DefaultCodespace, CodeInvalidInput, "nil validator address") + return ErrEmptyValidatorAddr } - if msg.Description == (Description{}) { - return sdk.NewError(DefaultCodespace, CodeInvalidInput, "transaction must include some information to modify") + return sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "empty description") } - if msg.MinSelfDelegation != nil && !msg.MinSelfDelegation.IsPositive() { - return ErrMinSelfDelegationInvalid(DefaultCodespace) + return ErrMinSelfDelegationInvalid } - if msg.CommissionRate != nil { if msg.CommissionRate.GT(sdk.OneDec()) || msg.CommissionRate.IsNegative() { - return sdk.NewError(DefaultCodespace, CodeInvalidInput, "commission rate must be between 0 and 1, inclusive") + return sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "commission rate must be between 0 and 1 (inclusive)") } } @@ -282,15 +280,15 @@ func (msg MsgDelegate) GetSignBytes() []byte { } // ValidateBasic implements the sdk.Msg interface. -func (msg MsgDelegate) ValidateBasic() sdk.Error { +func (msg MsgDelegate) ValidateBasic() error { if msg.DelegatorAddress.Empty() { - return ErrNilDelegatorAddr(DefaultCodespace) + return ErrEmptyDelegatorAddr } if msg.ValidatorAddress.Empty() { - return ErrNilValidatorAddr(DefaultCodespace) + return ErrEmptyValidatorAddr } if !msg.Amount.Amount.IsPositive() { - return ErrBadDelegationAmount(DefaultCodespace) + return ErrBadDelegationAmount } return nil } @@ -335,18 +333,18 @@ func (msg MsgBeginRedelegate) GetSignBytes() []byte { } // ValidateBasic implements the sdk.Msg interface. -func (msg MsgBeginRedelegate) ValidateBasic() sdk.Error { +func (msg MsgBeginRedelegate) ValidateBasic() error { if msg.DelegatorAddress.Empty() { - return ErrNilDelegatorAddr(DefaultCodespace) + return ErrEmptyDelegatorAddr } if msg.ValidatorSrcAddress.Empty() { - return ErrNilValidatorAddr(DefaultCodespace) + return ErrEmptyValidatorAddr } if msg.ValidatorDstAddress.Empty() { - return ErrNilValidatorAddr(DefaultCodespace) + return ErrEmptyValidatorAddr } if !msg.Amount.Amount.IsPositive() { - return ErrBadSharesAmount(DefaultCodespace) + return ErrBadSharesAmount } return nil } @@ -383,15 +381,15 @@ func (msg MsgUndelegate) GetSignBytes() []byte { } // ValidateBasic implements the sdk.Msg interface. -func (msg MsgUndelegate) ValidateBasic() sdk.Error { +func (msg MsgUndelegate) ValidateBasic() error { if msg.DelegatorAddress.Empty() { - return ErrNilDelegatorAddr(DefaultCodespace) + return ErrEmptyDelegatorAddr } if msg.ValidatorAddress.Empty() { - return ErrNilValidatorAddr(DefaultCodespace) + return ErrEmptyValidatorAddr } if !msg.Amount.Amount.IsPositive() { - return ErrBadSharesAmount(DefaultCodespace) + return ErrBadSharesAmount } return nil } diff --git a/x/staking/types/validator.go b/x/staking/types/validator.go index 37e6cbc02575..2ac2903dcf0b 100644 --- a/x/staking/types/validator.go +++ b/x/staking/types/validator.go @@ -14,6 +14,7 @@ import ( "github.com/cosmos/cosmos-sdk/codec" sdk "github.com/cosmos/cosmos-sdk/types" + sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" "github.com/cosmos/cosmos-sdk/x/staking/exported" ) @@ -304,7 +305,7 @@ func NewDescription(moniker, identity, website, securityContact, details string) // UpdateDescription updates the fields of a given description. An error is // returned if the resulting description contains an invalid length. -func (d Description) UpdateDescription(d2 Description) (Description, sdk.Error) { +func (d Description) UpdateDescription(d2 Description) (Description, error) { if d2.Moniker == DoNotModifyDesc { d2.Moniker = d.Moniker } @@ -331,21 +332,21 @@ func (d Description) UpdateDescription(d2 Description) (Description, sdk.Error) } // EnsureLength ensures the length of a validator's description. -func (d Description) EnsureLength() (Description, sdk.Error) { +func (d Description) EnsureLength() (Description, error) { if len(d.Moniker) > MaxMonikerLength { - return d, ErrDescriptionLength(DefaultCodespace, "moniker", len(d.Moniker), MaxMonikerLength) + return d, sdkerrors.Wrapf(sdkerrors.ErrInvalidRequest, "invalid moniker length; got: %d, max: %d", len(d.Moniker), MaxMonikerLength) } if len(d.Identity) > MaxIdentityLength { - return d, ErrDescriptionLength(DefaultCodespace, "identity", len(d.Identity), MaxIdentityLength) + return d, sdkerrors.Wrapf(sdkerrors.ErrInvalidRequest, "invalid identity length; got: %d, max: %d", len(d.Identity), MaxIdentityLength) } if len(d.Website) > MaxWebsiteLength { - return d, ErrDescriptionLength(DefaultCodespace, "website", len(d.Website), MaxWebsiteLength) + return d, sdkerrors.Wrapf(sdkerrors.ErrInvalidRequest, "invalid website length; got: %d, max: %d", len(d.Website), MaxWebsiteLength) } if len(d.SecurityContact) > MaxSecurityContactLength { - return d, ErrDescriptionLength(DefaultCodespace, "security contact", len(d.SecurityContact), MaxSecurityContactLength) + return d, sdkerrors.Wrapf(sdkerrors.ErrInvalidRequest, "invalid security contact length; got: %d, max: %d", len(d.SecurityContact), MaxSecurityContactLength) } if len(d.Details) > MaxDetailsLength { - return d, ErrDescriptionLength(DefaultCodespace, "details", len(d.Details), MaxDetailsLength) + return d, sdkerrors.Wrapf(sdkerrors.ErrInvalidRequest, "invalid details length; got: %d, max: %d", len(d.Details), MaxDetailsLength) } return d, nil @@ -371,7 +372,7 @@ func (v Validator) ABCIValidatorUpdateZero() abci.ValidatorUpdate { // SetInitialCommission attempts to set a validator's initial commission. An // error is returned if the commission is invalid. -func (v Validator) SetInitialCommission(commission Commission) (Validator, sdk.Error) { +func (v Validator) SetInitialCommission(commission Commission) (Validator, error) { if err := commission.Validate(); err != nil { return v, err } @@ -405,9 +406,9 @@ func (v Validator) TokensFromSharesRoundUp(shares sdk.Dec) sdk.Dec { // SharesFromTokens returns the shares of a delegation given a bond amount. It // returns an error if the validator has no tokens. -func (v Validator) SharesFromTokens(amt sdk.Int) (sdk.Dec, sdk.Error) { +func (v Validator) SharesFromTokens(amt sdk.Int) (sdk.Dec, error) { if v.Tokens.IsZero() { - return sdk.ZeroDec(), ErrInsufficientShares(DefaultCodespace) + return sdk.ZeroDec(), ErrInsufficientShares } return v.GetDelegatorShares().MulInt(amt).QuoInt(v.GetTokens()), nil @@ -415,9 +416,9 @@ func (v Validator) SharesFromTokens(amt sdk.Int) (sdk.Dec, sdk.Error) { // SharesFromTokensTruncated returns the truncated shares of a delegation given // a bond amount. It returns an error if the validator has no tokens. -func (v Validator) SharesFromTokensTruncated(amt sdk.Int) (sdk.Dec, sdk.Error) { +func (v Validator) SharesFromTokensTruncated(amt sdk.Int) (sdk.Dec, error) { if v.Tokens.IsZero() { - return sdk.ZeroDec(), ErrInsufficientShares(DefaultCodespace) + return sdk.ZeroDec(), ErrInsufficientShares } return v.GetDelegatorShares().MulInt(amt).QuoTruncate(v.GetTokens().ToDec()), nil diff --git a/x/supply/alias.go b/x/supply/alias.go index 9bc7f5f13530..1138f7c5eee2 100644 --- a/x/supply/alias.go +++ b/x/supply/alias.go @@ -38,8 +38,7 @@ var ( DefaultSupply = types.DefaultSupply // variable aliases - DefaultCodespace = keeper.DefaultCodespace - ModuleCdc = types.ModuleCdc + ModuleCdc = types.ModuleCdc ) type ( diff --git a/x/supply/client/cli/query.go b/x/supply/client/cli/query.go index 009f2f7df983..26c4a77cd506 100644 --- a/x/supply/client/cli/query.go +++ b/x/supply/client/cli/query.go @@ -8,6 +8,7 @@ import ( "github.com/cosmos/cosmos-sdk/client" "github.com/cosmos/cosmos-sdk/client/context" + "github.com/cosmos/cosmos-sdk/client/flags" "github.com/cosmos/cosmos-sdk/codec" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/version" @@ -25,7 +26,7 @@ func GetQueryCmd(cdc *codec.Codec) *cobra.Command { RunE: client.ValidateCmd, } - supplyQueryCmd.AddCommand(client.GetCommands( + supplyQueryCmd.AddCommand(flags.GetCommands( GetCmdQueryTotalSupply(cdc), )...) diff --git a/x/supply/internal/keeper/bank.go b/x/supply/internal/keeper/bank.go index 60efbc4c3df5..9117286aaeb6 100644 --- a/x/supply/internal/keeper/bank.go +++ b/x/supply/internal/keeper/bank.go @@ -4,103 +4,110 @@ import ( "fmt" sdk "github.com/cosmos/cosmos-sdk/types" + sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" "github.com/cosmos/cosmos-sdk/x/supply/internal/types" ) -// SendCoinsFromModuleToAccount transfers coins from a ModuleAccount to an AccAddress -func (k Keeper) SendCoinsFromModuleToAccount(ctx sdk.Context, senderModule string, - recipientAddr sdk.AccAddress, amt sdk.Coins) sdk.Error { +// SendCoinsFromModuleToAccount transfers coins from a ModuleAccount to an AccAddress. +// It will panic if the module account does not exist. +func (k Keeper) SendCoinsFromModuleToAccount( + ctx sdk.Context, senderModule string, recipientAddr sdk.AccAddress, amt sdk.Coins, +) error { senderAddr := k.GetModuleAddress(senderModule) if senderAddr == nil { - return sdk.ErrUnknownAddress(fmt.Sprintf("module account %s does not exist", senderModule)) + panic(sdkerrors.Wrapf(sdkerrors.ErrUnknownAddress, "module account %s does not exist", senderModule)) } return k.bk.SendCoins(ctx, senderAddr, recipientAddr, amt) } -// SendCoinsFromModuleToModule transfers coins from a ModuleAccount to another -func (k Keeper) SendCoinsFromModuleToModule(ctx sdk.Context, senderModule, recipientModule string, amt sdk.Coins) sdk.Error { +// SendCoinsFromModuleToModule transfers coins from a ModuleAccount to another. +// It will panic if either module account does not exist. +func (k Keeper) SendCoinsFromModuleToModule( + ctx sdk.Context, senderModule, recipientModule string, amt sdk.Coins, +) error { senderAddr := k.GetModuleAddress(senderModule) if senderAddr == nil { - return sdk.ErrUnknownAddress(fmt.Sprintf("module account %s does not exist", senderModule)) + panic(sdkerrors.Wrapf(sdkerrors.ErrUnknownAddress, "module account %s does not exist", senderModule)) } - // create the account if it doesn't yet exist recipientAcc := k.GetModuleAccount(ctx, recipientModule) if recipientAcc == nil { - panic(fmt.Sprintf("module account %s isn't able to be created", recipientModule)) + panic(sdkerrors.Wrapf(sdkerrors.ErrUnknownAddress, "module account %s does not exist", recipientModule)) } return k.bk.SendCoins(ctx, senderAddr, recipientAcc.GetAddress(), amt) } -// SendCoinsFromAccountToModule transfers coins from an AccAddress to a ModuleAccount -func (k Keeper) SendCoinsFromAccountToModule(ctx sdk.Context, senderAddr sdk.AccAddress, - recipientModule string, amt sdk.Coins) sdk.Error { +// SendCoinsFromAccountToModule transfers coins from an AccAddress to a ModuleAccount. +// It will panic if the module account does not exist. +func (k Keeper) SendCoinsFromAccountToModule( + ctx sdk.Context, senderAddr sdk.AccAddress, recipientModule string, amt sdk.Coins, +) error { - // create the account if it doesn't yet exist recipientAcc := k.GetModuleAccount(ctx, recipientModule) if recipientAcc == nil { - panic(fmt.Sprintf("module account %s isn't able to be created", recipientModule)) + panic(sdkerrors.Wrapf(sdkerrors.ErrUnknownAddress, "module account %s does not exist", recipientModule)) } return k.bk.SendCoins(ctx, senderAddr, recipientAcc.GetAddress(), amt) } -// DelegateCoinsFromAccountToModule delegates coins and transfers -// them from a delegator account to a module account -func (k Keeper) DelegateCoinsFromAccountToModule(ctx sdk.Context, senderAddr sdk.AccAddress, - recipientModule string, amt sdk.Coins) sdk.Error { +// DelegateCoinsFromAccountToModule delegates coins and transfers them from a +// delegator account to a module account. It will panic if the module account +// does not exist or is unauthorized. +func (k Keeper) DelegateCoinsFromAccountToModule( + ctx sdk.Context, senderAddr sdk.AccAddress, recipientModule string, amt sdk.Coins, +) error { - // create the account if it doesn't yet exist recipientAcc := k.GetModuleAccount(ctx, recipientModule) if recipientAcc == nil { - panic(fmt.Sprintf("module account %s isn't able to be created", recipientModule)) + panic(sdkerrors.Wrapf(sdkerrors.ErrUnknownAddress, "module account %s does not exist", recipientModule)) } if !recipientAcc.HasPermission(types.Staking) { - panic(fmt.Sprintf("module account %s does not have permissions to receive delegated coins", recipientModule)) + panic(sdkerrors.Wrapf(sdkerrors.ErrUnauthorized, "module account %s does not have permissions to receive delegated coins", recipientModule)) } return k.bk.DelegateCoins(ctx, senderAddr, recipientAcc.GetAddress(), amt) } // UndelegateCoinsFromModuleToAccount undelegates the unbonding coins and transfers -// them from a module account to the delegator account -func (k Keeper) UndelegateCoinsFromModuleToAccount(ctx sdk.Context, senderModule string, - recipientAddr sdk.AccAddress, amt sdk.Coins) sdk.Error { +// them from a module account to the delegator account. It will panic if the +// module account does not exist or is unauthorized. +func (k Keeper) UndelegateCoinsFromModuleToAccount( + ctx sdk.Context, senderModule string, recipientAddr sdk.AccAddress, amt sdk.Coins, +) error { acc := k.GetModuleAccount(ctx, senderModule) if acc == nil { - return sdk.ErrUnknownAddress(fmt.Sprintf("module account %s does not exist", senderModule)) + panic(sdkerrors.Wrapf(sdkerrors.ErrUnknownAddress, "module account %s does not exist", senderModule)) } if !acc.HasPermission(types.Staking) { - panic(fmt.Sprintf("module account %s does not have permissions to undelegate coins", senderModule)) + panic(sdkerrors.Wrapf(sdkerrors.ErrUnauthorized, "module account %s does not have permissions to undelegate coins", senderModule)) } return k.bk.UndelegateCoins(ctx, acc.GetAddress(), recipientAddr, amt) } // MintCoins creates new coins from thin air and adds it to the module account. -// Panics if the name maps to a non-minter module account or if the amount is invalid. -func (k Keeper) MintCoins(ctx sdk.Context, moduleName string, amt sdk.Coins) sdk.Error { - - // create the account if it doesn't yet exist +// It will panic if the module account does not exist or is unauthorized. +func (k Keeper) MintCoins(ctx sdk.Context, moduleName string, amt sdk.Coins) error { acc := k.GetModuleAccount(ctx, moduleName) if acc == nil { - return sdk.ErrUnknownAddress(fmt.Sprintf("module account %s does not exist", moduleName)) + panic(sdkerrors.Wrapf(sdkerrors.ErrUnknownAddress, "module account %s does not exist", moduleName)) } if !acc.HasPermission(types.Minter) { - panic(fmt.Sprintf("module account %s does not have permissions to mint tokens", moduleName)) + panic(sdkerrors.Wrapf(sdkerrors.ErrUnauthorized, "module account %s does not have permissions to mint tokens", moduleName)) } _, err := k.bk.AddCoins(ctx, acc.GetAddress(), amt) if err != nil { - panic(err) + return err } // update total supply @@ -116,22 +123,20 @@ func (k Keeper) MintCoins(ctx sdk.Context, moduleName string, amt sdk.Coins) sdk } // BurnCoins burns coins deletes coins from the balance of the module account. -// Panics if the name maps to a non-burner module account or if the amount is invalid. -func (k Keeper) BurnCoins(ctx sdk.Context, moduleName string, amt sdk.Coins) sdk.Error { - - // create the account if it doesn't yet exist +// It will panic if the module account does not exist or is unauthorized. +func (k Keeper) BurnCoins(ctx sdk.Context, moduleName string, amt sdk.Coins) error { acc := k.GetModuleAccount(ctx, moduleName) if acc == nil { - return sdk.ErrUnknownAddress(fmt.Sprintf("module account %s does not exist", moduleName)) + panic(sdkerrors.Wrapf(sdkerrors.ErrUnknownAddress, "module account %s does not exist", moduleName)) } if !acc.HasPermission(types.Burner) { - panic(fmt.Sprintf("module account %s does not have permissions to burn tokens", moduleName)) + panic(sdkerrors.Wrapf(sdkerrors.ErrUnauthorized, "module account %s does not have permissions to burn tokens", moduleName)) } _, err := k.bk.SubtractCoins(ctx, acc.GetAddress(), amt) if err != nil { - panic(err) + return err } // update total supply diff --git a/x/supply/internal/keeper/bank_test.go b/x/supply/internal/keeper/bank_test.go index f0cb48f1fc1f..bdd0a9430a1d 100644 --- a/x/supply/internal/keeper/bank_test.go +++ b/x/supply/internal/keeper/bank_test.go @@ -48,15 +48,17 @@ func TestSendCoins(t *testing.T) { keeper.SetModuleAccount(ctx, burnerAcc) ak.SetAccount(ctx, baseAcc) - err = keeper.SendCoinsFromModuleToModule(ctx, "", holderAcc.GetName(), initCoins) - require.Error(t, err) + require.Panics(t, func() { + keeper.SendCoinsFromModuleToModule(ctx, "", holderAcc.GetName(), initCoins) + }) require.Panics(t, func() { keeper.SendCoinsFromModuleToModule(ctx, types.Burner, "", initCoins) }) - err = keeper.SendCoinsFromModuleToAccount(ctx, "", baseAcc.GetAddress(), initCoins) - require.Error(t, err) + require.Panics(t, func() { + keeper.SendCoinsFromModuleToAccount(ctx, "", baseAcc.GetAddress(), initCoins) + }) err = keeper.SendCoinsFromModuleToAccount(ctx, holderAcc.GetName(), baseAcc.GetAddress(), initCoins.Add(initCoins)) require.Error(t, err) @@ -90,13 +92,14 @@ func TestMintCoins(t *testing.T) { initialSupply := keeper.GetSupply(ctx) - require.Error(t, keeper.MintCoins(ctx, "", initCoins), "no module account") + require.Panics(t, func() { keeper.MintCoins(ctx, "", initCoins) }, "no module account") require.Panics(t, func() { keeper.MintCoins(ctx, types.Burner, initCoins) }, "invalid permission") - require.Panics(t, func() { keeper.MintCoins(ctx, types.Minter, sdk.Coins{sdk.Coin{"denom", sdk.NewInt(-10)}}) }, "insufficient coins") //nolint + err := keeper.MintCoins(ctx, types.Minter, sdk.Coins{sdk.Coin{Denom: "denom", Amount: sdk.NewInt(-10)}}) + require.Error(t, err, "insufficient coins") require.Panics(t, func() { keeper.MintCoins(ctx, randomPerm, initCoins) }) - err := keeper.MintCoins(ctx, types.Minter, initCoins) + err = keeper.MintCoins(ctx, types.Minter, initCoins) require.NoError(t, err) require.Equal(t, initCoins, getCoinsByName(ctx, keeper, ak, types.Minter)) require.Equal(t, initialSupply.GetTotal().Add(initCoins), keeper.GetSupply(ctx).GetTotal()) @@ -125,12 +128,13 @@ func TestBurnCoins(t *testing.T) { initialSupply = initialSupply.Inflate(initCoins) keeper.SetSupply(ctx, initialSupply) - require.Error(t, keeper.BurnCoins(ctx, "", initCoins), "no module account") + require.Panics(t, func() { keeper.BurnCoins(ctx, "", initCoins) }, "no module account") require.Panics(t, func() { keeper.BurnCoins(ctx, types.Minter, initCoins) }, "invalid permission") require.Panics(t, func() { keeper.BurnCoins(ctx, randomPerm, initialSupply.GetTotal()) }, "random permission") - require.Panics(t, func() { keeper.BurnCoins(ctx, types.Burner, initialSupply.GetTotal()) }, "insufficient coins") + err := keeper.BurnCoins(ctx, types.Burner, initialSupply.GetTotal()) + require.Error(t, err, "insufficient coins") - err := keeper.BurnCoins(ctx, types.Burner, initCoins) + err = keeper.BurnCoins(ctx, types.Burner, initCoins) require.NoError(t, err) require.Equal(t, sdk.Coins(nil), getCoinsByName(ctx, keeper, ak, types.Burner)) require.Equal(t, initialSupply.GetTotal().Sub(initCoins), keeper.GetSupply(ctx).GetTotal()) diff --git a/x/supply/internal/keeper/key.go b/x/supply/internal/keeper/key.go index 6428d5445c05..65a23382961f 100644 --- a/x/supply/internal/keeper/key.go +++ b/x/supply/internal/keeper/key.go @@ -1,13 +1,5 @@ package keeper -import ( - sdk "github.com/cosmos/cosmos-sdk/types" - "github.com/cosmos/cosmos-sdk/x/supply/internal/types" -) - -// DefaultCodespace from the supply module -var DefaultCodespace sdk.CodespaceType = types.ModuleName - // Keys for supply store // Items are stored with the following key: values // diff --git a/x/supply/internal/keeper/querier.go b/x/supply/internal/keeper/querier.go index 9b74a45ccbe6..093edd2c6bea 100644 --- a/x/supply/internal/keeper/querier.go +++ b/x/supply/internal/keeper/querier.go @@ -1,18 +1,17 @@ package keeper import ( - "fmt" - abci "github.com/tendermint/tendermint/abci/types" "github.com/cosmos/cosmos-sdk/client" sdk "github.com/cosmos/cosmos-sdk/types" + sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" "github.com/cosmos/cosmos-sdk/x/supply/internal/types" ) // NewQuerier creates a querier for supply REST endpoints func NewQuerier(k Keeper) sdk.Querier { - return func(ctx sdk.Context, path []string, req abci.RequestQuery) (res []byte, err sdk.Error) { + return func(ctx sdk.Context, path []string, req abci.RequestQuery) ([]byte, error) { switch path[0] { case types.QueryTotalSupply: @@ -22,17 +21,17 @@ func NewQuerier(k Keeper) sdk.Querier { return querySupplyOf(ctx, req, k) default: - return nil, sdk.ErrUnknownRequest("unknown supply query endpoint") + return nil, sdkerrors.Wrapf(sdkerrors.ErrUnknownRequest, "unknown %s query endpoint: %s", types.ModuleName, path[0]) } } } -func queryTotalSupply(ctx sdk.Context, req abci.RequestQuery, k Keeper) ([]byte, sdk.Error) { +func queryTotalSupply(ctx sdk.Context, req abci.RequestQuery, k Keeper) ([]byte, error) { var params types.QueryTotalSupplyParams err := types.ModuleCdc.UnmarshalJSON(req.Data, ¶ms) if err != nil { - return nil, sdk.ErrInternal(fmt.Sprintf("failed to parse params: %s", err)) + return nil, sdkerrors.Wrap(sdkerrors.ErrJSONUnmarshal, err.Error()) } totalSupply := k.GetSupply(ctx).GetTotal() @@ -46,25 +45,25 @@ func queryTotalSupply(ctx sdk.Context, req abci.RequestQuery, k Keeper) ([]byte, res, err := totalSupply.MarshalJSON() if err != nil { - return nil, sdk.ErrInternal(sdk.AppendMsgToErr("failed to JSON marshal result: %s", err.Error())) + return nil, sdkerrors.Wrap(sdkerrors.ErrJSONMarshal, err.Error()) } return res, nil } -func querySupplyOf(ctx sdk.Context, req abci.RequestQuery, k Keeper) ([]byte, sdk.Error) { +func querySupplyOf(ctx sdk.Context, req abci.RequestQuery, k Keeper) ([]byte, error) { var params types.QuerySupplyOfParams err := types.ModuleCdc.UnmarshalJSON(req.Data, ¶ms) if err != nil { - return nil, sdk.ErrInternal(fmt.Sprintf("failed to parse params: %s", err)) + return nil, sdkerrors.Wrap(sdkerrors.ErrJSONUnmarshal, err.Error()) } supply := k.GetSupply(ctx).GetTotal().AmountOf(params.Denom) res, err := supply.MarshalJSON() if err != nil { - return nil, sdk.ErrInternal(sdk.AppendMsgToErr("failed to JSON marshal result: %s", err.Error())) + return nil, sdkerrors.Wrap(sdkerrors.ErrJSONMarshal, err.Error()) } return res, nil diff --git a/x/supply/internal/types/expected_keepers.go b/x/supply/internal/types/expected_keepers.go index bf0cc6ec328a..3ad1d8b13ce4 100644 --- a/x/supply/internal/types/expected_keepers.go +++ b/x/supply/internal/types/expected_keepers.go @@ -15,10 +15,10 @@ type AccountKeeper interface { // BankKeeper defines the expected bank keeper (noalias) type BankKeeper interface { - SendCoins(ctx sdk.Context, fromAddr sdk.AccAddress, toAddr sdk.AccAddress, amt sdk.Coins) sdk.Error - DelegateCoins(ctx sdk.Context, fromAdd, toAddr sdk.AccAddress, amt sdk.Coins) sdk.Error - UndelegateCoins(ctx sdk.Context, fromAddr, toAddr sdk.AccAddress, amt sdk.Coins) sdk.Error + SendCoins(ctx sdk.Context, fromAddr sdk.AccAddress, toAddr sdk.AccAddress, amt sdk.Coins) error + DelegateCoins(ctx sdk.Context, fromAdd, toAddr sdk.AccAddress, amt sdk.Coins) error + UndelegateCoins(ctx sdk.Context, fromAddr, toAddr sdk.AccAddress, amt sdk.Coins) error - SubtractCoins(ctx sdk.Context, addr sdk.AccAddress, amt sdk.Coins) (sdk.Coins, sdk.Error) - AddCoins(ctx sdk.Context, addr sdk.AccAddress, amt sdk.Coins) (sdk.Coins, sdk.Error) + SubtractCoins(ctx sdk.Context, addr sdk.AccAddress, amt sdk.Coins) (sdk.Coins, error) + AddCoins(ctx sdk.Context, addr sdk.AccAddress, amt sdk.Coins) (sdk.Coins, error) } diff --git a/x/upgrade/abci_test.go b/x/upgrade/abci_test.go index edc71590dc0f..34c8944e0017 100644 --- a/x/upgrade/abci_test.go +++ b/x/upgrade/abci_test.go @@ -1,11 +1,13 @@ package upgrade_test import ( + "errors" "testing" "time" "github.com/cosmos/cosmos-sdk/simapp" sdk "github.com/cosmos/cosmos-sdk/types" + sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" "github.com/cosmos/cosmos-sdk/types/module" "github.com/cosmos/cosmos-sdk/x/gov" "github.com/cosmos/cosmos-sdk/x/upgrade" @@ -37,25 +39,25 @@ func (s *TestSuite) SetupTest() { func (s *TestSuite) TestRequireName() { err := s.handler(s.ctx, upgrade.SoftwareUpgradeProposal{Title: "prop", Plan: upgrade.Plan{}}) s.Require().NotNil(err) - s.Require().Equal(sdk.CodeUnknownRequest, err.Code()) + s.Require().True(errors.Is(sdkerrors.ErrInvalidRequest, err), err) } func (s *TestSuite) TestRequireFutureTime() { err := s.handler(s.ctx, upgrade.SoftwareUpgradeProposal{Title: "prop", Plan: upgrade.Plan{Name: "test", Time: s.ctx.BlockHeader().Time}}) s.Require().NotNil(err) - s.Require().Equal(sdk.CodeUnknownRequest, err.Code()) + s.Require().True(errors.Is(sdkerrors.ErrInvalidRequest, err), err) } func (s *TestSuite) TestRequireFutureBlock() { err := s.handler(s.ctx, upgrade.SoftwareUpgradeProposal{Title: "prop", Plan: upgrade.Plan{Name: "test", Height: s.ctx.BlockHeight()}}) s.Require().NotNil(err) - s.Require().Equal(sdk.CodeUnknownRequest, err.Code()) + s.Require().True(errors.Is(sdkerrors.ErrInvalidRequest, err), err) } func (s *TestSuite) TestCantSetBothTimeAndHeight() { err := s.handler(s.ctx, upgrade.SoftwareUpgradeProposal{Title: "prop", Plan: upgrade.Plan{Name: "test", Time: time.Now(), Height: s.ctx.BlockHeight() + 1}}) s.Require().NotNil(err) - s.Require().Equal(sdk.CodeUnknownRequest, err.Code()) + s.Require().True(errors.Is(sdkerrors.ErrInvalidRequest, err), err) } func (s *TestSuite) TestDoTimeUpgrade() { @@ -156,7 +158,7 @@ func (s *TestSuite) TestCantApplySameUpgradeTwice() { s.T().Log("Verify an upgrade named \"test\" can't be scheduled twice") err := s.handler(s.ctx, upgrade.SoftwareUpgradeProposal{Title: "prop", Plan: upgrade.Plan{Name: "test", Time: time.Now()}}) s.Require().NotNil(err) - s.Require().Equal(sdk.CodeUnknownRequest, err.Code()) + s.Require().True(errors.Is(sdkerrors.ErrInvalidRequest, err), err) } func (s *TestSuite) TestNoSpuriousUpgrades() { diff --git a/x/upgrade/alias.go b/x/upgrade/alias.go index b7324f2c3e41..fe36f23097bc 100644 --- a/x/upgrade/alias.go +++ b/x/upgrade/alias.go @@ -1,10 +1,7 @@ -// nolint -// autogenerated code using github.com/rigelrozanski/multitool -// aliases generated for the following subdirectories: -// ALIASGEN: github.com/cosmos/cosmos-sdk/x/upgrade/internal/types -// ALIASGEN: github.com/cosmos/cosmos-sdk/x/upgrade/internal/keeper package upgrade +// nolint + import ( "github.com/cosmos/cosmos-sdk/x/upgrade/internal/keeper" "github.com/cosmos/cosmos-sdk/x/upgrade/internal/types" @@ -19,7 +16,6 @@ const ( DoneByte = types.DoneByte ProposalTypeSoftwareUpgrade = types.ProposalTypeSoftwareUpgrade ProposalTypeCancelSoftwareUpgrade = types.ProposalTypeCancelSoftwareUpgrade - DefaultCodespace = types.DefaultCodespace QueryCurrent = types.QueryCurrent QueryApplied = types.QueryApplied ) diff --git a/x/upgrade/handler.go b/x/upgrade/handler.go index 925d4e875c9d..8a4a9f89ab10 100644 --- a/x/upgrade/handler.go +++ b/x/upgrade/handler.go @@ -1,9 +1,8 @@ package upgrade import ( - "fmt" - sdk "github.com/cosmos/cosmos-sdk/types" + sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" govtypes "github.com/cosmos/cosmos-sdk/x/gov/types" ) @@ -11,7 +10,7 @@ import ( // It enables SoftwareUpgradeProposal to propose an Upgrade, and CancelSoftwareUpgradeProposal // to abort a previously voted upgrade. func NewSoftwareUpgradeProposalHandler(k Keeper) govtypes.Handler { - return func(ctx sdk.Context, content govtypes.Content) sdk.Error { + return func(ctx sdk.Context, content govtypes.Content) error { switch c := content.(type) { case SoftwareUpgradeProposal: return handleSoftwareUpgradeProposal(ctx, k, c) @@ -20,17 +19,16 @@ func NewSoftwareUpgradeProposalHandler(k Keeper) govtypes.Handler { return handleCancelSoftwareUpgradeProposal(ctx, k, c) default: - errMsg := fmt.Sprintf("unrecognized software upgrade proposal content type: %T", c) - return sdk.ErrUnknownRequest(errMsg) + return sdkerrors.Wrapf(sdkerrors.ErrUnknownRequest, "unrecognized software upgrade proposal content type: %T", c) } } } -func handleSoftwareUpgradeProposal(ctx sdk.Context, k Keeper, p SoftwareUpgradeProposal) sdk.Error { +func handleSoftwareUpgradeProposal(ctx sdk.Context, k Keeper, p SoftwareUpgradeProposal) error { return k.ScheduleUpgrade(ctx, p.Plan) } -func handleCancelSoftwareUpgradeProposal(ctx sdk.Context, k Keeper, p CancelSoftwareUpgradeProposal) sdk.Error { +func handleCancelSoftwareUpgradeProposal(ctx sdk.Context, k Keeper, p CancelSoftwareUpgradeProposal) error { k.ClearUpgradePlan(ctx) return nil } diff --git a/x/upgrade/internal/keeper/keeper.go b/x/upgrade/internal/keeper/keeper.go index bb95ec6eafdb..e0c0823b0842 100644 --- a/x/upgrade/internal/keeper/keeper.go +++ b/x/upgrade/internal/keeper/keeper.go @@ -7,6 +7,7 @@ import ( "github.com/cosmos/cosmos-sdk/codec" "github.com/cosmos/cosmos-sdk/store/prefix" sdk "github.com/cosmos/cosmos-sdk/types" + sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" "github.com/cosmos/cosmos-sdk/x/upgrade/internal/types" "github.com/tendermint/tendermint/libs/log" ) @@ -36,26 +37,27 @@ func (k Keeper) SetUpgradeHandler(name string, upgradeHandler types.UpgradeHandl // ScheduleUpgrade schedules an upgrade based on the specified plan. // If there is another Plan already scheduled, it will overwrite it // (implicitly cancelling the current plan) -func (k Keeper) ScheduleUpgrade(ctx sdk.Context, plan types.Plan) sdk.Error { +func (k Keeper) ScheduleUpgrade(ctx sdk.Context, plan types.Plan) error { if err := plan.ValidateBasic(); err != nil { return err } if !plan.Time.IsZero() { if !plan.Time.After(ctx.BlockHeader().Time) { - return sdk.ErrUnknownRequest("upgrade cannot be scheduled in the past") + return sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "upgrade cannot be scheduled in the past") } } else if plan.Height <= ctx.BlockHeight() { - return sdk.ErrUnknownRequest("upgrade cannot be scheduled in the past") + return sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "upgrade cannot be scheduled in the past") } if k.getDoneHeight(ctx, plan.Name) != 0 { - return sdk.ErrUnknownRequest(fmt.Sprintf("upgrade with name %s has already been completed", plan.Name)) + return sdkerrors.Wrapf(sdkerrors.ErrInvalidRequest, "upgrade with name %s has already been completed", plan.Name) } bz := k.cdc.MustMarshalBinaryBare(plan) store := ctx.KVStore(k.storeKey) store.Set(types.PlanKey(), bz) + return nil } diff --git a/x/upgrade/internal/keeper/querier.go b/x/upgrade/internal/keeper/querier.go index 291f7bb9d049..164a2340c0a7 100644 --- a/x/upgrade/internal/keeper/querier.go +++ b/x/upgrade/internal/keeper/querier.go @@ -2,16 +2,16 @@ package keeper import ( "encoding/binary" - "fmt" sdk "github.com/cosmos/cosmos-sdk/types" + sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" "github.com/cosmos/cosmos-sdk/x/upgrade/internal/types" abci "github.com/tendermint/tendermint/abci/types" ) // NewQuerier creates a querier for upgrade cli and REST endpoints func NewQuerier(k Keeper) sdk.Querier { - return func(ctx sdk.Context, path []string, req abci.RequestQuery) (res []byte, err sdk.Error) { + return func(ctx sdk.Context, path []string, req abci.RequestQuery) ([]byte, error) { switch path[0] { case types.QueryCurrent: @@ -21,38 +21,40 @@ func NewQuerier(k Keeper) sdk.Querier { return queryApplied(ctx, req, k) default: - return nil, sdk.ErrUnknownRequest("unknown supply query endpoint") + return nil, sdkerrors.Wrapf(sdkerrors.ErrUnknownRequest, "unknown %s query endpoint: %s", types.ModuleName, path[0]) } } } -func queryCurrent(ctx sdk.Context, req abci.RequestQuery, k Keeper) ([]byte, sdk.Error) { +func queryCurrent(ctx sdk.Context, req abci.RequestQuery, k Keeper) ([]byte, error) { plan, has := k.GetUpgradePlan(ctx) if !has { - // empty data - client can respond Not Found return nil, nil } + res, err := k.cdc.MarshalJSON(&plan) if err != nil { - return nil, sdk.ErrInternal(sdk.AppendMsgToErr("failed to JSON marshal result: %s", err.Error())) + return nil, sdkerrors.Wrap(sdkerrors.ErrJSONMarshal, err.Error()) } + return res, nil } -func queryApplied(ctx sdk.Context, req abci.RequestQuery, k Keeper) ([]byte, sdk.Error) { +func queryApplied(ctx sdk.Context, req abci.RequestQuery, k Keeper) ([]byte, error) { var params types.QueryAppliedParams err := k.cdc.UnmarshalJSON(req.Data, ¶ms) if err != nil { - return nil, sdk.ErrInternal(fmt.Sprintf("failed to parse params: %s", err)) + return nil, sdkerrors.Wrap(sdkerrors.ErrJSONUnmarshal, err.Error()) } applied := k.getDoneHeight(ctx, params.Name) if applied == 0 { - // empty data - client can respond Not Found return nil, nil } + bz := make([]byte, 8) binary.BigEndian.PutUint64(bz, uint64(applied)) + return bz, nil } diff --git a/x/upgrade/internal/types/plan.go b/x/upgrade/internal/types/plan.go index 24fd28b72005..c2b88171e218 100644 --- a/x/upgrade/internal/types/plan.go +++ b/x/upgrade/internal/types/plan.go @@ -6,6 +6,7 @@ import ( "time" sdk "github.com/cosmos/cosmos-sdk/types" + sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" ) // Plan specifies information about a planned upgrade and when it should occur @@ -40,19 +41,20 @@ func (p Plan) String() string { } // ValidateBasic does basic validation of a Plan -func (p Plan) ValidateBasic() sdk.Error { +func (p Plan) ValidateBasic() error { if len(p.Name) == 0 { - return sdk.ErrUnknownRequest("name cannot be empty") + return sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "name cannot be empty") } if p.Height < 0 { - return sdk.ErrUnknownRequest("height cannot be negative") + return sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "height cannot be negative") } if p.Time.IsZero() && p.Height == 0 { - return sdk.ErrUnknownRequest("must set either time or height") + return sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "must set either time or height") } if !p.Time.IsZero() && p.Height != 0 { - return sdk.ErrUnknownRequest("cannot set both time and height") + return sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "cannot set both time and height") } + return nil } diff --git a/x/upgrade/internal/types/proposal.go b/x/upgrade/internal/types/proposal.go index 3dc54f494f60..958c10674645 100644 --- a/x/upgrade/internal/types/proposal.go +++ b/x/upgrade/internal/types/proposal.go @@ -3,14 +3,12 @@ package types import ( "fmt" - sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/x/gov" ) const ( - ProposalTypeSoftwareUpgrade string = "SoftwareUpgrade" - ProposalTypeCancelSoftwareUpgrade string = "CancelSoftwareUpgrade" - DefaultCodespace sdk.CodespaceType = "upgrade" + ProposalTypeSoftwareUpgrade string = "SoftwareUpgrade" + ProposalTypeCancelSoftwareUpgrade string = "CancelSoftwareUpgrade" ) // Software Upgrade Proposals @@ -39,11 +37,11 @@ func (sup SoftwareUpgradeProposal) GetTitle() string { return sup.Title } func (sup SoftwareUpgradeProposal) GetDescription() string { return sup.Description } func (sup SoftwareUpgradeProposal) ProposalRoute() string { return RouterKey } func (sup SoftwareUpgradeProposal) ProposalType() string { return ProposalTypeSoftwareUpgrade } -func (sup SoftwareUpgradeProposal) ValidateBasic() sdk.Error { +func (sup SoftwareUpgradeProposal) ValidateBasic() error { if err := sup.Plan.ValidateBasic(); err != nil { return err } - return gov.ValidateAbstract(DefaultCodespace, sup) + return gov.ValidateAbstract(sup) } func (sup SoftwareUpgradeProposal) String() string { @@ -73,8 +71,8 @@ func (sup CancelSoftwareUpgradeProposal) ProposalRoute() string { return Router func (sup CancelSoftwareUpgradeProposal) ProposalType() string { return ProposalTypeCancelSoftwareUpgrade } -func (sup CancelSoftwareUpgradeProposal) ValidateBasic() sdk.Error { - return gov.ValidateAbstract(DefaultCodespace, sup) +func (sup CancelSoftwareUpgradeProposal) ValidateBasic() error { + return gov.ValidateAbstract(sup) } func (sup CancelSoftwareUpgradeProposal) String() string { diff --git a/x/upgrade/module.go b/x/upgrade/module.go index a365cd1a36c2..129cc904bf10 100644 --- a/x/upgrade/module.go +++ b/x/upgrade/module.go @@ -6,8 +6,8 @@ import ( "github.com/gorilla/mux" "github.com/spf13/cobra" - "github.com/cosmos/cosmos-sdk/client" "github.com/cosmos/cosmos-sdk/client/context" + "github.com/cosmos/cosmos-sdk/client/flags" "github.com/cosmos/cosmos-sdk/codec" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/types/module" @@ -52,7 +52,7 @@ func (AppModuleBasic) GetQueryCmd(cdc *codec.Codec) *cobra.Command { Use: "upgrade", Short: "Querying commands for the upgrade module", } - queryCmd.AddCommand(client.GetCommands( + queryCmd.AddCommand(flags.GetCommands( cli.GetPlanCmd(StoreKey, cdc), cli.GetAppliedHeightCmd(StoreKey, cdc), )...) @@ -66,7 +66,7 @@ func (AppModuleBasic) GetTxCmd(cdc *codec.Codec) *cobra.Command { Use: "upgrade", Short: "Upgrade transaction subcommands", } - txCmd.AddCommand(client.PostCommands()...) + txCmd.AddCommand(flags.PostCommands()...) return txCmd }