From ad66683e21ebfcbcfa62d550978387e093762577 Mon Sep 17 00:00:00 2001 From: Alex Megalokonomos Date: Tue, 12 Oct 2021 12:11:14 +0300 Subject: [PATCH 1/3] fix: null guard for tx fee amounts (#10327) ## Description It is possible to submit a TX with a fees object containing a Coin with a nil amount. This results in a rather cryptic redacted panic response when the basic validation checks fee Coins for negative amounts. This PR adds an additional check for nil to provide a friendlier error message. --- ### Author Checklist *All items are required. Please add a note to the item if the item is not applicable and please add links to any relevant follow up issues.* I have... - [x] included the correct [type prefix](https://github.com/commitizen/conventional-commit-types/blob/v3.0.0/index.json) in the PR title - [ ] added `!` to the type prefix if API or client breaking change - [x] targeted the correct branch (see [PR Targeting](https://github.com/cosmos/cosmos-sdk/blob/master/CONTRIBUTING.md#pr-targeting)) - [x] provided a link to the relevant issue or specification (note: No issue exists) - [x] followed the guidelines for [building modules](https://github.com/cosmos/cosmos-sdk/blob/master/docs/building-modules) - [x] included the necessary unit and integration [tests](https://github.com/cosmos/cosmos-sdk/blob/master/CONTRIBUTING.md#testing) (note: First PR against the SDK so please comment with what needs to be done) - [x] added a changelog entry to `CHANGELOG.md` - [x] included comments for [documenting Go code](https://blog.golang.org/godoc) - [ ] updated the relevant documentation or specification - [x] reviewed "Files changed" and left comments if necessary - [x] confirmed all CI checks have passed ### Reviewers Checklist *All items are required. Please add a note if the item is not applicable and please add your handle next to the items reviewed if you only reviewed selected items.* I have... - [ ] confirmed the correct [type prefix](https://github.com/commitizen/conventional-commit-types/blob/v3.0.0/index.json) in the PR title - [ ] confirmed `!` in the type prefix if API or client breaking change - [ ] confirmed all author checklist items have been addressed - [ ] reviewed state machine logic - [ ] reviewed API design and naming - [ ] reviewed documentation is accurate - [ ] reviewed tests and test coverage - [ ] manually tested (if applicable) (cherry picked from commit 96e162b8a3939c7999c0c12c39d196698594306c) # Conflicts: # CHANGELOG.md --- CHANGELOG.md | 6 ++++++ types/coin.go | 18 ++++++++++++++++++ types/coin_test.go | 27 +++++++++++++++++++++++++++ types/tx/types.go | 7 +++++++ 4 files changed, 58 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8f15d65c37ab..2ac6e817dbe8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -44,6 +44,12 @@ Ref: https://keepachangelog.com/en/1.0.0/ ### Improvements +<<<<<<< HEAD +======= +* [\#10327](https://github.com/cosmos/cosmos-sdk/pull/10327) Add null guard for possible nil `Amount` in tx fee `Coins` +* [\#9780](https://github.com/cosmos/cosmos-sdk/pull/9780) Remove gogoproto `moretags` YAML annotations and add `sigs.k8s.io/yaml` for YAML marshalling. +* (x/bank) [\#10134](https://github.com/cosmos/cosmos-sdk/pull/10134) Add `HasDenomMetadata` function to bank `Keeper` to check if a client coin denom metadata exists in state. +>>>>>>> 96e162b8a (fix: null guard for tx fee amounts (#10327)) * (store) [\#10026](https://github.com/cosmos/cosmos-sdk/pull/10026) Improve CacheKVStore datastructures / algorithms, to no longer take O(N^2) time when interleaving iterators and insertions. * (store) [\#10040](https://github.com/cosmos/cosmos-sdk/pull/10040) Bump IAVL to v0.17.1 which includes performance improvements on a batch load. * [\#10211](https://github.com/cosmos/cosmos-sdk/pull/10211) Backport of the mechanism to reject redundant IBC transactions from [ibc-go \#235](https://github.com/cosmos/ibc-go/pull/235). diff --git a/types/coin.go b/types/coin.go index b86cff51865e..2749edadc7fb 100644 --- a/types/coin.go +++ b/types/coin.go @@ -129,6 +129,11 @@ func (coin Coin) IsNegative() bool { return coin.Amount.Sign() == -1 } +// IsNil returns true if the coin amount is nil and false otherwise. +func (coin Coin) IsNil() bool { + return coin.Amount.i == nil +} + //----------------------------------------------------------------------------- // Coins @@ -543,6 +548,19 @@ func (coins Coins) IsAnyNegative() bool { return false } +// IsAnyNil returns true if there is at least one coin whose amount +// is nil; returns false otherwise. It returns false if the coin set +// is empty too. +func (coins Coins) IsAnyNil() bool { + for _, coin := range coins { + if coin.IsNil() { + return true + } + } + + return false +} + // negative returns a set of coins with all amount negative. // // TODO: Remove once unsigned integers are used. diff --git a/types/coin_test.go b/types/coin_test.go index ab69f16a17db..bb1d00f1380a 100644 --- a/types/coin_test.go +++ b/types/coin_test.go @@ -237,6 +237,20 @@ func (s *coinTestSuite) TestCoinIsZero() { s.Require().False(res) } +func (s *coinTestSuite) TestCoinIsNil() { + coin := sdk.Coin{} + res := coin.IsNil() + s.Require().True(res) + + coin = sdk.Coin{Denom: "uatom"} + res = coin.IsNil() + s.Require().True(res) + + coin = sdk.NewInt64Coin(testDenom1, 1) + res = coin.IsNil() + s.Require().False(res) +} + func (s *coinTestSuite) TestFilteredZeroCoins() { cases := []struct { name string @@ -902,6 +916,19 @@ func (s *coinTestSuite) TestCoinsIsAnyGT() { } } +func (s *coinTestSuite) TestCoinsIsAnyNil() { + twoAtom := sdk.NewInt64Coin("atom", 2) + fiveAtom := sdk.NewInt64Coin("atom", 5) + threeEth := sdk.NewInt64Coin("eth", 3) + nilAtom := sdk.Coin{Denom: "atom"} + + s.Require().True(sdk.Coins{twoAtom, fiveAtom, threeEth, nilAtom}.IsAnyNil()) + s.Require().True(sdk.Coins{twoAtom, nilAtom, fiveAtom, threeEth}.IsAnyNil()) + s.Require().True(sdk.Coins{nilAtom, twoAtom, fiveAtom, threeEth}.IsAnyNil()) + s.Require().False(sdk.Coins{twoAtom, fiveAtom, threeEth}.IsAnyNil()) + +} + func (s *coinTestSuite) TestMarshalJSONCoins() { cdc := codec.NewLegacyAmino() sdk.RegisterLegacyAminoCodec(cdc) diff --git a/types/tx/types.go b/types/tx/types.go index 0392b2fcfd08..65313f735b7a 100644 --- a/types/tx/types.go +++ b/types/tx/types.go @@ -72,6 +72,13 @@ func (t *Tx) ValidateBasic() error { ) } + if fee.Amount.IsAnyNil() { + return sdkerrors.Wrapf( + sdkerrors.ErrInsufficientFee, + "invalid fee provided: null", + ) + } + if fee.Amount.IsAnyNegative() { return sdkerrors.Wrapf( sdkerrors.ErrInsufficientFee, From ff0eaa77c7f6aa855e07ed20d5838a6eeae0afa8 Mon Sep 17 00:00:00 2001 From: marbar3778 Date: Tue, 12 Oct 2021 11:26:48 +0200 Subject: [PATCH 2/3] solve conflicts --- CHANGELOG.md | 5 ----- 1 file changed, 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2ac6e817dbe8..357329908ec0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -44,12 +44,7 @@ Ref: https://keepachangelog.com/en/1.0.0/ ### Improvements -<<<<<<< HEAD -======= * [\#10327](https://github.com/cosmos/cosmos-sdk/pull/10327) Add null guard for possible nil `Amount` in tx fee `Coins` -* [\#9780](https://github.com/cosmos/cosmos-sdk/pull/9780) Remove gogoproto `moretags` YAML annotations and add `sigs.k8s.io/yaml` for YAML marshalling. -* (x/bank) [\#10134](https://github.com/cosmos/cosmos-sdk/pull/10134) Add `HasDenomMetadata` function to bank `Keeper` to check if a client coin denom metadata exists in state. ->>>>>>> 96e162b8a (fix: null guard for tx fee amounts (#10327)) * (store) [\#10026](https://github.com/cosmos/cosmos-sdk/pull/10026) Improve CacheKVStore datastructures / algorithms, to no longer take O(N^2) time when interleaving iterators and insertions. * (store) [\#10040](https://github.com/cosmos/cosmos-sdk/pull/10040) Bump IAVL to v0.17.1 which includes performance improvements on a batch load. * [\#10211](https://github.com/cosmos/cosmos-sdk/pull/10211) Backport of the mechanism to reject redundant IBC transactions from [ibc-go \#235](https://github.com/cosmos/ibc-go/pull/235). From 3681c45776e96e312471a00b955c0a28498e5733 Mon Sep 17 00:00:00 2001 From: marbar3778 Date: Tue, 12 Oct 2021 11:32:38 +0200 Subject: [PATCH 3/3] move sections --- CHANGELOG.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 357329908ec0..e797f20787c1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -36,6 +36,10 @@ Ref: https://keepachangelog.com/en/1.0.0/ ## Unreleased +### Improvements + +* [\#10327](https://github.com/cosmos/cosmos-sdk/pull/10327) Add null guard for possible nil `Amount` in tx fee `Coins` + ### Bug Fixes * (client) [#10226](https://github.com/cosmos/cosmos-sdk/pull/10226) Fix --home flag parsing. @@ -44,7 +48,6 @@ Ref: https://keepachangelog.com/en/1.0.0/ ### Improvements -* [\#10327](https://github.com/cosmos/cosmos-sdk/pull/10327) Add null guard for possible nil `Amount` in tx fee `Coins` * (store) [\#10026](https://github.com/cosmos/cosmos-sdk/pull/10026) Improve CacheKVStore datastructures / algorithms, to no longer take O(N^2) time when interleaving iterators and insertions. * (store) [\#10040](https://github.com/cosmos/cosmos-sdk/pull/10040) Bump IAVL to v0.17.1 which includes performance improvements on a batch load. * [\#10211](https://github.com/cosmos/cosmos-sdk/pull/10211) Backport of the mechanism to reject redundant IBC transactions from [ibc-go \#235](https://github.com/cosmos/ibc-go/pull/235).