From 53170d00858c3d9428b54605449b16bbe09ca1de Mon Sep 17 00:00:00 2001 From: beer-1 <147697694+beer-1@users.noreply.github.com> Date: Thu, 31 Oct 2024 15:43:18 +0900 Subject: [PATCH 1/2] initialize staking at genesis (#290) --- x/bank/keeper/common_test.go | 2 +- x/distribution/keeper/common_test.go | 2 +- x/gov/keeper/common_test.go | 2 +- x/ibc-hooks/keeper/common_test.go | 2 +- x/ibc-hooks/move-hooks/common_test.go | 2 +- x/move/keeper/common_test.go | 2 +- x/move/keeper/genesis.go | 18 +++++++++++- x/move/keeper/staking_test.go | 42 +++++++++++++++++++++++++++ x/mstaking/keeper/common_test.go | 2 +- x/reward/keeper/common_test.go | 2 +- x/slashing/keeper/common_test.go | 2 +- 11 files changed, 68 insertions(+), 10 deletions(-) diff --git a/x/bank/keeper/common_test.go b/x/bank/keeper/common_test.go index 3ba17571..d3cef32a 100644 --- a/x/bank/keeper/common_test.go +++ b/x/bank/keeper/common_test.go @@ -394,7 +394,7 @@ func _createTestInput( moduleBytes, err := precompile.ReadStdlib() require.NoError(t, err) - err = moveKeeper.Initialize(ctx, moduleBytes, moveParams.AllowedPublishers) + err = moveKeeper.Initialize(ctx, moduleBytes, moveParams.AllowedPublishers, bondDenom) require.NoError(t, err) faucet := NewTestFaucet(t, ctx, bankKeeper, *moveKeeper, authtypes.Minter, initialTotalSupply()...) diff --git a/x/distribution/keeper/common_test.go b/x/distribution/keeper/common_test.go index 253bcfa1..79a9bf11 100644 --- a/x/distribution/keeper/common_test.go +++ b/x/distribution/keeper/common_test.go @@ -378,7 +378,7 @@ func _createTestInput( moduleBytes, err := precompile.ReadStdlib() require.NoError(t, err) - err = moveKeeper.Initialize(ctx, moduleBytes, moveParams.AllowedPublishers) + err = moveKeeper.Initialize(ctx, moduleBytes, moveParams.AllowedPublishers, bondDenom) require.NoError(t, err) faucet := NewTestFaucet(t, ctx, bankKeeper, *moveKeeper, authtypes.Minter, initialTotalSupply()...) diff --git a/x/gov/keeper/common_test.go b/x/gov/keeper/common_test.go index 40b9425b..e5c3e1ed 100644 --- a/x/gov/keeper/common_test.go +++ b/x/gov/keeper/common_test.go @@ -406,7 +406,7 @@ func _createTestInput( moduleBytes, err := precompile.ReadStdlib() require.NoError(t, err) - err = moveKeeper.Initialize(ctx, moduleBytes, moveParams.AllowedPublishers) + err = moveKeeper.Initialize(ctx, moduleBytes, moveParams.AllowedPublishers, bondDenom) require.NoError(t, err) faucet := NewTestFaucet(t, ctx, bankKeeper, *moveKeeper, authtypes.Minter, initialTotalSupply()...) diff --git a/x/ibc-hooks/keeper/common_test.go b/x/ibc-hooks/keeper/common_test.go index 6f7959af..20197b28 100644 --- a/x/ibc-hooks/keeper/common_test.go +++ b/x/ibc-hooks/keeper/common_test.go @@ -396,7 +396,7 @@ func _createTestInput( moduleBytes, err := precompile.ReadStdlib() require.NoError(t, err) - err = moveKeeper.Initialize(ctx, moduleBytes, moveParams.AllowedPublishers) + err = moveKeeper.Initialize(ctx, moduleBytes, moveParams.AllowedPublishers, bondDenom) require.NoError(t, err) faucet := NewTestFaucet(t, ctx, bankKeeper, *moveKeeper, authtypes.Minter, initialTotalSupply()...) diff --git a/x/ibc-hooks/move-hooks/common_test.go b/x/ibc-hooks/move-hooks/common_test.go index a6e8a52e..31922153 100644 --- a/x/ibc-hooks/move-hooks/common_test.go +++ b/x/ibc-hooks/move-hooks/common_test.go @@ -309,7 +309,7 @@ func _createTestInput( if initialize { stdlib, err := vmprecom.ReadStdlib() require.NoError(t, err) - require.NoError(t, moveKeeper.Initialize(ctx, stdlib, moveParams.AllowedPublishers)) + require.NoError(t, moveKeeper.Initialize(ctx, stdlib, moveParams.AllowedPublishers, bondDenom)) } faucet := NewTestFaucet(t, ctx, bankKeeper, authtypes.Minter, initialTotalSupply()...) diff --git a/x/move/keeper/common_test.go b/x/move/keeper/common_test.go index eac95a0e..b0d587f6 100644 --- a/x/move/keeper/common_test.go +++ b/x/move/keeper/common_test.go @@ -419,7 +419,7 @@ func _createTestInput( // append test module moduleBytes = append(moduleBytes, basicCoinModule) - err = moveKeeper.Initialize(ctx, moduleBytes, moveParams.AllowedPublishers) + err = moveKeeper.Initialize(ctx, moduleBytes, moveParams.AllowedPublishers, bondDenom) require.NoError(t, err) faucet := NewTestFaucet(t, ctx, bankKeeper, *moveKeeper, authtypes.Minter, initialTotalSupply()...) diff --git a/x/move/keeper/genesis.go b/x/move/keeper/genesis.go index 4ae2cab7..ad856db4 100644 --- a/x/move/keeper/genesis.go +++ b/x/move/keeper/genesis.go @@ -15,6 +15,7 @@ func (k Keeper) Initialize( ctx context.Context, moduleBytes [][]byte, allowedPublishers []string, + baseDenom string, ) error { sdkCtx := sdk.UnwrapSDKContext(ctx) ctx = sdkCtx.WithTxBytes(make([]byte, 32)) @@ -53,6 +54,21 @@ func (k Keeper) Initialize( if err != nil { return err } + if err = k.handleExecuteResponse(sdkCtx, sdkCtx.GasMeter(), execRes); err != nil { + return err + } + + // if staking keeper is available, initialize move staking module. + if k.StakingKeeper != nil { + if err := k.moveBankKeeper.InitializeCoin(ctx, baseDenom); err != nil { + return err + } + + // initialize move staking module if staking keeper is available + if err := k.InitializeStaking(ctx, baseDenom); err != nil { + return err + } + } return k.handleExecuteResponse(sdkCtx, sdkCtx.GasMeter(), execRes) } @@ -74,7 +90,7 @@ func (k Keeper) InitGenesis(ctx context.Context, moduleNames []string, genState } if len(genState.GetModules()) == 0 { - if err := k.Initialize(ctx, genState.GetStdlibs(), params.AllowedPublishers); err != nil { + if err := k.Initialize(ctx, genState.GetStdlibs(), params.AllowedPublishers, params.BaseDenom); err != nil { return err } } diff --git a/x/move/keeper/staking_test.go b/x/move/keeper/staking_test.go index c72d179b..ba21d845 100644 --- a/x/move/keeper/staking_test.go +++ b/x/move/keeper/staking_test.go @@ -233,6 +233,48 @@ func TestInstantUnbondFromBondedValidator(t *testing.T) { require.True(t, val.IsUnbonding()) } +func TestApplyStakingDeltas_BaseDenom(t *testing.T) { + ctx, input := createDefaultTestInput(t) + + // add second BondDenom to staking keeper + input.StakingKeeper.SetBondDenoms(ctx, []string{bondDenom}) + + // initialize staking + valAddr := createValidatorWithBalance(t, ctx, input, 100_000_000, 100_000) + + // mint not possible for lp coin, so transfer from the 0x2 + _, _, addr := keyPubAddr() + input.Faucet.Mint(ctx, addr, sdk.NewCoin(bondDenom, math.NewInt(100_000_000))) + + // delegate coins via move staking module + valAddrArg, err := vmtypes.SerializeString(valAddr.String()) + require.NoError(t, err) + + amountArg, err := vmtypes.SerializeUint64(50_000_000) + require.NoError(t, err) + + metadataAddr, err := types.MetadataAddressFromDenom(bondDenom) + require.NoError(t, err) + + vmAddr, err := vmtypes.NewAccountAddressFromBytes(addr) + require.NoError(t, err) + err = input.MoveKeeper.ExecuteEntryFunction( + ctx, + vmAddr, + vmtypes.StdAddress, + types.MoveModuleNameStaking, + types.FunctionNameStakingDelegateScript, + []vmtypes.TypeTag{}, + [][]byte{metadataAddr[:], valAddrArg, amountArg}, + ) + require.NoError(t, err) + + delModuleAddr := types.GetDelegatorModuleAddress(valAddr) + delegation, err := input.StakingKeeper.GetDelegation(ctx, delModuleAddr, valAddr) + require.NoError(t, err) + require.Equal(t, delegation.Shares, sdk.NewDecCoins(sdk.NewDecCoin(bondDenom, math.NewInt(50_000_000)))) +} + func TestApplyStakingDeltas(t *testing.T) { ctx, input := createDefaultTestInput(t) diff --git a/x/mstaking/keeper/common_test.go b/x/mstaking/keeper/common_test.go index 04bb912c..23fb5858 100644 --- a/x/mstaking/keeper/common_test.go +++ b/x/mstaking/keeper/common_test.go @@ -420,7 +420,7 @@ func _createTestInput( moduleBytes, err := precompile.ReadStdlib() require.NoError(t, err) - err = moveKeeper.Initialize(ctx, moduleBytes, moveParams.AllowedPublishers) + err = moveKeeper.Initialize(ctx, moduleBytes, moveParams.AllowedPublishers, bondDenom) require.NoError(t, err) faucet := NewTestFaucet(t, ctx, bankKeeper, *moveKeeper, authtypes.Minter, initialTotalSupply()...) diff --git a/x/reward/keeper/common_test.go b/x/reward/keeper/common_test.go index c0fff4ad..16a055aa 100644 --- a/x/reward/keeper/common_test.go +++ b/x/reward/keeper/common_test.go @@ -375,7 +375,7 @@ func _createTestInput( moduleBytes, err := precompile.ReadStdlib() require.NoError(t, err) - err = moveKeeper.Initialize(ctx, moduleBytes, moveParams.AllowedPublishers) + err = moveKeeper.Initialize(ctx, moduleBytes, moveParams.AllowedPublishers, bondDenom) require.NoError(t, err) faucet := NewTestFaucet(t, ctx, bankKeeper, *moveKeeper, authtypes.Minter, initialTotalSupply()...) diff --git a/x/slashing/keeper/common_test.go b/x/slashing/keeper/common_test.go index f3be7c9c..fae63447 100644 --- a/x/slashing/keeper/common_test.go +++ b/x/slashing/keeper/common_test.go @@ -389,7 +389,7 @@ func _createTestInput( moduleBytes, err := precompile.ReadStdlib() require.NoError(t, err) - err = moveKeeper.Initialize(ctx, moduleBytes, moveParams.AllowedPublishers) + err = moveKeeper.Initialize(ctx, moduleBytes, moveParams.AllowedPublishers, bondDenom) require.NoError(t, err) faucet := NewTestFaucet(t, ctx, bankKeeper, *moveKeeper, authtypes.Minter, initialTotalSupply()...) From e3ebdd461249d149b9428da0dec4e03d88e942a6 Mon Sep 17 00:00:00 2001 From: Hoon <48665813+sh-cha@users.noreply.github.com> Date: Thu, 31 Oct 2024 15:46:30 +0900 Subject: [PATCH 2/2] movevm loaderv2 integration (#284) * connect movevm with loaderv2 and introduce module & script cache * use cache context before query * disable unstable * update movevm to latest * add toml description --------- Co-authored-by: beer-1 --- Dockerfile | 2 +- go.mod | 3 +- go.sum | 4 +- x/move/config/config.go | 16 ++ x/move/keeper/common_test.go | 7 + x/move/keeper/genesis.go | 4 +- x/move/keeper/handler.go | 110 ++++--------- x/move/keeper/keeper.go | 33 ++-- x/move/keeper/vm_msg_stargate.go | 2 +- x/move/keeper/vm_msg_stargate_test.go | 4 +- x/move/keeper/vm_query.go | 4 + x/move/keeper/vmpool.go | 24 --- x/move/types/cosmos_message.go | 215 -------------------------- x/move/types/keys.go | 7 +- 14 files changed, 83 insertions(+), 352 deletions(-) delete mode 100644 x/move/keeper/vmpool.go delete mode 100644 x/move/types/cosmos_message.go diff --git a/Dockerfile b/Dockerfile index 8aaaa4e4..6319ad5f 100644 --- a/Dockerfile +++ b/Dockerfile @@ -6,7 +6,7 @@ ARG TARGETARCH ARG GOARCH # See https://github.com/initia-labs/movevm/releases -ENV LIBMOVEVM_VERSION=v0.5.1 +ENV LIBMOVEVM_VERSION=v0.6.0 # Install necessary packages RUN set -eux; apk add --no-cache ca-certificates build-base git cmake diff --git a/go.mod b/go.mod index 96b3321b..8defb22d 100644 --- a/go.mod +++ b/go.mod @@ -40,7 +40,7 @@ require ( github.com/hashicorp/go-metrics v0.5.3 github.com/initia-labs/OPinit v0.5.5 // we also need to update `LIBMOVEVM_VERSION` of Dockerfile#9 - github.com/initia-labs/movevm v0.5.1 + github.com/initia-labs/movevm v0.6.0 github.com/noble-assets/forwarding/v2 v2.0.0-20240521090705-86712c4c9e43 github.com/pelletier/go-toml v1.9.5 github.com/pkg/errors v0.9.1 @@ -232,6 +232,7 @@ replace ( // Fix upstream GHSA-h395-qcrw-5vmq vulnerability. // TODO Remove it: https://github.com/cosmos/cosmos-sdk/issues/10409 github.com/gin-gonic/gin => github.com/gin-gonic/gin v1.8.1 + // Downgraded to avoid bugs in following commits which caused simulations to fail. github.com/syndtr/goleveldb => github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 ) diff --git a/go.sum b/go.sum index 4e489523..456ddb2e 100644 --- a/go.sum +++ b/go.sum @@ -732,8 +732,8 @@ github.com/initia-labs/OPinit/api v0.5.1 h1:zwyJf7HtKJCKvLJ1R9PjVfJO1L+d/jKoeFyT github.com/initia-labs/OPinit/api v0.5.1/go.mod h1:gHK6DEWb3/DqQD5LjKirUx9jilAh2UioXanoQdgqVfU= github.com/initia-labs/cometbft v0.0.0-20240923045653-ba99eb347236 h1:+HmPQ1uptOe4r5oQHuHMG5zF1F3maNoEba5uiTUMnlk= github.com/initia-labs/cometbft v0.0.0-20240923045653-ba99eb347236/go.mod h1:GPHp3/pehPqgX1930HmK1BpBLZPxB75v/dZg8Viwy+o= -github.com/initia-labs/movevm v0.5.1 h1:Nl5SizJIfRLM6clz/zV8dOFUXcnlMP2wOQsZB/mmU2w= -github.com/initia-labs/movevm v0.5.1/go.mod h1:aUWdvFZPdULjJ2McQTE+mLnfnG3CLAz0TWJRFzFFUwg= +github.com/initia-labs/movevm v0.6.0 h1:46JjDfOId6hfeoqYqKWTzPeb5ESQzzm8AhhGWYnFOmE= +github.com/initia-labs/movevm v0.6.0/go.mod h1:aUWdvFZPdULjJ2McQTE+mLnfnG3CLAz0TWJRFzFFUwg= github.com/jhump/protoreflect v1.15.3 h1:6SFRuqU45u9hIZPJAoZ8c28T3nK64BNdp9w6jFonzls= github.com/jhump/protoreflect v1.15.3/go.mod h1:4ORHmSBmlCW8fh3xHmJMGyul1zNqZK4Elxc8qKP+p1k= github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= diff --git a/x/move/config/config.go b/x/move/config/config.go index 55678941..3b0a95bf 100644 --- a/x/move/config/config.go +++ b/x/move/config/config.go @@ -9,20 +9,28 @@ import ( // DefaultContractSimulationGasLimit - default max simulation gas const DefaultContractSimulationGasLimit = uint64(3_000_000) +const DefaultScriptCacheCapacity = uint64(100) +const DefaultModuleCacheCapacity = uint64(500) const ( flagContractSimulationGasLimit = "move.contract-simulation-gas-limit" + flagScriptCacheCapacity = "move.script-cache-capacity" + flagModuleCacheCapacity = "move.module-cache-capacity" ) // MoveConfig is the extra config required for move type MoveConfig struct { ContractSimulationGasLimit uint64 `mapstructure:"contract-simulation-gas-limit"` + ScriptCacheCapacity uint64 `mapstructure:"script-cache-capacity"` + ModuleCacheCapacity uint64 `mapstructure:"module-cache-capacity"` } // DefaultMoveConfig returns the default settings for MoveConfig func DefaultMoveConfig() MoveConfig { return MoveConfig{ ContractSimulationGasLimit: DefaultContractSimulationGasLimit, + ScriptCacheCapacity: DefaultScriptCacheCapacity, + ModuleCacheCapacity: DefaultModuleCacheCapacity, } } @@ -30,12 +38,16 @@ func DefaultMoveConfig() MoveConfig { func GetConfig(appOpts servertypes.AppOptions) MoveConfig { return MoveConfig{ ContractSimulationGasLimit: cast.ToUint64(appOpts.Get(flagContractSimulationGasLimit)), + ScriptCacheCapacity: cast.ToUint64(appOpts.Get(flagScriptCacheCapacity)), + ModuleCacheCapacity: cast.ToUint64(appOpts.Get(flagModuleCacheCapacity)), } } // AddConfigFlags implements servertypes.MoveConfigFlags interface. func AddConfigFlags(startCmd *cobra.Command) { startCmd.Flags().Uint64(flagContractSimulationGasLimit, DefaultContractSimulationGasLimit, "Set the max simulation gas for move contract execution") + startCmd.Flags().Uint64(flagScriptCacheCapacity, DefaultScriptCacheCapacity, "Set the script cache capacity") + startCmd.Flags().Uint64(flagModuleCacheCapacity, DefaultModuleCacheCapacity, "Set the module cache capacity") } // DefaultConfigTemplate default config template for move module @@ -47,4 +59,8 @@ const DefaultConfigTemplate = ` [move] # The maximum gas amount can be used in a tx simulation call. contract-simulation-gas-limit = "{{ .MoveConfig.ContractSimulationGasLimit }}" +# The capacity of the script cache in (MiB). +script-cache-capacity = "{{ .MoveConfig.ScriptCacheCapacity }}" +# The capacity of the module cache in (MiB). +module-cache-capacity = "{{ .MoveConfig.ModuleCacheCapacity }}" ` diff --git a/x/move/keeper/common_test.go b/x/move/keeper/common_test.go index b0d587f6..96684939 100644 --- a/x/move/keeper/common_test.go +++ b/x/move/keeper/common_test.go @@ -49,6 +49,10 @@ import ( govtypesv1 "github.com/cosmos/cosmos-sdk/x/gov/types/v1" slashingtypes "github.com/cosmos/cosmos-sdk/x/slashing/types" + ibcfee "github.com/cosmos/ibc-go/v8/modules/apps/29-fee" + ibctransfer "github.com/cosmos/ibc-go/v8/modules/apps/transfer" + ibcnfttransfer "github.com/initia-labs/initia/x/ibc/nft-transfer" + initiaapp "github.com/initia-labs/initia/app" initiaappparams "github.com/initia-labs/initia/app/params" "github.com/initia-labs/initia/x/bank" @@ -90,6 +94,9 @@ var ModuleBasics = module.NewBasicManager( slashing.AppModuleBasic{}, move.AppModuleBasic{}, oracle.AppModuleBasic{}, + ibctransfer.AppModuleBasic{}, + ibcnfttransfer.AppModuleBasic{}, + ibcfee.AppModuleBasic{}, ) // Bond denom should be set for staking test diff --git a/x/move/keeper/genesis.go b/x/move/keeper/genesis.go index ad856db4..9388ef78 100644 --- a/x/move/keeper/genesis.go +++ b/x/move/keeper/genesis.go @@ -48,9 +48,7 @@ func (k Keeper) Initialize( } vmStore := types.NewVMStore(ctx, k.VMStore) - execRes, err := execVM(ctx, k, func(vm types.VMEngine) (vmtypes.ExecutionResult, error) { - return vm.Initialize(vmStore, api, env, vmtypes.NewModuleBundle(modules...), _allowedPublishers) - }) + execRes, err := k.initiaMoveVM.Initialize(vmStore, api, env, vmtypes.NewModuleBundle(modules...), _allowedPublishers) if err != nil { return err } diff --git a/x/move/keeper/handler.go b/x/move/keeper/handler.go index 44fb1ea8..f1b1c095 100644 --- a/x/move/keeper/handler.go +++ b/x/move/keeper/handler.go @@ -197,16 +197,14 @@ func (k Keeper) executeEntryFunction( sdkCtx = sdkCtx.WithGasMeter(storetypes.NewInfiniteGasMeter()) gasBalance := gasForRuntime - execRes, err := execVM(ctx, k, func(vm types.VMEngine) (vmtypes.ExecutionResult, error) { - return vm.ExecuteEntryFunction( - &gasBalance, - types.NewVMStore(sdkCtx, k.VMStore), - NewApi(k, sdkCtx), - types.NewEnv(sdkCtx, ac, ec), - senders, - payload, - ) - }) + execRes, err := k.initiaMoveVM.ExecuteEntryFunction( + &gasBalance, + types.NewVMStore(sdkCtx, k.VMStore), + NewApi(k, sdkCtx), + types.NewEnv(sdkCtx, ac, ec), + senders, + payload, + ) // consume gas first and check error gasUsed := gasForRuntime - gasBalance @@ -309,16 +307,14 @@ func (k Keeper) executeScript( sdkCtx = sdkCtx.WithGasMeter(storetypes.NewInfiniteGasMeter()) gasBalance := gasForRuntime - execRes, err := execVM(ctx, k, func(vm types.VMEngine) (vmtypes.ExecutionResult, error) { - return vm.ExecuteScript( - &gasBalance, - types.NewVMStore(sdkCtx, k.VMStore), - NewApi(k, sdkCtx), - types.NewEnv(sdkCtx, ac, ec), - senders, - payload, - ) - }) + execRes, err := k.initiaMoveVM.ExecuteScript( + &gasBalance, + types.NewVMStore(sdkCtx, k.VMStore), + NewApi(k, sdkCtx), + types.NewEnv(sdkCtx, ac, ec), + senders, + payload, + ) // consume gas first and check error gasUsed := gasForRuntime - gasBalance @@ -419,10 +415,6 @@ func (k Keeper) DispatchMessages(ctx context.Context, messages []vmtypes.CosmosM } func (k Keeper) dispatchMessage(parentCtx sdk.Context, message vmtypes.CosmosMessage) (err error) { - var allowFailure bool - var callback *vmtypes.StargateCallback - var callbackSender vmtypes.AccountAddress - ctx, commit := parentCtx.CacheContext() defer func() { if r := recover(); r != nil { @@ -439,7 +431,7 @@ func (k Keeper) dispatchMessage(parentCtx sdk.Context, message vmtypes.CosmosMes if !success { // return error if failed and not allowed to fail - if !allowFailure { + if !message.AllowFailure { return } @@ -457,48 +449,27 @@ func (k Keeper) dispatchMessage(parentCtx sdk.Context, message vmtypes.CosmosMes parentCtx.EventManager().EmitEvent(event) // if callback exists, execute it with parent context becuase it's already committed - if callback != nil { + if message.Callback != nil { err = k.ExecuteEntryFunctionJSON( parentCtx, - callbackSender, - callback.ModuleAddress, - callback.ModuleName, - callback.FunctionName, + message.Sender, + message.Callback.ModuleAddress, + message.Callback.ModuleName, + message.Callback.FunctionName, []vmtypes.TypeTag{}, []string{ - fmt.Sprintf("\"%d\"", callback.Id), + fmt.Sprintf("\"%d\"", message.Callback.Id), fmt.Sprintf("%v", success), }, ) } }() + // validate basic & signer check is done in HandleVMStargateMsg var msg proto.Message - if stargateMsg, ok := message.(*vmtypes.CosmosMessage__Stargate); ok { - // callback only exists in stargate message - allowFailure = stargateMsg.Value.AllowFailure - callback = stargateMsg.Value.Callback - callbackSender = stargateMsg.Value.Sender - - // validate basic & signer check is done in HandleVMStargateMsg - msg, err = k.HandleVMStargateMsg(ctx, &stargateMsg.Value) - if err != nil { - return - } - } else { - // signer check had been done in moveVM - msg, err = types.ConvertToSDKMessage(ctx, k.MoveBankKeeper(), NewNftKeeper(&k), message, k.ac, k.vc) - if err != nil { - return - } - - // conduct validate basic - if msg, ok := msg.(sdk.HasValidateBasic); ok { - err = msg.ValidateBasic() - if err != nil { - return - } - } + msg, err = k.HandleVMStargateMsg(ctx, &message) + if err != nil { + return } // find the handler @@ -653,15 +624,13 @@ func (k Keeper) executeViewFunction( gasForRuntime := k.computeGasForRuntime(ctx, gasMeter) gasBalance := gasForRuntime - viewRes, err := execVM(ctx, k, func(vm types.VMEngine) (vmtypes.ViewOutput, error) { - return vm.ExecuteViewFunction( - &gasBalance, - types.NewVMStore(ctx, k.VMStore), - api, - env, - payload, - ) - }) + viewRes, err := k.initiaMoveVM.ExecuteViewFunction( + &gasBalance, + types.NewVMStore(ctx, k.VMStore), + api, + env, + payload, + ) // consume gas first and check error gasUsed := gasForRuntime - gasBalance @@ -673,17 +642,6 @@ func (k Keeper) executeViewFunction( return viewRes, gasUsed, nil } -// execVM runs vm in separate function statement to release right after execution -// to avoid deadlock even if the function panics -// -// TODO - remove this after loader v2 is installed -func execVM[T any](ctx context.Context, k Keeper, f func(types.VMEngine) (T, error)) (T, error) { - vm := k.acquireVM(ctx) - defer k.releaseVM() - - return f(vm) -} - func (k Keeper) computeGasForRuntime(ctx context.Context, gasMeter storetypes.GasMeter) uint64 { gasForRuntime := gasMeter.Limit() - gasMeter.GasConsumedToLimit() if isSimulation(ctx) { diff --git a/x/move/keeper/keeper.go b/x/move/keeper/keeper.go index a1f6914d..e0a47f5e 100644 --- a/x/move/keeper/keeper.go +++ b/x/move/keeper/keeper.go @@ -4,8 +4,6 @@ import ( "context" "errors" - "golang.org/x/sync/semaphore" - "cosmossdk.io/collections" "cosmossdk.io/core/address" corestoretypes "cosmossdk.io/core/store" @@ -49,10 +47,7 @@ type Keeper struct { config moveconfig.MoveConfig - // TODO - remove after loader v2 - moveVMs []types.VMEngine - moveVMIdx *uint64 - moveVMSemaphore *semaphore.Weighted + initiaMoveVM types.VMEngine feeCollector string authority string @@ -95,21 +90,13 @@ func NewKeeper( moveConfig.ContractSimulationGasLimit = moveconfig.DefaultContractSimulationGasLimit } - // use only one VM for now because we need to clear the cache on every module upgrade. - // but if we have multiple VMs, only the VM that executed the module upgrade will have the cache cleared. - vmCount := 1 - moveVMIdx := uint64(0) - vms := make([]types.VMEngine, vmCount) - for i := 0; i < vmCount; i++ { - moveVM, err := vm.NewVM(vmtypes.InitiaVMConfig{ - // TODO: check this before mainnet - AllowUnstable: true, - }) - if err != nil { - panic(err) - } - - vms[i] = &moveVM + moveVM, err := vm.NewVM(vmtypes.InitiaVMConfig{ + AllowUnstable: false, + ScriptCacheCapacity: moveConfig.ScriptCacheCapacity, + ModuleCacheCapacity: moveConfig.ModuleCacheCapacity, + }) + if err != nil { + panic(err) } sb := collections.NewSchemaBuilder(storeService) @@ -122,9 +109,7 @@ func NewKeeper( msgRouter: msgRouter, grpcRouter: grpcRouter, config: moveConfig, - moveVMs: vms, - moveVMIdx: &moveVMIdx, - moveVMSemaphore: semaphore.NewWeighted(int64(vmCount)), + initiaMoveVM: &moveVM, distrKeeper: distrKeeper, StakingKeeper: stakingKeeper, RewardKeeper: rewardKeeper, diff --git a/x/move/keeper/vm_msg_stargate.go b/x/move/keeper/vm_msg_stargate.go index e335b32b..9dd71ae1 100644 --- a/x/move/keeper/vm_msg_stargate.go +++ b/x/move/keeper/vm_msg_stargate.go @@ -14,7 +14,7 @@ import ( vmtypes "github.com/initia-labs/movevm/types" ) -func (k Keeper) HandleVMStargateMsg(ctx context.Context, req *vmtypes.StargateMessage) (proto.Message, error) { +func (k Keeper) HandleVMStargateMsg(ctx context.Context, req *vmtypes.CosmosMessage) (proto.Message, error) { var sdkMsg sdk.Msg err := k.cdc.UnmarshalInterfaceJSON(req.Data, &sdkMsg) if err != nil { diff --git a/x/move/keeper/vm_msg_stargate_test.go b/x/move/keeper/vm_msg_stargate_test.go index 80f3c188..f753bcba 100644 --- a/x/move/keeper/vm_msg_stargate_test.go +++ b/x/move/keeper/vm_msg_stargate_test.go @@ -31,14 +31,14 @@ func Test_HandleVMStargateMsg(t *testing.T) { }`, sdk.MsgTypeURL(&govtypes.MsgVote{}), addrs[1])) // unauthorized test - _, err = input.MoveKeeper.HandleVMStargateMsg(ctx, &vmtypes.StargateMessage{ + _, err = input.MoveKeeper.HandleVMStargateMsg(ctx, &vmtypes.CosmosMessage{ Sender: addr0, Data: jsonData, }) require.ErrorIs(t, err, sdkerrors.ErrUnauthorized) // valid test - res, err := input.MoveKeeper.HandleVMStargateMsg(ctx, &vmtypes.StargateMessage{ + res, err := input.MoveKeeper.HandleVMStargateMsg(ctx, &vmtypes.CosmosMessage{ Sender: addr1, Data: jsonData, }) diff --git a/x/move/keeper/vm_query.go b/x/move/keeper/vm_query.go index dc117054..01d8aa52 100644 --- a/x/move/keeper/vm_query.go +++ b/x/move/keeper/vm_query.go @@ -25,6 +25,8 @@ func (k Keeper) queryCustom(ctx sdk.Context, req *vmtypes.CustomQuery) ([]byte, return nil, types.ErrNotSupportedCustomQuery } + // create cache context for query + ctx, _ = ctx.CacheContext() return customQuery(ctx, req.Data) } @@ -44,6 +46,8 @@ func (k Keeper) queryStargate(ctx sdk.Context, req *vmtypes.StargateQuery) ([]by return nil, err } + // create cache context for query + ctx, _ = ctx.CacheContext() res, err := route(ctx, &abci.RequestQuery{ Data: reqData, Path: req.Path, diff --git a/x/move/keeper/vmpool.go b/x/move/keeper/vmpool.go deleted file mode 100644 index a5425486..00000000 --- a/x/move/keeper/vmpool.go +++ /dev/null @@ -1,24 +0,0 @@ -package keeper - -import ( - "context" - "sync/atomic" - - "github.com/initia-labs/initia/x/move/types" -) - -func (k Keeper) acquireVM(ctx context.Context) (vm types.VMEngine) { - err := k.moveVMSemaphore.Acquire(ctx, 1) - if err != nil { - panic(err) - } - - idx := atomic.AddUint64(k.moveVMIdx, 1) - vm = k.moveVMs[idx%uint64(len(k.moveVMs))] - - return -} - -func (k Keeper) releaseVM() { - k.moveVMSemaphore.Release(1) -} diff --git a/x/move/types/cosmos_message.go b/x/move/types/cosmos_message.go deleted file mode 100644 index 8721e697..00000000 --- a/x/move/types/cosmos_message.go +++ /dev/null @@ -1,215 +0,0 @@ -package types - -import ( - context "context" - - "cosmossdk.io/core/address" - "cosmossdk.io/math" - ibcfeetypes "github.com/cosmos/ibc-go/v8/modules/apps/29-fee/types" - transfertypes "github.com/cosmos/ibc-go/v8/modules/apps/transfer/types" - clienttypes "github.com/cosmos/ibc-go/v8/modules/core/02-client/types" - nfttransfertypes "github.com/initia-labs/initia/x/ibc/nft-transfer/types" - - sdk "github.com/cosmos/cosmos-sdk/types" - distrtypes "github.com/cosmos/cosmos-sdk/x/distribution/types" - - stakingtypes "github.com/initia-labs/initia/x/mstaking/types" - vmtypes "github.com/initia-labs/movevm/types" -) - -// ConvertToSDKMessage convert vm CosmosMessage to sdk.Msg -func ConvertToSDKMessage( - ctx context.Context, - fk FungibleAssetKeeper, - ck CollectionKeeper, - msg vmtypes.CosmosMessage, - ac address.Codec, - vc address.Codec, -) (sdk.Msg, error) { - switch msg := msg.(type) { - case *vmtypes.CosmosMessage__Move: - switch msg := msg.Value.(type) { - case *vmtypes.MoveMessage__Execute: - sender, err := ac.BytesToString(ConvertVMAddressToSDKAddress(msg.Sender)) - if err != nil { - return nil, err - } - if !msg.IsJson { - return NewMsgExecute( - sender, - msg.ModuleAddress.String(), - msg.ModuleName, - msg.FunctionName, - msg.TypeArgs, - msg.Args, - ), nil - } - - args := make([]string, len(msg.Args)) - for i, arg := range msg.Args { - args[i] = string(arg) - } - - return NewMsgExecuteJSON( - sender, - msg.ModuleAddress.String(), - msg.ModuleName, - msg.FunctionName, - msg.TypeArgs, - args, - ), nil - case *vmtypes.MoveMessage__Script: - sender, err := ac.BytesToString(ConvertVMAddressToSDKAddress(msg.Sender)) - if err != nil { - return nil, err - } - - if !msg.IsJson { - return NewMsgScript( - sender, - msg.CodeBytes, - msg.TypeArgs, - msg.Args, - ), nil - } - - args := make([]string, len(msg.Args)) - for i, arg := range msg.Args { - args[i] = string(arg) - } - - return NewMsgScriptJSON( - sender, - msg.CodeBytes, - msg.TypeArgs, - args, - ), nil - } - - case *vmtypes.CosmosMessage__Staking: - switch msg := msg.Value.(type) { - case *vmtypes.StakingMessage__Delegate: - denom, err := DenomFromMetadataAddress(ctx, fk, msg.Amount.Metadata) - if err != nil { - return nil, err - } - - delAddr, err := ac.BytesToString(ConvertVMAddressToSDKAddress(msg.DelegatorAddress)) - if err != nil { - return nil, err - } - - return stakingtypes.NewMsgDelegate( - delAddr, - msg.ValidatorAddress, - sdk.NewCoins(sdk.NewCoin(denom, math.NewIntFromUint64(msg.Amount.Amount))), - ), nil - } - case *vmtypes.CosmosMessage__Distribution: - switch msg := msg.Value.(type) { - case *vmtypes.DistributionMessage__FundCommunityPool: - denom, err := DenomFromMetadataAddress(ctx, fk, msg.Amount.Metadata) - if err != nil { - return nil, err - } - - senderAddr, err := ac.BytesToString(ConvertVMAddressToSDKAddress(msg.SenderAddress)) - if err != nil { - return nil, err - } - - fundCommunityPoolMsg := distrtypes.NewMsgFundCommunityPool( - sdk.NewCoins(sdk.NewCoin(denom, math.NewIntFromUint64(msg.Amount.Amount))), - senderAddr, - ) - - return fundCommunityPoolMsg, nil - } - case *vmtypes.CosmosMessage__Ibc: - switch msg := msg.Value.(type) { - case *vmtypes.IBCMessage__Transfer: - denom, err := DenomFromMetadataAddress(ctx, fk, msg.Token.Metadata) - if err != nil { - return nil, err - } - - senderAddr, err := ac.BytesToString(ConvertVMAddressToSDKAddress(msg.Sender)) - if err != nil { - return nil, err - } - - transferMsg := transfertypes.NewMsgTransfer( - msg.SourcePort, - msg.SourceChannel, - sdk.NewCoin(denom, math.NewIntFromUint64(msg.Token.Amount)), - senderAddr, - msg.Receiver, - clienttypes.NewHeight(msg.TimeoutHeight.RevisionNumber, msg.TimeoutHeight.RevisionHeight), - msg.TimeoutTimestamp, - msg.Memo, - ) - - return transferMsg, nil - case *vmtypes.IBCMessage__NftTransfer: - classId, err := ClassIdFromCollectionAddress(ctx, ck, msg.Collection) - if err != nil { - return nil, err - } - - senderAddr, err := ac.BytesToString(ConvertVMAddressToSDKAddress(msg.Sender)) - if err != nil { - return nil, err - } - - nftTransferMsg := nfttransfertypes.NewMsgTransfer( - msg.SourcePort, - msg.SourceChannel, - classId, - msg.TokenIds, - senderAddr, - msg.Receiver, - clienttypes.NewHeight(msg.TimeoutHeight.RevisionNumber, msg.TimeoutHeight.RevisionHeight), - msg.TimeoutTimestamp, - msg.Memo, - ) - - return nftTransferMsg, nil - case *vmtypes.IBCMessage__PayFee: - recvFeeDenom, err := DenomFromMetadataAddress(ctx, fk, msg.Fee.RecvFee.Metadata) - if err != nil { - return nil, err - } - - ackFeeDenom, err := DenomFromMetadataAddress(ctx, fk, msg.Fee.AckFee.Metadata) - if err != nil { - return nil, err - } - - timeoutFeeDenom, err := DenomFromMetadataAddress(ctx, fk, msg.Fee.TimeoutFee.Metadata) - if err != nil { - return nil, err - } - - senderAddr, err := ac.BytesToString(ConvertVMAddressToSDKAddress(msg.Signer)) - if err != nil { - return nil, err - } - - payPacketFeeMsg := ibcfeetypes.NewMsgPayPacketFee( - ibcfeetypes.NewFee( - sdk.NewCoins(sdk.NewCoin(recvFeeDenom, math.NewIntFromUint64(msg.Fee.RecvFee.Amount))), - sdk.NewCoins(sdk.NewCoin(ackFeeDenom, math.NewIntFromUint64(msg.Fee.AckFee.Amount))), - sdk.NewCoins(sdk.NewCoin(timeoutFeeDenom, math.NewIntFromUint64(msg.Fee.TimeoutFee.Amount))), - ), - msg.SourcePort, - msg.SourceChannel, - senderAddr, - []string{}, - ) - - return payPacketFeeMsg, nil - } - } - - return nil, ErrNotSupportedCosmosMessage -} diff --git a/x/move/types/keys.go b/x/move/types/keys.go index 71c0ba17..c718203a 100644 --- a/x/move/types/keys.go +++ b/x/move/types/keys.go @@ -65,9 +65,10 @@ var ( ParamsKey = []byte{0x31} // prefix for parameters for module x/move ModuleSeparator = byte(0) - ResourceSeparator = byte(1) - TableEntrySeparator = byte(2) - TableInfoSeparator = byte(3) + ChecksumSeparator = byte(1) + ResourceSeparator = byte(2) + TableEntrySeparator = byte(3) + TableInfoSeparator = byte(4) ) // GetModulePrefix returns the prefix key of an account module store