From e7675af8088c04496ad658816de7210e65183b5c Mon Sep 17 00:00:00 2001 From: zakir <80246097+zakir-code@users.noreply.github.com> Date: Fri, 18 Oct 2024 18:29:01 +0800 Subject: [PATCH] refactor(x/erc20): migrate legacy key store (#756) Co-authored-by: fx0x55 <80245546+fx0x55@users.noreply.github.com> --- app/upgrade_test.go | 9 ++++ app/upgrades/v8/upgrade.go | 4 ++ x/erc20/keeper/keeper.go | 2 +- x/erc20/migrations/v8/keys.go | 73 +++++++++++++++++++++++++++++ x/erc20/migrations/v8/keys_test.go | 21 +++++++++ x/erc20/migrations/v8/legacy.go | 20 +++++++- x/erc20/migrations/v8/migrations.go | 3 ++ x/erc20/types/keys.go | 20 +++----- 8 files changed, 135 insertions(+), 17 deletions(-) create mode 100644 x/erc20/migrations/v8/keys.go create mode 100644 x/erc20/migrations/v8/keys_test.go diff --git a/app/upgrade_test.go b/app/upgrade_test.go index 3e99b3a5..eb87487d 100644 --- a/app/upgrade_test.go +++ b/app/upgrade_test.go @@ -100,6 +100,15 @@ func checkAppUpgrade(t *testing.T, ctx sdk.Context, myApp *app.App) { checkStakingMigrationDelete(t, ctx, myApp) checkGovCustomParams(t, ctx, myApp) + + checkErc20Keys(t, ctx, myApp) +} + +func checkErc20Keys(t *testing.T, ctx sdk.Context, myApp *app.App) { + params, err := myApp.Erc20Keeper.Params.Get(ctx) + require.NoError(t, err) + + require.True(t, params.EnableErc20) } func checkGovCustomParams(t *testing.T, ctx sdk.Context, myApp *app.App) { diff --git a/app/upgrades/v8/upgrade.go b/app/upgrades/v8/upgrade.go index 5fb7576e..7a0e13f1 100644 --- a/app/upgrades/v8/upgrade.go +++ b/app/upgrades/v8/upgrade.go @@ -16,6 +16,8 @@ import ( "github.com/functionx/fx-core/v8/app/keepers" fxtypes "github.com/functionx/fx-core/v8/types" crosschainkeeper "github.com/functionx/fx-core/v8/x/crosschain/keeper" + erc20v8 "github.com/functionx/fx-core/v8/x/erc20/migrations/v8" + erc20types "github.com/functionx/fx-core/v8/x/erc20/types" "github.com/functionx/fx-core/v8/x/gov/keeper" fxgovv8 "github.com/functionx/fx-core/v8/x/gov/migrations/v8" fxstakingv8 "github.com/functionx/fx-core/v8/x/staking/migrations/v8" @@ -43,6 +45,8 @@ func CreateUpgradeHandler(mm *module.Manager, configurator module.Configurator, updateMetadata(cacheCtx, app.BankKeeper) + removeStoreKeys(cacheCtx, app.GetKey(erc20types.StoreKey), erc20v8.GetRemovedStoreKeys()) + commit() cacheCtx.Logger().Info("upgrade complete", "module", "upgrade") return toVM, nil diff --git a/x/erc20/keeper/keeper.go b/x/erc20/keeper/keeper.go index f9579064..816c5102 100644 --- a/x/erc20/keeper/keeper.go +++ b/x/erc20/keeper/keeper.go @@ -66,7 +66,7 @@ func NewKeeper( evmErc20Keeper: evmErc20Keeper, contractOwner: common.BytesToAddress(moduleAddress), authority: authority, - Params: collections.NewItem(sb, types.ParamsKey2, "params", codec.CollValue[types.Params](cdc)), + Params: collections.NewItem(sb, types.ParamsKey, "params", codec.CollValue[types.Params](cdc)), ERC20Token: collections.NewMap(sb, types.ERC20TokenKey, "erc20_token", collections.StringKey, codec.CollValue[types.ERC20Token](cdc)), BridgeToken: collections.NewMap(sb, types.BridgeTokenKey, "bridge_token", collections.PairKeyCodec(collections.StringKey, collections.StringKey), codec.CollValue[types.BridgeToken](cdc)), IBCToken: collections.NewMap(sb, types.IBCTokenKey, "ibc_token", collections.PairKeyCodec(collections.StringKey, collections.StringKey), codec.CollValue[types.IBCToken](cdc)), diff --git a/x/erc20/migrations/v8/keys.go b/x/erc20/migrations/v8/keys.go new file mode 100644 index 00000000..62525a26 --- /dev/null +++ b/x/erc20/migrations/v8/keys.go @@ -0,0 +1,73 @@ +package v8 + +import ( + sdkmath "cosmossdk.io/math" + storetypes "cosmossdk.io/store/types" + sdk "github.com/cosmos/cosmos-sdk/types" + + crosschaintypes "github.com/functionx/fx-core/v8/x/crosschain/types" + "github.com/functionx/fx-core/v8/x/erc20/types" +) + +func (m Migrator) migrateKeys(ctx sdk.Context) error { + store := ctx.KVStore(m.storeKey) + if err := m.migrateParams(ctx, store); err != nil { + return err + } + + if err := m.migrateRelationToCache(ctx, store); err != nil { + return err + } + return nil +} + +func (m Migrator) migrateRelationToCache(ctx sdk.Context, store storetypes.KVStore) error { + // 1. migrate ibc transfer relation + iterator := storetypes.KVStorePrefixIterator(store, KeyPrefixIBCTransfer) + defer iterator.Close() + for ; iterator.Valid(); iterator.Next() { + key := iterator.Key() + newKey := key[len(KeyPrefixIBCTransfer):] + if err := m.keeper.Cache.Set(ctx, string(newKey), sdkmath.ZeroInt()); err != nil { + return err + } + store.Delete(key) + } + + // 2. migrate outgoing transfer relation + iterator = storetypes.KVStorePrefixIterator(store, KeyPrefixOutgoingTransfer) + defer iterator.Close() + for ; iterator.Valid(); iterator.Next() { + key := iterator.Key() + originTokenKey := OutgoingTransferKeyToOriginTokenKey(key) + if err := m.keeper.Cache.Set(ctx, originTokenKey, sdkmath.ZeroInt()); err != nil { + return err + } + store.Delete(key) + } + return nil +} + +func (m Migrator) migrateParams(ctx sdk.Context, store storetypes.KVStore) error { + bz := store.Get(ParamsKey) + if len(bz) == 0 { + return nil + } + var legacyParams types.LegacyParams + m.cdc.MustUnmarshal(bz, &legacyParams) + + store.Delete(ParamsKey) + return m.keeper.Params.Set(ctx, types.Params{EnableErc20: legacyParams.EnableErc20}) +} + +func OutgoingTransferKeyToOriginTokenKey(key []byte) string { + // key = prefix + moduleName(string-) + sdk.Uint64ToBigEndian(id)(len = 8) + // 1. remove prefix + key = key[len(KeyPrefixOutgoingTransfer):] + // 2. get moduleName + moduleName := string(key[:len(key)-8]) + // 3. get id + id := sdk.BigEndianToUint64(key[len(key)-8:]) + // 4. new originTokenKey + return crosschaintypes.NewOriginTokenKey(moduleName, id) +} diff --git a/x/erc20/migrations/v8/keys_test.go b/x/erc20/migrations/v8/keys_test.go new file mode 100644 index 00000000..1fe29f9f --- /dev/null +++ b/x/erc20/migrations/v8/keys_test.go @@ -0,0 +1,21 @@ +package v8_test + +import ( + "testing" + + tmrand "github.com/cometbft/cometbft/libs/rand" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/stretchr/testify/require" + + "github.com/functionx/fx-core/v8/x/crosschain/types" + v8 "github.com/functionx/fx-core/v8/x/erc20/migrations/v8" +) + +func TestOutgoingTransferKeyToOriginTokenKey(t *testing.T) { + moduleName := tmrand.Str(5) + txID := uint64(tmrand.Int63n(100000)) + oldKey := append(append(v8.KeyPrefixOutgoingTransfer, []byte(moduleName)...), sdk.Uint64ToBigEndian(txID)...) + expectKey := types.NewOriginTokenKey(moduleName, txID) + actual := v8.OutgoingTransferKeyToOriginTokenKey(oldKey) + require.EqualValues(t, expectKey, actual) +} diff --git a/x/erc20/migrations/v8/legacy.go b/x/erc20/migrations/v8/legacy.go index 9f5d41db..5b3cd4af 100644 --- a/x/erc20/migrations/v8/legacy.go +++ b/x/erc20/migrations/v8/legacy.go @@ -8,10 +8,26 @@ import ( "github.com/functionx/fx-core/v8/x/erc20/types" ) +var ( + KeyPrefixTokenPair = []byte{0x01} + KeyPrefixTokenPairByERC20 = []byte{0x02} + KeyPrefixTokenPairByDenom = []byte{0x03} + KeyPrefixIBCTransfer = []byte{0x04} + KeyPrefixAliasDenom = []byte{0x05} + ParamsKey = []byte{0x06} + KeyPrefixOutgoingTransfer = []byte{0x07} +) + +func GetRemovedStoreKeys() [][]byte { + return [][]byte{ + KeyPrefixTokenPair, KeyPrefixTokenPairByERC20, KeyPrefixTokenPairByDenom, KeyPrefixAliasDenom, + } +} + func LegacyIsNativeERC20(ctx sdk.Context, storeKey storetypes.StoreKey, cdc codec.BinaryCodec, denom string) bool { store := ctx.KVStore(storeKey) - id := store.Get(append(types.KeyPrefixTokenPairByDenom, []byte(denom)...)) - bz := store.Get(append(types.KeyPrefixTokenPair, id...)) + id := store.Get(append(KeyPrefixTokenPairByDenom, []byte(denom)...)) + bz := store.Get(append(KeyPrefixTokenPair, id...)) if len(bz) == 0 { return false } diff --git a/x/erc20/migrations/v8/migrations.go b/x/erc20/migrations/v8/migrations.go index 60c8db2b..9d115655 100644 --- a/x/erc20/migrations/v8/migrations.go +++ b/x/erc20/migrations/v8/migrations.go @@ -30,5 +30,8 @@ func NewMigrator(storeKey storetypes.StoreKey, cdc codec.BinaryCodec, keeper kee // Migrate3to4 migrates from version 3 to 4. func (m Migrator) Migrate3to4(ctx sdk.Context) error { + if err := m.migrateKeys(ctx); err != nil { + return err + } return m.MigrateToken(ctx) } diff --git a/x/erc20/types/keys.go b/x/erc20/types/keys.go index 8e1d28f5..488c35d9 100644 --- a/x/erc20/types/keys.go +++ b/x/erc20/types/keys.go @@ -14,18 +14,10 @@ const ( // KVStore key prefixes var ( - KeyPrefixTokenPair = []byte{0x01} - KeyPrefixTokenPairByERC20 = []byte{0x02} - KeyPrefixTokenPairByDenom = []byte{0x03} - KeyPrefixIBCTransfer = []byte{0x04} - KeyPrefixAliasDenom = []byte{0x05} - ParamsKey = []byte{0x06} - KeyPrefixOutgoingTransfer = []byte{0x07} - - DenomIndexKey = collections.NewPrefix(1) - ParamsKey2 = collections.NewPrefix(2) - ERC20TokenKey = collections.NewPrefix(3) - BridgeTokenKey = collections.NewPrefix(4) - IBCTokenKey = collections.NewPrefix(5) - CacheKey = collections.NewPrefix(6) + DenomIndexKey = collections.NewPrefix(11) + ParamsKey = collections.NewPrefix(12) + ERC20TokenKey = collections.NewPrefix(13) + BridgeTokenKey = collections.NewPrefix(14) + IBCTokenKey = collections.NewPrefix(15) + CacheKey = collections.NewPrefix(16) )