From 4b2fc3bd43825dacb92140975644f100f56c1fd4 Mon Sep 17 00:00:00 2001 From: SaReN Date: Tue, 6 Apr 2021 19:31:57 +0530 Subject: [PATCH] Store supply as Int bytes rather than string bytes (#9051) * store supply as int bytes * update migrate * update migrate tests * add error context * fix lint * update spec * add changelog Co-authored-by: Amaury <1293565+amaurym@users.noreply.github.com> Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com> Co-authored-by: Jonathan Gimeno --- CHANGELOG.md | 1 + x/bank/keeper/keeper.go | 22 +++++++++++++++------- x/bank/legacy/v043/store.go | 2 +- x/bank/legacy/v043/store_test.go | 20 +++++++++++++++++--- x/bank/spec/01_state.md | 2 +- 5 files changed, 35 insertions(+), 12 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5c8fc67dd3e4..0a8f71dd0de4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -89,6 +89,7 @@ Ref: https://keepachangelog.com/en/1.0.0/ * (x/bank) [\#8656](https://github.com/cosmos/cosmos-sdk/pull/8656) balance and supply are now correctly tracked via `coin_spent`, `coin_received`, `coinbase` and `burn` events. * (x/bank) [\#8517](https://github.com/cosmos/cosmos-sdk/pull/8517) Supply is now stored and tracked as `sdk.Coins` * (store) [\#8790](https://github.com/cosmos/cosmos-sdk/pull/8790) Reduce gas costs by 10x for transient store operations. +* (x/bank) [\#9051](https://github.com/cosmos/cosmos-sdk/pull/9051) Supply value is stored as `sdk.Int` rather than `string`. ### Improvements diff --git a/x/bank/keeper/keeper.go b/x/bank/keeper/keeper.go index bb3bd1080c9c..9704e1595e8d 100644 --- a/x/bank/keeper/keeper.go +++ b/x/bank/keeper/keeper.go @@ -1,6 +1,8 @@ package keeper import ( + "fmt" + "github.com/cosmos/cosmos-sdk/codec" "github.com/cosmos/cosmos-sdk/store/prefix" sdk "github.com/cosmos/cosmos-sdk/types" @@ -184,9 +186,10 @@ func (k BaseKeeper) GetSupply(ctx sdk.Context, denom string) sdk.Coin { } } - amount, ok := sdk.NewIntFromString(string(bz)) - if !ok { - panic("unexpected supply") + var amount sdk.Int + err := amount.Unmarshal(bz) + if err != nil { + panic(fmt.Errorf("unable to unmarshal supply value %v", err)) } return sdk.Coin{ @@ -413,7 +416,11 @@ func (k BaseKeeper) setSupply(ctx sdk.Context, coin sdk.Coin) { store := ctx.KVStore(k.storeKey) supplyStore := prefix.NewStore(store, types.SupplyKey) - supplyStore.Set([]byte(coin.GetDenom()), []byte(coin.Amount.String())) + intBytes, err := coin.Amount.Marshal() + if err != nil { + panic(fmt.Errorf("unable to marshal amount value %v", err)) + } + supplyStore.Set([]byte(coin.GetDenom()), intBytes) } func (k BaseKeeper) trackDelegation(ctx sdk.Context, addr sdk.AccAddress, balance, amt sdk.Coins) error { @@ -454,9 +461,10 @@ func (k BaseViewKeeper) IterateTotalSupply(ctx sdk.Context, cb func(sdk.Coin) bo defer iterator.Close() for ; iterator.Valid(); iterator.Next() { - amount, ok := sdk.NewIntFromString(string(iterator.Value())) - if !ok { - panic("unexpected supply") + var amount sdk.Int + err := amount.Unmarshal(iterator.Value()) + if err != nil { + panic(fmt.Errorf("unable to unmarshal supply value %v", err)) } balance := sdk.Coin{ diff --git a/x/bank/legacy/v043/store.go b/x/bank/legacy/v043/store.go index 6dbc3ceab97f..dfd021abd9ea 100644 --- a/x/bank/legacy/v043/store.go +++ b/x/bank/legacy/v043/store.go @@ -35,7 +35,7 @@ func migrateSupply(store sdk.KVStore, cdc codec.BinaryMarshaler) error { oldSupply := oldSupplyI.(*types.Supply) for i := range oldSupply.Total { coin := oldSupply.Total[i] - coinBz, err := cdc.MarshalBinaryBare(&coin) + coinBz, err := coin.Amount.Marshal() if err != nil { return err } diff --git a/x/bank/legacy/v043/store_test.go b/x/bank/legacy/v043/store_test.go index 145db59f16cc..5f61e33dffde 100644 --- a/x/bank/legacy/v043/store_test.go +++ b/x/bank/legacy/v043/store_test.go @@ -36,12 +36,26 @@ func TestSupplyMigration(t *testing.T) { require.NoError(t, err) // New supply is indexed by denom. - var newFooCoin, newBarCoin sdk.Coin supplyStore := prefix.NewStore(store, types.SupplyKey) - encCfg.Marshaler.MustUnmarshalBinaryBare(supplyStore.Get([]byte("foo")), &newFooCoin) - encCfg.Marshaler.MustUnmarshalBinaryBare(supplyStore.Get([]byte("bar")), &newBarCoin) + bz := supplyStore.Get([]byte("foo")) + var amount sdk.Int + err = amount.Unmarshal(bz) + require.NoError(t, err) + newFooCoin := sdk.Coin{ + Denom: "foo", + Amount: amount, + } require.Equal(t, oldFooCoin, newFooCoin) + + bz = supplyStore.Get([]byte("bar")) + err = amount.Unmarshal(bz) + require.NoError(t, err) + + newBarCoin := sdk.Coin{ + Denom: "bar", + Amount: amount, + } require.Equal(t, oldBarCoin, newBarCoin) } diff --git a/x/bank/spec/01_state.md b/x/bank/spec/01_state.md index 4b8a512489e6..5328e8b3caee 100644 --- a/x/bank/spec/01_state.md +++ b/x/bank/spec/01_state.md @@ -7,6 +7,6 @@ order: 1 The `x/bank` module keeps state of three primary objects, account balances, denom metadata and the total supply of all balances. -- Supply: `0x0 | byte(denom) -> ProtocolBuffer(coin)` +- Supply: `0x0 | byte(denom) -> byte(amount)` - Denom Metadata: `0x1 | byte(denom) -> ProtocolBuffer(Metadata)` - Balances: `0x2 | byte(address length) | []byte(address) | []byte(balance.Denom) -> ProtocolBuffer(balance)`