diff --git a/CHANGELOG.md b/CHANGELOG.md index 5ebdf1237341..df970f97db48 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -45,7 +45,20 @@ Ref: https://keepachangelog.com/en/1.0.0/ * (x/params) [#12724](https://github.com/cosmos/cosmos-sdk/pull/12724) Add `GetParamSetIfExists` function to params `Subspace` to prevent panics on breaking changes. * [#12668](https://github.com/cosmos/cosmos-sdk/pull/12668) Add `authz_msg_index` event attribute to message events emitted when executing via `MsgExec` through `x/authz`. +<<<<<<< HEAD * [#12697](https://github.com/cosmos/cosmos-sdk/pull/12697) Upgrade IAVL to v0.19.0 with fast index and error propagation. NOTE: first start will take a while to propagate into new model. +======= +* [#12626](https://github.com/cosmos/cosmos-sdk/pull/12626) Upgrade IAVL to v0.19.0 with fast index and error propagation. NOTE: first start will take a while to propagate into new model. +* [#12649](https://github.com/cosmos/cosmos-sdk/pull/12649) Bump tendermint to v0.34.20. +* [#12576](https://github.com/cosmos/cosmos-sdk/pull/12576) Remove dependency on cosmos/keyring and upgrade to 99designs/keyring v1.2.1 +* [#12590](https://github.com/cosmos/cosmos-sdk/pull/12590) Allow zero gas in simulation mode. +* [#12453](https://github.com/cosmos/cosmos-sdk/pull/12453) Add `NewInMemoryWithKeyring` function which allows the creation of in memory `keystore` instances with a specified set of existing items. +* [#11390](https://github.com/cosmos/cosmos-sdk/pull/11390) `LatestBlockResponse` & `BlockByHeightResponse` types' `Block` filed has been deprecated and they now contains new field `sdk_block` with `proposer_address` as `string` +* (deps) Downgrade to Tendermint [v0.34.20-rc0](https://github.com/tendermint/tendermint/releases/tag/v0.34.20-rc0). +* [#12089](https://github.com/cosmos/cosmos-sdk/pull/12089) Mark the `TipDecorator` as beta, don't include it in simapp by default. +* [#12153](https://github.com/cosmos/cosmos-sdk/pull/12153) Add a new `NewSimulationManagerFromAppModules` constructor, to simplify simulation wiring. +* (x/bank) [#12674](https://github.com/cosmos/cosmos-sdk/pull/12674) Add convenience function `CreatePrefixedAccountStoreKey()` to construct key to access account's balance for a given denom. +>>>>>>> a1777a87b (feat: Add convenience method for constructing key to access account's balance for a given denom (#12674)) ### Bug Fixes diff --git a/x/bank/legacy/v043/store.go b/x/bank/legacy/v043/store.go index c4924f17df2d..e0528075660c 100644 --- a/x/bank/legacy/v043/store.go +++ b/x/bank/legacy/v043/store.go @@ -59,9 +59,15 @@ func migrateBalanceKeys(store sdk.KVStore) { defer oldStoreIter.Close() for ; oldStoreIter.Valid(); oldStoreIter.Next() { +<<<<<<< HEAD:x/bank/legacy/v043/store.go addr := v040bank.AddressFromBalancesStore(oldStoreIter.Key()) denom := oldStoreIter.Key()[v040auth.AddrLen:] newStoreKey := append(types.CreateAccountBalancesPrefix(addr), denom...) +======= + addr := v1.AddressFromBalancesStore(oldStoreIter.Key()) + denom := oldStoreIter.Key()[v042auth.AddrLen:] + newStoreKey := types.CreatePrefixedAccountStoreKey(addr, denom) +>>>>>>> a1777a87b (feat: Add convenience method for constructing key to access account's balance for a given denom (#12674)):x/bank/migrations/v2/store.go // Set new key on store. Values don't change. store.Set(newStoreKey, oldStoreIter.Value()) diff --git a/x/bank/legacy/v043/store_test.go b/x/bank/legacy/v043/store_test.go index 2b6af2c6ed9b..8d6474de8b83 100644 --- a/x/bank/legacy/v043/store_test.go +++ b/x/bank/legacy/v043/store_test.go @@ -90,13 +90,13 @@ func TestBalanceKeysMigration(t *testing.T) { err = v043bank.MigrateStore(ctx, bankKey, encCfg.Marshaler) require.NoError(t, err) - newKey := append(types.CreateAccountBalancesPrefix(addr), []byte(fooCoin.Denom)...) + newKey := types.CreatePrefixedAccountStoreKey(addr, []byte(fooCoin.Denom)) // -7 because we replaced "balances" with 0x02, // +1 because we added length-prefix to address. require.Equal(t, len(oldFooKey)-7+1, len(newKey)) require.Nil(t, store.Get(oldFooKey)) require.Equal(t, fooBz, store.Get(newKey)) - newKeyFooBar := append(types.CreateAccountBalancesPrefix(addr), []byte(fooBarCoin.Denom)...) + newKeyFooBar := types.CreatePrefixedAccountStoreKey(addr, []byte(fooBarCoin.Denom)) require.Nil(t, store.Get(newKeyFooBar)) // after migration zero balances pruned from store. } diff --git a/x/bank/types/keys.go b/x/bank/types/keys.go new file mode 100644 index 000000000000..09938efc9271 --- /dev/null +++ b/x/bank/types/keys.go @@ -0,0 +1,112 @@ +package types + +import ( + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/types/address" + "github.com/cosmos/cosmos-sdk/types/kv" +) + +const ( + // ModuleName defines the module name + ModuleName = "bank" + + // StoreKey defines the primary module store key + StoreKey = ModuleName + + // RouterKey defines the module's message routing key + RouterKey = ModuleName + + // QuerierRoute defines the module's query routing key + QuerierRoute = ModuleName + + // ModuleQueryPath defines the ABCI query path of the module + ModuleQueryPath = "store/bank/key" +) + +// KVStore keys +var ( + SupplyKey = []byte{0x00} + DenomMetadataPrefix = []byte{0x1} + DenomAddressPrefix = []byte{0x03} + + // BalancesPrefix is the prefix for the account balances store. We use a byte + // (instead of `[]byte("balances")` to save some disk space). + BalancesPrefix = []byte{0x02} + + // SendEnabledPrefix is the prefix for the SendDisabled flags for a Denom. + SendEnabledPrefix = []byte{0x04} + + // ParamsKey is the prefix for x/bank parameters + ParamsKey = []byte{0x05} +) + +const ( + // TrueB is a byte with value 1 that represents true. + TrueB = byte(0x01) + // FalseB is a byte with value 0 that represents false. + FalseB = byte(0x00) +) + +// AddressAndDenomFromBalancesStore returns an account address and denom from a balances prefix +// store. The key must not contain the prefix BalancesPrefix as the prefix store +// iterator discards the actual prefix. +// +// If invalid key is passed, AddressAndDenomFromBalancesStore returns ErrInvalidKey. +func AddressAndDenomFromBalancesStore(key []byte) (sdk.AccAddress, string, error) { + if len(key) == 0 { + return nil, "", ErrInvalidKey + } + + kv.AssertKeyAtLeastLength(key, 1) + + addrBound := int(key[0]) + + if len(key)-1 < addrBound { + return nil, "", ErrInvalidKey + } + + return key[1 : addrBound+1], string(key[addrBound+1:]), nil +} + +// CreatePrefixedAccountStoreKey returns the key for the given account and denomination. +// This method can be used when performing an ABCI query for the balance of an account. +func CreatePrefixedAccountStoreKey(addr []byte, denom []byte) []byte { + return append(CreateAccountBalancesPrefix(addr), denom...) +} + +// CreateAccountBalancesPrefix creates the prefix for an account's balances. +func CreateAccountBalancesPrefix(addr []byte) []byte { + return append(BalancesPrefix, address.MustLengthPrefix(addr)...) +} + +// CreateDenomAddressPrefix creates a prefix for a reverse index of denomination +// to account balance for that denomination. +func CreateDenomAddressPrefix(denom string) []byte { + // we add a "zero" byte at the end - null byte terminator, to allow prefix denom prefix + // scan. Setting it is not needed (key[last] = 0) - because this is the default. + key := make([]byte, len(DenomAddressPrefix)+len(denom)+1) + copy(key, DenomAddressPrefix) + copy(key[len(DenomAddressPrefix):], denom) + return key +} + +// CreateSendEnabledKey creates the key of the SendDisabled flag for a denom. +func CreateSendEnabledKey(denom string) []byte { + key := make([]byte, len(SendEnabledPrefix)+len(denom)) + copy(key, SendEnabledPrefix) + copy(key[len(SendEnabledPrefix):], denom) + return key +} + +// IsTrueB returns true if the provided byte slice has exactly one byte, and it is equal to TrueB. +func IsTrueB(bz []byte) bool { + return len(bz) == 1 && bz[0] == TrueB +} + +// ToBoolB returns TrueB if v is true, and FalseB if it's false. +func ToBoolB(v bool) byte { + if v { + return TrueB + } + return FalseB +}