diff --git a/CHANGELOG.md b/CHANGELOG.md index 443bdfa9f0c1..1032f3b13184 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -52,6 +52,7 @@ Ref: https://keepachangelog.com/en/1.0.0/ * (x/group) [#13214](https://github.com/cosmos/cosmos-sdk/pull/13214) Add `withdraw-proposal` command to group module's CLI transaction commands. * (x/auth) [#13048](https://github.com/cosmos/cosmos-sdk/pull/13048) Add handling of AccountNumberStoreKeyPrefix to the simulation decoder. * (simapp) [#13108](https://github.com/cosmos/cosmos-sdk/pull/13108) Call `SetIAVLCacheSize` with the configured value in simapp. +* [#13318](https://github.com/cosmos/cosmos-sdk/pull/13318) Keep the balance query endpoint compatible with legacy blocks ### Bug Fixes diff --git a/x/bank/keeper/grpc_query.go b/x/bank/keeper/grpc_query.go index 26efb3f1a7fe..a96ade989c9f 100644 --- a/x/bank/keeper/grpc_query.go +++ b/x/bank/keeper/grpc_query.go @@ -3,7 +3,6 @@ package keeper import ( "context" - "cosmossdk.io/math" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" @@ -61,11 +60,12 @@ func (k BaseKeeper) AllBalances(ctx context.Context, req *types.QueryAllBalances accountStore := k.getAccountStore(sdkCtx, addr) pageRes, err := query.Paginate(accountStore, req.Pagination, func(key, value []byte) error { - var amount math.Int - if err := amount.Unmarshal(value); err != nil { + denom := string(key) + balance, err := UnmarshalBalanceCompat(k.cdc, value, denom) + if err != nil { return err } - balances = append(balances, sdk.NewCoin(string(key), amount)) + balances = append(balances, balance) return nil }) if err != nil { diff --git a/x/bank/keeper/view.go b/x/bank/keeper/view.go index 5fc3446c2da5..e189edca1de3 100644 --- a/x/bank/keeper/view.go +++ b/x/bank/keeper/view.go @@ -99,17 +99,13 @@ func (k BaseViewKeeper) GetAccountsBalances(ctx sdk.Context) []types.Balance { // by address. func (k BaseViewKeeper) GetBalance(ctx sdk.Context, addr sdk.AccAddress, denom string) sdk.Coin { accountStore := k.getAccountStore(ctx, addr) - amount := sdk.ZeroInt() bz := accountStore.Get([]byte(denom)) - if bz == nil { - return sdk.NewCoin(denom, amount) - } - - if err := amount.Unmarshal(bz); err != nil { + balance, err := UnmarshalBalanceCompat(k.cdc, bz, denom) + if err != nil { panic(err) } - return sdk.NewCoin(denom, amount) + return balance } // IterateAccountBalances iterates over the balances of a single account and @@ -122,12 +118,13 @@ func (k BaseViewKeeper) IterateAccountBalances(ctx sdk.Context, addr sdk.AccAddr defer iterator.Close() for ; iterator.Valid(); iterator.Next() { - var amount math.Int - if err := amount.Unmarshal(iterator.Value()); err != nil { + denom := string(iterator.Key()) + balance, err := UnmarshalBalanceCompat(k.cdc, iterator.Value(), denom) + if err != nil { panic(err) } - if cb(sdk.NewCoin(string(iterator.Key()), amount)) { + if cb(balance) { break } } @@ -152,12 +149,12 @@ func (k BaseViewKeeper) IterateAllBalances(ctx sdk.Context, cb func(sdk.AccAddre panic(err) } - var amount math.Int - if err := amount.Unmarshal(iterator.Value()); err != nil { + balance, err := UnmarshalBalanceCompat(k.cdc, iterator.Value(), denom) + if err != nil { panic(err) } - if cb(address, sdk.NewCoin(denom, amount)) { + if cb(address, balance) { break } } @@ -242,3 +239,23 @@ func (k BaseViewKeeper) getAccountStore(ctx sdk.Context, addr sdk.AccAddress) pr func (k BaseViewKeeper) getDenomAddressPrefixStore(ctx sdk.Context, denom string) prefix.Store { return prefix.NewStore(ctx.KVStore(k.storeKey), types.CreateDenomAddressPrefix(denom)) } + +// UnmarshalBalanceCompat unmarshal balance amount from storage, it's backward-compatible with the legacy format. +func UnmarshalBalanceCompat(cdc codec.BinaryCodec, bz []byte, denom string) (sdk.Coin, error) { + amount := math.ZeroInt() + if bz == nil { + return sdk.NewCoin(denom, amount), nil + } + + if err := amount.Unmarshal(bz); err != nil { + // try to unmarshal with the legacy format. + var balance sdk.Coin + if cdc.Unmarshal(bz, &balance) != nil { + // return with the original error + return sdk.Coin{}, err + } + return balance, nil + } + + return sdk.NewCoin(denom, amount), nil +}