From a6209918bf1b0ff25b3ae83fbd80c128ef80bb33 Mon Sep 17 00:00:00 2001 From: lumtis Date: Wed, 11 Dec 2024 13:31:51 +0100 Subject: [PATCH] add migration script --- pkg/crypto/evm_address.go | 3 +- testutil/sample/fungible.go | 1 + x/crosschain/types/message_whitelist_erc20.go | 1 + x/fungible/keeper/migrator.go | 24 ++++++ x/fungible/migrations/v3/migrate.go | 27 +++++++ x/fungible/migrations/v3/migrate_test.go | 76 +++++++++++++++++++ x/fungible/module.go | 6 +- 7 files changed, 136 insertions(+), 2 deletions(-) create mode 100644 x/fungible/keeper/migrator.go create mode 100644 x/fungible/migrations/v3/migrate.go create mode 100644 x/fungible/migrations/v3/migrate_test.go diff --git a/pkg/crypto/evm_address.go b/pkg/crypto/evm_address.go index 03a2db2353..359d458bf7 100644 --- a/pkg/crypto/evm_address.go +++ b/pkg/crypto/evm_address.go @@ -1,9 +1,10 @@ package crypto import ( - "github.com/ethereum/go-ethereum/common" "strings" + "github.com/ethereum/go-ethereum/common" + "github.com/zeta-chain/node/pkg/constant" ) diff --git a/testutil/sample/fungible.go b/testutil/sample/fungible.go index 7d4ae17577..4aecea486b 100644 --- a/testutil/sample/fungible.go +++ b/testutil/sample/fungible.go @@ -20,6 +20,7 @@ func ForeignCoins(t *testing.T, address string) types.ForeignCoins { Symbol: StringRandom(r, 32), CoinType: coin.CoinType_ERC20, GasLimit: r.Uint64(), + LiquidityCap: UintInRange(0, 10000000000), } } diff --git a/x/crosschain/types/message_whitelist_erc20.go b/x/crosschain/types/message_whitelist_erc20.go index 4fb576b358..be5ca0e9ca 100644 --- a/x/crosschain/types/message_whitelist_erc20.go +++ b/x/crosschain/types/message_whitelist_erc20.go @@ -5,6 +5,7 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" "github.com/pkg/errors" + "github.com/zeta-chain/node/pkg/crypto" "github.com/zeta-chain/node/x/fungible/types" ) diff --git a/x/fungible/keeper/migrator.go b/x/fungible/keeper/migrator.go new file mode 100644 index 0000000000..011b284074 --- /dev/null +++ b/x/fungible/keeper/migrator.go @@ -0,0 +1,24 @@ +package keeper + +import ( + sdk "github.com/cosmos/cosmos-sdk/types" + + v3 "github.com/zeta-chain/node/x/fungible/migrations/v3" +) + +// Migrator is a struct for handling in-place store migrations. +type Migrator struct { + fungibleKeeper Keeper +} + +// NewMigrator returns a new Migrator. +func NewMigrator(keeper Keeper) Migrator { + return Migrator{ + fungibleKeeper: keeper, + } +} + +// Migrate2to3 migrates the store from consensus version 2 to 3 +func (m Migrator) Migrate2to3(ctx sdk.Context) error { + return v3.MigrateStore(ctx, m.fungibleKeeper) +} diff --git a/x/fungible/migrations/v3/migrate.go b/x/fungible/migrations/v3/migrate.go new file mode 100644 index 0000000000..1899da56ed --- /dev/null +++ b/x/fungible/migrations/v3/migrate.go @@ -0,0 +1,27 @@ +package v3 + +import ( + sdk "github.com/cosmos/cosmos-sdk/types" + + "github.com/zeta-chain/node/pkg/crypto" + "github.com/zeta-chain/node/x/fungible/types" +) + +type fungibleKeeper interface { + GetAllForeignCoins(ctx sdk.Context) (list []types.ForeignCoins) + SetForeignCoins(ctx sdk.Context, foreignCoins types.ForeignCoins) +} + +// MigrateStore migrates the x/fungible module state from the consensus version 2 to 3 +// It updates all existing address in ForeignCoin to use checksum format if the address is EVM type +func MigrateStore(ctx sdk.Context, fungibleKeeper fungibleKeeper) error { + fcs := fungibleKeeper.GetAllForeignCoins(ctx) + for _, fc := range fcs { + if fc.Asset != "" && crypto.IsEVMAddress(fc.Asset) && !crypto.IsChecksumAddress(fc.Asset) { + fc.Asset = crypto.ToChecksumAddress(fc.Asset) + fungibleKeeper.SetForeignCoins(ctx, fc) + } + } + + return nil +} diff --git a/x/fungible/migrations/v3/migrate_test.go b/x/fungible/migrations/v3/migrate_test.go new file mode 100644 index 0000000000..f1561e2c56 --- /dev/null +++ b/x/fungible/migrations/v3/migrate_test.go @@ -0,0 +1,76 @@ +package v3_test + +import ( + "github.com/stretchr/testify/require" + keepertest "github.com/zeta-chain/node/testutil/keeper" + "github.com/zeta-chain/node/testutil/sample" + "github.com/zeta-chain/node/x/fungible/migrations/v3" + "github.com/zeta-chain/node/x/fungible/types" + "testing" +) + +func TestMigrateStore(t *testing.T) { + tests := []struct { + name string + assetList []string + expectedList []string + }{ + { + name: "no asset to update", + assetList: []string{}, + expectedList: []string{}, + }, + { + name: "assets to update", + assetList: []string{ + "", + "0x5a4f260a7d716c859a2736151cb38b9c58c32c64", // lowercase + "", + "0xc0ffee254729296a45a3885639AC7E10F9d54979", // checksum + "", + "", + "Gh9ZwEmdLJ8DscKNTkTqPbNwLNNBjuSzaG9Vp2KGtKJr", + "BrS9iNMC3y8J4QTmCz8VrGrYepdoxXYvKxcDMiixwLn5", + "0x999999CF1046E68E36E1AA2E0E07105EDDD1F08E", // uppcase + }, + expectedList: []string{ + "", + "0x5a4f260A7D716c859A2736151cB38b9c58C32c64", + "", + "0xc0ffee254729296a45a3885639AC7E10F9d54979", + "", + "", + "Gh9ZwEmdLJ8DscKNTkTqPbNwLNNBjuSzaG9Vp2KGtKJr", + "BrS9iNMC3y8J4QTmCz8VrGrYepdoxXYvKxcDMiixwLn5", + "0x999999cf1046e68e36E1aA2E0E07105eDDD1f08E", + }, + }, + } + + for _, tt := range tests { + k, ctx, _, _ := keepertest.FungibleKeeper(t) + // Arrange + + // set sample foreign coins + expectedForeignCoins := make([]types.ForeignCoins, len(tt.assetList)) + for i, asset := range tt.assetList { + expectedForeignCoins[i] = sample.ForeignCoins(t, sample.EthAddress().Hex()) + expectedForeignCoins[i].Asset = asset + k.SetForeignCoins(ctx, expectedForeignCoins[i]) + } + + // update for expected list + for i := range tt.assetList { + expectedForeignCoins[i].Asset = tt.expectedList[i] + } + + // Act + err := v3.MigrateStore(ctx, k) + require.NoError(t, err) + + // Assert + actualForeignCoins := k.GetAllForeignCoins(ctx) + require.ElementsMatch(t, expectedForeignCoins, actualForeignCoins) + } + +} diff --git a/x/fungible/module.go b/x/fungible/module.go index fcec27c9d4..149ef5cce4 100644 --- a/x/fungible/module.go +++ b/x/fungible/module.go @@ -123,6 +123,10 @@ func (am AppModule) Name() string { func (am AppModule) RegisterServices(cfg module.Configurator) { types.RegisterMsgServer(cfg.MsgServer(), keeper.NewMsgServerImpl(am.keeper)) types.RegisterQueryServer(cfg.QueryServer(), am.keeper) + m := keeper.NewMigrator(am.keeper) + if err := cfg.RegisterMigration(types.ModuleName, 2, m.Migrate2to3); err != nil { + panic(err) + } } // RegisterInvariants registers the fungible module's invariants. @@ -153,7 +157,7 @@ func (am AppModule) ExportGenesis(ctx sdk.Context, cdc codec.JSONCodec) json.Raw } // ConsensusVersion implements ConsensusVersion. -func (AppModule) ConsensusVersion() uint64 { return 2 } +func (AppModule) ConsensusVersion() uint64 { return 3 } // BeginBlock executes all ABCI BeginBlock logic respective to the fungible module. func (am AppModule) BeginBlock(_ sdk.Context, _ abci.RequestBeginBlock) {}