fix: keep the balance query endpoint compatible with legacy blocks (#13301)

* keep the balance query endpoint compatible with legacy blocks

Closes: #13296

A temporary solution before the proxy tool developed, since the balance endpoint is too important.

* Update CHANGELOG.md

* Apply suggestions from code review

Co-authored-by: Julien Robert <julien@rbrt.fr>
Co-authored-by: Marko <marbar3778@yahoo.com>
This commit is contained in:
yihuang
2022-09-16 09:57:42 +02:00
committed by GitHub
co-authored by Julien Robert Marko
parent ceffc5e01c
commit 6c4f94b671
3 changed files with 35 additions and 16 deletions
+1
View File
@@ -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
+4 -3
View File
@@ -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 {
+30 -13
View File
@@ -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
}