Skip to content

Commit

Permalink
add 08-wasm Keeper constructor that accepts pointer to Wasm VM instan…
Browse files Browse the repository at this point in the history
…ce (#4109)

* add constructor that accepts pointer to Wasm VM instance

* typo

* add functions that returns wasm config with default values

* review comment

* Apply suggestions from code review

Co-authored-by: Cian Hatton <cian@interchain.io>

* review comments

* rename constructor function

* address review comments

* set contract debug mode to false

---------

Co-authored-by: Cian Hatton <cian@interchain.io>
  • Loading branch information
crodriguezvega and chatton authored Aug 1, 2023
1 parent 54f29ee commit c4f8da4
Show file tree
Hide file tree
Showing 4 changed files with 101 additions and 22 deletions.
48 changes: 32 additions & 16 deletions modules/light-clients/08-wasm/keeper/keeper.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,9 @@ import (
"bytes"
"crypto/sha256"
"encoding/hex"
"math"
"strings"
"fmt"

cosmwasm "github.com/CosmWasm/wasmvm"
wasmvm "github.com/CosmWasm/wasmvm"

errorsmod "cosmossdk.io/errors"

Expand All @@ -25,23 +24,23 @@ type Keeper struct {

storeKey storetypes.StoreKey
cdc codec.BinaryCodec
wasmVM *cosmwasm.VM
wasmVM *wasmvm.VM
authority string
}

// NewKeeper creates a new NewKeeper instance
func NewKeeper(cdc codec.BinaryCodec, key storetypes.StoreKey, authority string) Keeper {
// Wasm VM
const wasmDataDir = "ibc_08-wasm_client_data"
wasmSupportedFeatures := strings.Join([]string{"storage", "iterator"}, ",")
wasmMemoryLimitMb := uint32(math.Pow(2, 12))
wasmPrintDebug := true
wasmCacheSizeMb := uint32(math.Pow(2, 8))

vm, err := cosmwasm.NewVM(wasmDataDir, wasmSupportedFeatures, wasmMemoryLimitMb, wasmPrintDebug, wasmCacheSizeMb)
if err != nil {
panic(err)
// NewKeeperWithVM creates a new Keeper instance with the provided Wasm VM.
// This constructor function is meant to be used when the chain uses x/wasm
// and the same Wasm VM instance should be shared with it.
func NewKeeperWithVM(
cdc codec.BinaryCodec,
key storetypes.StoreKey,
authority string,
vm *wasmvm.VM,
) Keeper {
if types.WasmVM != nil {
panic("global Wasm VM instance should not be already set before calling this function")
}

types.WasmVM = vm
types.WasmStoreKey = key

Expand All @@ -53,6 +52,23 @@ func NewKeeper(cdc codec.BinaryCodec, key storetypes.StoreKey, authority string)
}
}

// NewKeeperWithConfig creates a new Keeper instance with the provided Wasm configuration.
// This constructor function is meant to be used when the chain does not use x/wasm
// and a Wasm VM needs to be instantiated using the provided parameters.
func NewKeeperWithConfig(
cdc codec.BinaryCodec,
key storetypes.StoreKey,
authority string,
wasmConfig types.WasmConfig,
) Keeper {
vm, err := wasmvm.NewVM(wasmConfig.DataDir, wasmConfig.SupportedFeatures, types.ContractMemoryLimit, wasmConfig.ContractDebugMode, wasmConfig.MemoryCacheSize)
if err != nil {
panic(fmt.Sprintf("failed to instantiate new Wasm VM instance: %v", err))
}

return NewKeeperWithVM(cdc, key, authority, vm)
}

// GetAuthority returns the 08-wasm module's authority.
func (k Keeper) GetAuthority() string {
return k.authority
Expand Down
37 changes: 37 additions & 0 deletions modules/light-clients/08-wasm/types/config.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package types

const (
// contractMemoryLimit is the memory limit of each contract execution (in MiB)
// constant value so all nodes run with the same limit.
ContractMemoryLimit = 32

defaultDataDir string = "ibc_08-wasm_client_data"
defaultSupportedFeatures string = "iterator"
defaultMemoryCacheSize uint32 = 256 // in MiB
defaultContractDebugMode = false
)

type WasmConfig struct {
// DataDir is the directory for Wasm blobs and various caches
DataDir string
// SupportedFeatures is a comma separated list of capabilities supported by the chain
// See https://github.com/CosmWasm/wasmd/blob/e5049ba686ab71164a01f6e71e54347710a1f740/app/wasm.go#L3-L15
// for more information.
SupportedFeatures string
// MemoryCacheSize in MiB not bytes. It is not consensus-critical and should
// be defined on a per-node basis, often 100-1000 MB.
MemoryCacheSize uint32
// ContractDebugMode is a flag to log what contracts print. It must be false on all
// production nodes, and only enabled in test environments or debug non-validating nodes.
ContractDebugMode bool
}

// DefaultWasmConfig returns the default settings for WasmConfig
func DefaultWasmConfig() WasmConfig {
return WasmConfig{
DataDir: defaultDataDir,
SupportedFeatures: defaultSupportedFeatures,
MemoryCacheSize: defaultMemoryCacheSize,
ContractDebugMode: defaultContractDebugMode,
}
}
10 changes: 5 additions & 5 deletions modules/light-clients/08-wasm/types/vm.go
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
package types

import (
cosmwasm "github.com/CosmWasm/wasmvm"
wasmvm "github.com/CosmWasm/wasmvm"
wasmvmtypes "github.com/CosmWasm/wasmvm/types"

storetypes "github.com/cosmos/cosmos-sdk/store/types"
sdk "github.com/cosmos/cosmos-sdk/types"
)

var (
WasmVM *cosmwasm.VM
WasmVM *wasmvm.VM
// Store key for 08-wasm module, required as a global so that the KV store can be retrieved
// in the ClientState Initialize function which doesn't have access to the keeper.
// The storeKey is used to check the code hash of the contract and determine if the light client
Expand All @@ -32,7 +32,7 @@ func initContract(ctx sdk.Context, clientStore sdk.KVStore, codeHash []byte, msg
}

ctx.GasMeter().ConsumeGas(VMGasRegister.NewContractInstanceCosts(len(msg)), "Loading CosmWasm module: instantiate")
response, gasUsed, err := WasmVM.Instantiate(codeHash, env, msgInfo, msg, newStoreAdapter(clientStore), cosmwasm.GoAPI{}, nil, multipliedGasMeter, gasLimit, costJSONDeserialization)
response, gasUsed, err := WasmVM.Instantiate(codeHash, env, msgInfo, msg, newStoreAdapter(clientStore), wasmvm.GoAPI{}, nil, multipliedGasMeter, gasLimit, costJSONDeserialization)
VMGasRegister.consumeRuntimeGas(ctx, gasUsed)
return response, err
}
Expand All @@ -45,7 +45,7 @@ func callContract(ctx sdk.Context, clientStore sdk.KVStore, codeHash []byte, msg
env := getEnv(ctx)

ctx.GasMeter().ConsumeGas(VMGasRegister.InstantiateContractCosts(len(msg)), "Loading CosmWasm module: sudo")
resp, gasUsed, err := WasmVM.Sudo(codeHash, env, msg, newStoreAdapter(clientStore), cosmwasm.GoAPI{}, nil, multipliedGasMeter, gasLimit, costJSONDeserialization)
resp, gasUsed, err := WasmVM.Sudo(codeHash, env, msg, newStoreAdapter(clientStore), wasmvm.GoAPI{}, nil, multipliedGasMeter, gasLimit, costJSONDeserialization)
VMGasRegister.consumeRuntimeGas(ctx, gasUsed)
return resp, err
}
Expand All @@ -59,7 +59,7 @@ func queryContract(ctx sdk.Context, clientStore sdk.KVStore, codeHash []byte, ms
env := getEnv(ctx)

ctx.GasMeter().ConsumeGas(VMGasRegister.InstantiateContractCosts(len(msg)), "Loading CosmWasm module: query")
resp, gasUsed, err := WasmVM.Query(codeHash, env, msg, newStoreAdapter(clientStore), cosmwasm.GoAPI{}, nil, multipliedGasMeter, gasLimit, costJSONDeserialization)
resp, gasUsed, err := WasmVM.Query(codeHash, env, msg, newStoreAdapter(clientStore), wasmvm.GoAPI{}, nil, multipliedGasMeter, gasLimit, costJSONDeserialization)
VMGasRegister.consumeRuntimeGas(ctx, gasUsed)
return resp, err
}
Expand Down
28 changes: 27 additions & 1 deletion testing/simapp/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"encoding/json"
"fmt"
"io"
"math"
"os"
"path/filepath"

Expand Down Expand Up @@ -465,7 +466,32 @@ func NewSimApp(
),
)

app.WasmClientKeeper = wasmkeeper.NewKeeper(appCodec, keys[wasmtypes.StoreKey], authtypes.NewModuleAddress(govtypes.ModuleName).String())
// 08-wasm's Keeper can be instantiated in two different ways:
// 1. If the chain uses x/wasm:
// Both x/wasm's Keeper and 08-wasm Keeper should share the same Wasm VM instance.
// - Instantiate the Wasm VM in app.go with the parameters of your choice.
// - Create an Option with this Wasm VM instance (see https://github.com/CosmWasm/wasmd/blob/v0.41.0/x/wasm/keeper/options.go#L26-L32).
// - Pass the option to the x/wasm NewKeeper contructor function (https://github.com/CosmWasm/wasmd/blob/v0.41.0/x/wasm/keeper/keeper_cgo.go#L36).
// - Pass a pointer to the Wasm VM instance to 08-wasm NewKeeperWithVM constructor function.
//
// 2. If the chain does not use x/wasm:
// Even though it is still possible to use method 1 above
// (e.g. instantiating a Wasm VM in app.go an pass it in 08-wasm NewKeeper),
// since there is no need to share the Wasm VM instance with another module
// you can use NewKeeperWithConfig constructor function and provide
// the Wasm VM configuration parameters of your choice.
// Check out the WasmConfig type definition for more information on
// each parameter. Some parameters allow node-leve configurations.
// Function DefaultWasmConfig can also be used to use default values.
//
// In the code below we use the second method because we are not using x/wasm in this app.go.
wasmConfig := wasmtypes.WasmConfig{
DataDir: "ibc_08-wasm_client_data",
SupportedFeatures: "iterator",
MemoryCacheSize: uint32(math.Pow(2, 8)),
ContractDebugMode: false,
}
app.WasmClientKeeper = wasmkeeper.NewKeeperWithConfig(appCodec, keys[wasmtypes.StoreKey], authtypes.NewModuleAddress(govtypes.ModuleName).String(), wasmConfig)

// IBC Fee Module keeper
app.IBCFeeKeeper = ibcfeekeeper.NewKeeper(
Expand Down

0 comments on commit c4f8da4

Please sign in to comment.