diff --git a/CHANGELOG.md b/CHANGELOG.md index ab2b4cdbdb64..7664dd0995c7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -85,6 +85,7 @@ Ref: https://keepachangelog.com/en/1.0.0/ * [#13178](https://github.com/cosmos/cosmos-sdk/pull/13178) Add `cosmos.msg.v1.service` protobuf annotation to allow tooling to distinguish between Msg and Query services via reflection. * [#13233](https://github.com/cosmos/cosmos-sdk/pull/13233) Add `--append` to `add-genesis-account` sub-command to append new tokens after an account is already created. * [#13236](https://github.com/cosmos/cosmos-sdk/pull/13236) Integrate Filter Logging +* [#13301](https://github.com/cosmos/cosmos-sdk/pull/13301) Keep the balance query endpoint compatible with legacy blocks ### State Machine Breaking diff --git a/x/bank/keeper/grpc_query.go b/x/bank/keeper/grpc_query.go index 3ea34a445212..60d0be75c630 100644 --- a/x/bank/keeper/grpc_query.go +++ b/x/bank/keeper/grpc_query.go @@ -62,11 +62,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 32e146ecdd15..865b6e1eda4e 100644 --- a/x/bank/keeper/view.go +++ b/x/bank/keeper/view.go @@ -100,17 +100,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 := math.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 @@ -123,12 +119,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 } } @@ -153,12 +150,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 } } @@ -252,3 +249,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 +}