From 031c2b83117bda32ae64c24965b520b17569d6de Mon Sep 17 00:00:00 2001 From: Damian Nolan Date: Tue, 2 Apr 2024 16:59:22 +0200 Subject: [PATCH] imp: adding 08-wasm build opts with libwasmvm linking disabled (#5923) * wip: messing with build options for wasm cgo * chore: mv type assertion to wasm_cgo with build flags * chore: mv make target to build section * chore: revert cgo enabled 0 build opt for testing * chore: rm unneeded file * update build tag * linter * update panic message * add Codec back * refactor: adapt build tags to match wasmvm * Update modules/light-clients/08-wasm/doc.go Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> * Update modules/light-clients/08-wasm/keeper/keeper_vm.go Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> * chore: make lint-fix * chore: make lint-fix --------- Co-authored-by: Charly Co-authored-by: Charly Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> Co-authored-by: Cian Hatton --- Makefile | 7 +- modules/light-clients/08-wasm/doc.go | 7 ++ .../internal/ibcwasm/expected_interfaces.go | 2 - .../08-wasm/internal/ibcwasm/wasm_vm.go | 7 ++ .../light-clients/08-wasm/keeper/keeper.go | 72 --------------- .../08-wasm/keeper/keeper_no_vm.go | 44 ++++++++++ .../light-clients/08-wasm/keeper/keeper_vm.go | 87 +++++++++++++++++++ scripts/build-wasm-simapp-docker.sh | 16 ++++ 8 files changed, 167 insertions(+), 75 deletions(-) create mode 100644 modules/light-clients/08-wasm/internal/ibcwasm/wasm_vm.go create mode 100644 modules/light-clients/08-wasm/keeper/keeper_no_vm.go create mode 100644 modules/light-clients/08-wasm/keeper/keeper_vm.go create mode 100755 scripts/build-wasm-simapp-docker.sh diff --git a/Makefile b/Makefile index ac929270114..75db4c1bae2 100644 --- a/Makefile +++ b/Makefile @@ -135,6 +135,12 @@ clean: .PHONY: distclean clean +#? build-docker-wasm: Build wasm simapp with specified tag. +build-docker-wasm: + ./scripts/build-wasm-simapp-docker.sh $(tag) + +.PHONY: build-docker-wasm + ############################################################################### ### Tools & Dependencies ### ############################################################################### @@ -385,7 +391,6 @@ proto-update-deps: .PHONY: proto-all proto-gen proto-gen-any proto-swagger-gen proto-format proto-lint proto-check-breaking proto-update-deps - #? help: Get more info on make commands help: Makefile @echo " Choose a command run in "$(PROJECT_NAME)":" diff --git a/modules/light-clients/08-wasm/doc.go b/modules/light-clients/08-wasm/doc.go index e6329104356..d7783575d03 100644 --- a/modules/light-clients/08-wasm/doc.go +++ b/modules/light-clients/08-wasm/doc.go @@ -4,5 +4,12 @@ ClientMessage and types for the proxy light client module communicating with underlying Wasm light clients. This implementation is based off the ICS 08 specification (https://github.com/cosmos/ibc/blob/main/spec/client/ics-008-wasm-client) + +By default the 08-wasm module requires cgo and libwasmvm dependencies available on the system. +However, users of this module may want to depend only on types, without incurring the dependency on cgo or libwasmvm. +In this case, it is possible to build the code with either cgo disabled or a custom build directive: nolink_libwasmvm. +This allows disabling linking of libwasmvm and not forcing users to have specific libraries available on their systems. + +Please refer to the 08-wasm module documentation for more information. */ package wasm diff --git a/modules/light-clients/08-wasm/internal/ibcwasm/expected_interfaces.go b/modules/light-clients/08-wasm/internal/ibcwasm/expected_interfaces.go index 3d2eff35537..e03c156071a 100644 --- a/modules/light-clients/08-wasm/internal/ibcwasm/expected_interfaces.go +++ b/modules/light-clients/08-wasm/internal/ibcwasm/expected_interfaces.go @@ -8,8 +8,6 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" ) -var _ WasmEngine = (*wasmvm.VM)(nil) - type WasmEngine interface { // StoreCode will compile the Wasm code, and store the resulting compiled module // as well as the original code. Both can be referenced later via Checksum. diff --git a/modules/light-clients/08-wasm/internal/ibcwasm/wasm_vm.go b/modules/light-clients/08-wasm/internal/ibcwasm/wasm_vm.go new file mode 100644 index 00000000000..32b22a3f9e4 --- /dev/null +++ b/modules/light-clients/08-wasm/internal/ibcwasm/wasm_vm.go @@ -0,0 +1,7 @@ +//go:build cgo && !nolink_libwasmvm + +package ibcwasm + +import wasmvm "github.com/CosmWasm/wasmvm/v2" + +var _ WasmEngine = (*wasmvm.VM)(nil) diff --git a/modules/light-clients/08-wasm/keeper/keeper.go b/modules/light-clients/08-wasm/keeper/keeper.go index 13ef78cd089..9f323cf3a8f 100644 --- a/modules/light-clients/08-wasm/keeper/keeper.go +++ b/modules/light-clients/08-wasm/keeper/keeper.go @@ -3,9 +3,6 @@ package keeper import ( "bytes" "encoding/hex" - "errors" - "fmt" - "strings" wasmvm "github.com/CosmWasm/wasmvm/v2" @@ -34,75 +31,6 @@ type Keeper struct { authority string } -// 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, - storeService store.KVStoreService, - clientKeeper types.ClientKeeper, - authority string, - vm ibcwasm.WasmEngine, - queryRouter ibcwasm.QueryRouter, - opts ...Option, -) Keeper { - if clientKeeper == nil { - panic(errors.New("client keeper must not be nil")) - } - - if vm == nil { - panic(errors.New("wasm VM must not be nil")) - } - - if storeService == nil { - panic(errors.New("store service must not be nil")) - } - - if strings.TrimSpace(authority) == "" { - panic(errors.New("authority must be non-empty")) - } - - keeper := &Keeper{ - cdc: cdc, - storeService: storeService, - clientKeeper: clientKeeper, - authority: authority, - } - - // set query plugins to ensure there is a non-nil query plugin - // regardless of what options the user provides - ibcwasm.SetQueryPlugins(types.NewDefaultQueryPlugins()) - for _, opt := range opts { - opt.apply(keeper) - } - - ibcwasm.SetVM(vm) - ibcwasm.SetQueryRouter(queryRouter) - ibcwasm.SetupWasmStoreService(storeService) - - return *keeper -} - -// 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, - storeService store.KVStoreService, - clientKeeper types.ClientKeeper, - authority string, - wasmConfig types.WasmConfig, - queryRouter ibcwasm.QueryRouter, - opts ...Option, -) Keeper { - vm, err := wasmvm.NewVM(wasmConfig.DataDir, wasmConfig.SupportedCapabilities, types.ContractMemoryLimit, wasmConfig.ContractDebugMode, types.MemoryCacheSize) - if err != nil { - panic(fmt.Errorf("failed to instantiate new Wasm VM instance: %v", err)) - } - - return NewKeeperWithVM(cdc, storeService, clientKeeper, authority, vm, queryRouter, opts...) -} - // Codec returns the 08-wasm module's codec. func (k Keeper) Codec() codec.BinaryCodec { return k.cdc diff --git a/modules/light-clients/08-wasm/keeper/keeper_no_vm.go b/modules/light-clients/08-wasm/keeper/keeper_no_vm.go new file mode 100644 index 00000000000..9f50a598dda --- /dev/null +++ b/modules/light-clients/08-wasm/keeper/keeper_no_vm.go @@ -0,0 +1,44 @@ +//go:build !cgo || nolink_libwasmvm + +package keeper + +import ( + storetypes "cosmossdk.io/core/store" + + "github.com/cosmos/cosmos-sdk/codec" + + "github.com/cosmos/ibc-go/modules/light-clients/08-wasm/internal/ibcwasm" + "github.com/cosmos/ibc-go/modules/light-clients/08-wasm/types" +) + +// NewKeeperWithVM creates a new Keeper instance with the provided Wasm VM. +// This constructor function is used when binaries are compiled with cgo disabled or the +// custom build directive: nolink_libwasmvm. +// This function is intended to panic and notify users that 08-wasm keeper functionality is not available. +func NewKeeperWithVM( + _ codec.BinaryCodec, + _ storetypes.KVStoreService, + _ types.ClientKeeper, + _ string, + _ ibcwasm.WasmEngine, + _ ibcwasm.QueryRouter, + _ ...Option, +) Keeper { + panic("not implemented, please build with cgo enabled or nolink_libwasmvm disabled") +} + +// NewKeeperWithConfig creates a new Keeper instance with the provided Wasm configuration. +// This constructor function is used when binaries are compiled with cgo disabled or the +// custom build directive: nolink_libwasmvm. +// This function is intended to panic and notify users that 08-wasm keeper functionality is not available. +func NewKeeperWithConfig( + _ codec.BinaryCodec, + _ storetypes.KVStoreService, + _ types.ClientKeeper, + _ string, + _ types.WasmConfig, + _ ibcwasm.QueryRouter, + _ ...Option, +) Keeper { + panic("not implemented, please build with cgo enabled or nolink_libwasmvm disabled") +} diff --git a/modules/light-clients/08-wasm/keeper/keeper_vm.go b/modules/light-clients/08-wasm/keeper/keeper_vm.go new file mode 100644 index 00000000000..6173ceb06b8 --- /dev/null +++ b/modules/light-clients/08-wasm/keeper/keeper_vm.go @@ -0,0 +1,87 @@ +//go:build cgo && !nolink_libwasmvm + +package keeper + +import ( + "errors" + "fmt" + "strings" + + wasmvm "github.com/CosmWasm/wasmvm/v2" + + "cosmossdk.io/core/store" + + "github.com/cosmos/cosmos-sdk/codec" + + "github.com/cosmos/ibc-go/modules/light-clients/08-wasm/internal/ibcwasm" + "github.com/cosmos/ibc-go/modules/light-clients/08-wasm/types" +) + +// 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, + storeService store.KVStoreService, + clientKeeper types.ClientKeeper, + authority string, + vm ibcwasm.WasmEngine, + queryRouter ibcwasm.QueryRouter, + opts ...Option, +) Keeper { + if clientKeeper == nil { + panic(errors.New("client keeper must not be nil")) + } + + if vm == nil { + panic(errors.New("wasm VM must not be nil")) + } + + if storeService == nil { + panic(errors.New("store service must not be nil")) + } + + if strings.TrimSpace(authority) == "" { + panic(errors.New("authority must be non-empty")) + } + + keeper := &Keeper{ + cdc: cdc, + storeService: storeService, + clientKeeper: clientKeeper, + authority: authority, + } + + // set query plugins to ensure there is a non-nil query plugin + // regardless of what options the user provides + ibcwasm.SetQueryPlugins(types.NewDefaultQueryPlugins()) + for _, opt := range opts { + opt.apply(keeper) + } + + ibcwasm.SetVM(vm) + ibcwasm.SetQueryRouter(queryRouter) + ibcwasm.SetupWasmStoreService(storeService) + + return *keeper +} + +// 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, + storeService store.KVStoreService, + clientKeeper types.ClientKeeper, + authority string, + wasmConfig types.WasmConfig, + queryRouter ibcwasm.QueryRouter, + opts ...Option, +) Keeper { + vm, err := wasmvm.NewVM(wasmConfig.DataDir, wasmConfig.SupportedCapabilities, types.ContractMemoryLimit, wasmConfig.ContractDebugMode, types.MemoryCacheSize) + if err != nil { + panic(fmt.Errorf("failed to instantiate new Wasm VM instance: %v", err)) + } + + return NewKeeperWithVM(cdc, storeService, clientKeeper, authority, vm, queryRouter, opts...) +} diff --git a/scripts/build-wasm-simapp-docker.sh b/scripts/build-wasm-simapp-docker.sh new file mode 100755 index 00000000000..739097ae038 --- /dev/null +++ b/scripts/build-wasm-simapp-docker.sh @@ -0,0 +1,16 @@ +#!/bin/bash + +set -eou pipefail + +# build_wasm_image extracts the correct libwasm version and checksum +# based on the go.mod and builds a docker image with the provided tag. +function build_wasm_image(){ + local version="$(scripts/get-libwasm-version.py --get-version)" + local checksum="$(scripts/get-libwasm-version.py --get-checksum)" + docker build . -t "${1}" -f modules/light-clients/08-wasm/Dockerfile --build-arg LIBWASM_VERSION=${version} --build-arg LIBWASM_CHECKSUM=${checksum} +} + +# default to latest if no tag is specified. +TAG="${1:-ibc-go-wasm-simd:latest}" + +build_wasm_image "${TAG}" \ No newline at end of file