diff --git a/Dockerfile b/Dockerfile index de65643960..b8e39c14f4 100644 --- a/Dockerfile +++ b/Dockerfile @@ -23,9 +23,6 @@ WORKDIR /go/src/github.com/ChainSafe/gossamer COPY go.mod go.sum ./ RUN go mod download -# Prepare libwasmer.so for COPY -RUN cp /go/pkg/mod/github.com/wasmerio/go-ext-wasm@*/wasmer/libwasmer.so libwasmer.so - # Copy gossamer sources COPY . . diff --git a/README.md b/README.md index b80ba1191d..a1c7f01120 100644 --- a/README.md +++ b/README.md @@ -81,22 +81,15 @@ make install To install Gossamer -#### Troubleshooting for Apple Silicon users - -Apple Silicon users may encounter these errors: - -```sh -undefined: cWasmerImportObjectT -undefined: cWasmerImportFuncT -undefined: cWasmerValueTag -``` - -If so, set the following -[Golang environment variables](https://pkg.go.dev/cmd/go#hdr-Environment_variables): - -```sh -GOARCH="amd64" -``` +**Note**: Apple Silicon users running aarch64 might run into issues +with our wasm interpreter since wasmer is still working on supporting this architecture. +See their [README](https://github.com/wasmerio/wasmer-go) for me info on supported platforms. +Currently, there are no known issues regarding this within the Gossamer repo, but if you run into one please open an issue +on our GitHub. + +If you are an Apple Silicon user make sure the `GOARCH` env variable is +set to `arm64` by executing `go env`, if the variable contains another value you can change +by executing `go env -w GOARCH=arm64` ## Use Gossamer diff --git a/dot/core/interfaces.go b/dot/core/interfaces.go index 33dc42013c..352f07fc29 100644 --- a/dot/core/interfaces.go +++ b/dot/core/interfaces.go @@ -24,7 +24,6 @@ import ( // RuntimeInstance for runtime methods type RuntimeInstance interface { - UpdateRuntimeCode([]byte) error Stop() NodeStorage() runtime.NodeStorage NetworkService() runtime.BasicNetwork diff --git a/dot/core/mocks_test.go b/dot/core/mocks_test.go index 897530802a..00803f8278 100644 --- a/dot/core/mocks_test.go +++ b/dot/core/mocks_test.go @@ -870,20 +870,6 @@ func (mr *MockRuntimeInstanceMockRecorder) Stop() *gomock.Call { return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Stop", reflect.TypeOf((*MockRuntimeInstance)(nil).Stop)) } -// UpdateRuntimeCode mocks base method. -func (m *MockRuntimeInstance) UpdateRuntimeCode(arg0 []byte) error { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "UpdateRuntimeCode", arg0) - ret0, _ := ret[0].(error) - return ret0 -} - -// UpdateRuntimeCode indicates an expected call of UpdateRuntimeCode. -func (mr *MockRuntimeInstanceMockRecorder) UpdateRuntimeCode(arg0 interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "UpdateRuntimeCode", reflect.TypeOf((*MockRuntimeInstance)(nil).UpdateRuntimeCode), arg0) -} - // ValidateTransaction mocks base method. func (m *MockRuntimeInstance) ValidateTransaction(arg0 types.Extrinsic) (*transaction.Validity, error) { m.ctrl.T.Helper() diff --git a/dot/core/service.go b/dot/core/service.go index 660ee482b0..d7bf738ea8 100644 --- a/dot/core/service.go +++ b/dot/core/service.go @@ -279,6 +279,8 @@ func (s *Service) handleCodeSubstitution(hash common.Hash, return fmt.Errorf("creating new runtime instance: %w", err) } + logger.Info("instantiated runtime!!!") + err = s.codeSubstitutedState.StoreCodeSubstitutedBlockHash(hash) if err != nil { return fmt.Errorf("storing code substituted block hash: %w", err) diff --git a/dot/core/service_test.go b/dot/core/service_test.go index 48a735ccdf..b15e398483 100644 --- a/dot/core/service_test.go +++ b/dot/core/service_test.go @@ -252,7 +252,7 @@ func Test_Service_handleCodeSubstitution(t *testing.T) { }, blockHash: common.Hash{0x01}, errWrapped: wasmer.ErrWASMDecompress, - errMessage: "creating new runtime instance: setting up VM: " + + errMessage: "creating new runtime instance: " + "wasm decompression failed: unexpected EOF", }, "store_code_substitution_block_hash_error": { diff --git a/dot/interfaces.go b/dot/interfaces.go index a9255d0d3c..5df70127cd 100644 --- a/dot/interfaces.go +++ b/dot/interfaces.go @@ -43,7 +43,6 @@ type Telemetry interface { // Note: only used internally in `loadRuntime` and // `createRuntime`. type runtimeInterface interface { - UpdateRuntimeCode([]byte) error Stop() NodeStorage() runtime.NodeStorage NetworkService() runtime.BasicNetwork diff --git a/dot/rpc/modules/interfaces_test.go b/dot/rpc/modules/interfaces_test.go index b731759d54..4088b9ec75 100644 --- a/dot/rpc/modules/interfaces_test.go +++ b/dot/rpc/modules/interfaces_test.go @@ -13,7 +13,6 @@ import ( ) type Runtime interface { - UpdateRuntimeCode([]byte) error Stop() NodeStorage() runtime.NodeStorage NetworkService() runtime.BasicNetwork diff --git a/dot/services.go b/dot/services.go index 039d10ca63..987cec50c7 100644 --- a/dot/services.go +++ b/dot/services.go @@ -155,6 +155,7 @@ func createRuntime(cfg *Config, ns runtime.NodeStorage, st *state.Service, if err != nil { return nil, fmt.Errorf("failed to create runtime executor: %s", err) } + logger.Info("instantiated runtime!!!") default: return nil, fmt.Errorf("%w: %s", ErrWasmInterpreterName, cfg.Core.WasmInterpreter) } diff --git a/dot/state/block.go b/dot/state/block.go index 08760bb92b..47c339a6c6 100644 --- a/dot/state/block.go +++ b/dot/state/block.go @@ -885,6 +885,8 @@ func (bs *BlockState) HandleRuntimeChanges(newState *rtstorage.TrieState, return err } + logger.Info("instantiated runtime!!!") + bs.StoreRuntime(bHash, instance) err = bs.baseState.StoreCodeSubstitutedBlockHash(common.Hash{}) diff --git a/dot/state/initialize.go b/dot/state/initialize.go index 253030965f..3cdb932bb8 100644 --- a/dot/state/initialize.go +++ b/dot/state/initialize.go @@ -163,5 +163,7 @@ func (s *Service) CreateGenesisRuntime(t *trie.Trie, gen *genesis.Genesis) (Runt return nil, fmt.Errorf("failed to create genesis runtime: %w", err) } + logger.Info("instantiated runtime!!!") + return r, nil } diff --git a/dot/state/interfaces.go b/dot/state/interfaces.go index f12e2e24d3..a35096d0b4 100644 --- a/dot/state/interfaces.go +++ b/dot/state/interfaces.go @@ -68,7 +68,6 @@ type NewBatcher interface { // Runtime interface. type Runtime interface { - UpdateRuntimeCode([]byte) error Stop() NodeStorage() runtime.NodeStorage NetworkService() runtime.BasicNetwork diff --git a/dot/sync/mock_runtime_test.go b/dot/sync/mock_runtime_test.go index d6c6474c49..a34c43a09f 100644 --- a/dot/sync/mock_runtime_test.go +++ b/dot/sync/mock_runtime_test.go @@ -389,20 +389,6 @@ func (mr *MockInstanceMockRecorder) Stop() *gomock.Call { return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Stop", reflect.TypeOf((*MockInstance)(nil).Stop)) } -// UpdateRuntimeCode mocks base method. -func (m *MockInstance) UpdateRuntimeCode(arg0 []byte) error { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "UpdateRuntimeCode", arg0) - ret0, _ := ret[0].(error) - return ret0 -} - -// UpdateRuntimeCode indicates an expected call of UpdateRuntimeCode. -func (mr *MockInstanceMockRecorder) UpdateRuntimeCode(arg0 interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "UpdateRuntimeCode", reflect.TypeOf((*MockInstance)(nil).UpdateRuntimeCode), arg0) -} - // ValidateTransaction mocks base method. func (m *MockInstance) ValidateTransaction(arg0 types.Extrinsic) (*transaction.Validity, error) { m.ctrl.T.Helper() diff --git a/go.mod b/go.mod index 9d7ec3bbd4..a12242c882 100644 --- a/go.mod +++ b/go.mod @@ -37,7 +37,6 @@ require ( github.com/qdm12/gotree v0.2.0 github.com/stretchr/testify v1.8.2 github.com/urfave/cli/v2 v2.25.1 - github.com/wasmerio/go-ext-wasm v0.3.2-0.20200326095750-0a32be6068ec github.com/wasmerio/wasmer-go v1.0.4 github.com/whyrusleeping/mdns v0.0.0-20190826153040-b9b60ed33aa9 golang.org/x/crypto v0.8.0 diff --git a/go.sum b/go.sum index 1ca5195c92..fd0f96bc69 100644 --- a/go.sum +++ b/go.sum @@ -611,7 +611,6 @@ github.com/ugorji/go/codec v1.1.7 h1:2SvQaVZ1ouYrrKKwoSk2pzd4A9evlKJb9oTL+OaLUSs github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY= github.com/urfave/cli v1.22.2/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= github.com/urfave/cli v1.22.10/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= -github.com/urfave/cli/v2 v2.1.1/go.mod h1:SE9GqnLQmjVa0iPEY0f1w3ygNIYcIJ0OKPMoW2caLfQ= github.com/urfave/cli/v2 v2.25.1 h1:zw8dSP7ghX0Gmm8vugrs6q9Ku0wzweqPyshy+syu9Gw= github.com/urfave/cli/v2 v2.25.1/go.mod h1:GHupkWPMM0M/sj1a2b4wUrWBPzazNrIjouW6fmdJLxc= github.com/vedhavyas/go-subkey v1.0.3 h1:iKR33BB/akKmcR2PMlXPBeeODjWLM90EL98OrOGs8CA= @@ -620,8 +619,6 @@ github.com/viant/assertly v0.4.8/go.mod h1:aGifi++jvCrUaklKEKT0BU95igDNaqkvz+49u github.com/viant/toolbox v0.24.0/go.mod h1:OxMCG57V0PXuIP2HNQrtJf2CjqdmbrOx5EkMILuUhzM= github.com/warpfork/go-wish v0.0.0-20220906213052-39a1cc7a02d0 h1:GDDkbFiaK8jsSDJfjId/PEGEShv6ugrt4kYsC5UIDaQ= github.com/warpfork/go-wish v0.0.0-20220906213052-39a1cc7a02d0/go.mod h1:x6AKhvSSexNrVSrViXSHUEbICjmGXhtgABaHIySUSGw= -github.com/wasmerio/go-ext-wasm v0.3.2-0.20200326095750-0a32be6068ec h1:VElCeVyfCWNmCv6UisKQrr+P2/JRG0uf4/FIdCB4pL0= -github.com/wasmerio/go-ext-wasm v0.3.2-0.20200326095750-0a32be6068ec/go.mod h1:VGyarTzasuS7k5KhSIGpM3tciSZlkP31Mp9VJTHMMeI= github.com/wasmerio/wasmer-go v1.0.4 h1:MnqHoOGfiQ8MMq2RF6wyCeebKOe84G88h5yv+vmxJgs= github.com/wasmerio/wasmer-go v1.0.4/go.mod h1:0gzVdSfg6pysA6QVp6iVRPTagC6Wq9pOE8J86WKb2Fk= github.com/whyrusleeping/go-keyspace v0.0.0-20160322163242-5b898ac5add1 h1:EKhdznlJHPMoKr0XTrX+IlJs1LH3lyx2nfr1dOlZ79k= diff --git a/lib/babe/mocks/runtime.go b/lib/babe/mocks/runtime.go index 6c18d6b903..3e178640c2 100644 --- a/lib/babe/mocks/runtime.go +++ b/lib/babe/mocks/runtime.go @@ -389,20 +389,6 @@ func (mr *MockRuntimeInstanceMockRecorder) Stop() *gomock.Call { return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Stop", reflect.TypeOf((*MockRuntimeInstance)(nil).Stop)) } -// UpdateRuntimeCode mocks base method. -func (m *MockRuntimeInstance) UpdateRuntimeCode(arg0 []byte) error { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "UpdateRuntimeCode", arg0) - ret0, _ := ret[0].(error) - return ret0 -} - -// UpdateRuntimeCode indicates an expected call of UpdateRuntimeCode. -func (mr *MockRuntimeInstanceMockRecorder) UpdateRuntimeCode(arg0 interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "UpdateRuntimeCode", reflect.TypeOf((*MockRuntimeInstance)(nil).UpdateRuntimeCode), arg0) -} - // ValidateTransaction mocks base method. func (m *MockRuntimeInstance) ValidateTransaction(arg0 types.Extrinsic) (*transaction.Validity, error) { m.ctrl.T.Helper() diff --git a/lib/blocktree/interfaces.go b/lib/blocktree/interfaces.go index 3a4480e170..6f545be8b6 100644 --- a/lib/blocktree/interfaces.go +++ b/lib/blocktree/interfaces.go @@ -14,7 +14,6 @@ import ( // Runtime interface. type Runtime interface { - UpdateRuntimeCode([]byte) error Stop() NodeStorage() runtime.NodeStorage NetworkService() runtime.BasicNetwork diff --git a/lib/blocktree/mocks_test.go b/lib/blocktree/mocks_test.go index fe5943fd46..6f2e839db8 100644 --- a/lib/blocktree/mocks_test.go +++ b/lib/blocktree/mocks_test.go @@ -389,20 +389,6 @@ func (mr *MockRuntimeMockRecorder) Stop() *gomock.Call { return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Stop", reflect.TypeOf((*MockRuntime)(nil).Stop)) } -// UpdateRuntimeCode mocks base method. -func (m *MockRuntime) UpdateRuntimeCode(arg0 []byte) error { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "UpdateRuntimeCode", arg0) - ret0, _ := ret[0].(error) - return ret0 -} - -// UpdateRuntimeCode indicates an expected call of UpdateRuntimeCode. -func (mr *MockRuntimeMockRecorder) UpdateRuntimeCode(arg0 interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "UpdateRuntimeCode", reflect.TypeOf((*MockRuntime)(nil).UpdateRuntimeCode), arg0) -} - // ValidateTransaction mocks base method. func (m *MockRuntime) ValidateTransaction(arg0 types.Extrinsic) (*transaction.Validity, error) { m.ctrl.T.Helper() diff --git a/lib/grandpa/mocks_runtime_test.go b/lib/grandpa/mocks_runtime_test.go index 28be8acfde..1b378d8188 100644 --- a/lib/grandpa/mocks_runtime_test.go +++ b/lib/grandpa/mocks_runtime_test.go @@ -389,20 +389,6 @@ func (mr *MockInstanceMockRecorder) Stop() *gomock.Call { return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Stop", reflect.TypeOf((*MockInstance)(nil).Stop)) } -// UpdateRuntimeCode mocks base method. -func (m *MockInstance) UpdateRuntimeCode(arg0 []byte) error { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "UpdateRuntimeCode", arg0) - ret0, _ := ret[0].(error) - return ret0 -} - -// UpdateRuntimeCode indicates an expected call of UpdateRuntimeCode. -func (mr *MockInstanceMockRecorder) UpdateRuntimeCode(arg0 interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "UpdateRuntimeCode", reflect.TypeOf((*MockInstance)(nil).UpdateRuntimeCode), arg0) -} - // ValidateTransaction mocks base method. func (m *MockInstance) ValidateTransaction(arg0 types.Extrinsic) (*transaction.Validity, error) { m.ctrl.T.Helper() diff --git a/lib/runtime/interfaces.go b/lib/runtime/interfaces.go index a69f444689..996b59946f 100644 --- a/lib/runtime/interfaces.go +++ b/lib/runtime/interfaces.go @@ -32,6 +32,7 @@ type Storage interface { BeginStorageTransaction() CommitStorageTransaction() RollbackStorageTransaction() + LoadCode() []byte } // BasicNetwork interface for functions used by runtime network state function diff --git a/lib/runtime/mocks/instance.go b/lib/runtime/mocks/instance.go deleted file mode 100644 index d4d0d5e628..0000000000 --- a/lib/runtime/mocks/instance.go +++ /dev/null @@ -1,476 +0,0 @@ -// Code generated by mockery v2.14.1. DO NOT EDIT. - -package mocks - -import ( - common "github.com/ChainSafe/gossamer/lib/common" - ed25519 "github.com/ChainSafe/gossamer/lib/crypto/ed25519" - - keystore "github.com/ChainSafe/gossamer/lib/keystore" - - mock "github.com/stretchr/testify/mock" - - runtime "github.com/ChainSafe/gossamer/lib/runtime" - - transaction "github.com/ChainSafe/gossamer/lib/transaction" - - types "github.com/ChainSafe/gossamer/dot/types" -) - -// Instance is an autogenerated mock type for the Instance type -type Instance struct { - mock.Mock -} - -// ApplyExtrinsic provides a mock function with given fields: data -func (_m *Instance) ApplyExtrinsic(data types.Extrinsic) ([]byte, error) { - ret := _m.Called(data) - - var r0 []byte - if rf, ok := ret.Get(0).(func(types.Extrinsic) []byte); ok { - r0 = rf(data) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).([]byte) - } - } - - var r1 error - if rf, ok := ret.Get(1).(func(types.Extrinsic) error); ok { - r1 = rf(data) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// BabeConfiguration provides a mock function with given fields: -func (_m *Instance) BabeConfiguration() (*types.BabeConfiguration, error) { - ret := _m.Called() - - var r0 *types.BabeConfiguration - if rf, ok := ret.Get(0).(func() *types.BabeConfiguration); ok { - r0 = rf() - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*types.BabeConfiguration) - } - } - - var r1 error - if rf, ok := ret.Get(1).(func() error); ok { - r1 = rf() - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// CheckInherents provides a mock function with given fields: -func (_m *Instance) CheckInherents() { - _m.Called() -} - -// DecodeSessionKeys provides a mock function with given fields: enc -func (_m *Instance) DecodeSessionKeys(enc []byte) ([]byte, error) { - ret := _m.Called(enc) - - var r0 []byte - if rf, ok := ret.Get(0).(func([]byte) []byte); ok { - r0 = rf(enc) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).([]byte) - } - } - - var r1 error - if rf, ok := ret.Get(1).(func([]byte) error); ok { - r1 = rf(enc) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// Exec provides a mock function with given fields: function, data -func (_m *Instance) Exec(function string, data []byte) ([]byte, error) { - ret := _m.Called(function, data) - - var r0 []byte - if rf, ok := ret.Get(0).(func(string, []byte) []byte); ok { - r0 = rf(function, data) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).([]byte) - } - } - - var r1 error - if rf, ok := ret.Get(1).(func(string, []byte) error); ok { - r1 = rf(function, data) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// ExecuteBlock provides a mock function with given fields: block -func (_m *Instance) ExecuteBlock(block *types.Block) ([]byte, error) { - ret := _m.Called(block) - - var r0 []byte - if rf, ok := ret.Get(0).(func(*types.Block) []byte); ok { - r0 = rf(block) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).([]byte) - } - } - - var r1 error - if rf, ok := ret.Get(1).(func(*types.Block) error); ok { - r1 = rf(block) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// FinalizeBlock provides a mock function with given fields: -func (_m *Instance) FinalizeBlock() (*types.Header, error) { - ret := _m.Called() - - var r0 *types.Header - if rf, ok := ret.Get(0).(func() *types.Header); ok { - r0 = rf() - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*types.Header) - } - } - - var r1 error - if rf, ok := ret.Get(1).(func() error); ok { - r1 = rf() - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// GenerateSessionKeys provides a mock function with given fields: -func (_m *Instance) GenerateSessionKeys() { - _m.Called() -} - -// GetCodeHash provides a mock function with given fields: -func (_m *Instance) GetCodeHash() common.Hash { - ret := _m.Called() - - var r0 common.Hash - if rf, ok := ret.Get(0).(func() common.Hash); ok { - r0 = rf() - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(common.Hash) - } - } - - return r0 -} - -// GrandpaAuthorities provides a mock function with given fields: -func (_m *Instance) GrandpaAuthorities() ([]types.Authority, error) { - ret := _m.Called() - - var r0 []types.Authority - if rf, ok := ret.Get(0).(func() []types.Authority); ok { - r0 = rf() - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).([]types.Authority) - } - } - - var r1 error - if rf, ok := ret.Get(1).(func() error); ok { - r1 = rf() - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// GrandpaGenerateKeyOwnershipProof provides a mock function with given fields: authSetID, authorityID -func (_m *Instance) GrandpaGenerateKeyOwnershipProof(authSetID uint64, authorityID ed25519.PublicKeyBytes) (types.GrandpaOpaqueKeyOwnershipProof, error) { - ret := _m.Called(authSetID, authorityID) - - var r0 types.GrandpaOpaqueKeyOwnershipProof - if rf, ok := ret.Get(0).(func(uint64, ed25519.PublicKeyBytes) types.GrandpaOpaqueKeyOwnershipProof); ok { - r0 = rf(authSetID, authorityID) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(types.GrandpaOpaqueKeyOwnershipProof) - } - } - - var r1 error - if rf, ok := ret.Get(1).(func(uint64, ed25519.PublicKeyBytes) error); ok { - r1 = rf(authSetID, authorityID) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// GrandpaSubmitReportEquivocationUnsignedExtrinsic provides a mock function with given fields: equivocationProof, keyOwnershipProof -func (_m *Instance) GrandpaSubmitReportEquivocationUnsignedExtrinsic(equivocationProof types.GrandpaEquivocationProof, keyOwnershipProof types.GrandpaOpaqueKeyOwnershipProof) error { - ret := _m.Called(equivocationProof, keyOwnershipProof) - - var r0 error - if rf, ok := ret.Get(0).(func(types.GrandpaEquivocationProof, types.GrandpaOpaqueKeyOwnershipProof) error); ok { - r0 = rf(equivocationProof, keyOwnershipProof) - } else { - r0 = ret.Error(0) - } - - return r0 -} - -// InherentExtrinsics provides a mock function with given fields: data -func (_m *Instance) InherentExtrinsics(data []byte) ([]byte, error) { - ret := _m.Called(data) - - var r0 []byte - if rf, ok := ret.Get(0).(func([]byte) []byte); ok { - r0 = rf(data) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).([]byte) - } - } - - var r1 error - if rf, ok := ret.Get(1).(func([]byte) error); ok { - r1 = rf(data) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// InitializeBlock provides a mock function with given fields: header -func (_m *Instance) InitializeBlock(header *types.Header) error { - ret := _m.Called(header) - - var r0 error - if rf, ok := ret.Get(0).(func(*types.Header) error); ok { - r0 = rf(header) - } else { - r0 = ret.Error(0) - } - - return r0 -} - -// Keystore provides a mock function with given fields: -func (_m *Instance) Keystore() *keystore.GlobalKeystore { - ret := _m.Called() - - var r0 *keystore.GlobalKeystore - if rf, ok := ret.Get(0).(func() *keystore.GlobalKeystore); ok { - r0 = rf() - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*keystore.GlobalKeystore) - } - } - - return r0 -} - -// Metadata provides a mock function with given fields: -func (_m *Instance) Metadata() ([]byte, error) { - ret := _m.Called() - - var r0 []byte - if rf, ok := ret.Get(0).(func() []byte); ok { - r0 = rf() - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).([]byte) - } - } - - var r1 error - if rf, ok := ret.Get(1).(func() error); ok { - r1 = rf() - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// NetworkService provides a mock function with given fields: -func (_m *Instance) NetworkService() runtime.BasicNetwork { - ret := _m.Called() - - var r0 runtime.BasicNetwork - if rf, ok := ret.Get(0).(func() runtime.BasicNetwork); ok { - r0 = rf() - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(runtime.BasicNetwork) - } - } - - return r0 -} - -// NodeStorage provides a mock function with given fields: -func (_m *Instance) NodeStorage() runtime.NodeStorage { - ret := _m.Called() - - var r0 runtime.NodeStorage - if rf, ok := ret.Get(0).(func() runtime.NodeStorage); ok { - r0 = rf() - } else { - r0 = ret.Get(0).(runtime.NodeStorage) - } - - return r0 -} - -// OffchainWorker provides a mock function with given fields: -func (_m *Instance) OffchainWorker() { - _m.Called() -} - -// PaymentQueryInfo provides a mock function with given fields: ext -func (_m *Instance) PaymentQueryInfo(ext []byte) (*types.RuntimeDispatchInfo, error) { - ret := _m.Called(ext) - - var r0 *types.RuntimeDispatchInfo - if rf, ok := ret.Get(0).(func([]byte) *types.RuntimeDispatchInfo); ok { - r0 = rf(ext) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*types.RuntimeDispatchInfo) - } - } - - var r1 error - if rf, ok := ret.Get(1).(func([]byte) error); ok { - r1 = rf(ext) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// RandomSeed provides a mock function with given fields: -func (_m *Instance) RandomSeed() { - _m.Called() -} - -// SetContextStorage provides a mock function with given fields: s -func (_m *Instance) SetContextStorage(s runtime.Storage) { - _m.Called(s) -} - -// Stop provides a mock function with given fields: -func (_m *Instance) Stop() { - _m.Called() -} - -// UpdateRuntimeCode provides a mock function with given fields: _a0 -func (_m *Instance) UpdateRuntimeCode(_a0 []byte) error { - ret := _m.Called(_a0) - - var r0 error - if rf, ok := ret.Get(0).(func([]byte) error); ok { - r0 = rf(_a0) - } else { - r0 = ret.Error(0) - } - - return r0 -} - -// ValidateTransaction provides a mock function with given fields: e -func (_m *Instance) ValidateTransaction(e types.Extrinsic) (*transaction.Validity, error) { - ret := _m.Called(e) - - var r0 *transaction.Validity - if rf, ok := ret.Get(0).(func(types.Extrinsic) *transaction.Validity); ok { - r0 = rf(e) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*transaction.Validity) - } - } - - var r1 error - if rf, ok := ret.Get(1).(func(types.Extrinsic) error); ok { - r1 = rf(e) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// Validator provides a mock function with given fields: -func (_m *Instance) Validator() bool { - ret := _m.Called() - - var r0 bool - if rf, ok := ret.Get(0).(func() bool); ok { - r0 = rf() - } else { - r0 = ret.Get(0).(bool) - } - - return r0 -} - -// Version provides a mock function with given fields: -func (_m *Instance) Version() runtime.Version { - ret := _m.Called() - - var r0 runtime.Version - if rf, ok := ret.Get(0).(func() runtime.Version); ok { - r0 = rf() - } else { - r0 = ret.Get(0).(runtime.Version) - } - - return r0 -} - -type mockConstructorTestingTNewInstance interface { - mock.TestingT - Cleanup(func()) -} - -// NewInstance creates a new instance of Instance. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. -func NewInstance(t mockConstructorTestingTNewInstance) *Instance { - mock := &Instance{} - mock.Mock.Test(t) - - t.Cleanup(func() { mock.AssertExpectations(t) }) - - return mock -} diff --git a/lib/runtime/mocks/mocks.go b/lib/runtime/mocks/mocks.go index c5f2629105..191a34c5d5 100644 --- a/lib/runtime/mocks/mocks.go +++ b/lib/runtime/mocks/mocks.go @@ -389,20 +389,6 @@ func (mr *MockInstanceMockRecorder) Stop() *gomock.Call { return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Stop", reflect.TypeOf((*MockInstance)(nil).Stop)) } -// UpdateRuntimeCode mocks base method. -func (m *MockInstance) UpdateRuntimeCode(arg0 []byte) error { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "UpdateRuntimeCode", arg0) - ret0, _ := ret[0].(error) - return ret0 -} - -// UpdateRuntimeCode indicates an expected call of UpdateRuntimeCode. -func (mr *MockInstanceMockRecorder) UpdateRuntimeCode(arg0 interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "UpdateRuntimeCode", reflect.TypeOf((*MockInstance)(nil).UpdateRuntimeCode), arg0) -} - // ValidateTransaction mocks base method. func (m *MockInstance) ValidateTransaction(arg0 types.Extrinsic) (*transaction.Validity, error) { m.ctrl.T.Helper() diff --git a/lib/runtime/test_helpers.go b/lib/runtime/test_helpers.go index 7ece8ea0d4..acfac3218a 100644 --- a/lib/runtime/test_helpers.go +++ b/lib/runtime/test_helpers.go @@ -244,7 +244,6 @@ func NewTestExtrinsic(t *testing.T, rt MetadataVersioner, genHash, blockHash com // Instance is the interface to interact with the runtime. type Instance interface { - UpdateRuntimeCode([]byte) error Stop() NodeStorage() NodeStorage NetworkService() BasicNetwork diff --git a/lib/runtime/types.go b/lib/runtime/types.go index c3901de63d..148880c57d 100644 --- a/lib/runtime/types.go +++ b/lib/runtime/types.go @@ -57,4 +57,5 @@ type Context struct { SigVerifier *crypto.SignatureVerifier OffchainHTTPSet *offchain.HTTPSet Version Version + Memory Memory } diff --git a/lib/runtime/wasmer/config.go b/lib/runtime/wasmer/config.go index 17b7b1540b..2a5675f46f 100644 --- a/lib/runtime/wasmer/config.go +++ b/lib/runtime/wasmer/config.go @@ -12,8 +12,7 @@ import ( "github.com/ChainSafe/gossamer/lib/runtime" ) -// Config is the configuration used to create a -// Wasmer runtime instance. +// Config is the configuration used to create a Wasmer runtime instance. type Config struct { Storage Storage Keystore *keystore.GlobalKeystore diff --git a/lib/runtime/wasmer/exports_test.go b/lib/runtime/wasmer/exports_test.go index ab4bda60b8..a6da3188ac 100644 --- a/lib/runtime/wasmer/exports_test.go +++ b/lib/runtime/wasmer/exports_test.go @@ -6,7 +6,6 @@ package wasmer import ( "bytes" "encoding/json" - "fmt" "math/big" "os" "testing" @@ -23,7 +22,6 @@ import ( "github.com/ChainSafe/gossamer/lib/utils" "github.com/ChainSafe/gossamer/pkg/scale" "github.com/centrifuge/go-substrate-rpc-client/v4/signature" - "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) @@ -33,8 +31,6 @@ import ( var testKeyOwnershipProof types.OpaqueKeyOwnershipProof = types.OpaqueKeyOwnershipProof([]byte{64, 138, 252, 29, 127, 102, 189, 129, 207, 47, 157, 60, 17, 138, 194, 121, 139, 92, 176, 175, 224, 16, 185, 93, 175, 251, 224, 81, 209, 61, 0, 71}) //nolint:lll func Test_Instance_Version(t *testing.T) { - t.Parallel() - type instanceVersioner interface { Version() (version runtime.Version) } @@ -148,8 +144,6 @@ func Test_Instance_Version(t *testing.T) { for name, testCase := range testCases { testCase := testCase t.Run(name, func(t *testing.T) { - t.Parallel() - instance := testCase.instanceBuilder(t) version := instance.Version() assert.Equal(t, testCase.expectedVersion, version) @@ -232,7 +226,6 @@ func TestNodeRuntime_ValidateTransaction(t *testing.T) { func TestInstance_GrandpaAuthorities_NodeRuntime(t *testing.T) { tt := trie.NewEmptyTrie() - value, err := common.HexToBytes("0x0108eea1eabcac7d2c8a6459b7322cf997874482bfc3d2ec7a80888a3a7d714103640100000000000000b64994460e59b30364cad3c92e3df6052f9b0ebbb8f88460c194dc5794d6d7170100000000000000") //nolint:lll require.NoError(t, err) @@ -260,7 +253,6 @@ func TestInstance_GrandpaAuthorities_NodeRuntime(t *testing.T) { func TestInstance_GrandpaAuthorities_PolkadotRuntime(t *testing.T) { tt := trie.NewEmptyTrie() - value, err := common.HexToBytes("0x0108eea1eabcac7d2c8a6459b7322cf997874482bfc3d2ec7a80888a3a7d714103640100000000000000b64994460e59b30364cad3c92e3df6052f9b0ebbb8f88460c194dc5794d6d7170100000000000000") //nolint:lll require.NoError(t, err) @@ -282,13 +274,10 @@ func TestInstance_GrandpaAuthorities_PolkadotRuntime(t *testing.T) { {Key: authA, Weight: 1}, {Key: authB, Weight: 1}, } - require.Equal(t, expected, auths) } func TestInstance_BabeGenerateKeyOwnershipProof(t *testing.T) { - t.Parallel() - testCases := []struct { name string targetRuntime string @@ -305,10 +294,7 @@ func TestInstance_BabeGenerateKeyOwnershipProof(t *testing.T) { for _, testCase := range testCases { testCase := testCase t.Run(testCase.name, func(t *testing.T) { - t.Parallel() - tt := trie.NewEmptyTrie() - randomnessValue, err := common.HexToHash("0x01") require.NoError(t, err) key := common.MustHexToBytes(genesis.BABERandomnessKeyHex) @@ -337,8 +323,6 @@ func TestInstance_BabeGenerateKeyOwnershipProof(t *testing.T) { } func TestInstance_BabeSubmitReportEquivocationUnsignedExtrinsic(t *testing.T) { - t.Parallel() - testCases := []struct { name string targetRuntime string @@ -355,8 +339,6 @@ func TestInstance_BabeSubmitReportEquivocationUnsignedExtrinsic(t *testing.T) { for _, testCase := range testCases { testCase := testCase t.Run(testCase.name, func(t *testing.T) { - t.Parallel() - tt := trie.NewEmptyTrie() rt := NewTestInstanceWithTrie(t, testCase.targetRuntime, tt) authorityID := types.AuthorityID{1} @@ -428,7 +410,6 @@ func TestInstance_BabeConfiguration_WestendRuntime_WithAuthorities(t *testing.T) Randomness: [32]byte{1}, SecondarySlots: 2, } - require.Equal(t, expected, cfg) } @@ -944,15 +925,13 @@ func TestInstance_PaymentQueryInfo(t *testing.T) { }, { // incomplete extrinsic - ext: "0x4ccde39a5684e7a56da23b22d4d9fbadb023baa19c56495432884d0640000000000000000000000000000000", - errMessage: "running runtime function: " + - "Failed to call the `TransactionPaymentApi_query_info` exported function.", + ext: "0x4ccde39a5684e7a56da23b22d4d9fbadb023baa19c56495432884d0640000000000000000000000000000000", + errMessage: "running runtime function: unreachable", }, { // incomplete extrinsic - extB: nil, - errMessage: "running runtime function: " + - "Failed to call the `TransactionPaymentApi_query_info` exported function.", + extB: nil, + errMessage: "running runtime function: unreachable", }, } @@ -975,10 +954,6 @@ func TestInstance_PaymentQueryInfo(t *testing.T) { continue } require.NoError(t, err) - - fmt.Println(info.PartialFee.String()) - fmt.Println(test.expect.PartialFee.String()) - require.NoError(t, err) require.NotNil(t, info) require.Equal(t, test.expect, info) @@ -1006,7 +981,6 @@ func newTrieFromPairs(t *testing.T, filename string) *trie.Trie { } func TestInstance_TransactionPaymentCallApi_QueryCallInfo(t *testing.T) { - t.Parallel() ins := NewTestInstance(t, runtime.WESTEND_RUNTIME_v0929) tests := []struct { callHex string @@ -1031,17 +1005,15 @@ func TestInstance_TransactionPaymentCallApi_QueryCallInfo(t *testing.T) { // polkadot.js/api returns error: RPC-CORE: call(method: Text, data: Bytes, at?: BlockHash): // Bytes:: -32000: Client error: Execution failed: Execution aborted due to trap: wasm trap: wasm //`unreachable` instruction executed - callHex: "0x040001084564", - errMessage: "running runtime function: " + - "Failed to call the `TransactionPaymentCallApi_query_call_info` exported function.", + callHex: "0x040001084564", + errMessage: "running runtime function: unreachable", }, { // call without removing any bytes, polkadot.js/api v9.5.1: api.tx.system.remark("Ed test") // polkadot.js/api returns error: Error: createType(Call):: findMetaCall: Unable to find Call with index // [44, 4]/[44,4] - callHex: "0x2c0400011c45642074657374", - errMessage: "running runtime function: " + - "Failed to call the `TransactionPaymentCallApi_query_call_info` exported function.", + callHex: "0x2c0400011c45642074657374", + errMessage: "running runtime function: unreachable", }, } @@ -1066,7 +1038,6 @@ func TestInstance_TransactionPaymentCallApi_QueryCallInfo(t *testing.T) { } func TestInstance_TransactionPaymentCallApi_QueryCallFeeDetails(t *testing.T) { - t.Parallel() ins := NewTestInstance(t, runtime.WESTEND_RUNTIME_v0929) tests := []struct { callHex string @@ -1097,17 +1068,15 @@ func TestInstance_TransactionPaymentCallApi_QueryCallFeeDetails(t *testing.T) { // when calling polkadot node (v0.9.29) with polkadot.js/api the node returns error: RPC-CORE: call( // method: Text, data: Bytes, at?: BlockHash): Bytes:: -32000: Client error: Execution failed: // Execution aborted due to trap: wasm trap: wasm `unreachable` instruction executed - callHex: "0x040001084564", - errMessage: "running runtime function: " + - "Failed to call the `TransactionPaymentCallApi_query_call_fee_details` exported function.", + callHex: "0x040001084564", + errMessage: "running runtime function: unreachable", }, { // call without removing any bytes, polkadot.js/api v9.5.1: api.tx.system.remark("Ed test") // when calling polkadot (v0.9.29) with polkadot.js/api the node returns error: Error: createType( //Call):: findMetaCall: Unable to find Call with index [44, 4]/[44,4] - callHex: "0x18040001084564", - errMessage: "running runtime function: " + - "Failed to call the `TransactionPaymentCallApi_query_call_fee_details` exported function.", + callHex: "0x18040001084564", + errMessage: "running runtime function: unreachable", }, } @@ -1129,7 +1098,6 @@ func TestInstance_TransactionPaymentCallApi_QueryCallFeeDetails(t *testing.T) { } func TestInstance_GrandpaGenerateKeyOwnershipProof(t *testing.T) { - t.Parallel() instance := NewTestInstance(t, runtime.WESTEND_RUNTIME_v0929) identity := common.MustHexToBytes("0x88dc3417d5058ec4b4503e0c12ea1a0a89be200fe98922423d4334014fa6b0ee") identityPubKey, _ := ed25519.NewPublicKey(identity) @@ -1142,7 +1110,6 @@ func TestInstance_GrandpaGenerateKeyOwnershipProof(t *testing.T) { } func TestInstance_GrandpaSubmitReportEquivocationUnsignedExtrinsic(t *testing.T) { - t.Parallel() identity := common.MustHexToBytes("0x88dc3417d5058ec4b4503e0c12ea1a0a89be200fe98922423d4334014fa6b0ee") identityPubKey, _ := ed25519.NewPublicKey(identity) runtime := NewTestInstance(t, runtime.WESTEND_RUNTIME_v0929) diff --git a/lib/runtime/wasmer/genesis_test.go b/lib/runtime/wasmer/genesis_test.go index b261f4e397..b5e93df355 100644 --- a/lib/runtime/wasmer/genesis_test.go +++ b/lib/runtime/wasmer/genesis_test.go @@ -13,8 +13,6 @@ import ( ) func Test_NewTrieFromGenesis(t *testing.T) { - t.Parallel() - testCases := map[string]struct { genesis genesis.Genesis expectedKV map[string]string @@ -64,8 +62,6 @@ func Test_NewTrieFromGenesis(t *testing.T) { for name, testCase := range testCases { testCase := testCase t.Run(name, func(t *testing.T) { - t.Parallel() - tr, err := NewTrieFromGenesis(testCase.genesis) require.ErrorIs(t, err, testCase.errSentinel) diff --git a/lib/runtime/wasmer/helpers.go b/lib/runtime/wasmer/helpers.go index f8eb008415..c64c533256 100644 --- a/lib/runtime/wasmer/helpers.go +++ b/lib/runtime/wasmer/helpers.go @@ -3,19 +3,24 @@ package wasmer -// #include -import "C" //skipcq: SCC-compile - import ( "fmt" + "math" "math/big" "github.com/ChainSafe/gossamer/lib/common/types" "github.com/ChainSafe/gossamer/lib/runtime" "github.com/ChainSafe/gossamer/pkg/scale" - "github.com/wasmerio/go-ext-wasm/wasmer" + "github.com/wasmerio/wasmer-go/wasmer" ) +func safeCastInt32(value uint32) (int32, error) { + if value > math.MaxInt32 { + return 0, fmt.Errorf("%w", errMemoryValueOutOfBounds) + } + return int32(value), nil +} + // toPointerSize converts an uint32 pointer and uint32 size // to an int64 pointer size. func toPointerSize(ptr, size uint32) (pointerSize int64) { @@ -29,17 +34,17 @@ func splitPointerSize(pointerSize int64) (ptr, size uint32) { } // asMemorySlice converts a 64 bit pointer size to a Go byte slice. -func asMemorySlice(context wasmer.InstanceContext, pointerSize C.int64_t) (data []byte) { - memory := context.Memory().Data() - ptr, size := splitPointerSize(int64(pointerSize)) +func asMemorySlice(context *runtime.Context, pointerSize int64) (data []byte) { + memory := context.Memory.Data() + ptr, size := splitPointerSize(pointerSize) return memory[ptr : ptr+size] } // toWasmMemory copies a Go byte slice to wasm memory and returns the corresponding // 64 bit pointer size. -func toWasmMemory(context wasmer.InstanceContext, data []byte) ( +func toWasmMemory(context *runtime.Context, data []byte) ( pointerSize int64, err error) { - allocator := context.Data().(*runtime.Context).Allocator + allocator := context.Allocator size := uint32(len(data)) ptr, err := allocator.Allocate(size) @@ -47,7 +52,7 @@ func toWasmMemory(context wasmer.InstanceContext, data []byte) ( return 0, fmt.Errorf("allocating: %w", err) } - memory := context.Memory().Data() + memory := context.Memory.Data() if uint32(len(memory)) < ptr+size { panic(fmt.Sprintf("length of memory is less than expected, want %d have %d", ptr+size, len(memory))) @@ -60,9 +65,9 @@ func toWasmMemory(context wasmer.InstanceContext, data []byte) ( // toWasmMemorySized copies a Go byte slice to wasm memory and returns the corresponding // 32 bit pointer. Note the data must have a well known fixed length in the runtime. -func toWasmMemorySized(context wasmer.InstanceContext, data []byte) ( +func toWasmMemorySized(context *runtime.Context, data []byte) ( pointer uint32, err error) { - allocator := context.Data().(*runtime.Context).Allocator + allocator := context.Allocator size := uint32(len(data)) pointer, err = allocator.Allocate(size) @@ -70,7 +75,7 @@ func toWasmMemorySized(context wasmer.InstanceContext, data []byte) ( return 0, fmt.Errorf("allocating: %w", err) } - memory := context.Memory().Data() + memory := context.Memory.Data() copy(memory[pointer:pointer+size], data) return pointer, nil @@ -78,7 +83,7 @@ func toWasmMemorySized(context wasmer.InstanceContext, data []byte) ( // toWasmMemoryOptional scale encodes the byte slice `data`, writes it to wasm memory // and returns the corresponding 64 bit pointer size. -func toWasmMemoryOptional(context wasmer.InstanceContext, data []byte) ( +func toWasmMemoryOptional(context *runtime.Context, data []byte) ( pointerSize int64, err error) { var optionalSlice *[]byte if data != nil { @@ -92,10 +97,43 @@ func toWasmMemoryOptional(context wasmer.InstanceContext, data []byte) ( return toWasmMemory(context, encoded) } +func toWasmMemoryOptionalNil(context *runtime.Context) ( + cPointerSize []wasmer.Value, err error) { + pointerSize, err := toWasmMemoryOptional(context, nil) + if err != nil { + return []wasmer.Value{wasmer.NewI64(0)}, err + } + + return []wasmer.Value{wasmer.NewI64(pointerSize)}, nil +} + +func mustToWasmMemoryOptionalNil(context *runtime.Context) ( + cPointerSize []wasmer.Value) { + cPointerSize, err := toWasmMemoryOptionalNil(context) + if err != nil { + panic(err) + } + + return cPointerSize +} + +// toWasmMemoryFixedSizeOptional copies the `data` byte slice to a 64B array, +// scale encodes the pointer to the resulting array, writes it to wasm memory +// and returns the corresponding 64 bit pointer size. +func toWasmMemoryFixedSizeOptional(context *runtime.Context, data []byte) ( + pointerSize int64, err error) { + var optionalFixedSize [64]byte + copy(optionalFixedSize[:], data) + encodedOptionalFixedSize, err := scale.Marshal(&optionalFixedSize) + if err != nil { + return 0, fmt.Errorf("scale encoding: %w", err) + } + return toWasmMemory(context, encodedOptionalFixedSize) +} // toWasmMemoryResult wraps the data byte slice in a Result type, scale encodes it, // copies it to wasm memory and returns the corresponding 64 bit pointer size. -func toWasmMemoryResult(context wasmer.InstanceContext, data []byte) ( +func toWasmMemoryResult(context *runtime.Context, data []byte) ( pointerSize int64, err error) { var result *types.Result if len(data) == 0 { @@ -112,64 +150,45 @@ func toWasmMemoryResult(context wasmer.InstanceContext, data []byte) ( return toWasmMemory(context, encodedResult) } -// toWasmMemoryOptional scale encodes the uint32 pointer `data`, writes it to wasm memory -// and returns the corresponding 64 bit pointer size. -func toWasmMemoryOptionalUint32(context wasmer.InstanceContext, data *uint32) ( - pointerSize int64, err error) { - enc, err := scale.Marshal(data) - if err != nil { - return 0, fmt.Errorf("scale encoding: %w", err) - } - return toWasmMemory(context, enc) -} - -func mustToWasmMemoryNil(context wasmer.InstanceContext) ( - cPointerSize C.int64_t) { - allocator := context.Data().(*runtime.Context).Allocator - ptr, err := allocator.Allocate(0) - if err != nil { - // we allocate 0 byte, this should never fail - panic(err) - } - pointerSize := toPointerSize(ptr, 0) - return C.int64_t(pointerSize) -} - -func toWasmMemoryOptionalNil(context wasmer.InstanceContext) ( - cPointerSize C.int64_t, err error) { - pointerSize, err := toWasmMemoryOptional(context, nil) +func toWasmMemoryResultEmpty(context *runtime.Context) ( + cPointerSize []wasmer.Value, err error) { + pointerSize, err := toWasmMemoryResult(context, nil) if err != nil { - return 0, err + return []wasmer.Value{wasmer.NewI64(0)}, err } - - return C.int64_t(pointerSize), nil + return []wasmer.Value{wasmer.NewI64(pointerSize)}, nil } -func mustToWasmMemoryOptionalNil(context wasmer.InstanceContext) ( - cPointerSize C.int64_t) { - cPointerSize, err := toWasmMemoryOptionalNil(context) +func mustToWasmMemoryResultEmpty(context *runtime.Context) ( + cPointerSize []wasmer.Value) { + cPointerSize, err := toWasmMemoryResultEmpty(context) if err != nil { panic(err) } return cPointerSize } -func toWasmMemoryResultEmpty(context wasmer.InstanceContext) ( - cPointerSize C.int64_t, err error) { - pointerSize, err := toWasmMemoryResult(context, nil) +// toWasmMemoryOptional scale encodes the uint32 pointer `data`, writes it to wasm memory +// and returns the corresponding 64 bit pointer size. +func toWasmMemoryOptionalUint32(context *runtime.Context, data *uint32) ( + pointerSize int64, err error) { + enc, err := scale.Marshal(data) if err != nil { - return 0, err + return 0, fmt.Errorf("scale encoding: %w", err) } - return C.int64_t(pointerSize), nil + return toWasmMemory(context, enc) } -func mustToWasmMemoryResultEmpty(context wasmer.InstanceContext) ( - cPointerSize C.int64_t) { - cPointerSize, err := toWasmMemoryResultEmpty(context) +func mustToWasmMemoryNil(context *runtime.Context) ( + cPointerSize []wasmer.Value) { + allocator := context.Allocator + ptr, err := allocator.Allocate(0) if err != nil { + // we allocate 0 byte, this should never fail panic(err) } - return cPointerSize + pointerSize := toPointerSize(ptr, 0) + return []wasmer.Value{wasmer.NewI64(pointerSize)} } // toKillStorageResultEnum encodes the `allRemoved` flag and @@ -194,20 +213,6 @@ func toKillStorageResultEnum(allRemoved bool, numRemoved uint32) ( return encodedEnumValue, nil } -// toWasmMemoryFixedSizeOptional copies the `data` byte slice to a 64B array, -// scale encodes the pointer to the resulting array, writes it to wasm memory -// and returns the corresponding 64 bit pointer size. -func toWasmMemoryFixedSizeOptional(context wasmer.InstanceContext, data []byte) ( - pointerSize int64, err error) { - var optionalFixedSize [64]byte - copy(optionalFixedSize[:], data) - encodedOptionalFixedSize, err := scale.Marshal(&optionalFixedSize) - if err != nil { - return 0, fmt.Errorf("scale encoding: %w", err) - } - return toWasmMemory(context, encodedOptionalFixedSize) -} - func storageAppend(storage GetSetter, key, valueToAppend []byte) (err error) { // this function assumes the item in storage is a SCALE encoded array of items // the valueToAppend is a new item, so it appends the item and increases the length prefix by 1 diff --git a/lib/runtime/wasmer/helpers_test.go b/lib/runtime/wasmer/helpers_test.go index 191e4a7abb..6e6f5fc941 100644 --- a/lib/runtime/wasmer/helpers_test.go +++ b/lib/runtime/wasmer/helpers_test.go @@ -6,6 +6,7 @@ package wasmer import ( "encoding/json" "errors" + "math" "os" "path/filepath" "testing" @@ -30,6 +31,46 @@ func genesisFromRawJSON(t *testing.T, jsonFilepath string) (gen genesis.Genesis) return gen } +func TestMemory_safeCastInt32(t *testing.T) { + t.Parallel() + testCases := []struct { + name string + value uint32 + exp int32 + expErr error + expErrMsg string + }{ + { + name: "valid cast", + value: uint32(0), + exp: int32(0), + }, + { + name: "max uint32", + value: uint32(math.MaxInt32), + exp: math.MaxInt32, + }, + { + name: "out of bounds", + value: uint32(math.MaxInt32 + 1), + expErr: errMemoryValueOutOfBounds, + expErrMsg: errMemoryValueOutOfBounds.Error(), + }, + } + for _, test := range testCases { + test := test + t.Run(test.name, func(t *testing.T) { + t.Parallel() + res, err := safeCastInt32(test.value) + assert.ErrorIs(t, err, test.expErr) + if test.expErr != nil { + assert.EqualError(t, err, test.expErrMsg) + } + assert.Equal(t, test.exp, res) + }) + } +} + func Test_pointerSize(t *testing.T) { t.Parallel() diff --git a/lib/runtime/wasmer/imports.go b/lib/runtime/wasmer/imports.go index 3d38cdfa0b..04943208ae 100644 --- a/lib/runtime/wasmer/imports.go +++ b/lib/runtime/wasmer/imports.go @@ -3,103 +3,6 @@ package wasmer -// #include -// -// extern void ext_logging_log_version_1(void *context, int32_t level, int64_t target, int64_t msg); -// extern int32_t ext_logging_max_level_version_1(void *context); -// -// extern void ext_sandbox_instance_teardown_version_1(void *context, int32_t a); -// extern int32_t ext_sandbox_instantiate_version_1(void *context, int32_t a, int64_t b, int64_t c, int32_t d); -// extern int32_t ext_sandbox_invoke_version_1(void *context, int32_t a, int64_t b, int64_t c, int32_t d, int32_t e, int32_t f); -// extern int32_t ext_sandbox_memory_get_version_1(void *context, int32_t a, int32_t b, int32_t c, int32_t d); -// extern int32_t ext_sandbox_memory_new_version_1(void *context, int32_t a, int32_t b); -// extern int32_t ext_sandbox_memory_set_version_1(void *context, int32_t a, int32_t b, int32_t c, int32_t d); -// extern void ext_sandbox_memory_teardown_version_1(void *context, int32_t a); -// -// extern int32_t ext_crypto_ed25519_generate_version_1(void *context, int32_t a, int64_t b); -// extern int64_t ext_crypto_ed25519_public_keys_version_1(void *context, int32_t a); -// extern int64_t ext_crypto_ed25519_sign_version_1(void *context, int32_t a, int32_t b, int64_t c); -// extern int32_t ext_crypto_ed25519_verify_version_1(void *context, int32_t a, int64_t b, int32_t c); -// extern int32_t ext_crypto_finish_batch_verify_version_1(void *context); -// extern int64_t ext_crypto_secp256k1_ecdsa_recover_version_1(void *context, int32_t a, int32_t b); -// extern int64_t ext_crypto_secp256k1_ecdsa_recover_version_2(void *context, int32_t a, int32_t b); -// extern int64_t ext_crypto_secp256k1_ecdsa_recover_compressed_version_1(void *context, int32_t a, int32_t b); -// extern int64_t ext_crypto_secp256k1_ecdsa_recover_compressed_version_2(void *context, int32_t a, int32_t b); -// extern int32_t ext_crypto_ecdsa_verify_version_2(void *context, int32_t a, int64_t b, int32_t c); -// extern int32_t ext_crypto_sr25519_generate_version_1(void *context, int32_t a, int64_t b); -// extern int64_t ext_crypto_sr25519_public_keys_version_1(void *context, int32_t a); -// extern int64_t ext_crypto_sr25519_sign_version_1(void *context, int32_t a, int32_t b, int64_t c); -// extern int32_t ext_crypto_sr25519_verify_version_1(void *context, int32_t a, int64_t b, int32_t c); -// extern int32_t ext_crypto_sr25519_verify_version_2(void *context, int32_t a, int64_t b, int32_t c); -// extern void ext_crypto_start_batch_verify_version_1(void *context); -// -// extern int32_t ext_trie_blake2_256_root_version_1(void *context, int64_t a); -// extern int32_t ext_trie_blake2_256_ordered_root_version_1(void *context, int64_t a); -// extern int32_t ext_trie_blake2_256_ordered_root_version_2(void *context, int64_t a, int32_t b); -// extern int32_t ext_trie_blake2_256_verify_proof_version_1(void *context, int32_t a, int64_t b, int64_t c, int64_t d); -// -// extern int64_t ext_misc_runtime_version_version_1(void *context, int64_t a); -// extern void ext_misc_print_hex_version_1(void *context, int64_t a); -// extern void ext_misc_print_num_version_1(void *context, int64_t a); -// extern void ext_misc_print_utf8_version_1(void *context, int64_t a); -// -// extern void ext_default_child_storage_clear_version_1(void *context, int64_t a, int64_t b); -// extern int64_t ext_default_child_storage_get_version_1(void *context, int64_t a, int64_t b); -// extern int64_t ext_default_child_storage_next_key_version_1(void *context, int64_t a, int64_t b); -// extern int64_t ext_default_child_storage_read_version_1(void *context, int64_t a, int64_t b, int64_t c, int32_t d); -// extern int64_t ext_default_child_storage_root_version_1(void *context, int64_t a); -// extern void ext_default_child_storage_set_version_1(void *context, int64_t a, int64_t b, int64_t c); -// extern void ext_default_child_storage_storage_kill_version_1(void *context, int64_t a); -// extern int32_t ext_default_child_storage_storage_kill_version_2(void *context, int64_t a, int64_t b); -// extern int64_t ext_default_child_storage_storage_kill_version_3(void *context, int64_t a, int64_t b); -// extern void ext_default_child_storage_clear_prefix_version_1(void *context, int64_t a, int64_t b); -// extern int32_t ext_default_child_storage_exists_version_1(void *context, int64_t a, int64_t b); -// -// extern void ext_allocator_free_version_1(void *context, int32_t a); -// extern int32_t ext_allocator_malloc_version_1(void *context, int32_t a); -// -// extern int32_t ext_hashing_blake2_128_version_1(void *context, int64_t a); -// extern int32_t ext_hashing_blake2_256_version_1(void *context, int64_t a); -// extern int32_t ext_hashing_keccak_256_version_1(void *context, int64_t a); -// extern int32_t ext_hashing_sha2_256_version_1(void *context, int64_t a); -// extern int32_t ext_hashing_twox_256_version_1(void *context, int64_t a); -// extern int32_t ext_hashing_twox_128_version_1(void *context, int64_t a); -// extern int32_t ext_hashing_twox_64_version_1(void *context, int64_t a); -// -// extern void ext_offchain_index_set_version_1(void *context, int64_t a, int64_t b); -// extern int32_t ext_offchain_is_validator_version_1(void *context); -// extern void ext_offchain_local_storage_clear_version_1(void *context, int32_t a, int64_t b); -// extern int32_t ext_offchain_local_storage_compare_and_set_version_1(void *context, int32_t a, int64_t b, int64_t c, int64_t d); -// extern int64_t ext_offchain_local_storage_get_version_1(void *context, int32_t a, int64_t b); -// extern void ext_offchain_local_storage_set_version_1(void *context, int32_t a, int64_t b, int64_t c); -// extern int64_t ext_offchain_network_state_version_1(void *context); -// extern int32_t ext_offchain_random_seed_version_1(void *context); -// extern int64_t ext_offchain_submit_transaction_version_1(void *context, int64_t a); -// extern int64_t ext_offchain_timestamp_version_1(void *context); -// extern void ext_offchain_sleep_until_version_1(void *context, int64_t a); -// extern int64_t ext_offchain_http_request_start_version_1(void *context, int64_t a, int64_t b, int64_t c); -// extern int64_t ext_offchain_http_request_add_header_version_1(void *context, int32_t a, int64_t k, int64_t v); -// -// extern void ext_storage_append_version_1(void *context, int64_t a, int64_t b); -// extern int64_t ext_storage_changes_root_version_1(void *context, int64_t a); -// extern void ext_storage_clear_version_1(void *context, int64_t a); -// extern void ext_storage_clear_prefix_version_1(void *context, int64_t a); -// extern int64_t ext_storage_clear_prefix_version_2(void *context, int64_t a, int64_t b); -// extern void ext_storage_commit_transaction_version_1(void *context); -// extern int32_t ext_storage_exists_version_1(void *context, int64_t a); -// extern int64_t ext_storage_get_version_1(void *context, int64_t a); -// extern int64_t ext_storage_next_key_version_1(void *context, int64_t a); -// extern int64_t ext_storage_read_version_1(void *context, int64_t a, int64_t b, int32_t c); -// extern void ext_storage_rollback_transaction_version_1(void *context); -// extern int64_t ext_storage_root_version_1(void *context); -// extern int64_t ext_storage_root_version_2(void *context, int32_t a); -// extern void ext_storage_set_version_1(void *context, int64_t a, int64_t b); -// extern void ext_storage_start_transaction_version_1(void *context); -// -// extern void ext_transaction_index_index_version_1(void *context, int32_t a, int32_t b, int32_t c); -// extern void ext_transaction_index_renew_version_1(void *context, int32_t a, int32_t b); -import "C" //skipcq: SCC-compile - import ( "encoding/binary" "fmt" @@ -107,7 +10,6 @@ import ( "math/rand" "reflect" "time" - "unsafe" "github.com/ChainSafe/gossamer/lib/common" "github.com/ChainSafe/gossamer/lib/crypto" @@ -119,8 +21,7 @@ import ( "github.com/ChainSafe/gossamer/lib/trie" "github.com/ChainSafe/gossamer/lib/trie/proof" "github.com/ChainSafe/gossamer/pkg/scale" - - wasm "github.com/wasmerio/go-ext-wasm/wasmer" + "github.com/wasmerio/wasmer-go/wasmer" ) const ( @@ -128,12 +29,20 @@ const ( ) //export ext_logging_log_version_1 -func ext_logging_log_version_1(context unsafe.Pointer, level C.int32_t, targetData, msgData C.int64_t) { +func ext_logging_log_version_1(env interface{}, args []wasmer.Value) ([]wasmer.Value, error) { logger.Trace("executing...") - instanceContext := wasm.IntoInstanceContext(context) + ctx := env.(*runtime.Context) + + level, ok := args[0].Unwrap().(int32) + if !ok { + logger.Criticalf("[ext_logging_log_version_1]", "error", "addr cannot be converted to int32") + } - target := string(asMemorySlice(instanceContext, targetData)) - msg := string(asMemorySlice(instanceContext, msgData)) + targetData := args[1].I64() + msgData := args[2].I64() + + target := string(asMemorySlice(ctx, targetData)) + msg := string(asMemorySlice(ctx, msgData)) switch int(level) { case 0: @@ -149,89 +58,96 @@ func ext_logging_log_version_1(context unsafe.Pointer, level C.int32_t, targetDa default: logger.Errorf("level=%d target=%s message=%s", int(level), target, msg) } + return nil, nil } //export ext_logging_max_level_version_1 -func ext_logging_max_level_version_1(context unsafe.Pointer) C.int32_t { +func ext_logging_max_level_version_1(_ interface{}, _ []wasmer.Value) ([]wasmer.Value, error) { logger.Trace("executing...") - return 4 + return []wasmer.Value{wasmer.NewI32(4)}, nil } //export ext_transaction_index_index_version_1 -func ext_transaction_index_index_version_1(context unsafe.Pointer, a, b, c C.int32_t) { +func ext_transaction_index_index_version_1(_ interface{}, _ []wasmer.Value) ([]wasmer.Value, error) { logger.Trace("executing...") logger.Warn("unimplemented") + return nil, nil } //export ext_transaction_index_renew_version_1 -func ext_transaction_index_renew_version_1(context unsafe.Pointer, a, b C.int32_t) { +func ext_transaction_index_renew_version_1(_ interface{}, _ []wasmer.Value) ([]wasmer.Value, error) { logger.Trace("executing...") logger.Warn("unimplemented") + return nil, nil } //export ext_sandbox_instance_teardown_version_1 -func ext_sandbox_instance_teardown_version_1(context unsafe.Pointer, a C.int32_t) { +func ext_sandbox_instance_teardown_version_1(_ interface{}, _ []wasmer.Value) ([]wasmer.Value, error) { logger.Trace("executing...") logger.Warn("unimplemented") + return nil, nil } //export ext_sandbox_instantiate_version_1 -func ext_sandbox_instantiate_version_1(context unsafe.Pointer, a C.int32_t, x, y C.int64_t, z C.int32_t) C.int32_t { +func ext_sandbox_instantiate_version_1(_ interface{}, _ []wasmer.Value) ([]wasmer.Value, error) { logger.Trace("executing...") logger.Warn("unimplemented") - return 0 + return []wasmer.Value{wasmer.NewI32(0)}, nil } //export ext_sandbox_invoke_version_1 -func ext_sandbox_invoke_version_1(context unsafe.Pointer, a C.int32_t, x, y C.int64_t, z, d, e C.int32_t) C.int32_t { +func ext_sandbox_invoke_version_1(_ interface{}, _ []wasmer.Value) ([]wasmer.Value, error) { logger.Trace("executing...") logger.Warn("unimplemented") - return 0 + return []wasmer.Value{wasmer.NewI32(0)}, nil } //export ext_sandbox_memory_get_version_1 -func ext_sandbox_memory_get_version_1(context unsafe.Pointer, a, z, d, e C.int32_t) C.int32_t { +func ext_sandbox_memory_get_version_1(_ interface{}, _ []wasmer.Value) ([]wasmer.Value, error) { logger.Trace("executing...") logger.Warn("unimplemented") - return 0 + return []wasmer.Value{wasmer.NewI32(0)}, nil } //export ext_sandbox_memory_new_version_1 -func ext_sandbox_memory_new_version_1(context unsafe.Pointer, a, z C.int32_t) C.int32_t { +func ext_sandbox_memory_new_version_1(_ interface{}, _ []wasmer.Value) ([]wasmer.Value, error) { logger.Trace("executing...") logger.Warn("unimplemented") - return 0 + return []wasmer.Value{wasmer.NewI32(0)}, nil } //export ext_sandbox_memory_set_version_1 -func ext_sandbox_memory_set_version_1(context unsafe.Pointer, a, z, d, e C.int32_t) C.int32_t { +func ext_sandbox_memory_set_version_1(_ interface{}, _ []wasmer.Value) ([]wasmer.Value, error) { logger.Trace("executing...") logger.Warn("unimplemented") - return 0 + return []wasmer.Value{wasmer.NewI32(0)}, nil } //export ext_sandbox_memory_teardown_version_1 -func ext_sandbox_memory_teardown_version_1(context unsafe.Pointer, a C.int32_t) { +func ext_sandbox_memory_teardown_version_1(_ interface{}, _ []wasmer.Value) ([]wasmer.Value, error) { logger.Trace("executing...") logger.Warn("unimplemented") + return nil, nil } //export ext_crypto_ed25519_generate_version_1 -func ext_crypto_ed25519_generate_version_1(context unsafe.Pointer, keyTypeID C.int32_t, seedSpan C.int64_t) C.int32_t { +func ext_crypto_ed25519_generate_version_1(env interface{}, args []wasmer.Value) ([]wasmer.Value, error) { logger.Trace("executing...") - instanceContext := wasm.IntoInstanceContext(context) - runtimeCtx := instanceContext.Data().(*runtime.Context) - memory := instanceContext.Memory().Data() + runtimeCtx := env.(*runtime.Context) + memory := runtimeCtx.Memory.Data() + + keyTypeID := args[0].I32() + seedSpan := args[1].I64() id := memory[keyTypeID : keyTypeID+4] - seedBytes := asMemorySlice(instanceContext, seedSpan) + seedBytes := asMemorySlice(runtimeCtx, seedSpan) var seed *[]byte err := scale.Unmarshal(seedBytes, &seed) if err != nil { logger.Warnf("cannot generate key: %s", err) - return 0 + return []wasmer.Value{wasmer.NewI32(0)}, nil } var kp KeyPair @@ -244,54 +160,59 @@ func ext_crypto_ed25519_generate_version_1(context unsafe.Pointer, keyTypeID C.i if err != nil { logger.Warnf("cannot generate key: %s", err) - return 0 + return []wasmer.Value{wasmer.NewI32(0)}, nil } ks, err := runtimeCtx.Keystore.GetKeystore(id) if err != nil { logger.Warnf("error for id 0x%x: %s", id, err) - return 0 + return []wasmer.Value{wasmer.NewI32(0)}, nil } err = ks.Insert(kp) if err != nil { logger.Warnf("failed to insert key: %s", err) - return 0 + return []wasmer.Value{wasmer.NewI32(0)}, nil } - ret, err := toWasmMemorySized(instanceContext, kp.Public().Encode()) + ret, err := toWasmMemorySized(runtimeCtx, kp.Public().Encode()) if err != nil { logger.Warnf("failed to allocate memory: %s", err) - return 0 + return []wasmer.Value{wasmer.NewI32(0)}, nil + } + + castedRet, err := safeCastInt32(ret) + if err != nil { + logger.Errorf("failed to safely cast pointer: %s", err) + return []wasmer.Value{wasmer.NewI32(0)}, err } logger.Debug("generated ed25519 keypair with public key: " + kp.Public().Hex()) - return C.int32_t(ret) + return []wasmer.Value{wasmer.NewI32(castedRet)}, nil } //export ext_crypto_ed25519_public_keys_version_1 -func ext_crypto_ed25519_public_keys_version_1(context unsafe.Pointer, keyTypeID C.int32_t) C.int64_t { +func ext_crypto_ed25519_public_keys_version_1(env interface{}, args []wasmer.Value) ([]wasmer.Value, error) { logger.Debug("executing...") + runtimeCtx := env.(*runtime.Context) + memory := runtimeCtx.Memory.Data() - instanceContext := wasm.IntoInstanceContext(context) - runtimeCtx := instanceContext.Data().(*runtime.Context) - memory := instanceContext.Memory().Data() - + keyTypeID := args[0].I32() id := memory[keyTypeID : keyTypeID+4] ks, err := runtimeCtx.Keystore.GetKeystore(id) if err != nil { logger.Warnf("error for id 0x%x: %s", id, err) - ret, _ := toWasmMemory(instanceContext, []byte{0}) - return C.int64_t(ret) + ret, _ := toWasmMemory(runtimeCtx, []byte{0}) + return []wasmer.Value{wasmer.NewI64(ret)}, nil } if ks.Type() != crypto.Ed25519Type && ks.Type() != crypto.UnknownType { logger.Warnf( "error for id 0x%x: keystore type is %s and not the expected ed25519", id, ks.Type()) - ret, _ := toWasmMemory(instanceContext, []byte{0}) - return C.int64_t(ret) + ret, _ := toWasmMemory(runtimeCtx, []byte{0}) + return []wasmer.Value{wasmer.NewI64(ret)}, nil } keys := ks.PublicKeys() @@ -304,85 +225,90 @@ func ext_crypto_ed25519_public_keys_version_1(context unsafe.Pointer, keyTypeID prefix, err := scale.Marshal(big.NewInt(int64(len(keys)))) if err != nil { logger.Errorf("failed to allocate memory: %s", err) - ret, _ := toWasmMemory(instanceContext, []byte{0}) - return C.int64_t(ret) + ret, _ := toWasmMemory(runtimeCtx, []byte{0}) + return []wasmer.Value{wasmer.NewI64(ret)}, nil } - ret, err := toWasmMemory(instanceContext, append(prefix, encodedKeys...)) + ret, err := toWasmMemory(runtimeCtx, append(prefix, encodedKeys...)) if err != nil { logger.Errorf("failed to allocate memory: %s", err) - ret, _ = toWasmMemory(instanceContext, []byte{0}) - return C.int64_t(ret) + ret, _ = toWasmMemory(runtimeCtx, []byte{0}) + return []wasmer.Value{wasmer.NewI64(ret)}, nil } - return C.int64_t(ret) + return []wasmer.Value{wasmer.NewI64(ret)}, nil } //export ext_crypto_ed25519_sign_version_1 -func ext_crypto_ed25519_sign_version_1(context unsafe.Pointer, keyTypeID, key C.int32_t, msg C.int64_t) C.int64_t { +func ext_crypto_ed25519_sign_version_1(env interface{}, args []wasmer.Value) ([]wasmer.Value, error) { logger.Debug("executing...") - instanceContext := wasm.IntoInstanceContext(context) - runtimeCtx := instanceContext.Data().(*runtime.Context) - memory := instanceContext.Memory().Data() + runtimeCtx := env.(*runtime.Context) + memory := runtimeCtx.Memory.Data() + keyTypeID := args[0].I32() + key := args[1].I32() + msg := args[2].I64() id := memory[keyTypeID : keyTypeID+4] pubKeyData := memory[key : key+32] pubKey, err := ed25519.NewPublicKey(pubKeyData) if err != nil { logger.Errorf("failed to get public keys: %s", err) - return 0 + return []wasmer.Value{wasmer.NewI64(0)}, nil } ks, err := runtimeCtx.Keystore.GetKeystore(id) if err != nil { logger.Warnf("error for id 0x%x: %s", id, err) - return mustToWasmMemoryOptionalNil(instanceContext) + return mustToWasmMemoryOptionalNil(runtimeCtx), nil } signingKey := ks.GetKeypair(pubKey) if signingKey == nil { logger.Error("could not find public key " + pubKey.Hex() + " in keystore") - ret, err := toWasmMemoryOptionalNil(instanceContext) + ret, err := toWasmMemoryOptionalNil(runtimeCtx) if err != nil { logger.Errorf("failed to allocate memory: %s", err) - return 0 + return []wasmer.Value{wasmer.NewI64(0)}, nil } - return ret + return ret, nil } - sig, err := signingKey.Sign(asMemorySlice(instanceContext, msg)) + sig, err := signingKey.Sign(asMemorySlice(runtimeCtx, msg)) if err != nil { logger.Error("could not sign message") } - ret, err := toWasmMemoryFixedSizeOptional(instanceContext, sig) + ret, err := toWasmMemoryFixedSizeOptional(runtimeCtx, sig) if err != nil { logger.Errorf("failed to allocate memory: %s", err) - return 0 + return []wasmer.Value{wasmer.NewI64(0)}, nil } - return C.int64_t(ret) + return []wasmer.Value{wasmer.NewI64(ret)}, nil } //export ext_crypto_ed25519_verify_version_1 -func ext_crypto_ed25519_verify_version_1(context unsafe.Pointer, sig C.int32_t, - msg C.int64_t, key C.int32_t) C.int32_t { +func ext_crypto_ed25519_verify_version_1(env interface{}, args []wasmer.Value) ([]wasmer.Value, error) { logger.Debug("executing...") - instanceContext := wasm.IntoInstanceContext(context) - memory := instanceContext.Memory().Data() - sigVerifier := instanceContext.Data().(*runtime.Context).SigVerifier + runtimeCtx := env.(*runtime.Context) + memory := runtimeCtx.Memory.Data() + sigVerifier := runtimeCtx.SigVerifier + + sig := args[0].I32() + msg := args[1].I64() + key := args[2].I32() signature := memory[sig : sig+64] - message := asMemorySlice(instanceContext, msg) + message := asMemorySlice(runtimeCtx, msg) pubKeyData := memory[key : key+32] pubKey, err := ed25519.NewPublicKey(pubKeyData) if err != nil { logger.Error("failed to create public key") - return 0 + return []wasmer.Value{wasmer.NewI32(0)}, err } if sigVerifier.IsStarted() { @@ -393,23 +319,26 @@ func ext_crypto_ed25519_verify_version_1(context unsafe.Pointer, sig C.int32_t, VerifyFunc: ed25519.VerifySignature, } sigVerifier.Add(&signature) - return 1 + return []wasmer.Value{wasmer.NewI32(1)}, nil } if ok, err := pubKey.Verify(message, signature); err != nil || !ok { logger.Error("failed to verify") - return 0 + return []wasmer.Value{wasmer.NewI32(0)}, err } logger.Debug("verified ed25519 signature") - return 1 + return []wasmer.Value{wasmer.NewI32(1)}, nil } //export ext_crypto_secp256k1_ecdsa_recover_version_1 -func ext_crypto_secp256k1_ecdsa_recover_version_1(context unsafe.Pointer, sig, msg C.int32_t) C.int64_t { +func ext_crypto_secp256k1_ecdsa_recover_version_1(env interface{}, args []wasmer.Value) ([]wasmer.Value, error) { logger.Trace("executing...") - instanceContext := wasm.IntoInstanceContext(context) - memory := instanceContext.Memory().Data() + instanceContext := env.(*runtime.Context) + memory := instanceContext.Memory.Data() + + sig := args[0].I32() + msg := args[1].I32() // msg must be the 32-byte hash of the message to be signed. // sig must be a 65-byte compact ECDSA signature containing the @@ -423,9 +352,9 @@ func ext_crypto_secp256k1_ecdsa_recover_version_1(context unsafe.Pointer, sig, m ret, err := toWasmMemoryResultEmpty(instanceContext) if err != nil { logger.Errorf("failed to allocate memory: %s", err) - return 0 + return []wasmer.Value{wasmer.NewI64(0)}, nil } - return ret + return ret, nil } logger.Debugf( @@ -435,25 +364,29 @@ func ext_crypto_secp256k1_ecdsa_recover_version_1(context unsafe.Pointer, sig, m ret, err := toWasmMemoryResult(instanceContext, pub[1:]) if err != nil { logger.Errorf("failed to allocate memory: %s", err) - return 0 + return []wasmer.Value{wasmer.NewI64(0)}, nil } - return C.int64_t(ret) + return []wasmer.Value{wasmer.NewI64(ret)}, nil } //export ext_crypto_secp256k1_ecdsa_recover_version_2 -func ext_crypto_secp256k1_ecdsa_recover_version_2(context unsafe.Pointer, sig, msg C.int32_t) C.int64_t { +func ext_crypto_secp256k1_ecdsa_recover_version_2(env interface{}, args []wasmer.Value) ([]wasmer.Value, error) { logger.Trace("executing...") - return ext_crypto_secp256k1_ecdsa_recover_version_1(context, sig, msg) + return ext_crypto_secp256k1_ecdsa_recover_version_1(env, args) } //export ext_crypto_ecdsa_verify_version_2 -func ext_crypto_ecdsa_verify_version_2(context unsafe.Pointer, sig C.int32_t, msg C.int64_t, key C.int32_t) C.int32_t { +func ext_crypto_ecdsa_verify_version_2(env interface{}, args []wasmer.Value) ([]wasmer.Value, error) { logger.Trace("executing...") - instanceContext := wasm.IntoInstanceContext(context) - memory := instanceContext.Memory().Data() - sigVerifier := instanceContext.Data().(*runtime.Context).SigVerifier + instanceContext := env.(*runtime.Context) + memory := instanceContext.Memory.Data() + sigVerifier := instanceContext.SigVerifier + + sig := args[0].I32() + msg := args[1].I64() + key := args[2].I32() message := asMemorySlice(instanceContext, msg) signature := memory[sig : sig+64] @@ -463,7 +396,7 @@ func ext_crypto_ecdsa_verify_version_2(context unsafe.Pointer, sig C.int32_t, ms err := pub.Decode(pubKey) if err != nil { logger.Errorf("failed to decode public key: %s", err) - return C.int32_t(0) + return []wasmer.Value{wasmer.NewI32(0)}, nil } logger.Debugf("pub=%s, message=0x%x, signature=0x%x", @@ -472,7 +405,7 @@ func ext_crypto_ecdsa_verify_version_2(context unsafe.Pointer, sig C.int32_t, ms hash, err := common.Blake2bHash(message) if err != nil { logger.Errorf("failed to hash message: %s", err) - return C.int32_t(0) + return []wasmer.Value{wasmer.NewI32(0)}, nil } if sigVerifier.IsStarted() { @@ -483,7 +416,7 @@ func ext_crypto_ecdsa_verify_version_2(context unsafe.Pointer, sig C.int32_t, ms VerifyFunc: secp256k1.VerifySignature, } sigVerifier.Add(&signature) - return C.int32_t(1) + return []wasmer.Value{wasmer.NewI32(1)}, nil } ok, err := pub.Verify(hash[:], signature) @@ -493,18 +426,22 @@ func ext_crypto_ecdsa_verify_version_2(context unsafe.Pointer, sig C.int32_t, ms message += ": " + err.Error() } logger.Errorf(message) - return C.int32_t(0) + return []wasmer.Value{wasmer.NewI32(0)}, nil } logger.Debug("validated signature") - return C.int32_t(1) + return []wasmer.Value{wasmer.NewI32(1)}, nil } //export ext_crypto_secp256k1_ecdsa_recover_compressed_version_1 -func ext_crypto_secp256k1_ecdsa_recover_compressed_version_1(context unsafe.Pointer, sig, msg C.int32_t) C.int64_t { +func ext_crypto_secp256k1_ecdsa_recover_compressed_version_1(env interface{}, + args []wasmer.Value) ([]wasmer.Value, error) { logger.Trace("executing...") - instanceContext := wasm.IntoInstanceContext(context) - memory := instanceContext.Memory().Data() + instanceContext := env.(*runtime.Context) + memory := instanceContext.Memory.Data() + + sig := args[0].I32() + msg := args[1].I32() // msg must be the 32-byte hash of the message to be signed. // sig must be a 65-byte compact ECDSA signature containing the @@ -515,7 +452,7 @@ func ext_crypto_secp256k1_ecdsa_recover_compressed_version_1(context unsafe.Poin cpub, err := secp256k1.RecoverPublicKeyCompressed(message, signature) if err != nil { logger.Errorf("failed to recover public key: %s", err) - return mustToWasmMemoryResultEmpty(instanceContext) + return mustToWasmMemoryResultEmpty(instanceContext), nil } logger.Debugf( @@ -525,25 +462,27 @@ func ext_crypto_secp256k1_ecdsa_recover_compressed_version_1(context unsafe.Poin ret, err := toWasmMemoryResult(instanceContext, cpub) if err != nil { logger.Errorf("failed to allocate memory: %s", err) - return 0 + return []wasmer.Value{wasmer.NewI64(0)}, nil } - return C.int64_t(ret) + return []wasmer.Value{wasmer.NewI64(ret)}, nil } //export ext_crypto_secp256k1_ecdsa_recover_compressed_version_2 -func ext_crypto_secp256k1_ecdsa_recover_compressed_version_2(context unsafe.Pointer, sig, msg C.int32_t) C.int64_t { +func ext_crypto_secp256k1_ecdsa_recover_compressed_version_2(env interface{}, + args []wasmer.Value) ([]wasmer.Value, error) { logger.Trace("executing...") - return ext_crypto_secp256k1_ecdsa_recover_compressed_version_1(context, sig, msg) + return ext_crypto_secp256k1_ecdsa_recover_compressed_version_1(env, args) } //export ext_crypto_sr25519_generate_version_1 -func ext_crypto_sr25519_generate_version_1(context unsafe.Pointer, keyTypeID C.int32_t, seedSpan C.int64_t) C.int32_t { +func ext_crypto_sr25519_generate_version_1(env interface{}, args []wasmer.Value) ([]wasmer.Value, error) { logger.Trace("executing...") - instanceContext := wasm.IntoInstanceContext(context) - runtimeCtx := instanceContext.Data().(*runtime.Context) - memory := instanceContext.Memory().Data() + instanceContext := env.(*runtime.Context) + memory := instanceContext.Memory.Data() + keyTypeID := args[0].I32() + seedSpan := args[1].I64() id := memory[keyTypeID : keyTypeID+4] seedBytes := asMemorySlice(instanceContext, seedSpan) @@ -552,7 +491,7 @@ func ext_crypto_sr25519_generate_version_1(context unsafe.Pointer, keyTypeID C.i err := scale.Unmarshal(seedBytes, &seed) if err != nil { logger.Warnf("cannot generate key: %s", err) - return 0 + return []wasmer.Value{wasmer.NewI32(0)}, nil } var kp KeyPair @@ -567,43 +506,52 @@ func ext_crypto_sr25519_generate_version_1(context unsafe.Pointer, keyTypeID C.i panic(err) } - ks, err := runtimeCtx.Keystore.GetKeystore(id) + ks, err := instanceContext.Keystore.GetKeystore(id) if err != nil { logger.Warnf("error for id "+common.BytesToHex(id)+": %s", err) - return 0 + return []wasmer.Value{wasmer.NewI32(0)}, nil } err = ks.Insert(kp) if err != nil { logger.Warnf("failed to insert key: %s", err) - return 0 + return []wasmer.Value{wasmer.NewI32(0)}, nil } ret, err := toWasmMemorySized(instanceContext, kp.Public().Encode()) if err != nil { logger.Errorf("failed to allocate memory: %s", err) - return 0 + return []wasmer.Value{wasmer.NewI32(0)}, nil + } + + castedRet, err := safeCastInt32(ret) + if err != nil { + logger.Errorf("failed to safely cast pointer: %s", err) + return []wasmer.Value{wasmer.NewI32(0)}, err } logger.Debug("generated sr25519 keypair with public key: " + kp.Public().Hex()) - return C.int32_t(ret) + return []wasmer.Value{wasmer.NewI32(castedRet)}, nil } //export ext_crypto_sr25519_public_keys_version_1 -func ext_crypto_sr25519_public_keys_version_1(context unsafe.Pointer, keyTypeID C.int32_t) C.int64_t { +func ext_crypto_sr25519_public_keys_version_1(env interface{}, args []wasmer.Value) ([]wasmer.Value, error) { logger.Debug("executing...") - instanceContext := wasm.IntoInstanceContext(context) - runtimeCtx := instanceContext.Data().(*runtime.Context) - memory := instanceContext.Memory().Data() + instanceContext := env.(*runtime.Context) + memory := instanceContext.Memory.Data() + keyTypeID, ok := args[0].Unwrap().(int32) + if !ok { + panic("keyTypeID is not int32") + } id := memory[keyTypeID : keyTypeID+4] - ks, err := runtimeCtx.Keystore.GetKeystore(id) + ks, err := instanceContext.Keystore.GetKeystore(id) if err != nil { logger.Warnf("error for id "+common.BytesToHex(id)+": %s", err) ret, _ := toWasmMemory(instanceContext, []byte{0}) - return C.int64_t(ret) + return []wasmer.Value{wasmer.NewI64(ret)}, nil } if ks.Type() != crypto.Sr25519Type && ks.Type() != crypto.UnknownType { @@ -611,7 +559,7 @@ func ext_crypto_sr25519_public_keys_version_1(context unsafe.Pointer, keyTypeID "keystore type for id 0x%x is %s and not expected sr25519", id, ks.Type()) ret, _ := toWasmMemory(instanceContext, []byte{0}) - return C.int64_t(ret) + return []wasmer.Value{wasmer.NewI64(ret)}, nil } keys := ks.PublicKeys() @@ -625,71 +573,78 @@ func ext_crypto_sr25519_public_keys_version_1(context unsafe.Pointer, keyTypeID if err != nil { logger.Errorf("failed to allocate memory: %s", err) ret, _ := toWasmMemory(instanceContext, []byte{0}) - return C.int64_t(ret) + return []wasmer.Value{wasmer.NewI64(ret)}, nil } ret, err := toWasmMemory(instanceContext, append(prefix, encodedKeys...)) if err != nil { logger.Errorf("failed to allocate memory: %s", err) ret, _ = toWasmMemory(instanceContext, []byte{0}) - return C.int64_t(ret) + return []wasmer.Value{wasmer.NewI64(ret)}, nil } - return C.int64_t(ret) + return []wasmer.Value{wasmer.NewI64(ret)}, nil } //export ext_crypto_sr25519_sign_version_1 -func ext_crypto_sr25519_sign_version_1(context unsafe.Pointer, keyTypeID, key C.int32_t, msg C.int64_t) C.int64_t { +func ext_crypto_sr25519_sign_version_1(env interface{}, args []wasmer.Value) ([]wasmer.Value, error) { logger.Debug("executing...") - instanceContext := wasm.IntoInstanceContext(context) - runtimeCtx := instanceContext.Data().(*runtime.Context) - memory := instanceContext.Memory().Data() + runtimeCtx := env.(*runtime.Context) + memory := runtimeCtx.Memory.Data() + keyTypeID := args[0].I32() + key := args[1].I32() + msg := args[2].I64() + + emptyRet, _ := toWasmMemoryOptional(runtimeCtx, nil) id := memory[keyTypeID : keyTypeID+4] ks, err := runtimeCtx.Keystore.GetKeystore(id) if err != nil { logger.Warnf("error for id 0x%x: %s", id, err) - return mustToWasmMemoryOptionalNil(instanceContext) + return []wasmer.Value{wasmer.NewI64(emptyRet)}, nil } var ret int64 pubKey, err := sr25519.NewPublicKey(memory[key : key+32]) if err != nil { logger.Errorf("failed to get public key: %s", err) - return mustToWasmMemoryOptionalNil(instanceContext) + return []wasmer.Value{wasmer.NewI64(emptyRet)}, nil } signingKey := ks.GetKeypair(pubKey) if signingKey == nil { logger.Error("could not find public key " + pubKey.Hex() + " in keystore") - return mustToWasmMemoryOptionalNil(instanceContext) + return []wasmer.Value{wasmer.NewI64(emptyRet)}, nil } - msgData := asMemorySlice(instanceContext, msg) + msgData := asMemorySlice(runtimeCtx, msg) sig, err := signingKey.Sign(msgData) if err != nil { logger.Errorf("could not sign message: %s", err) - return mustToWasmMemoryOptionalNil(instanceContext) + return []wasmer.Value{wasmer.NewI64(emptyRet)}, nil } - ret, err = toWasmMemoryFixedSizeOptional(instanceContext, sig) + ret, err = toWasmMemoryFixedSizeOptional(runtimeCtx, sig) if err != nil { logger.Errorf("failed to allocate memory: %s", err) - return mustToWasmMemoryOptionalNil(instanceContext) + return []wasmer.Value{wasmer.NewI64(emptyRet)}, nil } - return C.int64_t(ret) + return []wasmer.Value{wasmer.NewI64(ret)}, nil } //export ext_crypto_sr25519_verify_version_1 -func ext_crypto_sr25519_verify_version_1(context unsafe.Pointer, sig C.int32_t, - msg C.int64_t, key C.int32_t) C.int32_t { +func ext_crypto_sr25519_verify_version_1(env interface{}, args []wasmer.Value) ([]wasmer.Value, error) { logger.Debug("executing...") - instanceContext := wasm.IntoInstanceContext(context) - memory := instanceContext.Memory().Data() - sigVerifier := instanceContext.Data().(*runtime.Context).SigVerifier + instanceContext := env.(*runtime.Context) + memory := instanceContext.Memory.Data() + sigVerifier := instanceContext.SigVerifier + + sig := args[0].I32() + msg := args[1].I64() + key := args[2].I32() message := asMemorySlice(instanceContext, msg) signature := memory[sig : sig+64] @@ -697,7 +652,7 @@ func ext_crypto_sr25519_verify_version_1(context unsafe.Pointer, sig C.int32_t, pub, err := sr25519.NewPublicKey(memory[key : key+32]) if err != nil { logger.Error("invalid sr25519 public key") - return 0 + return []wasmer.Value{wasmer.NewI32(0)}, nil //nolint } logger.Debugf( @@ -712,7 +667,7 @@ func ext_crypto_sr25519_verify_version_1(context unsafe.Pointer, sig C.int32_t, VerifyFunc: sr25519.VerifySignature, } sigVerifier.Add(&signature) - return 1 + return []wasmer.Value{wasmer.NewI32(1)}, nil } ok, err := pub.VerifyDeprecated(message, signature) @@ -723,21 +678,24 @@ func ext_crypto_sr25519_verify_version_1(context unsafe.Pointer, sig C.int32_t, } logger.Debugf(message) // this fails at block 3876, which seems to be expected, based on discussions - return 1 + return []wasmer.Value{wasmer.NewI32(1)}, nil } logger.Debug("verified sr25519 signature") - return 1 + return []wasmer.Value{wasmer.NewI32(1)}, nil } //export ext_crypto_sr25519_verify_version_2 -func ext_crypto_sr25519_verify_version_2(context unsafe.Pointer, sig C.int32_t, - msg C.int64_t, key C.int32_t) C.int32_t { +func ext_crypto_sr25519_verify_version_2(env interface{}, args []wasmer.Value) ([]wasmer.Value, error) { logger.Trace("executing...") - instanceContext := wasm.IntoInstanceContext(context) - memory := instanceContext.Memory().Data() - sigVerifier := instanceContext.Data().(*runtime.Context).SigVerifier + instanceContext := env.(*runtime.Context) + memory := instanceContext.Memory.Data() + sigVerifier := instanceContext.SigVerifier + + sig := args[0].I32() + msg := args[1].I64() + key := args[2].I32() message := asMemorySlice(instanceContext, msg) signature := memory[sig : sig+64] @@ -745,7 +703,7 @@ func ext_crypto_sr25519_verify_version_2(context unsafe.Pointer, sig C.int32_t, pub, err := sr25519.NewPublicKey(memory[key : key+32]) if err != nil { logger.Error("invalid sr25519 public key") - return 0 + return []wasmer.Value{wasmer.NewI32(0)}, nil //nolint } logger.Debugf( @@ -760,7 +718,7 @@ func ext_crypto_sr25519_verify_version_2(context unsafe.Pointer, sig C.int32_t, VerifyFunc: sr25519.VerifySignature, } sigVerifier.Add(&signature) - return 1 + return []wasmer.Value{wasmer.NewI32(1)}, nil } ok, err := pub.Verify(message, signature) @@ -770,38 +728,40 @@ func ext_crypto_sr25519_verify_version_2(context unsafe.Pointer, sig C.int32_t, message += ": " + err.Error() } logger.Errorf(message) - return 0 + return []wasmer.Value{wasmer.NewI32(0)}, nil } logger.Debug("validated signature") - return C.int32_t(1) + return []wasmer.Value{wasmer.NewI32(1)}, nil } //export ext_crypto_start_batch_verify_version_1 -func ext_crypto_start_batch_verify_version_1(context unsafe.Pointer) { +func ext_crypto_start_batch_verify_version_1(_ interface{}, _ []wasmer.Value) ([]wasmer.Value, error) { logger.Debug("executing...") // TODO: fix and re-enable signature verification (#1405) // beginBatchVerify(context) + return nil, nil } //export ext_crypto_finish_batch_verify_version_1 -func ext_crypto_finish_batch_verify_version_1(context unsafe.Pointer) C.int32_t { +func ext_crypto_finish_batch_verify_version_1(_ interface{}, _ []wasmer.Value) ([]wasmer.Value, error) { logger.Debug("executing...") // TODO: fix and re-enable signature verification (#1405) // return finishBatchVerify(context) - return 1 + return []wasmer.Value{wasmer.NewI32(1)}, nil } //export ext_trie_blake2_256_root_version_1 -func ext_trie_blake2_256_root_version_1(context unsafe.Pointer, dataSpan C.int64_t) C.int32_t { +func ext_trie_blake2_256_root_version_1(env interface{}, args []wasmer.Value) ([]wasmer.Value, error) { logger.Debug("executing...") - instanceContext := wasm.IntoInstanceContext(context) - memory := instanceContext.Memory().Data() - runtimeCtx := instanceContext.Data().(*runtime.Context) - data := asMemorySlice(instanceContext, dataSpan) + runtimeCtx := env.(*runtime.Context) + memory := runtimeCtx.Memory.Data() + dataSpan := args[0].I64() + + data := asMemorySlice(runtimeCtx, dataSpan) t := trie.NewEmptyTrie() @@ -813,7 +773,7 @@ func ext_trie_blake2_256_root_version_1(context unsafe.Pointer, dataSpan C.int64 var kvs []kv if err := scale.Unmarshal(data, &kvs); err != nil { logger.Errorf("failed scale decoding data: %s", err) - return 0 + return []wasmer.Value{wasmer.NewI32(0)}, nil } for _, kv := range kvs { @@ -821,7 +781,7 @@ func ext_trie_blake2_256_root_version_1(context unsafe.Pointer, dataSpan C.int64 if err != nil { logger.Errorf("failed putting key 0x%x and value 0x%x into trie: %s", kv.Key, kv.Value, err) - return 0 + return []wasmer.Value{wasmer.NewI32(0)}, nil } } @@ -829,42 +789,49 @@ func ext_trie_blake2_256_root_version_1(context unsafe.Pointer, dataSpan C.int64 ptr, err := runtimeCtx.Allocator.Allocate(32) if err != nil { logger.Errorf("failed allocating: %s", err) - return 0 + return []wasmer.Value{wasmer.NewI32(0)}, nil } hash, err := t.Hash() if err != nil { logger.Errorf("failed computing trie Merkle root hash: %s", err) - return 0 + return []wasmer.Value{wasmer.NewI32(0)}, nil + } + + castedPtr, err := safeCastInt32(ptr) + if err != nil { + logger.Errorf("failed to safely cast pointer: %s", err) + return []wasmer.Value{wasmer.NewI32(0)}, err } logger.Debugf("root hash is %s", hash) copy(memory[ptr:ptr+32], hash[:]) - return C.int32_t(ptr) + return []wasmer.Value{wasmer.NewI32(castedPtr)}, nil } //export ext_trie_blake2_256_ordered_root_version_1 -func ext_trie_blake2_256_ordered_root_version_1(context unsafe.Pointer, dataSpan C.int64_t) C.int32_t { +func ext_trie_blake2_256_ordered_root_version_1(env interface{}, args []wasmer.Value) ([]wasmer.Value, error) { logger.Debug("executing...") - instanceContext := wasm.IntoInstanceContext(context) - memory := instanceContext.Memory().Data() - runtimeCtx := instanceContext.Data().(*runtime.Context) - data := asMemorySlice(instanceContext, dataSpan) + runtimeCtx := env.(*runtime.Context) + memory := runtimeCtx.Memory.Data() + dataSpan := args[0].I64() + + data := asMemorySlice(runtimeCtx, dataSpan) t := trie.NewEmptyTrie() var values [][]byte err := scale.Unmarshal(data, &values) if err != nil { logger.Errorf("failed scale decoding data: %s", err) - return 0 + return []wasmer.Value{wasmer.NewI32(0)}, nil } for i, value := range values { key, err := scale.Marshal(big.NewInt(int64(i))) if err != nil { logger.Errorf("failed scale encoding value index %d: %s", i, err) - return 0 + return []wasmer.Value{wasmer.NewI32(0)}, nil } logger.Tracef( "put key=0x%x and value=0x%x", @@ -874,7 +841,7 @@ func ext_trie_blake2_256_ordered_root_version_1(context unsafe.Pointer, dataSpan if err != nil { logger.Errorf("failed putting key 0x%x and value 0x%x into trie: %s", key, value, err) - return 0 + return []wasmer.Value{wasmer.NewI32(0)}, nil } } @@ -882,93 +849,107 @@ func ext_trie_blake2_256_ordered_root_version_1(context unsafe.Pointer, dataSpan ptr, err := runtimeCtx.Allocator.Allocate(32) if err != nil { logger.Errorf("failed allocating: %s", err) - return 0 + return []wasmer.Value{wasmer.NewI32(0)}, nil } hash, err := t.Hash() if err != nil { logger.Errorf("failed computing trie Merkle root hash: %s", err) - return 0 + return []wasmer.Value{wasmer.NewI32(0)}, nil + } + + castedPtr, err := safeCastInt32(ptr) + if err != nil { + logger.Errorf("failed to safely cast pointer: %s", err) + return []wasmer.Value{wasmer.NewI32(0)}, err } logger.Debugf("root hash is %s", hash) copy(memory[ptr:ptr+32], hash[:]) - return C.int32_t(ptr) + return []wasmer.Value{wasmer.NewI32(castedPtr)}, nil } //export ext_trie_blake2_256_ordered_root_version_2 -func ext_trie_blake2_256_ordered_root_version_2(context unsafe.Pointer, - dataSpan C.int64_t, version C.int32_t) C.int32_t { +func ext_trie_blake2_256_ordered_root_version_2(env interface{}, args []wasmer.Value) ([]wasmer.Value, error) { // TODO: update to use state trie version 1 (#2418) - return ext_trie_blake2_256_ordered_root_version_1(context, dataSpan) + return ext_trie_blake2_256_ordered_root_version_1(env, args) } //export ext_trie_blake2_256_verify_proof_version_1 -func ext_trie_blake2_256_verify_proof_version_1(context unsafe.Pointer, - rootSpan C.int32_t, proofSpan, keySpan, valueSpan C.int64_t) C.int32_t { +func ext_trie_blake2_256_verify_proof_version_1(env interface{}, args []wasmer.Value) ([]wasmer.Value, error) { logger.Debug("executing...") - instanceContext := wasm.IntoInstanceContext(context) + instanceContext := env.(*runtime.Context) + rootSpan := args[0].I32() + proofSpan := args[1].I64() + keySpan := args[2].I64() + valueSpan := args[3].I64() toDecProofs := asMemorySlice(instanceContext, proofSpan) var encodedProofNodes [][]byte err := scale.Unmarshal(toDecProofs, &encodedProofNodes) if err != nil { logger.Errorf("failed scale decoding proof data: %s", err) - return C.int32_t(0) + return []wasmer.Value{wasmer.NewI32(0)}, nil } key := asMemorySlice(instanceContext, keySpan) value := asMemorySlice(instanceContext, valueSpan) - mem := instanceContext.Memory().Data() + mem := instanceContext.Memory.Data() trieRoot := mem[rootSpan : rootSpan+32] err = proof.Verify(encodedProofNodes, trieRoot, key, value) if err != nil { logger.Errorf("failed proof verification: %s", err) - return C.int32_t(0) + return []wasmer.Value{wasmer.NewI32(0)}, nil } - return C.int32_t(1) + return []wasmer.Value{wasmer.NewI32(1)}, nil } //export ext_misc_print_hex_version_1 -func ext_misc_print_hex_version_1(context unsafe.Pointer, dataSpan C.int64_t) { +func ext_misc_print_hex_version_1(env interface{}, args []wasmer.Value) ([]wasmer.Value, error) { logger.Trace("executing...") - instanceContext := wasm.IntoInstanceContext(context) - data := asMemorySlice(instanceContext, dataSpan) + ctx := env.(*runtime.Context) + dataSpan := args[0].I64() + data := asMemorySlice(ctx, dataSpan) logger.Debugf("data: 0x%x", data) + return nil, nil } //export ext_misc_print_num_version_1 -func ext_misc_print_num_version_1(_ unsafe.Pointer, data C.int64_t) { +func ext_misc_print_num_version_1(_ interface{}, args []wasmer.Value) ([]wasmer.Value, error) { logger.Trace("executing...") - - logger.Debugf("num: %d", int64(data)) + data := args[0].I64() + logger.Debugf("num: %d", data) + return nil, nil } //export ext_misc_print_utf8_version_1 -func ext_misc_print_utf8_version_1(context unsafe.Pointer, dataSpan C.int64_t) { +func ext_misc_print_utf8_version_1(env interface{}, args []wasmer.Value) ([]wasmer.Value, error) { logger.Trace("executing...") - instanceContext := wasm.IntoInstanceContext(context) - data := asMemorySlice(instanceContext, dataSpan) + ctx := env.(*runtime.Context) + dataSpan := args[0].I64() + data := asMemorySlice(ctx, dataSpan) logger.Debug("utf8: " + string(data)) + return nil, nil } //export ext_misc_runtime_version_version_1 -func ext_misc_runtime_version_version_1(context unsafe.Pointer, dataSpan C.int64_t) C.int64_t { +func ext_misc_runtime_version_version_1(env interface{}, args []wasmer.Value) ([]wasmer.Value, error) { logger.Trace("executing...") - instanceContext := wasm.IntoInstanceContext(context) + instanceContext := env.(*runtime.Context) + dataSpan := args[0].I64() code := asMemorySlice(instanceContext, dataSpan) version, err := GetRuntimeVersion(code) if err != nil { logger.Errorf("failed to get runtime version: %s", err) - return mustToWasmMemoryOptionalNil(instanceContext) + return mustToWasmMemoryOptionalNil(instanceContext), nil } // Note the encoding contains all the latest Core_version fields as defined in @@ -981,36 +962,40 @@ func ext_misc_runtime_version_version_1(context unsafe.Pointer, dataSpan C.int64 encodedData, err := scale.Marshal(version) if err != nil { logger.Errorf("failed to encode result: %s", err) - return 0 + return []wasmer.Value{wasmer.NewI64(0)}, nil } out, err := toWasmMemoryOptional(instanceContext, encodedData) if err != nil { logger.Errorf("failed to allocate: %s", err) - return 0 + return []wasmer.Value{wasmer.NewI64(0)}, nil } - return C.int64_t(out) + return []wasmer.Value{wasmer.NewI64(out)}, nil } //export ext_default_child_storage_read_version_1 -func ext_default_child_storage_read_version_1(context unsafe.Pointer, - childStorageKey, key, valueOut C.int64_t, offset C.int32_t) C.int64_t { +func ext_default_child_storage_read_version_1(env interface{}, args []wasmer.Value) ([]wasmer.Value, error) { logger.Debug("executing...") - instanceContext := wasm.IntoInstanceContext(context) - storage := instanceContext.Data().(*runtime.Context).Storage - memory := instanceContext.Memory().Data() + instanceContext := env.(*runtime.Context) + memory := instanceContext.Memory.Data() + storage := instanceContext.Storage + + childStorageKey := args[0].I64() + key := args[1].I64() + valueOut := args[2].I64() + offset := args[3].I32() keyToChild := asMemorySlice(instanceContext, childStorageKey) keyBytes := asMemorySlice(instanceContext, key) value, err := storage.GetChildStorage(keyToChild, keyBytes) if err != nil { logger.Errorf("failed to get child storage: %s", err) - return 0 + return []wasmer.Value{wasmer.NewI64(0)}, nil } - valueBuf, valueLen := splitPointerSize(int64(valueOut)) + valueBuf, valueLen := splitPointerSize(valueOut) copy(memory[valueBuf:valueBuf+valueLen], value[offset:]) size := uint32(len(value[offset:])) @@ -1020,19 +1005,20 @@ func ext_default_child_storage_read_version_1(context unsafe.Pointer, sizeSpan, err := toWasmMemoryOptional(instanceContext, sizeBuf) if err != nil { logger.Errorf("failed to allocate: %s", err) - return 0 + return []wasmer.Value{wasmer.NewI64(0)}, nil } - return C.int64_t(sizeSpan) + return []wasmer.Value{wasmer.NewI64(sizeSpan)}, nil } //export ext_default_child_storage_clear_version_1 -func ext_default_child_storage_clear_version_1(context unsafe.Pointer, childStorageKey, keySpan C.int64_t) { +func ext_default_child_storage_clear_version_1(env interface{}, args []wasmer.Value) ([]wasmer.Value, error) { logger.Debug("executing...") - instanceContext := wasm.IntoInstanceContext(context) - ctx := instanceContext.Data().(*runtime.Context) - storage := ctx.Storage + instanceContext := env.(*runtime.Context) + storage := instanceContext.Storage + childStorageKey := args[0].I64() + keySpan := args[1].I64() keyToChild := asMemorySlice(instanceContext, childStorageKey) key := asMemorySlice(instanceContext, keySpan) @@ -1041,15 +1027,17 @@ func ext_default_child_storage_clear_version_1(context unsafe.Pointer, childStor if err != nil { logger.Errorf("failed to clear child storage: %s", err) } + return nil, nil } //export ext_default_child_storage_clear_prefix_version_1 -func ext_default_child_storage_clear_prefix_version_1(context unsafe.Pointer, childStorageKey, prefixSpan C.int64_t) { +func ext_default_child_storage_clear_prefix_version_1(env interface{}, args []wasmer.Value) ([]wasmer.Value, error) { logger.Debug("executing...") - instanceContext := wasm.IntoInstanceContext(context) - ctx := instanceContext.Data().(*runtime.Context) - storage := ctx.Storage + instanceContext := env.(*runtime.Context) + storage := instanceContext.Storage + childStorageKey := args[0].I64() + prefixSpan := args[1].I64() keyToChild := asMemorySlice(instanceContext, childStorageKey) prefix := asMemorySlice(instanceContext, prefixSpan) @@ -1058,114 +1046,132 @@ func ext_default_child_storage_clear_prefix_version_1(context unsafe.Pointer, ch if err != nil { logger.Errorf("failed to clear prefix in child: %s", err) } + return nil, nil } //export ext_default_child_storage_exists_version_1 -func ext_default_child_storage_exists_version_1(context unsafe.Pointer, - childStorageKey, key C.int64_t) C.int32_t { +func ext_default_child_storage_exists_version_1(env interface{}, args []wasmer.Value) ([]wasmer.Value, error) { logger.Debug("executing...") - instanceContext := wasm.IntoInstanceContext(context) - storage := instanceContext.Data().(*runtime.Context).Storage + instanceContext := env.(*runtime.Context) + storage := instanceContext.Storage + + childStorageKey := args[0].I64() + key := args[1].I64() keyToChild := asMemorySlice(instanceContext, childStorageKey) keyBytes := asMemorySlice(instanceContext, key) child, err := storage.GetChildStorage(keyToChild, keyBytes) if err != nil { logger.Errorf("failed to get child from child storage: %s", err) - return 0 + return []wasmer.Value{wasmer.NewI32(0)}, nil } if child != nil { - return 1 + return []wasmer.Value{wasmer.NewI32(1)}, nil } - return 0 + return []wasmer.Value{wasmer.NewI32(0)}, nil } //export ext_default_child_storage_get_version_1 -func ext_default_child_storage_get_version_1(context unsafe.Pointer, childStorageKey, key C.int64_t) C.int64_t { +func ext_default_child_storage_get_version_1(env interface{}, args []wasmer.Value) ([]wasmer.Value, error) { logger.Debug("executing...") - instanceContext := wasm.IntoInstanceContext(context) - storage := instanceContext.Data().(*runtime.Context).Storage + instanceContext := env.(*runtime.Context) + storage := instanceContext.Storage + + childStorageKey := args[0].I64() + key := args[1].I64() keyToChild := asMemorySlice(instanceContext, childStorageKey) keyBytes := asMemorySlice(instanceContext, key) child, err := storage.GetChildStorage(keyToChild, keyBytes) if err != nil { logger.Errorf("failed to get child from child storage: %s", err) - return 0 + return []wasmer.Value{wasmer.NewI64(0)}, nil } value, err := toWasmMemoryOptional(instanceContext, child) if err != nil { logger.Errorf("failed to allocate: %s", err) - return 0 + return []wasmer.Value{wasmer.NewI64(0)}, nil } - return C.int64_t(value) + return []wasmer.Value{wasmer.NewI64(value)}, nil } //export ext_default_child_storage_next_key_version_1 -func ext_default_child_storage_next_key_version_1(context unsafe.Pointer, childStorageKey, key C.int64_t) C.int64_t { +func ext_default_child_storage_next_key_version_1(env interface{}, args []wasmer.Value) ([]wasmer.Value, error) { logger.Debug("executing...") - instanceContext := wasm.IntoInstanceContext(context) - storage := instanceContext.Data().(*runtime.Context).Storage + instanceContext := env.(*runtime.Context) + storage := instanceContext.Storage + + childStorageKey, ok := args[0].Unwrap().(int64) + if !ok { + panic("childStorageKey is not int64") + } + key, ok := args[1].Unwrap().(int64) + if !ok { + panic("key is not int64") + } keyToChild := asMemorySlice(instanceContext, childStorageKey) keyBytes := asMemorySlice(instanceContext, key) child, err := storage.GetChildNextKey(keyToChild, keyBytes) if err != nil { logger.Errorf("failed to get child's next key: %s", err) - return 0 + return []wasmer.Value{wasmer.NewI64(0)}, nil } value, err := toWasmMemoryOptional(instanceContext, child) if err != nil { logger.Errorf("failed to allocate: %s", err) - return 0 + return []wasmer.Value{wasmer.NewI64(0)}, nil } - return C.int64_t(value) + return []wasmer.Value{wasmer.NewI64(value)}, nil } //export ext_default_child_storage_root_version_1 -func ext_default_child_storage_root_version_1(context unsafe.Pointer, - childStorageKey C.int64_t) (ptrSize C.int64_t) { +func ext_default_child_storage_root_version_1(env interface{}, args []wasmer.Value) ([]wasmer.Value, error) { logger.Debug("executing...") - instanceContext := wasm.IntoInstanceContext(context) - storage := instanceContext.Data().(*runtime.Context).Storage + instanceContext := env.(*runtime.Context) + storage := instanceContext.Storage + + childStorageKey := args[0].I64() child, err := storage.GetChild(asMemorySlice(instanceContext, childStorageKey)) if err != nil { logger.Errorf("failed to retrieve child: %s", err) - return 0 + return []wasmer.Value{wasmer.NewI64(0)}, nil } childRoot, err := child.Hash() if err != nil { logger.Errorf("failed to encode child root: %s", err) - return 0 + return []wasmer.Value{wasmer.NewI64(0)}, nil } root, err := toWasmMemoryOptional(instanceContext, childRoot[:]) if err != nil { logger.Errorf("failed to allocate: %s", err) - return 0 + return []wasmer.Value{wasmer.NewI64(0)}, nil } - return C.int64_t(root) + return []wasmer.Value{wasmer.NewI64(root)}, nil } //export ext_default_child_storage_set_version_1 -func ext_default_child_storage_set_version_1(context unsafe.Pointer, - childStorageKeySpan, keySpan, valueSpan C.int64_t) { +func ext_default_child_storage_set_version_1(env interface{}, args []wasmer.Value) ([]wasmer.Value, error) { logger.Debug("executing...") - instanceContext := wasm.IntoInstanceContext(context) - ctx := instanceContext.Data().(*runtime.Context) - storage := ctx.Storage + instanceContext := env.(*runtime.Context) + storage := instanceContext.Storage + + childStorageKeySpan := args[0].I64() + keySpan := args[1].I64() + valueSpan := args[2].I64() childStorageKey := asMemorySlice(instanceContext, childStorageKeySpan) key := asMemorySlice(instanceContext, keySpan) @@ -1177,31 +1183,34 @@ func ext_default_child_storage_set_version_1(context unsafe.Pointer, err := storage.SetChildStorage(childStorageKey, key, cp) if err != nil { logger.Errorf("failed to set value in child storage: %s", err) - return + return nil, nil } + return nil, nil } //export ext_default_child_storage_storage_kill_version_1 -func ext_default_child_storage_storage_kill_version_1(context unsafe.Pointer, childStorageKeySpan C.int64_t) { +func ext_default_child_storage_storage_kill_version_1(env interface{}, args []wasmer.Value) ([]wasmer.Value, error) { logger.Debug("executing...") - instanceContext := wasm.IntoInstanceContext(context) - ctx := instanceContext.Data().(*runtime.Context) - storage := ctx.Storage + instanceContext := env.(*runtime.Context) + storage := instanceContext.Storage + childStorageKeySpan := args[0].I64() childStorageKey := asMemorySlice(instanceContext, childStorageKeySpan) err := storage.DeleteChild(childStorageKey) panicOnError(err) + return nil, nil } //export ext_default_child_storage_storage_kill_version_2 -func ext_default_child_storage_storage_kill_version_2(context unsafe.Pointer, - childStorageKeySpan, lim C.int64_t) (allDeleted C.int32_t) { +func ext_default_child_storage_storage_kill_version_2(env interface{}, args []wasmer.Value) ([]wasmer.Value, error) { logger.Debug("executing...") - instanceContext := wasm.IntoInstanceContext(context) - ctx := instanceContext.Data().(*runtime.Context) - storage := ctx.Storage + instanceContext := env.(*runtime.Context) + storage := instanceContext.Storage + childStorageKeySpan := args[0].I64() + lim := args[1].I64() + childStorageKey := asMemorySlice(instanceContext, childStorageKeySpan) limitBytes := asMemorySlice(instanceContext, lim) @@ -1210,7 +1219,7 @@ func ext_default_child_storage_storage_kill_version_2(context unsafe.Pointer, err := scale.Unmarshal(limitBytes, &limit) if err != nil { logger.Warnf("cannot generate limit: %s", err) - return 0 + return []wasmer.Value{wasmer.NewI32(0)}, nil } _, all, err := storage.DeleteChildLimit(childStorageKey, limit) @@ -1219,10 +1228,10 @@ func ext_default_child_storage_storage_kill_version_2(context unsafe.Pointer, } if all { - return 1 + return []wasmer.Value{wasmer.NewI32(1)}, nil } - return 0 + return []wasmer.Value{wasmer.NewI32(0)}, nil } type noneRemain uint32 @@ -1236,12 +1245,12 @@ func (someRemain) Index() uint { return 1 } func (sr someRemain) String() string { return fmt.Sprintf("someRemain(%d)", sr) } //export ext_default_child_storage_storage_kill_version_3 -func ext_default_child_storage_storage_kill_version_3(context unsafe.Pointer, - childStorageKeySpan, lim C.int64_t) (pointerSize C.int64_t) { +func ext_default_child_storage_storage_kill_version_3(env interface{}, args []wasmer.Value) ([]wasmer.Value, error) { logger.Debug("executing...") - instanceContext := wasm.IntoInstanceContext(context) - ctx := instanceContext.Data().(*runtime.Context) - storage := ctx.Storage + instanceContext := env.(*runtime.Context) + storage := instanceContext.Storage + childStorageKeySpan := args[0].I64() + lim := args[1].I64() childStorageKey := asMemorySlice(instanceContext, childStorageKeySpan) limitBytes := asMemorySlice(instanceContext, lim) @@ -1255,7 +1264,7 @@ func ext_default_child_storage_storage_kill_version_3(context unsafe.Pointer, deleted, all, err := storage.DeleteChildLimit(childStorageKey, limit) if err != nil { logger.Warnf("cannot get child storage: %s", err) - return C.int64_t(0) + return []wasmer.Value{wasmer.NewI64(0)}, nil } vdt, err := scale.NewVaryingDataType(noneRemain(0), someRemain(0)) @@ -1270,43 +1279,50 @@ func ext_default_child_storage_storage_kill_version_3(context unsafe.Pointer, } if err != nil { logger.Warnf("cannot set varying data type: %s", err) - return C.int64_t(0) + return []wasmer.Value{wasmer.NewI64(0)}, nil } encoded, err := scale.Marshal(vdt) if err != nil { logger.Warnf("problem marshalling varying data type: %s", err) - return C.int64_t(0) + return []wasmer.Value{wasmer.NewI64(0)}, nil } out, err := toWasmMemoryOptional(instanceContext, encoded) if err != nil { logger.Warnf("failed to allocate: %s", err) - return 0 + return []wasmer.Value{wasmer.NewI64(0)}, nil } - return C.int64_t(out) + return []wasmer.Value{wasmer.NewI64(out)}, nil } //export ext_allocator_free_version_1 -func ext_allocator_free_version_1(context unsafe.Pointer, addr C.int32_t) { +func ext_allocator_free_version_1(env interface{}, args []wasmer.Value) ([]wasmer.Value, error) { logger.Trace("executing...") - instanceContext := wasm.IntoInstanceContext(context) - runtimeCtx := instanceContext.Data().(*runtime.Context) + runtimeCtx := env.(*runtime.Context) + addr, ok := args[0].Unwrap().(int32) + if !ok { + logger.Criticalf("[ext_allocator_free_version_1]", "error", "addr cannot be converted to int32") + } // Deallocate memory err := runtimeCtx.Allocator.Deallocate(uint32(addr)) if err != nil { logger.Errorf("failed to free memory: %s", err) } + return nil, nil } //export ext_allocator_malloc_version_1 -func ext_allocator_malloc_version_1(context unsafe.Pointer, size C.int32_t) C.int32_t { +func ext_allocator_malloc_version_1(env interface{}, args []wasmer.Value) ([]wasmer.Value, error) { + size, ok := args[0].Unwrap().(int32) + if !ok { + logger.Criticalf("[ext_allocator_malloc_version_1]", "error", "addr cannot be converted to int32") + } logger.Tracef("executing with size %d...", int64(size)) - instanceContext := wasm.IntoInstanceContext(context) - ctx := instanceContext.Data().(*runtime.Context) + ctx := env.(*runtime.Context) // Allocate memory res, err := ctx.Allocator.Allocate(uint32(size)) @@ -1315,20 +1331,26 @@ func ext_allocator_malloc_version_1(context unsafe.Pointer, size C.int32_t) C.in panic(err) } - return C.int32_t(res) + castedRes, err := safeCastInt32(res) + if err != nil { + logger.Errorf("failed to safely cast pointer: %s", err) + return []wasmer.Value{wasmer.NewI32(0)}, err + } + + return []wasmer.Value{wasmer.NewI32(castedRes)}, nil } //export ext_hashing_blake2_128_version_1 -func ext_hashing_blake2_128_version_1(context unsafe.Pointer, dataSpan C.int64_t) C.int32_t { +func ext_hashing_blake2_128_version_1(env interface{}, args []wasmer.Value) ([]wasmer.Value, error) { logger.Trace("executing...") - instanceContext := wasm.IntoInstanceContext(context) - + instanceContext := env.(*runtime.Context) + dataSpan := args[0].I64() data := asMemorySlice(instanceContext, dataSpan) hash, err := common.Blake2b128(data) if err != nil { logger.Errorf("failed hashing data: %s", err) - return 0 + return []wasmer.Value{wasmer.NewI32(int32(0))}, nil } logger.Debugf( @@ -1338,23 +1360,29 @@ func ext_hashing_blake2_128_version_1(context unsafe.Pointer, dataSpan C.int64_t out, err := toWasmMemorySized(instanceContext, hash) if err != nil { logger.Errorf("failed to allocate: %s", err) - return 0 + return []wasmer.Value{wasmer.NewI32(int32(0))}, nil + } + + castedOut, err := safeCastInt32(out) + if err != nil { + logger.Errorf("failed to safely cast pointer: %s", err) + return []wasmer.Value{wasmer.NewI32(0)}, err } - return C.int32_t(out) + return []wasmer.Value{wasmer.NewI32(castedOut)}, nil } //export ext_hashing_blake2_256_version_1 -func ext_hashing_blake2_256_version_1(context unsafe.Pointer, dataSpan C.int64_t) C.int32_t { +func ext_hashing_blake2_256_version_1(env interface{}, args []wasmer.Value) ([]wasmer.Value, error) { logger.Trace("executing...") - instanceContext := wasm.IntoInstanceContext(context) - + instanceContext := env.(*runtime.Context) + dataSpan := args[0].I64() data := asMemorySlice(instanceContext, dataSpan) hash, err := common.Blake2bHash(data) if err != nil { logger.Errorf("failed hashing data: %s", err) - return 0 + return []wasmer.Value{wasmer.NewI32(int32(0))}, nil } logger.Debugf("data 0x%x has hash %s", data, hash) @@ -1362,23 +1390,29 @@ func ext_hashing_blake2_256_version_1(context unsafe.Pointer, dataSpan C.int64_t out, err := toWasmMemorySized(instanceContext, hash[:]) if err != nil { logger.Errorf("failed to allocate: %s", err) - return 0 + return []wasmer.Value{wasmer.NewI32(int32(0))}, nil } - return C.int32_t(out) + castedOut, err := safeCastInt32(out) + if err != nil { + logger.Errorf("failed to safely cast pointer: %s", err) + return []wasmer.Value{wasmer.NewI32(0)}, err + } + + return []wasmer.Value{wasmer.NewI32(castedOut)}, nil } //export ext_hashing_keccak_256_version_1 -func ext_hashing_keccak_256_version_1(context unsafe.Pointer, dataSpan C.int64_t) C.int32_t { +func ext_hashing_keccak_256_version_1(env interface{}, args []wasmer.Value) ([]wasmer.Value, error) { logger.Trace("executing...") - instanceContext := wasm.IntoInstanceContext(context) - + instanceContext := env.(*runtime.Context) + dataSpan := args[0].I64() data := asMemorySlice(instanceContext, dataSpan) hash, err := common.Keccak256(data) if err != nil { logger.Errorf("failed hashing data: %s", err) - return 0 + return []wasmer.Value{wasmer.NewI32(int32(0))}, nil } logger.Debugf("data 0x%x has hash %s", data, hash) @@ -1386,17 +1420,23 @@ func ext_hashing_keccak_256_version_1(context unsafe.Pointer, dataSpan C.int64_t out, err := toWasmMemorySized(instanceContext, hash[:]) if err != nil { logger.Errorf("failed to allocate: %s", err) - return 0 + return []wasmer.Value{wasmer.NewI32(int32(0))}, nil + } + + castedOut, err := safeCastInt32(out) + if err != nil { + logger.Errorf("failed to safely cast pointer: %s", err) + return []wasmer.Value{wasmer.NewI32(0)}, err } - return C.int32_t(out) + return []wasmer.Value{wasmer.NewI32(castedOut)}, nil } //export ext_hashing_sha2_256_version_1 -func ext_hashing_sha2_256_version_1(context unsafe.Pointer, dataSpan C.int64_t) C.int32_t { +func ext_hashing_sha2_256_version_1(env interface{}, args []wasmer.Value) ([]wasmer.Value, error) { logger.Trace("executing...") - instanceContext := wasm.IntoInstanceContext(context) - + instanceContext := env.(*runtime.Context) + dataSpan := args[0].I64() data := asMemorySlice(instanceContext, dataSpan) hash := common.Sha256(data) @@ -1405,23 +1445,29 @@ func ext_hashing_sha2_256_version_1(context unsafe.Pointer, dataSpan C.int64_t) out, err := toWasmMemorySized(instanceContext, hash[:]) if err != nil { logger.Errorf("failed to allocate: %s", err) - return 0 + return []wasmer.Value{wasmer.NewI32(int32(0))}, nil + } + + castedOut, err := safeCastInt32(out) + if err != nil { + logger.Errorf("failed to safely cast pointer: %s", err) + return []wasmer.Value{wasmer.NewI32(0)}, err } - return C.int32_t(out) + return []wasmer.Value{wasmer.NewI32(castedOut)}, nil } //export ext_hashing_twox_256_version_1 -func ext_hashing_twox_256_version_1(context unsafe.Pointer, dataSpan C.int64_t) C.int32_t { +func ext_hashing_twox_256_version_1(env interface{}, args []wasmer.Value) ([]wasmer.Value, error) { logger.Trace("executing...") - instanceContext := wasm.IntoInstanceContext(context) - + instanceContext := env.(*runtime.Context) + dataSpan := args[0].I64() data := asMemorySlice(instanceContext, dataSpan) hash, err := common.Twox256(data) if err != nil { logger.Errorf("failed hashing data: %s", err) - return 0 + return []wasmer.Value{wasmer.NewI32(int32(0))}, nil } logger.Debugf("data 0x%x has hash %s", data, hash) @@ -1429,22 +1475,29 @@ func ext_hashing_twox_256_version_1(context unsafe.Pointer, dataSpan C.int64_t) out, err := toWasmMemorySized(instanceContext, hash[:]) if err != nil { logger.Errorf("failed to allocate: %s", err) - return 0 + return []wasmer.Value{wasmer.NewI32(int32(0))}, nil + } + + castedOut, err := safeCastInt32(out) + if err != nil { + logger.Errorf("failed to safely cast pointer: %s", err) + return []wasmer.Value{wasmer.NewI32(0)}, err } - return C.int32_t(out) + return []wasmer.Value{wasmer.NewI32(castedOut)}, nil } //export ext_hashing_twox_128_version_1 -func ext_hashing_twox_128_version_1(context unsafe.Pointer, dataSpan C.int64_t) C.int32_t { +func ext_hashing_twox_128_version_1(env interface{}, args []wasmer.Value) ([]wasmer.Value, error) { logger.Trace("executing...") - instanceContext := wasm.IntoInstanceContext(context) + instanceContext := env.(*runtime.Context) + dataSpan := args[0].I64() data := asMemorySlice(instanceContext, dataSpan) hash, err := common.Twox128Hash(data) if err != nil { logger.Errorf("failed hashing data: %s", err) - return 0 + return []wasmer.Value{wasmer.NewI32(int32(0))}, nil } logger.Debugf( @@ -1454,23 +1507,29 @@ func ext_hashing_twox_128_version_1(context unsafe.Pointer, dataSpan C.int64_t) out, err := toWasmMemorySized(instanceContext, hash) if err != nil { logger.Errorf("failed to allocate: %s", err) - return 0 + return []wasmer.Value{wasmer.NewI32(int32(0))}, nil } - return C.int32_t(out) + castedOut, err := safeCastInt32(out) + if err != nil { + logger.Errorf("failed to safely cast pointer: %s", err) + return []wasmer.Value{wasmer.NewI32(0)}, err + } + + return []wasmer.Value{wasmer.NewI32(castedOut)}, nil } //export ext_hashing_twox_64_version_1 -func ext_hashing_twox_64_version_1(context unsafe.Pointer, dataSpan C.int64_t) C.int32_t { +func ext_hashing_twox_64_version_1(env interface{}, args []wasmer.Value) ([]wasmer.Value, error) { logger.Trace("executing...") - instanceContext := wasm.IntoInstanceContext(context) - + instanceContext := env.(*runtime.Context) + dataSpan := args[0].I64() data := asMemorySlice(instanceContext, dataSpan) hash, err := common.Twox64(data) if err != nil { logger.Errorf("failed hashing data: %s", err) - return 0 + return []wasmer.Value{wasmer.NewI32(int32(0))}, nil } logger.Debugf( @@ -1480,75 +1539,86 @@ func ext_hashing_twox_64_version_1(context unsafe.Pointer, dataSpan C.int64_t) C out, err := toWasmMemorySized(instanceContext, hash) if err != nil { logger.Errorf("failed to allocate: %s", err) - return 0 + return []wasmer.Value{wasmer.NewI32(int32(0))}, nil } - return C.int32_t(out) + castedOut, err := safeCastInt32(out) + if err != nil { + logger.Errorf("failed to safely cast pointer: %s", err) + return []wasmer.Value{wasmer.NewI32(0)}, err + } + + return []wasmer.Value{wasmer.NewI32(castedOut)}, nil } //export ext_offchain_index_set_version_1 -func ext_offchain_index_set_version_1(context unsafe.Pointer, keySpan, valueSpan C.int64_t) { +func ext_offchain_index_set_version_1(env interface{}, args []wasmer.Value) ([]wasmer.Value, error) { logger.Trace("executing...") - instanceContext := wasm.IntoInstanceContext(context) - runtimeCtx := instanceContext.Data().(*runtime.Context) + instanceContext := env.(*runtime.Context) + keySpan := args[0].I64() + valueSpan := args[1].I64() storageKey := asMemorySlice(instanceContext, keySpan) newValue := asMemorySlice(instanceContext, valueSpan) cp := make([]byte, len(newValue)) copy(cp, newValue) - err := runtimeCtx.NodeStorage.BaseDB.Put(storageKey, cp) + err := instanceContext.NodeStorage.BaseDB.Put(storageKey, cp) if err != nil { logger.Errorf("failed to set value in raw storage: %s", err) } + return nil, nil } //export ext_offchain_local_storage_clear_version_1 -func ext_offchain_local_storage_clear_version_1(context unsafe.Pointer, kind C.int32_t, key C.int64_t) { +func ext_offchain_local_storage_clear_version_1(env interface{}, args []wasmer.Value) ([]wasmer.Value, error) { logger.Trace("executing...") - instanceContext := wasm.IntoInstanceContext(context) - runtimeCtx := instanceContext.Data().(*runtime.Context) + instanceContext := env.(*runtime.Context) + kind := args[0].I32() + key := args[1].I64() storageKey := asMemorySlice(instanceContext, key) - memory := instanceContext.Memory().Data() + memory := instanceContext.Memory.Data() kindInt := binary.LittleEndian.Uint32(memory[kind : kind+4]) var err error switch runtime.NodeStorageType(kindInt) { case runtime.NodeStorageTypePersistent: - err = runtimeCtx.NodeStorage.PersistentStorage.Del(storageKey) + err = instanceContext.NodeStorage.PersistentStorage.Del(storageKey) case runtime.NodeStorageTypeLocal: - err = runtimeCtx.NodeStorage.LocalStorage.Del(storageKey) + err = instanceContext.NodeStorage.LocalStorage.Del(storageKey) } if err != nil { logger.Errorf("failed to clear value from storage: %s", err) } + return nil, nil } //export ext_offchain_is_validator_version_1 -func ext_offchain_is_validator_version_1(context unsafe.Pointer) C.int32_t { +func ext_offchain_is_validator_version_1(env interface{}, _ []wasmer.Value) ([]wasmer.Value, error) { logger.Debug("executing...") - instanceContext := wasm.IntoInstanceContext(context) - - runtimeCtx := instanceContext.Data().(*runtime.Context) - if runtimeCtx.Validator { - return 1 + instanceContext := env.(*runtime.Context) + if instanceContext.Validator { + return []wasmer.Value{wasmer.NewI32(int32(1))}, nil } - return 0 + return []wasmer.Value{wasmer.NewI32(int32(0))}, nil } //export ext_offchain_local_storage_compare_and_set_version_1 -func ext_offchain_local_storage_compare_and_set_version_1(context unsafe.Pointer, - kind C.int32_t, key, oldValue, newValue C.int64_t) (newValueSet C.int32_t) { +func ext_offchain_local_storage_compare_and_set_version_1(env interface{}, + args []wasmer.Value) ([]wasmer.Value, error) { logger.Debug("executing...") - instanceContext := wasm.IntoInstanceContext(context) - runtimeCtx := instanceContext.Data().(*runtime.Context) + runtimeCtx := env.(*runtime.Context) + kind := args[0].I32() + key := args[1].I64() + oldValue := args[2].I64() + newValue := args[3].I64() - storageKey := asMemorySlice(instanceContext, key) + storageKey := asMemorySlice(runtimeCtx, key) var storedValue []byte var err error @@ -1562,31 +1632,32 @@ func ext_offchain_local_storage_compare_and_set_version_1(context unsafe.Pointer if err != nil { logger.Errorf("failed to get value from storage: %s", err) - return 0 + return []wasmer.Value{wasmer.NewI32(int32(0))}, nil } - oldVal := asMemorySlice(instanceContext, oldValue) - newVal := asMemorySlice(instanceContext, newValue) + oldVal := asMemorySlice(runtimeCtx, oldValue) + newVal := asMemorySlice(runtimeCtx, newValue) if reflect.DeepEqual(storedValue, oldVal) { cp := make([]byte, len(newVal)) copy(cp, newVal) err = runtimeCtx.NodeStorage.LocalStorage.Put(storageKey, cp) if err != nil { logger.Errorf("failed to set value in storage: %s", err) - return 0 + return []wasmer.Value{wasmer.NewI32(int32(0))}, nil } } - return 1 + return []wasmer.Value{wasmer.NewI32(int32(1))}, nil } //export ext_offchain_local_storage_get_version_1 -func ext_offchain_local_storage_get_version_1(context unsafe.Pointer, kind C.int32_t, key C.int64_t) C.int64_t { +func ext_offchain_local_storage_get_version_1(env interface{}, args []wasmer.Value) ([]wasmer.Value, error) { logger.Debug("executing...") - instanceContext := wasm.IntoInstanceContext(context) - runtimeCtx := instanceContext.Data().(*runtime.Context) - storageKey := asMemorySlice(instanceContext, key) + runtimeCtx := env.(*runtime.Context) + kind := args[0].I32() + key := args[1].I64() + storageKey := asMemorySlice(runtimeCtx, key) var res []byte var err error @@ -1602,22 +1673,26 @@ func ext_offchain_local_storage_get_version_1(context unsafe.Pointer, kind C.int logger.Errorf("failed to get value from storage: %s", err) } // allocate memory for value and copy value to memory - ptr, err := toWasmMemoryOptional(instanceContext, res) + ptr, err := toWasmMemoryOptional(runtimeCtx, res) if err != nil { logger.Errorf("failed to allocate memory: %s", err) - return 0 + return []wasmer.Value{wasmer.NewI64(int64(0))}, nil } - return C.int64_t(ptr) + + return []wasmer.Value{wasmer.NewI64(ptr)}, nil } //export ext_offchain_local_storage_set_version_1 -func ext_offchain_local_storage_set_version_1(context unsafe.Pointer, kind C.int32_t, key, value C.int64_t) { +func ext_offchain_local_storage_set_version_1(env interface{}, args []wasmer.Value) ([]wasmer.Value, error) { logger.Debug("executing...") - instanceContext := wasm.IntoInstanceContext(context) - runtimeCtx := instanceContext.Data().(*runtime.Context) - storageKey := asMemorySlice(instanceContext, key) - newValue := asMemorySlice(instanceContext, value) + runtimeCtx := env.(*runtime.Context) + kind := args[0].I32() + key := args[1].I64() + value := args[2].I64() + + storageKey := asMemorySlice(runtimeCtx, key) + newValue := asMemorySlice(runtimeCtx, value) cp := make([]byte, len(newValue)) copy(cp, newValue) @@ -1632,40 +1707,40 @@ func ext_offchain_local_storage_set_version_1(context unsafe.Pointer, kind C.int if err != nil { logger.Errorf("failed to set value in storage: %s", err) } + return nil, nil } //export ext_offchain_network_state_version_1 -func ext_offchain_network_state_version_1(context unsafe.Pointer) C.int64_t { +func ext_offchain_network_state_version_1(env interface{}, _ []wasmer.Value) ([]wasmer.Value, error) { logger.Debug("executing...") - instanceContext := wasm.IntoInstanceContext(context) - runtimeCtx := instanceContext.Data().(*runtime.Context) + runtimeCtx := env.(*runtime.Context) if runtimeCtx.Network == nil { - return 0 + return []wasmer.Value{wasmer.NewI64(int64(0))}, nil } nsEnc, err := scale.Marshal(runtimeCtx.Network.NetworkState()) if err != nil { logger.Errorf("failed at encoding network state: %s", err) - return 0 + return []wasmer.Value{wasmer.NewI64(int64(0))}, nil } // allocate memory for value and copy value to memory - ptr, err := toWasmMemorySized(instanceContext, nsEnc) + ptr, err := toWasmMemorySized(runtimeCtx, nsEnc) if err != nil { logger.Errorf("failed to allocate memory: %s", err) - return 0 + return []wasmer.Value{wasmer.NewI64(int64(0))}, nil } - return C.int64_t(ptr) + return []wasmer.Value{wasmer.NewI64(int64(ptr))}, nil } //export ext_offchain_random_seed_version_1 -func ext_offchain_random_seed_version_1(context unsafe.Pointer) C.int32_t { +func ext_offchain_random_seed_version_1(env interface{}, _ []wasmer.Value) ([]wasmer.Value, error) { logger.Debug("executing...") - instanceContext := wasm.IntoInstanceContext(context) + instanceContext := env.(*runtime.Context) seed := make([]byte, 32) - _, err := rand.Read(seed) + _, err := rand.Read(seed) //nolint if err != nil { logger.Errorf("failed to generate random seed: %s", err) } @@ -1673,14 +1748,22 @@ func ext_offchain_random_seed_version_1(context unsafe.Pointer) C.int32_t { if err != nil { logger.Errorf("failed to allocate memory: %s", err) } - return C.int32_t(ptr) + + castedPtr, err := safeCastInt32(ptr) + if err != nil { + logger.Errorf("failed to safely cast pointer: %s", err) + return []wasmer.Value{wasmer.NewI32(0)}, err + } + + return []wasmer.Value{wasmer.NewI32(castedPtr)}, nil } //export ext_offchain_submit_transaction_version_1 -func ext_offchain_submit_transaction_version_1(context unsafe.Pointer, data C.int64_t) C.int64_t { +func ext_offchain_submit_transaction_version_1(env interface{}, args []wasmer.Value) ([]wasmer.Value, error) { logger.Debug("executing...") - instanceContext := wasm.IntoInstanceContext(context) + instanceContext := env.(*runtime.Context) + data := args[0].I64() extBytes := asMemorySlice(instanceContext, data) var extrinsic []byte @@ -1693,48 +1776,49 @@ func ext_offchain_submit_transaction_version_1(context unsafe.Pointer, data C.in txv := transaction.NewValidity(0, [][]byte{{}}, [][]byte{{}}, 0, false) vtx := transaction.NewValidTransaction(extrinsic, txv) - runtimeCtx := instanceContext.Data().(*runtime.Context) - runtimeCtx.Transaction.AddToPool(vtx) + instanceContext.Transaction.AddToPool(vtx) ptr, err := toWasmMemoryOptionalNil(instanceContext) if err != nil { logger.Errorf("failed to allocate memory: %s", err) } - return ptr + return ptr, nil } //export ext_offchain_timestamp_version_1 -func ext_offchain_timestamp_version_1(_ unsafe.Pointer) C.int64_t { +func ext_offchain_timestamp_version_1(_ interface{}, _ []wasmer.Value) ([]wasmer.Value, error) { logger.Trace("executing...") now := time.Now().Unix() - return C.int64_t(now) + return []wasmer.Value{wasmer.NewI64(now)}, nil } //export ext_offchain_sleep_until_version_1 -func ext_offchain_sleep_until_version_1(_ unsafe.Pointer, deadline C.int64_t) { +func ext_offchain_sleep_until_version_1(_ interface{}, args []wasmer.Value) ([]wasmer.Value, error) { logger.Trace("executing...") - - dur := time.Until(time.UnixMilli(int64(deadline))) + deadline := args[0].I64() + dur := time.Until(time.UnixMilli(deadline)) if dur > 0 { time.Sleep(dur) } + return nil, nil } //export ext_offchain_http_request_start_version_1 -func ext_offchain_http_request_start_version_1(context unsafe.Pointer, - methodSpan, uriSpan, metaSpan C.int64_t) (pointerSize C.int64_t) { +func ext_offchain_http_request_start_version_1(env interface{}, args []wasmer.Value) ([]wasmer.Value, error) { logger.Debug("executing...") - instanceContext := wasm.IntoInstanceContext(context) - runtimeCtx := instanceContext.Data().(*runtime.Context) + instanceContext := env.(*runtime.Context) + methodSpan := args[0].I64() + uriSpan := args[1].I64() + _ = args[2].I64() // metaSpan - unused httpMethod := asMemorySlice(instanceContext, methodSpan) uri := asMemorySlice(instanceContext, uriSpan) result := scale.NewResult(int16(0), nil) - reqID, err := runtimeCtx.OffchainHTTPSet.StartRequest(string(httpMethod), string(uri)) + reqID, err := instanceContext.OffchainHTTPSet.StartRequest(string(httpMethod), string(uri)) if err != nil { // StartRequest error already was logged logger.Errorf("failed to start request: %s", err) @@ -1746,35 +1830,36 @@ func ext_offchain_http_request_start_version_1(context unsafe.Pointer, // note: just check if an error occurs while setting the result data if err != nil { logger.Errorf("failed to set the result data: %s", err) - return C.int64_t(0) + return []wasmer.Value{wasmer.NewI64(int64(0))}, nil } enc, err := scale.Marshal(result) if err != nil { logger.Errorf("failed to scale marshal the result: %s", err) - return C.int64_t(0) + return []wasmer.Value{wasmer.NewI64(int64(0))}, nil } ptr, err := toWasmMemory(instanceContext, enc) if err != nil { logger.Errorf("failed to allocate result on memory: %s", err) - return C.int64_t(0) + return []wasmer.Value{wasmer.NewI64(int64(0))}, nil } - return C.int64_t(ptr) + return []wasmer.Value{wasmer.NewI64(ptr)}, nil } //export ext_offchain_http_request_add_header_version_1 -func ext_offchain_http_request_add_header_version_1(context unsafe.Pointer, - reqID C.int32_t, nameSpan, valueSpan C.int64_t) (pointerSize C.int64_t) { +func ext_offchain_http_request_add_header_version_1(env interface{}, args []wasmer.Value) ([]wasmer.Value, error) { logger.Debug("executing...") - instanceContext := wasm.IntoInstanceContext(context) + instanceContext := env.(*runtime.Context) + reqID := args[0].I32() + nameSpan := args[1].I64() + valueSpan := args[2].I64() name := asMemorySlice(instanceContext, nameSpan) value := asMemorySlice(instanceContext, valueSpan) - runtimeCtx := instanceContext.Data().(*runtime.Context) - offchainReq := runtimeCtx.OffchainHTTPSet.Get(int16(reqID)) + offchainReq := instanceContext.OffchainHTTPSet.Get(int16(reqID)) result := scale.NewResult(nil, nil) resultMode := scale.OK @@ -1788,30 +1873,31 @@ func ext_offchain_http_request_add_header_version_1(context unsafe.Pointer, err = result.Set(resultMode, nil) if err != nil { logger.Errorf("failed to set the result data: %s", err) - return C.int64_t(0) + return []wasmer.Value{wasmer.NewI64(int64(0))}, nil } enc, err := scale.Marshal(result) if err != nil { logger.Errorf("failed to scale marshal the result: %s", err) - return C.int64_t(0) + return []wasmer.Value{wasmer.NewI64(int64(0))}, nil } ptr, err := toWasmMemory(instanceContext, enc) if err != nil { logger.Errorf("failed to allocate result on memory: %s", err) - return C.int64_t(0) + return []wasmer.Value{wasmer.NewI64(int64(0))}, nil } - return C.int64_t(ptr) + return []wasmer.Value{wasmer.NewI64(ptr)}, nil } //export ext_storage_append_version_1 -func ext_storage_append_version_1(context unsafe.Pointer, keySpan, valueSpan C.int64_t) { +func ext_storage_append_version_1(env interface{}, args []wasmer.Value) ([]wasmer.Value, error) { logger.Trace("executing...") - instanceContext := wasm.IntoInstanceContext(context) - ctx := instanceContext.Data().(*runtime.Context) - storage := ctx.Storage + instanceContext := env.(*runtime.Context) + keySpan := args[0].I64() + valueSpan := args[1].I64() + storage := instanceContext.Storage key := asMemorySlice(instanceContext, keySpan) valueAppend := asMemorySlice(instanceContext, valueSpan) @@ -1826,59 +1912,64 @@ func ext_storage_append_version_1(context unsafe.Pointer, keySpan, valueSpan C.i if err != nil { logger.Errorf("failed appending to storage: %s", err) } + return nil, nil } //export ext_storage_changes_root_version_1 -func ext_storage_changes_root_version_1(context unsafe.Pointer, parentHashSpan C.int64_t) C.int64_t { +func ext_storage_changes_root_version_1(env interface{}, args []wasmer.Value) ([]wasmer.Value, error) { logger.Trace("executing...") logger.Debug("returning None") - instanceContext := wasm.IntoInstanceContext(context) + instanceContext := env.(*runtime.Context) + _ = args[0].I64() // parentHashSpan - unused rootSpan, err := toWasmMemoryOptionalNil(instanceContext) if err != nil { logger.Errorf("failed to allocate: %s", err) - return 0 + return []wasmer.Value{wasmer.NewI64(int64(0))}, nil } - return rootSpan + return rootSpan, nil } //export ext_storage_clear_version_1 -func ext_storage_clear_version_1(context unsafe.Pointer, keySpan C.int64_t) { +func ext_storage_clear_version_1(env interface{}, args []wasmer.Value) ([]wasmer.Value, error) { logger.Trace("executing...") - instanceContext := wasm.IntoInstanceContext(context) - ctx := instanceContext.Data().(*runtime.Context) - storage := ctx.Storage + instanceContext := env.(*runtime.Context) + keySpan := args[0].I64() + storage := instanceContext.Storage key := asMemorySlice(instanceContext, keySpan) logger.Debugf("key: 0x%x", key) err := storage.Delete(key) panicOnError(err) + return nil, nil } //export ext_storage_clear_prefix_version_1 -func ext_storage_clear_prefix_version_1(context unsafe.Pointer, prefixSpan C.int64_t) { +func ext_storage_clear_prefix_version_1(env interface{}, args []wasmer.Value) ([]wasmer.Value, error) { logger.Trace("executing...") - instanceContext := wasm.IntoInstanceContext(context) - ctx := instanceContext.Data().(*runtime.Context) - storage := ctx.Storage + instanceContext := env.(*runtime.Context) + prefixSpan := args[0].I64() + storage := instanceContext.Storage prefix := asMemorySlice(instanceContext, prefixSpan) logger.Debugf("prefix: 0x%x", prefix) err := storage.ClearPrefix(prefix) panicOnError(err) + return nil, nil } //export ext_storage_clear_prefix_version_2 -func ext_storage_clear_prefix_version_2(context unsafe.Pointer, prefixSpan, lim C.int64_t) C.int64_t { +func ext_storage_clear_prefix_version_2(env interface{}, args []wasmer.Value) ([]wasmer.Value, error) { logger.Trace("executing...") - instanceContext := wasm.IntoInstanceContext(context) - ctx := instanceContext.Data().(*runtime.Context) - storage := ctx.Storage + instanceContext := env.(*runtime.Context) + prefixSpan := args[0].I64() + lim := args[1].I64() + storage := instanceContext.Storage prefix := asMemorySlice(instanceContext, prefixSpan) logger.Debugf("prefix: 0x%x", prefix) @@ -1889,7 +1980,7 @@ func ext_storage_clear_prefix_version_2(context unsafe.Pointer, prefixSpan, lim err := scale.Unmarshal(limitBytes, &limit) if err != nil { logger.Warnf("failed scale decoding limit: %s", err) - return mustToWasmMemoryNil(instanceContext) + return mustToWasmMemoryNil(instanceContext), nil } if len(limit) == 0 { @@ -1901,47 +1992,49 @@ func ext_storage_clear_prefix_version_2(context unsafe.Pointer, prefixSpan, lim numRemoved, all, err := storage.ClearPrefixLimit(prefix, limitUint) if err != nil { logger.Errorf("failed to clear prefix limit: %s", err) - return mustToWasmMemoryNil(instanceContext) + return mustToWasmMemoryNil(instanceContext), nil } encBytes, err := toKillStorageResultEnum(all, numRemoved) if err != nil { logger.Errorf("failed to allocate memory: %s", err) - return mustToWasmMemoryNil(instanceContext) + return mustToWasmMemoryNil(instanceContext), nil } valueSpan, err := toWasmMemory(instanceContext, encBytes) if err != nil { logger.Errorf("failed to allocate: %s", err) - return mustToWasmMemoryNil(instanceContext) + return mustToWasmMemoryNil(instanceContext), nil } - return C.int64_t(valueSpan) + return []wasmer.Value{wasmer.NewI64(valueSpan)}, nil } //export ext_storage_exists_version_1 -func ext_storage_exists_version_1(context unsafe.Pointer, keySpan C.int64_t) C.int32_t { +func ext_storage_exists_version_1(env interface{}, args []wasmer.Value) ([]wasmer.Value, error) { logger.Trace("executing...") - instanceContext := wasm.IntoInstanceContext(context) - storage := instanceContext.Data().(*runtime.Context).Storage + instanceContext := env.(*runtime.Context) + keySpan := args[0].I64() + storage := instanceContext.Storage key := asMemorySlice(instanceContext, keySpan) logger.Debugf("key: 0x%x", key) value := storage.Get(key) if value != nil { - return 1 + return []wasmer.Value{wasmer.NewI32(int32(1))}, nil } - return 0 + return []wasmer.Value{wasmer.NewI32(int32(0))}, nil } //export ext_storage_get_version_1 -func ext_storage_get_version_1(context unsafe.Pointer, keySpan C.int64_t) C.int64_t { +func ext_storage_get_version_1(env interface{}, args []wasmer.Value) ([]wasmer.Value, error) { logger.Trace("executing...") - instanceContext := wasm.IntoInstanceContext(context) - storage := instanceContext.Data().(*runtime.Context).Storage + instanceContext := env.(*runtime.Context) + keySpan := args[0].I64() + storage := instanceContext.Storage key := asMemorySlice(instanceContext, keySpan) logger.Debugf("key: 0x%x", key) @@ -1952,18 +2045,19 @@ func ext_storage_get_version_1(context unsafe.Pointer, keySpan C.int64_t) C.int6 valueSpan, err := toWasmMemoryOptional(instanceContext, value) if err != nil { logger.Errorf("failed to allocate: %s", err) - return mustToWasmMemoryOptionalNil(instanceContext) + return mustToWasmMemoryOptionalNil(instanceContext), nil } - return C.int64_t(valueSpan) + return []wasmer.Value{wasmer.NewI64(valueSpan)}, nil } //export ext_storage_next_key_version_1 -func ext_storage_next_key_version_1(context unsafe.Pointer, keySpan C.int64_t) C.int64_t { +func ext_storage_next_key_version_1(env interface{}, args []wasmer.Value) ([]wasmer.Value, error) { logger.Trace("executing...") - instanceContext := wasm.IntoInstanceContext(context) - storage := instanceContext.Data().(*runtime.Context).Storage + instanceContext := env.(*runtime.Context) + keySpan := args[0].I64() + storage := instanceContext.Storage key := asMemorySlice(instanceContext, keySpan) @@ -1975,19 +2069,22 @@ func ext_storage_next_key_version_1(context unsafe.Pointer, keySpan C.int64_t) C nextSpan, err := toWasmMemoryOptional(instanceContext, next) if err != nil { logger.Errorf("failed to allocate: %s", err) - return 0 + return []wasmer.Value{wasmer.NewI64(0)}, nil } - return C.int64_t(nextSpan) + return []wasmer.Value{wasmer.NewI64(nextSpan)}, nil } //export ext_storage_read_version_1 -func ext_storage_read_version_1(context unsafe.Pointer, keySpan, valueOut C.int64_t, offset C.int32_t) C.int64_t { +func ext_storage_read_version_1(env interface{}, args []wasmer.Value) ([]wasmer.Value, error) { logger.Trace("executing...") - instanceContext := wasm.IntoInstanceContext(context) - storage := instanceContext.Data().(*runtime.Context).Storage - memory := instanceContext.Memory().Data() + instanceContext := env.(*runtime.Context) + keySpan := args[0].I64() + valueOut := args[1].I64() + offset := args[2].I32() + storage := instanceContext.Storage + memory := instanceContext.Memory.Data() key := asMemorySlice(instanceContext, keySpan) value := storage.Get(key) @@ -1996,36 +2093,37 @@ func ext_storage_read_version_1(context unsafe.Pointer, keySpan, valueOut C.int6 key, value) if value == nil { - return mustToWasmMemoryOptionalNil(instanceContext) + + return mustToWasmMemoryOptionalNil(instanceContext), nil } var size uint32 if uint32(offset) <= uint32(len(value)) { size = uint32(len(value[offset:])) - valueBuf, valueLen := splitPointerSize(int64(valueOut)) + valueBuf, valueLen := splitPointerSize(valueOut) copy(memory[valueBuf:valueBuf+valueLen], value[offset:]) } sizeSpan, err := toWasmMemoryOptionalUint32(instanceContext, &size) if err != nil { logger.Errorf("failed to allocate: %s", err) - return 0 + return []wasmer.Value{wasmer.NewI64(0)}, nil } - return C.int64_t(sizeSpan) + return []wasmer.Value{wasmer.NewI64(sizeSpan)}, nil } //export ext_storage_root_version_1 -func ext_storage_root_version_1(context unsafe.Pointer) C.int64_t { +func ext_storage_root_version_1(env interface{}, _ []wasmer.Value) ([]wasmer.Value, error) { logger.Trace("executing...") - instanceContext := wasm.IntoInstanceContext(context) - storage := instanceContext.Data().(*runtime.Context).Storage + instanceContext := env.(*runtime.Context) + storage := instanceContext.Storage root, err := storage.Root() if err != nil { logger.Errorf("failed to get storage root: %s", err) - return 0 + return []wasmer.Value{wasmer.NewI64(0)}, nil } logger.Debugf("root hash is: %s", root) @@ -2033,25 +2131,28 @@ func ext_storage_root_version_1(context unsafe.Pointer) C.int64_t { rootSpan, err := toWasmMemory(instanceContext, root[:]) if err != nil { logger.Errorf("failed to allocate: %s", err) - return 0 + return []wasmer.Value{wasmer.NewI64(0)}, nil } - return C.int64_t(rootSpan) + return []wasmer.Value{wasmer.NewI64(rootSpan)}, nil } //export ext_storage_root_version_2 -func ext_storage_root_version_2(context unsafe.Pointer, version C.int32_t) C.int64_t { +func ext_storage_root_version_2(env interface{}, args []wasmer.Value) ([]wasmer.Value, error) { // TODO: update to use state trie version 1 (#2418) - return ext_storage_root_version_1(context) + instanceContext := env.(*runtime.Context) + _ = args[0].I32() // version - unused + return ext_storage_root_version_1(instanceContext, args) } //export ext_storage_set_version_1 -func ext_storage_set_version_1(context unsafe.Pointer, keySpan, valueSpan C.int64_t) { +func ext_storage_set_version_1(env interface{}, args []wasmer.Value) ([]wasmer.Value, error) { logger.Trace("executing...") - instanceContext := wasm.IntoInstanceContext(context) - ctx := instanceContext.Data().(*runtime.Context) - storage := ctx.Storage + instanceContext := env.(*runtime.Context) + keySpan := args[0].I64() + valueSpan := args[1].I64() + storage := instanceContext.Storage key := asMemorySlice(instanceContext, keySpan) value := asMemorySlice(instanceContext, valueSpan) @@ -2064,128 +2165,29 @@ func ext_storage_set_version_1(context unsafe.Pointer, keySpan, valueSpan C.int6 key, value) err := storage.Put(key, cp) panicOnError(err) + return nil, nil } //export ext_storage_start_transaction_version_1 -func ext_storage_start_transaction_version_1(context unsafe.Pointer) { +func ext_storage_start_transaction_version_1(env interface{}, _ []wasmer.Value) ([]wasmer.Value, error) { logger.Debug("executing...") - instanceContext := wasm.IntoInstanceContext(context) - instanceContext.Data().(*runtime.Context).Storage.BeginStorageTransaction() + instanceContext := env.(*runtime.Context) + instanceContext.Storage.BeginStorageTransaction() + return nil, nil } //export ext_storage_rollback_transaction_version_1 -func ext_storage_rollback_transaction_version_1(context unsafe.Pointer) { +func ext_storage_rollback_transaction_version_1(env interface{}, _ []wasmer.Value) ([]wasmer.Value, error) { logger.Debug("executing...") - instanceContext := wasm.IntoInstanceContext(context) - instanceContext.Data().(*runtime.Context).Storage.RollbackStorageTransaction() + instanceContext := env.(*runtime.Context) + instanceContext.Storage.RollbackStorageTransaction() + return nil, nil } //export ext_storage_commit_transaction_version_1 -func ext_storage_commit_transaction_version_1(context unsafe.Pointer) { +func ext_storage_commit_transaction_version_1(env interface{}, _ []wasmer.Value) ([]wasmer.Value, error) { logger.Debug("executing...") - instanceContext := wasm.IntoInstanceContext(context) - instanceContext.Data().(*runtime.Context).Storage.CommitStorageTransaction() -} - -// importsNodeRuntime returns the WASM imports for the node runtime. -func importsNodeRuntime() (imports *wasm.Imports, err error) { - imports = wasm.NewImports() - // Note imports are closed by the call to wasm.Instance.Close() - - for _, toRegister := range []struct { - importName string - implementation interface{} - cgoPointer unsafe.Pointer - }{ - {"ext_allocator_free_version_1", ext_allocator_free_version_1, C.ext_allocator_free_version_1}, - {"ext_allocator_malloc_version_1", ext_allocator_malloc_version_1, C.ext_allocator_malloc_version_1}, - {"ext_crypto_ecdsa_verify_version_2", ext_crypto_ecdsa_verify_version_2, C.ext_crypto_ecdsa_verify_version_2}, - {"ext_crypto_ed25519_generate_version_1", ext_crypto_ed25519_generate_version_1, C.ext_crypto_ed25519_generate_version_1}, - {"ext_crypto_ed25519_public_keys_version_1", ext_crypto_ed25519_public_keys_version_1, C.ext_crypto_ed25519_public_keys_version_1}, - {"ext_crypto_ed25519_sign_version_1", ext_crypto_ed25519_sign_version_1, C.ext_crypto_ed25519_sign_version_1}, - {"ext_crypto_ed25519_verify_version_1", ext_crypto_ed25519_verify_version_1, C.ext_crypto_ed25519_verify_version_1}, - {"ext_crypto_finish_batch_verify_version_1", ext_crypto_finish_batch_verify_version_1, C.ext_crypto_finish_batch_verify_version_1}, - {"ext_crypto_secp256k1_ecdsa_recover_compressed_version_1", ext_crypto_secp256k1_ecdsa_recover_compressed_version_1, C.ext_crypto_secp256k1_ecdsa_recover_compressed_version_1}, - {"ext_crypto_secp256k1_ecdsa_recover_compressed_version_2", ext_crypto_secp256k1_ecdsa_recover_compressed_version_2, C.ext_crypto_secp256k1_ecdsa_recover_compressed_version_2}, - {"ext_crypto_secp256k1_ecdsa_recover_version_1", ext_crypto_secp256k1_ecdsa_recover_version_1, C.ext_crypto_secp256k1_ecdsa_recover_version_1}, - {"ext_crypto_secp256k1_ecdsa_recover_version_2", ext_crypto_secp256k1_ecdsa_recover_version_2, C.ext_crypto_secp256k1_ecdsa_recover_version_2}, - {"ext_crypto_sr25519_generate_version_1", ext_crypto_sr25519_generate_version_1, C.ext_crypto_sr25519_generate_version_1}, - {"ext_crypto_sr25519_public_keys_version_1", ext_crypto_sr25519_public_keys_version_1, C.ext_crypto_sr25519_public_keys_version_1}, - {"ext_crypto_sr25519_sign_version_1", ext_crypto_sr25519_sign_version_1, C.ext_crypto_sr25519_sign_version_1}, - {"ext_crypto_sr25519_verify_version_1", ext_crypto_sr25519_verify_version_1, C.ext_crypto_sr25519_verify_version_1}, - {"ext_crypto_sr25519_verify_version_2", ext_crypto_sr25519_verify_version_2, C.ext_crypto_sr25519_verify_version_2}, - {"ext_crypto_start_batch_verify_version_1", ext_crypto_start_batch_verify_version_1, C.ext_crypto_start_batch_verify_version_1}, - {"ext_default_child_storage_clear_prefix_version_1", ext_default_child_storage_clear_prefix_version_1, C.ext_default_child_storage_clear_prefix_version_1}, - {"ext_default_child_storage_clear_version_1", ext_default_child_storage_clear_version_1, C.ext_default_child_storage_clear_version_1}, - {"ext_default_child_storage_exists_version_1", ext_default_child_storage_exists_version_1, C.ext_default_child_storage_exists_version_1}, - {"ext_default_child_storage_get_version_1", ext_default_child_storage_get_version_1, C.ext_default_child_storage_get_version_1}, - {"ext_default_child_storage_next_key_version_1", ext_default_child_storage_next_key_version_1, C.ext_default_child_storage_next_key_version_1}, - {"ext_default_child_storage_read_version_1", ext_default_child_storage_read_version_1, C.ext_default_child_storage_read_version_1}, - {"ext_default_child_storage_root_version_1", ext_default_child_storage_root_version_1, C.ext_default_child_storage_root_version_1}, - {"ext_default_child_storage_set_version_1", ext_default_child_storage_set_version_1, C.ext_default_child_storage_set_version_1}, - {"ext_default_child_storage_storage_kill_version_1", ext_default_child_storage_storage_kill_version_1, C.ext_default_child_storage_storage_kill_version_1}, - {"ext_default_child_storage_storage_kill_version_2", ext_default_child_storage_storage_kill_version_2, C.ext_default_child_storage_storage_kill_version_2}, - {"ext_default_child_storage_storage_kill_version_3", ext_default_child_storage_storage_kill_version_3, C.ext_default_child_storage_storage_kill_version_3}, - {"ext_hashing_blake2_128_version_1", ext_hashing_blake2_128_version_1, C.ext_hashing_blake2_128_version_1}, - {"ext_hashing_blake2_256_version_1", ext_hashing_blake2_256_version_1, C.ext_hashing_blake2_256_version_1}, - {"ext_hashing_keccak_256_version_1", ext_hashing_keccak_256_version_1, C.ext_hashing_keccak_256_version_1}, - {"ext_hashing_sha2_256_version_1", ext_hashing_sha2_256_version_1, C.ext_hashing_sha2_256_version_1}, - {"ext_hashing_twox_128_version_1", ext_hashing_twox_128_version_1, C.ext_hashing_twox_128_version_1}, - {"ext_hashing_twox_256_version_1", ext_hashing_twox_256_version_1, C.ext_hashing_twox_256_version_1}, - {"ext_hashing_twox_64_version_1", ext_hashing_twox_64_version_1, C.ext_hashing_twox_64_version_1}, - {"ext_logging_log_version_1", ext_logging_log_version_1, C.ext_logging_log_version_1}, - {"ext_logging_max_level_version_1", ext_logging_max_level_version_1, C.ext_logging_max_level_version_1}, - {"ext_misc_print_hex_version_1", ext_misc_print_hex_version_1, C.ext_misc_print_hex_version_1}, - {"ext_misc_print_num_version_1", ext_misc_print_num_version_1, C.ext_misc_print_num_version_1}, - {"ext_misc_print_utf8_version_1", ext_misc_print_utf8_version_1, C.ext_misc_print_utf8_version_1}, - {"ext_misc_runtime_version_version_1", ext_misc_runtime_version_version_1, C.ext_misc_runtime_version_version_1}, - {"ext_offchain_http_request_add_header_version_1", ext_offchain_http_request_add_header_version_1, C.ext_offchain_http_request_add_header_version_1}, - {"ext_offchain_http_request_start_version_1", ext_offchain_http_request_start_version_1, C.ext_offchain_http_request_start_version_1}, - {"ext_offchain_index_set_version_1", ext_offchain_index_set_version_1, C.ext_offchain_index_set_version_1}, - {"ext_offchain_is_validator_version_1", ext_offchain_is_validator_version_1, C.ext_offchain_is_validator_version_1}, - {"ext_offchain_local_storage_clear_version_1", ext_offchain_local_storage_clear_version_1, C.ext_offchain_local_storage_clear_version_1}, - {"ext_offchain_local_storage_compare_and_set_version_1", ext_offchain_local_storage_compare_and_set_version_1, C.ext_offchain_local_storage_compare_and_set_version_1}, - {"ext_offchain_local_storage_get_version_1", ext_offchain_local_storage_get_version_1, C.ext_offchain_local_storage_get_version_1}, - {"ext_offchain_local_storage_set_version_1", ext_offchain_local_storage_set_version_1, C.ext_offchain_local_storage_set_version_1}, - {"ext_offchain_network_state_version_1", ext_offchain_network_state_version_1, C.ext_offchain_network_state_version_1}, - {"ext_offchain_random_seed_version_1", ext_offchain_random_seed_version_1, C.ext_offchain_random_seed_version_1}, - {"ext_offchain_sleep_until_version_1", ext_offchain_sleep_until_version_1, C.ext_offchain_sleep_until_version_1}, - {"ext_offchain_submit_transaction_version_1", ext_offchain_submit_transaction_version_1, C.ext_offchain_submit_transaction_version_1}, - {"ext_offchain_timestamp_version_1", ext_offchain_timestamp_version_1, C.ext_offchain_timestamp_version_1}, - {"ext_sandbox_instance_teardown_version_1", ext_sandbox_instance_teardown_version_1, C.ext_sandbox_instance_teardown_version_1}, - {"ext_sandbox_instantiate_version_1", ext_sandbox_instantiate_version_1, C.ext_sandbox_instantiate_version_1}, - {"ext_sandbox_invoke_version_1", ext_sandbox_invoke_version_1, C.ext_sandbox_invoke_version_1}, - {"ext_sandbox_memory_get_version_1", ext_sandbox_memory_get_version_1, C.ext_sandbox_memory_get_version_1}, - {"ext_sandbox_memory_new_version_1", ext_sandbox_memory_new_version_1, C.ext_sandbox_memory_new_version_1}, - {"ext_sandbox_memory_set_version_1", ext_sandbox_memory_set_version_1, C.ext_sandbox_memory_set_version_1}, - {"ext_sandbox_memory_teardown_version_1", ext_sandbox_memory_teardown_version_1, C.ext_sandbox_memory_teardown_version_1}, - {"ext_storage_append_version_1", ext_storage_append_version_1, C.ext_storage_append_version_1}, - {"ext_storage_changes_root_version_1", ext_storage_changes_root_version_1, C.ext_storage_changes_root_version_1}, - {"ext_storage_clear_prefix_version_1", ext_storage_clear_prefix_version_1, C.ext_storage_clear_prefix_version_1}, - {"ext_storage_clear_prefix_version_2", ext_storage_clear_prefix_version_2, C.ext_storage_clear_prefix_version_2}, - {"ext_storage_clear_version_1", ext_storage_clear_version_1, C.ext_storage_clear_version_1}, - {"ext_storage_commit_transaction_version_1", ext_storage_commit_transaction_version_1, C.ext_storage_commit_transaction_version_1}, - {"ext_storage_exists_version_1", ext_storage_exists_version_1, C.ext_storage_exists_version_1}, - {"ext_storage_get_version_1", ext_storage_get_version_1, C.ext_storage_get_version_1}, - {"ext_storage_next_key_version_1", ext_storage_next_key_version_1, C.ext_storage_next_key_version_1}, - {"ext_storage_read_version_1", ext_storage_read_version_1, C.ext_storage_read_version_1}, - {"ext_storage_rollback_transaction_version_1", ext_storage_rollback_transaction_version_1, C.ext_storage_rollback_transaction_version_1}, - {"ext_storage_root_version_1", ext_storage_root_version_1, C.ext_storage_root_version_1}, - {"ext_storage_root_version_2", ext_storage_root_version_2, C.ext_storage_root_version_2}, - {"ext_storage_set_version_1", ext_storage_set_version_1, C.ext_storage_set_version_1}, - {"ext_storage_start_transaction_version_1", ext_storage_start_transaction_version_1, C.ext_storage_start_transaction_version_1}, - {"ext_transaction_index_index_version_1", ext_transaction_index_index_version_1, C.ext_transaction_index_index_version_1}, - {"ext_transaction_index_renew_version_1", ext_transaction_index_renew_version_1, C.ext_transaction_index_renew_version_1}, - {"ext_trie_blake2_256_ordered_root_version_1", ext_trie_blake2_256_ordered_root_version_1, C.ext_trie_blake2_256_ordered_root_version_1}, - {"ext_trie_blake2_256_ordered_root_version_2", ext_trie_blake2_256_ordered_root_version_2, C.ext_trie_blake2_256_ordered_root_version_2}, - {"ext_trie_blake2_256_root_version_1", ext_trie_blake2_256_root_version_1, C.ext_trie_blake2_256_root_version_1}, - {"ext_trie_blake2_256_verify_proof_version_1", ext_trie_blake2_256_verify_proof_version_1, C.ext_trie_blake2_256_verify_proof_version_1}, - } { - _, err = imports.AppendFunction(toRegister.importName, toRegister.implementation, toRegister.cgoPointer) - if err != nil { - return nil, fmt.Errorf("importing function: %w", err) - } - } - - return imports, nil + instanceContext := env.(*runtime.Context) + instanceContext.Storage.CommitStorageTransaction() + return nil, nil } diff --git a/lib/runtime/wasmer/imports_func.go b/lib/runtime/wasmer/imports_func.go new file mode 100644 index 0000000000..fce74a0d0e --- /dev/null +++ b/lib/runtime/wasmer/imports_func.go @@ -0,0 +1,533 @@ +// Copyright 2023 ChainSafe Systems (ON) Corp. +// This file is part of gossamer. +// +// The gossamer library is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// The gossamer library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with the gossamer library. If not, see . + +package wasmer + +import ( + "github.com/ChainSafe/gossamer/lib/runtime" + "github.com/wasmerio/wasmer-go/wasmer" +) + +// importsNodeRuntime returns the WASM imports for the node runtime. +func importsNodeRuntime(store *wasmer.Store, memory *wasmer.Memory, ctx *runtime.Context) *wasmer.ImportObject { + importsMap := make(map[string]wasmer.IntoExtern) + + if memory != nil { + importsMap["memory"] = memory + } + + importsMap["ext_logging_log_version_1"] = wasmer.NewFunctionWithEnvironment(store, + wasmer.NewFunctionType( + wasmer.NewValueTypes(wasmer.I32, wasmer.I64, wasmer.I64), + wasmer.NewValueTypes(), + ), ctx, ext_logging_log_version_1) + + importsMap["ext_logging_max_level_version_1"] = wasmer.NewFunctionWithEnvironment(store, + wasmer.NewFunctionType( + wasmer.NewValueTypes(), + wasmer.NewValueTypes(wasmer.I32), + ), ctx, ext_logging_max_level_version_1) + + importsMap["ext_transaction_index_index_version_1"] = wasmer.NewFunctionWithEnvironment(store, + wasmer.NewFunctionType( + wasmer.NewValueTypes(wasmer.I32, wasmer.I32, wasmer.I32), + wasmer.NewValueTypes(), + ), ctx, ext_transaction_index_index_version_1) + + importsMap["ext_transaction_index_renew_version_1"] = wasmer.NewFunctionWithEnvironment(store, + wasmer.NewFunctionType( + wasmer.NewValueTypes(wasmer.I32, wasmer.I32), + wasmer.NewValueTypes(), + ), ctx, ext_transaction_index_renew_version_1) + + importsMap["ext_sandbox_instance_teardown_version_1"] = wasmer.NewFunctionWithEnvironment(store, + wasmer.NewFunctionType( + wasmer.NewValueTypes(wasmer.I32), + wasmer.NewValueTypes(), + ), ctx, ext_sandbox_instance_teardown_version_1) + + importsMap["ext_sandbox_instantiate_version_1"] = wasmer.NewFunctionWithEnvironment(store, + wasmer.NewFunctionType( + wasmer.NewValueTypes(wasmer.I32, wasmer.I64, wasmer.I64, wasmer.I32), + wasmer.NewValueTypes(wasmer.I32), + ), ctx, ext_sandbox_instantiate_version_1) + + importsMap["ext_sandbox_invoke_version_1"] = wasmer.NewFunctionWithEnvironment(store, + wasmer.NewFunctionType( + wasmer.NewValueTypes(wasmer.I32, wasmer.I64, wasmer.I64, wasmer.I32, wasmer.I32, wasmer.I32), + wasmer.NewValueTypes(wasmer.I32), + ), ctx, ext_sandbox_invoke_version_1) + + importsMap["ext_sandbox_memory_get_version_1"] = wasmer.NewFunctionWithEnvironment(store, + wasmer.NewFunctionType( + wasmer.NewValueTypes(wasmer.I32, wasmer.I32, wasmer.I32, wasmer.I32), + wasmer.NewValueTypes(wasmer.I32), + ), ctx, ext_sandbox_memory_get_version_1) + + importsMap["ext_sandbox_memory_new_version_1"] = wasmer.NewFunctionWithEnvironment(store, + wasmer.NewFunctionType( + wasmer.NewValueTypes(wasmer.I32, wasmer.I32), + wasmer.NewValueTypes(wasmer.I32), + ), ctx, ext_sandbox_memory_new_version_1) + + importsMap["ext_sandbox_memory_set_version_1"] = wasmer.NewFunctionWithEnvironment(store, + wasmer.NewFunctionType( + wasmer.NewValueTypes(wasmer.I32, wasmer.I32, wasmer.I32, wasmer.I32), + wasmer.NewValueTypes(wasmer.I32), + ), ctx, ext_sandbox_memory_set_version_1) + + importsMap["ext_sandbox_memory_teardown_version_1"] = wasmer.NewFunctionWithEnvironment(store, + wasmer.NewFunctionType( + wasmer.NewValueTypes(wasmer.I32), + wasmer.NewValueTypes(), + ), ctx, ext_sandbox_memory_teardown_version_1) + + importsMap["ext_crypto_ed25519_generate_version_1"] = wasmer.NewFunctionWithEnvironment(store, + wasmer.NewFunctionType( + wasmer.NewValueTypes(wasmer.I32, wasmer.I64), + wasmer.NewValueTypes(wasmer.I32), + ), ctx, ext_crypto_ed25519_generate_version_1) + + importsMap["ext_crypto_ed25519_public_keys_version_1"] = wasmer.NewFunctionWithEnvironment(store, + wasmer.NewFunctionType( + wasmer.NewValueTypes(wasmer.I32), + wasmer.NewValueTypes(wasmer.I64), + ), ctx, ext_crypto_ed25519_public_keys_version_1) + + importsMap["ext_crypto_ed25519_sign_version_1"] = wasmer.NewFunctionWithEnvironment(store, + wasmer.NewFunctionType( + wasmer.NewValueTypes(wasmer.I32, wasmer.I32, wasmer.I64), + wasmer.NewValueTypes(wasmer.I64), + ), ctx, ext_crypto_ed25519_sign_version_1) + + importsMap["ext_crypto_ed25519_verify_version_1"] = wasmer.NewFunctionWithEnvironment(store, + wasmer.NewFunctionType( + wasmer.NewValueTypes(wasmer.I32, wasmer.I64, wasmer.I32), + wasmer.NewValueTypes(wasmer.I32), + ), ctx, ext_crypto_ed25519_verify_version_1) + + importsMap["ext_crypto_secp256k1_ecdsa_recover_version_1"] = wasmer.NewFunctionWithEnvironment(store, + wasmer.NewFunctionType( + wasmer.NewValueTypes(wasmer.I32, wasmer.I32), + wasmer.NewValueTypes(wasmer.I64), + ), ctx, ext_crypto_secp256k1_ecdsa_recover_version_1) + + importsMap["ext_crypto_secp256k1_ecdsa_recover_version_2"] = wasmer.NewFunctionWithEnvironment(store, + wasmer.NewFunctionType( + wasmer.NewValueTypes(wasmer.I32, wasmer.I32), + wasmer.NewValueTypes(wasmer.I64), + ), ctx, ext_crypto_secp256k1_ecdsa_recover_version_2) + + importsMap["ext_crypto_ecdsa_verify_version_2"] = wasmer.NewFunctionWithEnvironment(store, + wasmer.NewFunctionType( + wasmer.NewValueTypes(wasmer.I32, wasmer.I64, wasmer.I32), + wasmer.NewValueTypes(wasmer.I32), + ), ctx, ext_crypto_ecdsa_verify_version_2) + + importsMap["ext_crypto_secp256k1_ecdsa_recover_compressed_version_1"] = wasmer.NewFunctionWithEnvironment(store, + wasmer.NewFunctionType( + wasmer.NewValueTypes(wasmer.I32, wasmer.I32), + wasmer.NewValueTypes(wasmer.I64), + ), ctx, ext_crypto_secp256k1_ecdsa_recover_compressed_version_1) + + importsMap["ext_crypto_secp256k1_ecdsa_recover_compressed_version_2"] = wasmer.NewFunctionWithEnvironment(store, + wasmer.NewFunctionType( + wasmer.NewValueTypes(wasmer.I32, wasmer.I32), + wasmer.NewValueTypes(wasmer.I64), + ), ctx, ext_crypto_secp256k1_ecdsa_recover_compressed_version_2) + + importsMap["ext_crypto_sr25519_generate_version_1"] = wasmer.NewFunctionWithEnvironment(store, + wasmer.NewFunctionType( + wasmer.NewValueTypes(wasmer.I32, wasmer.I64), + wasmer.NewValueTypes(wasmer.I32), + ), ctx, ext_crypto_sr25519_generate_version_1) + + importsMap["ext_crypto_sr25519_public_keys_version_1"] = wasmer.NewFunctionWithEnvironment(store, + wasmer.NewFunctionType( + wasmer.NewValueTypes(wasmer.I32), + wasmer.NewValueTypes(wasmer.I64), + ), ctx, ext_crypto_sr25519_public_keys_version_1) + + importsMap["ext_crypto_sr25519_sign_version_1"] = wasmer.NewFunctionWithEnvironment(store, + wasmer.NewFunctionType( + wasmer.NewValueTypes(wasmer.I32, wasmer.I32, wasmer.I64), + wasmer.NewValueTypes(wasmer.I64), + ), ctx, ext_crypto_sr25519_sign_version_1) + + importsMap["ext_crypto_sr25519_verify_version_1"] = wasmer.NewFunctionWithEnvironment(store, + wasmer.NewFunctionType( + wasmer.NewValueTypes(wasmer.I32, wasmer.I64, wasmer.I32), + wasmer.NewValueTypes(wasmer.I32), + ), ctx, ext_crypto_sr25519_verify_version_1) + + importsMap["ext_crypto_sr25519_verify_version_2"] = wasmer.NewFunctionWithEnvironment(store, + wasmer.NewFunctionType( + wasmer.NewValueTypes(wasmer.I32, wasmer.I64, wasmer.I32), + wasmer.NewValueTypes(wasmer.I32), + ), ctx, ext_crypto_sr25519_verify_version_2) + + importsMap["ext_crypto_start_batch_verify_version_1"] = wasmer.NewFunctionWithEnvironment(store, + wasmer.NewFunctionType( + wasmer.NewValueTypes(), + wasmer.NewValueTypes(), + ), ctx, ext_crypto_start_batch_verify_version_1) + + importsMap["ext_crypto_finish_batch_verify_version_1"] = wasmer.NewFunctionWithEnvironment(store, + wasmer.NewFunctionType( + wasmer.NewValueTypes(), + wasmer.NewValueTypes(wasmer.I32), + ), ctx, ext_crypto_finish_batch_verify_version_1) + + importsMap["ext_trie_blake2_256_root_version_1"] = wasmer.NewFunctionWithEnvironment(store, + wasmer.NewFunctionType( + wasmer.NewValueTypes(wasmer.I64), + wasmer.NewValueTypes(wasmer.I32), + ), ctx, ext_trie_blake2_256_root_version_1) + + importsMap["ext_trie_blake2_256_ordered_root_version_1"] = wasmer.NewFunctionWithEnvironment(store, + wasmer.NewFunctionType( + wasmer.NewValueTypes(wasmer.I64), + wasmer.NewValueTypes(wasmer.I32), + ), ctx, ext_trie_blake2_256_ordered_root_version_1) + + importsMap["ext_trie_blake2_256_ordered_root_version_2"] = wasmer.NewFunctionWithEnvironment(store, + wasmer.NewFunctionType( + wasmer.NewValueTypes(wasmer.I64, wasmer.I32), + wasmer.NewValueTypes(wasmer.I32), + ), ctx, ext_trie_blake2_256_ordered_root_version_2) + + importsMap["ext_trie_blake2_256_verify_proof_version_1"] = wasmer.NewFunctionWithEnvironment(store, + wasmer.NewFunctionType( + wasmer.NewValueTypes(wasmer.I32, wasmer.I64, wasmer.I64, wasmer.I64), + wasmer.NewValueTypes(wasmer.I32), + ), ctx, ext_trie_blake2_256_verify_proof_version_1) + + importsMap["ext_misc_print_hex_version_1"] = wasmer.NewFunctionWithEnvironment(store, + wasmer.NewFunctionType( + wasmer.NewValueTypes(wasmer.I64), + wasmer.NewValueTypes(), + ), ctx, ext_misc_print_hex_version_1) + + importsMap["ext_misc_print_num_version_1"] = wasmer.NewFunctionWithEnvironment(store, + wasmer.NewFunctionType( + wasmer.NewValueTypes(wasmer.I64), + wasmer.NewValueTypes(), + ), ctx, ext_misc_print_num_version_1) + + importsMap["ext_misc_print_utf8_version_1"] = wasmer.NewFunctionWithEnvironment(store, + wasmer.NewFunctionType( + wasmer.NewValueTypes(wasmer.I64), + wasmer.NewValueTypes(), + ), ctx, ext_misc_print_utf8_version_1) + + importsMap["ext_misc_runtime_version_version_1"] = wasmer.NewFunctionWithEnvironment(store, + wasmer.NewFunctionType( + wasmer.NewValueTypes(wasmer.I64), + wasmer.NewValueTypes(wasmer.I64), + ), ctx, ext_misc_runtime_version_version_1) + + importsMap["ext_default_child_storage_read_version_1"] = wasmer.NewFunctionWithEnvironment(store, + wasmer.NewFunctionType( + wasmer.NewValueTypes(wasmer.I64, wasmer.I64, wasmer.I64, wasmer.I32), + wasmer.NewValueTypes(wasmer.I64), + ), ctx, ext_default_child_storage_read_version_1) + + importsMap["ext_default_child_storage_clear_version_1"] = wasmer.NewFunctionWithEnvironment(store, + wasmer.NewFunctionType( + wasmer.NewValueTypes(wasmer.I64, wasmer.I64), + wasmer.NewValueTypes(), + ), ctx, ext_default_child_storage_clear_version_1) + + importsMap["ext_default_child_storage_clear_prefix_version_1"] = wasmer.NewFunctionWithEnvironment(store, + wasmer.NewFunctionType( + wasmer.NewValueTypes(wasmer.I64, wasmer.I64), + wasmer.NewValueTypes(), + ), ctx, ext_default_child_storage_clear_prefix_version_1) + + importsMap["ext_default_child_storage_exists_version_1"] = wasmer.NewFunctionWithEnvironment(store, + wasmer.NewFunctionType( + wasmer.NewValueTypes(wasmer.I64, wasmer.I64), + wasmer.NewValueTypes(wasmer.I32), + ), ctx, ext_default_child_storage_exists_version_1) + + importsMap["ext_default_child_storage_get_version_1"] = wasmer.NewFunctionWithEnvironment(store, + wasmer.NewFunctionType( + wasmer.NewValueTypes(wasmer.I64, wasmer.I64), + wasmer.NewValueTypes(wasmer.I64), + ), ctx, ext_default_child_storage_get_version_1) + + importsMap["ext_default_child_storage_next_key_version_1"] = wasmer.NewFunctionWithEnvironment(store, + wasmer.NewFunctionType( + wasmer.NewValueTypes(wasmer.I64, wasmer.I64), + wasmer.NewValueTypes(wasmer.I64), + ), ctx, ext_default_child_storage_next_key_version_1) + + importsMap["ext_default_child_storage_root_version_1"] = wasmer.NewFunctionWithEnvironment(store, + wasmer.NewFunctionType( + wasmer.NewValueTypes(wasmer.I64), + wasmer.NewValueTypes(wasmer.I64), + ), ctx, ext_default_child_storage_root_version_1) + + importsMap["ext_default_child_storage_set_version_1"] = wasmer.NewFunctionWithEnvironment(store, + wasmer.NewFunctionType( + wasmer.NewValueTypes(wasmer.I64, wasmer.I64, wasmer.I64), + wasmer.NewValueTypes(), + ), ctx, ext_default_child_storage_set_version_1) + + importsMap["ext_default_child_storage_storage_kill_version_1"] = wasmer.NewFunctionWithEnvironment(store, + wasmer.NewFunctionType( + wasmer.NewValueTypes(wasmer.I64), + wasmer.NewValueTypes(), + ), ctx, ext_default_child_storage_storage_kill_version_1) + + importsMap["ext_default_child_storage_storage_kill_version_2"] = wasmer.NewFunctionWithEnvironment(store, + wasmer.NewFunctionType( + wasmer.NewValueTypes(wasmer.I64, wasmer.I64), + wasmer.NewValueTypes(wasmer.I32), + ), ctx, ext_default_child_storage_storage_kill_version_2) + + importsMap["ext_default_child_storage_storage_kill_version_3"] = wasmer.NewFunctionWithEnvironment(store, + wasmer.NewFunctionType( + wasmer.NewValueTypes(wasmer.I64, wasmer.I64), + wasmer.NewValueTypes(wasmer.I64), + ), ctx, ext_default_child_storage_storage_kill_version_3) + + importsMap["ext_allocator_free_version_1"] = wasmer.NewFunctionWithEnvironment(store, + wasmer.NewFunctionType( + wasmer.NewValueTypes(wasmer.I32), + wasmer.NewValueTypes(), + ), ctx, ext_allocator_free_version_1) + + importsMap["ext_allocator_malloc_version_1"] = wasmer.NewFunctionWithEnvironment(store, + wasmer.NewFunctionType( + wasmer.NewValueTypes(wasmer.I32), + wasmer.NewValueTypes(wasmer.I32), + ), ctx, ext_allocator_malloc_version_1) + + importsMap["ext_hashing_blake2_128_version_1"] = wasmer.NewFunctionWithEnvironment(store, + wasmer.NewFunctionType( + wasmer.NewValueTypes(wasmer.I64), + wasmer.NewValueTypes(wasmer.I32), + ), ctx, ext_hashing_blake2_128_version_1) + + importsMap["ext_hashing_blake2_256_version_1"] = wasmer.NewFunctionWithEnvironment(store, + wasmer.NewFunctionType( + wasmer.NewValueTypes(wasmer.I64), + wasmer.NewValueTypes(wasmer.I32), + ), ctx, ext_hashing_blake2_256_version_1) + + importsMap["ext_hashing_keccak_256_version_1"] = wasmer.NewFunctionWithEnvironment(store, + wasmer.NewFunctionType( + wasmer.NewValueTypes(wasmer.I64), + wasmer.NewValueTypes(wasmer.I32), + ), ctx, ext_hashing_keccak_256_version_1) + + importsMap["ext_hashing_sha2_256_version_1"] = wasmer.NewFunctionWithEnvironment(store, + wasmer.NewFunctionType( + wasmer.NewValueTypes(wasmer.I64), + wasmer.NewValueTypes(wasmer.I32), + ), ctx, ext_hashing_sha2_256_version_1) + + importsMap["ext_hashing_twox_256_version_1"] = wasmer.NewFunctionWithEnvironment(store, + wasmer.NewFunctionType( + wasmer.NewValueTypes(wasmer.I64), + wasmer.NewValueTypes(wasmer.I32), + ), ctx, ext_hashing_twox_256_version_1) + + importsMap["ext_hashing_twox_128_version_1"] = wasmer.NewFunctionWithEnvironment(store, + wasmer.NewFunctionType( + wasmer.NewValueTypes(wasmer.I64), + wasmer.NewValueTypes(wasmer.I32), + ), ctx, ext_hashing_twox_128_version_1) + + importsMap["ext_hashing_twox_64_version_1"] = wasmer.NewFunctionWithEnvironment(store, + wasmer.NewFunctionType( + wasmer.NewValueTypes(wasmer.I64), + wasmer.NewValueTypes(wasmer.I32), + ), ctx, ext_hashing_twox_64_version_1) + + importsMap["ext_offchain_index_set_version_1"] = wasmer.NewFunctionWithEnvironment(store, + wasmer.NewFunctionType( + wasmer.NewValueTypes(wasmer.I64, wasmer.I64), + wasmer.NewValueTypes(), + ), ctx, ext_offchain_index_set_version_1) + + importsMap["ext_offchain_local_storage_clear_version_1"] = wasmer.NewFunctionWithEnvironment(store, + wasmer.NewFunctionType( + wasmer.NewValueTypes(wasmer.I32, wasmer.I64), + wasmer.NewValueTypes(), + ), ctx, ext_offchain_local_storage_clear_version_1) + + importsMap["ext_offchain_is_validator_version_1"] = wasmer.NewFunctionWithEnvironment(store, + wasmer.NewFunctionType( + wasmer.NewValueTypes(), + wasmer.NewValueTypes(wasmer.I32), + ), ctx, ext_offchain_is_validator_version_1) + + importsMap["ext_offchain_local_storage_compare_and_set_version_1"] = wasmer.NewFunctionWithEnvironment(store, + wasmer.NewFunctionType( + wasmer.NewValueTypes(wasmer.I32, wasmer.I64, wasmer.I64, wasmer.I64), + wasmer.NewValueTypes(wasmer.I32), + ), ctx, ext_offchain_local_storage_compare_and_set_version_1) + + importsMap["ext_offchain_local_storage_get_version_1"] = wasmer.NewFunctionWithEnvironment(store, + wasmer.NewFunctionType( + wasmer.NewValueTypes(wasmer.I32, wasmer.I64), + wasmer.NewValueTypes(wasmer.I64), + ), ctx, ext_offchain_local_storage_get_version_1) + + importsMap["ext_offchain_local_storage_set_version_1"] = wasmer.NewFunctionWithEnvironment(store, + wasmer.NewFunctionType( + wasmer.NewValueTypes(wasmer.I32, wasmer.I64, wasmer.I64), + wasmer.NewValueTypes(), + ), ctx, ext_offchain_local_storage_set_version_1) + + importsMap["ext_offchain_network_state_version_1"] = wasmer.NewFunctionWithEnvironment(store, + wasmer.NewFunctionType( + wasmer.NewValueTypes(), + wasmer.NewValueTypes(wasmer.I64), + ), ctx, ext_offchain_network_state_version_1) + + importsMap["ext_offchain_random_seed_version_1"] = wasmer.NewFunctionWithEnvironment(store, + wasmer.NewFunctionType( + wasmer.NewValueTypes(), + wasmer.NewValueTypes(wasmer.I32), + ), ctx, ext_offchain_random_seed_version_1) + + importsMap["ext_offchain_submit_transaction_version_1"] = wasmer.NewFunctionWithEnvironment(store, + wasmer.NewFunctionType( + wasmer.NewValueTypes(wasmer.I64), + wasmer.NewValueTypes(wasmer.I64), + ), ctx, ext_offchain_submit_transaction_version_1) + + importsMap["ext_offchain_timestamp_version_1"] = wasmer.NewFunctionWithEnvironment(store, + wasmer.NewFunctionType( + wasmer.NewValueTypes(), + wasmer.NewValueTypes(wasmer.I64), + ), ctx, ext_offchain_timestamp_version_1) + + importsMap["ext_offchain_sleep_until_version_1"] = wasmer.NewFunctionWithEnvironment(store, + wasmer.NewFunctionType( + wasmer.NewValueTypes(wasmer.I64), + wasmer.NewValueTypes(), + ), ctx, ext_offchain_sleep_until_version_1) + + importsMap["ext_offchain_http_request_start_version_1"] = wasmer.NewFunctionWithEnvironment(store, + wasmer.NewFunctionType( + wasmer.NewValueTypes(wasmer.I64, wasmer.I64, wasmer.I64), + wasmer.NewValueTypes(wasmer.I64), + ), ctx, ext_offchain_http_request_start_version_1) + + importsMap["ext_offchain_http_request_add_header_version_1"] = wasmer.NewFunctionWithEnvironment(store, + wasmer.NewFunctionType( + wasmer.NewValueTypes(wasmer.I32, wasmer.I64, wasmer.I64), + wasmer.NewValueTypes(wasmer.I64), + ), ctx, ext_offchain_http_request_add_header_version_1) + + importsMap["ext_storage_append_version_1"] = wasmer.NewFunctionWithEnvironment(store, + wasmer.NewFunctionType( + wasmer.NewValueTypes(wasmer.I64, wasmer.I64), + wasmer.NewValueTypes(), + ), ctx, ext_storage_append_version_1) + + importsMap["ext_storage_changes_root_version_1"] = wasmer.NewFunctionWithEnvironment(store, + wasmer.NewFunctionType( + wasmer.NewValueTypes(wasmer.I64), + wasmer.NewValueTypes(wasmer.I64), + ), ctx, ext_storage_changes_root_version_1) + + importsMap["ext_storage_clear_version_1"] = wasmer.NewFunctionWithEnvironment(store, + wasmer.NewFunctionType( + wasmer.NewValueTypes(wasmer.I64), + wasmer.NewValueTypes(), + ), ctx, ext_storage_clear_version_1) + + importsMap["ext_storage_clear_prefix_version_1"] = wasmer.NewFunctionWithEnvironment(store, + wasmer.NewFunctionType( + wasmer.NewValueTypes(wasmer.I64), + wasmer.NewValueTypes(), + ), ctx, ext_storage_clear_prefix_version_1) + + importsMap["ext_storage_clear_prefix_version_2"] = wasmer.NewFunctionWithEnvironment(store, + wasmer.NewFunctionType( + wasmer.NewValueTypes(wasmer.I64, wasmer.I64), + wasmer.NewValueTypes(wasmer.I64), + ), ctx, ext_storage_clear_prefix_version_2) + + importsMap["ext_storage_exists_version_1"] = wasmer.NewFunctionWithEnvironment(store, + wasmer.NewFunctionType( + wasmer.NewValueTypes(wasmer.I64), + wasmer.NewValueTypes(wasmer.I32), + ), ctx, ext_storage_exists_version_1) + + importsMap["ext_storage_get_version_1"] = wasmer.NewFunctionWithEnvironment(store, + wasmer.NewFunctionType( + wasmer.NewValueTypes(wasmer.I64), + wasmer.NewValueTypes(wasmer.I64), + ), ctx, ext_storage_get_version_1) + + importsMap["ext_storage_next_key_version_1"] = wasmer.NewFunctionWithEnvironment(store, + wasmer.NewFunctionType( + wasmer.NewValueTypes(wasmer.I64), + wasmer.NewValueTypes(wasmer.I64), + ), ctx, ext_storage_next_key_version_1) + + importsMap["ext_storage_read_version_1"] = wasmer.NewFunctionWithEnvironment(store, + wasmer.NewFunctionType( + wasmer.NewValueTypes(wasmer.I64, wasmer.I64, wasmer.I32), + wasmer.NewValueTypes(wasmer.I64), + ), ctx, ext_storage_read_version_1) + + importsMap["ext_storage_root_version_1"] = wasmer.NewFunctionWithEnvironment(store, + wasmer.NewFunctionType( + wasmer.NewValueTypes(), + wasmer.NewValueTypes(wasmer.I64), + ), ctx, ext_storage_root_version_1) + + importsMap["ext_storage_root_version_2"] = wasmer.NewFunctionWithEnvironment(store, + wasmer.NewFunctionType( + wasmer.NewValueTypes(wasmer.I32), + wasmer.NewValueTypes(wasmer.I64), + ), ctx, ext_storage_root_version_2) + + importsMap["ext_storage_set_version_1"] = wasmer.NewFunctionWithEnvironment(store, + wasmer.NewFunctionType( + wasmer.NewValueTypes(wasmer.I64, wasmer.I64), + wasmer.NewValueTypes(), + ), ctx, ext_storage_set_version_1) + + importsMap["ext_storage_start_transaction_version_1"] = wasmer.NewFunctionWithEnvironment(store, + wasmer.NewFunctionType( + wasmer.NewValueTypes(), + wasmer.NewValueTypes(), + ), ctx, ext_storage_start_transaction_version_1) + + importsMap["ext_storage_rollback_transaction_version_1"] = wasmer.NewFunctionWithEnvironment(store, + wasmer.NewFunctionType( + wasmer.NewValueTypes(), + wasmer.NewValueTypes(), + ), ctx, ext_storage_rollback_transaction_version_1) + + importsMap["ext_storage_commit_transaction_version_1"] = wasmer.NewFunctionWithEnvironment(store, + wasmer.NewFunctionType( + wasmer.NewValueTypes(), + wasmer.NewValueTypes(), + ), ctx, ext_storage_commit_transaction_version_1) + + imports := wasmer.NewImportObject() + imports.Register("env", importsMap) + return imports +} diff --git a/lib/runtime/wasmer/imports_test.go b/lib/runtime/wasmer/imports_test.go index 553547fc73..1bc47992b6 100644 --- a/lib/runtime/wasmer/imports_test.go +++ b/lib/runtime/wasmer/imports_test.go @@ -6,6 +6,7 @@ package wasmer import ( "bytes" "encoding/binary" + "fmt" "net/http" "sort" "testing" @@ -24,9 +25,10 @@ import ( "github.com/ChainSafe/gossamer/lib/trie" "github.com/ChainSafe/gossamer/lib/trie/proof" "github.com/ChainSafe/gossamer/pkg/scale" + "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - "github.com/wasmerio/go-ext-wasm/wasmer" + "github.com/wasmerio/wasmer-go/wasmer" ) var testChildKey = []byte("childKey") @@ -35,14 +37,15 @@ var testValue = []byte("value") func Test_ext_offchain_timestamp_version_1(t *testing.T) { inst := NewTestInstance(t, runtime.HOST_API_TEST_RUNTIME) - runtimeFunc, ok := inst.vm.Exports["rtm_ext_offchain_timestamp_version_1"] - require.True(t, ok) + runtimeFunc, err := inst.vm.Exports.GetFunction("rtm_ext_offchain_timestamp_version_1") + require.NoError(t, err) res, err := runtimeFunc(0, 0) require.NoError(t, err) - outputPtr, outputLength := splitPointerSize(res.ToI64()) - memory := inst.vm.Memory.Data() + wasmRes := wasmer.NewI64(res) + outputPtr, outputLength := splitPointerSize(wasmRes.I64()) + memory := inst.ctx.Memory.Data() data := memory[outputPtr : outputPtr+outputLength] var timestamp int64 err = scale.Unmarshal(data, ×tamp) @@ -64,7 +67,6 @@ func Test_ext_offchain_sleep_until_version_1(t *testing.T) { } func Test_ext_hashing_blake2_128_version_1(t *testing.T) { - t.Parallel() inst := NewTestInstance(t, runtime.HOST_API_TEST_RUNTIME) data := []byte("helloworld") @@ -84,7 +86,6 @@ func Test_ext_hashing_blake2_128_version_1(t *testing.T) { } func Test_ext_hashing_blake2_256_version_1(t *testing.T) { - t.Parallel() inst := NewTestInstance(t, runtime.HOST_API_TEST_RUNTIME) data := []byte("helloworld") @@ -101,10 +102,10 @@ func Test_ext_hashing_blake2_256_version_1(t *testing.T) { expected, err := common.Blake2bHash(data) require.NoError(t, err) require.Equal(t, expected[:], hash) + } func Test_ext_hashing_keccak_256_version_1(t *testing.T) { - t.Parallel() inst := NewTestInstance(t, runtime.HOST_API_TEST_RUNTIME) data := []byte("helloworld") @@ -124,7 +125,6 @@ func Test_ext_hashing_keccak_256_version_1(t *testing.T) { } func Test_ext_hashing_twox_128_version_1(t *testing.T) { - t.Parallel() inst := NewTestInstance(t, runtime.HOST_API_TEST_RUNTIME) data := []byte("helloworld") @@ -144,7 +144,6 @@ func Test_ext_hashing_twox_128_version_1(t *testing.T) { } func Test_ext_hashing_twox_64_version_1(t *testing.T) { - t.Parallel() inst := NewTestInstance(t, runtime.HOST_API_TEST_RUNTIME) data := []byte("helloworld") @@ -161,10 +160,10 @@ func Test_ext_hashing_twox_64_version_1(t *testing.T) { expected, err := common.Twox64(data) require.NoError(t, err) require.Equal(t, expected[:], hash) + } func Test_ext_hashing_sha2_256_version_1(t *testing.T) { - t.Parallel() inst := NewTestInstance(t, runtime.HOST_API_TEST_RUNTIME) data := []byte("helloworld") @@ -183,7 +182,6 @@ func Test_ext_hashing_sha2_256_version_1(t *testing.T) { } func Test_ext_storage_clear_version_1(t *testing.T) { - t.Parallel() inst := NewTestInstance(t, runtime.HOST_API_TEST_RUNTIME) testkey := []byte("noot") @@ -200,11 +198,11 @@ func Test_ext_storage_clear_version_1(t *testing.T) { } func Test_ext_offchain_local_storage_clear_version_1_Persistent(t *testing.T) { - t.Parallel() inst := NewTestInstance(t, runtime.HOST_API_TEST_RUNTIME) testkey := []byte("key1") err := inst.NodeStorage().PersistentStorage.Put(testkey, []byte{1}) + require.NoError(t, err) kind := int32(1) @@ -223,7 +221,6 @@ func Test_ext_offchain_local_storage_clear_version_1_Persistent(t *testing.T) { } func Test_ext_offchain_local_storage_clear_version_1_Local(t *testing.T) { - t.Parallel() inst := NewTestInstance(t, runtime.HOST_API_TEST_RUNTIME) testkey := []byte("key1") @@ -246,7 +243,6 @@ func Test_ext_offchain_local_storage_clear_version_1_Local(t *testing.T) { } func Test_ext_offchain_http_request_start_version_1(t *testing.T) { - t.Parallel() inst := NewTestInstance(t, runtime.HOST_API_TEST_RUNTIME) encMethod, err := scale.Marshal([]byte("GET")) @@ -303,8 +299,6 @@ func Test_ext_offchain_http_request_start_version_1(t *testing.T) { } func Test_ext_offchain_http_request_add_header(t *testing.T) { - t.Parallel() - inst := NewTestInstance(t, runtime.HOST_API_TEST_RUNTIME) cases := map[string]struct { @@ -326,8 +320,6 @@ func Test_ext_offchain_http_request_add_header(t *testing.T) { for tname, tcase := range cases { t.Run(tname, func(t *testing.T) { - t.Parallel() - reqID, err := inst.ctx.OffchainHTTPSet.StartRequest(http.MethodGet, "http://uri.example") require.NoError(t, err) @@ -368,7 +360,6 @@ func Test_ext_offchain_http_request_add_header(t *testing.T) { } func Test_ext_storage_clear_prefix_version_1_hostAPI(t *testing.T) { - t.Parallel() inst := NewTestInstance(t, runtime.HOST_API_TEST_RUNTIME) testkey := []byte("static") @@ -391,7 +382,6 @@ func Test_ext_storage_clear_prefix_version_1_hostAPI(t *testing.T) { } func Test_ext_storage_clear_prefix_version_1(t *testing.T) { - t.Parallel() inst := NewTestInstance(t, runtime.HOST_API_TEST_RUNTIME) testkey := []byte("noot") @@ -414,24 +404,28 @@ func Test_ext_storage_clear_prefix_version_1(t *testing.T) { } func Test_ext_storage_clear_prefix_version_2(t *testing.T) { - t.Parallel() inst := NewTestInstance(t, runtime.HOST_API_TEST_RUNTIME) - testkey := []byte("noot") - inst.ctx.Storage.Put(testkey, []byte{1}) + testkey := []byte("testkey") + err := inst.ctx.Storage.Put(testkey, []byte{1}) + require.NoError(t, err) - testkey2 := []byte("noot1") - inst.ctx.Storage.Put(testkey2, []byte{1}) + testkey2 := []byte("testkey2") + err = inst.ctx.Storage.Put(testkey2, []byte{1}) + require.NoError(t, err) - testkey3 := []byte("noot2") - inst.ctx.Storage.Put(testkey3, []byte{1}) + testkey3 := []byte("testkey3") + err = inst.ctx.Storage.Put(testkey3, []byte{1}) + require.NoError(t, err) - testkey4 := []byte("noot3") - inst.ctx.Storage.Put(testkey4, []byte{1}) + testkey4 := []byte("testkey4") + err = inst.ctx.Storage.Put(testkey4, []byte{1}) + require.NoError(t, err) - testkey5 := []byte("spaghet") + testkey5 := []byte("keyToKeep") testValue5 := []byte{2} - inst.ctx.Storage.Put(testkey5, testValue5) + err = inst.ctx.Storage.Put(testkey5, testValue5) + require.NoError(t, err) enc, err := scale.Marshal(testkey[:3]) require.NoError(t, err) @@ -448,11 +442,13 @@ func Test_ext_storage_clear_prefix_version_2(t *testing.T) { require.NoError(t, err) var decVal []byte - scale.Unmarshal(encValue, &decVal) + err = scale.Unmarshal(encValue, &decVal) + require.NoError(t, err) var numDeleted uint32 // numDeleted represents no. of actual keys deleted - scale.Unmarshal(decVal[1:], &numDeleted) + err = scale.Unmarshal(decVal[1:], &numDeleted) + require.NoError(t, err) require.Equal(t, uint32(2), numDeleted) var expectedAllDeleted byte @@ -471,8 +467,10 @@ func Test_ext_storage_clear_prefix_version_2(t *testing.T) { encValue, err = inst.Exec("rtm_ext_storage_clear_prefix_version_2", append(enc, optLimit...)) require.NoError(t, err) - scale.Unmarshal(encValue, &decVal) - scale.Unmarshal(decVal[1:], &numDeleted) + err = scale.Unmarshal(encValue, &decVal) + require.NoError(t, err) + err = scale.Unmarshal(decVal[1:], &numDeleted) + require.NoError(t, err) require.Equal(t, uint32(2), numDeleted) expectedAllDeleted = 0 @@ -487,7 +485,6 @@ func Test_ext_storage_clear_prefix_version_2(t *testing.T) { } func Test_ext_storage_get_version_1(t *testing.T) { - t.Parallel() inst := NewTestInstance(t, runtime.HOST_API_TEST_RUNTIME) testkey := []byte("noot") @@ -508,8 +505,6 @@ func Test_ext_storage_get_version_1(t *testing.T) { } func Test_ext_storage_exists_version_1(t *testing.T) { - t.Parallel() - testCases := map[string]struct { key []byte value []byte // leave to nil to not insert pair @@ -534,7 +529,6 @@ func Test_ext_storage_exists_version_1(t *testing.T) { for name, testCase := range testCases { testCase := testCase t.Run(name, func(t *testing.T) { - t.Parallel() instance := NewTestInstance(t, runtime.HOST_API_TEST_RUNTIME) if testCase.value != nil { @@ -557,7 +551,6 @@ func Test_ext_storage_exists_version_1(t *testing.T) { } func Test_ext_storage_next_key_version_1(t *testing.T) { - t.Parallel() inst := NewTestInstance(t, runtime.HOST_API_TEST_RUNTIME) testkey := []byte("noot") @@ -580,7 +573,6 @@ func Test_ext_storage_next_key_version_1(t *testing.T) { } func Test_ext_storage_read_version_1(t *testing.T) { - t.Parallel() inst := NewTestInstance(t, runtime.HOST_API_TEST_RUNTIME) testkey := []byte("noot") @@ -609,7 +601,6 @@ func Test_ext_storage_read_version_1(t *testing.T) { } func Test_ext_storage_read_version_1_again(t *testing.T) { - t.Parallel() inst := NewTestInstance(t, runtime.HOST_API_TEST_RUNTIME) testkey := []byte("noot") @@ -639,7 +630,6 @@ func Test_ext_storage_read_version_1_again(t *testing.T) { } func Test_ext_storage_read_version_1_OffsetLargerThanValue(t *testing.T) { - t.Parallel() inst := NewTestInstance(t, runtime.HOST_API_TEST_RUNTIME) testkey := []byte("noot") @@ -668,7 +658,6 @@ func Test_ext_storage_read_version_1_OffsetLargerThanValue(t *testing.T) { } func Test_ext_storage_root_version_1(t *testing.T) { - t.Parallel() inst := NewTestInstance(t, runtime.HOST_API_TEST_RUNTIME) ret, err := inst.Exec("rtm_ext_storage_root_version_1", []byte{}) @@ -683,7 +672,6 @@ func Test_ext_storage_root_version_1(t *testing.T) { } func Test_ext_storage_set_version_1(t *testing.T) { - t.Parallel() inst := NewTestInstance(t, runtime.HOST_API_TEST_RUNTIME) testkey := []byte("noot") @@ -702,7 +690,6 @@ func Test_ext_storage_set_version_1(t *testing.T) { } func Test_ext_offline_index_set_version_1(t *testing.T) { - t.Parallel() // TODO this currently fails with error could not find exported function, add rtm_ func to tester wasm (#1026) t.Skip() inst := NewTestInstance(t, runtime.HOST_API_TEST_RUNTIME) @@ -724,7 +711,6 @@ func Test_ext_offline_index_set_version_1(t *testing.T) { } func Test_ext_crypto_ed25519_generate_version_1(t *testing.T) { - t.Parallel() inst := NewTestInstance(t, runtime.HOST_API_TEST_RUNTIME) idData := []byte(keystore.AccoName) @@ -747,20 +733,21 @@ func Test_ext_crypto_ed25519_generate_version_1(t *testing.T) { ptr, err := inst.ctx.Allocator.Allocate(uint32(len(params))) require.NoError(t, err) - memory := inst.vm.Memory.Data() + memory := inst.ctx.Memory.Data() copy(memory[ptr:ptr+uint32(len(params))], params) dataLen := int32(len(params)) - - runtimeFunc, ok := inst.vm.Exports["rtm_ext_crypto_ed25519_generate_version_1"] - require.True(t, ok) + runtimeFunc, err := inst.vm.Exports.GetFunction("rtm_ext_crypto_ed25519_generate_version_1") + require.NoError(t, err) ret, err := runtimeFunc(int32(ptr), dataLen) require.NoError(t, err) - mem := inst.vm.Memory.Data() + mem := inst.ctx.Memory.Data() + wasmRetI64 := wasmer.NewI64(ret) + retI64 := wasmRetI64.I64() // this SCALE encoded, but it should just be a 32 byte buffer. may be due to way test runtime is written. - pubKeyBytes := mem[ret.ToI32()+1 : ret.ToI32()+1+32] + pubKeyBytes := mem[int32(retI64)+1 : int32(retI64)+1+32] pubKey, err := ed25519.NewPublicKey(pubKeyBytes) require.NoError(t, err) @@ -770,7 +757,6 @@ func Test_ext_crypto_ed25519_generate_version_1(t *testing.T) { } func Test_ext_crypto_ed25519_public_keys_version_1(t *testing.T) { - t.Parallel() inst := NewTestInstance(t, runtime.HOST_API_TEST_RUNTIME) idData := []byte(keystore.DumyName) @@ -810,7 +796,6 @@ func Test_ext_crypto_ed25519_public_keys_version_1(t *testing.T) { } func Test_ext_crypto_ed25519_sign_version_1(t *testing.T) { - t.Parallel() inst := NewTestInstance(t, runtime.HOST_API_TEST_RUNTIME) kp, err := ed25519.GenerateKeypair() @@ -849,7 +834,6 @@ func Test_ext_crypto_ed25519_sign_version_1(t *testing.T) { } func Test_ext_crypto_ed25519_verify_version_1(t *testing.T) { - t.Parallel() inst := NewTestInstance(t, runtime.HOST_API_TEST_RUNTIME) kp, err := ed25519.GenerateKeypair() @@ -882,8 +866,6 @@ func Test_ext_crypto_ed25519_verify_version_1(t *testing.T) { } func Test_ext_crypto_ecdsa_verify_version_2(t *testing.T) { - t.Parallel() - inst := NewTestInstance(t, runtime.HOST_API_TEST_RUNTIME) kp, err := secp256k1.GenerateKeypair() @@ -917,7 +899,6 @@ func Test_ext_crypto_ecdsa_verify_version_2(t *testing.T) { } func Test_ext_crypto_ecdsa_verify_version_2_Table(t *testing.T) { - t.Parallel() testCases := map[string]struct { sig []byte msg []byte @@ -943,30 +924,23 @@ func Test_ext_crypto_ecdsa_verify_version_2_Table(t *testing.T) { key: []byte{132, 2, 39, 0, 55, 134, 131, 142, 43, 100, 63, 134, 96, 14, 253, 15, 222, 119, 154, 110, 188, 20, 159, 62, 125, 42, 59, 127, 19, 16, 0, 161, 236, 109}, //nolint:lll expected: []byte{0, 0, 0, 0}, }, - "invalid_key": { + "invalid_key_length": { sig: []byte{5, 1, 187, 0, 0, 183, 46, 115, 242, 32, 9, 54, 141, 207, 44, 15, 238, 42, 217, 196, 111, 173, 239, 204, 128, 93, 49, 179, 137, 150, 162, 125, 226, 225, 28, 145, 122, 127, 15, 154, 185, 11, 3, 66, 27, 187, 204, 242, 107, 68, 26, 111, 245, 30, 115, 141, 85, 74, 158, 211, 161, 217, 43, 151, 120, 125, 1}, //nolint:lll msg: []byte{48, 72, 101, 108, 108, 111, 32, 119, 111, 114, 108, 100, 33}, key: []byte{132, 2, 39, 55, 134, 131, 142, 43, 100, 63, 134, 96, 14, 253, 15, 222, 119, 154, 110, 188, 20, 159, 62, 125, 42, 59, 127, 19, 16, 0, 161, 236, 109}, //nolint:lll - err: wasmer.NewExportedFunctionError( - "rtm_ext_crypto_ecdsa_verify_version_2", - "running runtime function: Failed to call the `%s` exported function."), + err: fmt.Errorf("running runtime function: unreachable"), }, - "invalid_message": { + "invalid_message_length": { sig: []byte{5, 1, 187, 179, 88, 183, 46, 115, 242, 32, 9, 54, 141, 207, 44, 15, 238, 42, 217, 196, 111, 173, 239, 204, 128, 93, 49, 179, 137, 150, 162, 125, 226, 225, 28, 145, 122, 127, 15, 154, 185, 11, 3, 66, 27, 187, 204, 242, 107, 68, 26, 111, 245, 30, 115, 141, 85, 74, 158, 211, 161, 217, 43, 151, 120, 125, 1}, //nolint:lll msg: []byte{48, 72, 101, 108, 108, 111, 32, 119, 111, 114, 108, 100}, key: []byte{132, 2, 39, 206, 55, 134, 131, 142, 43, 100, 63, 134, 96, 14, 253, 15, 222, 119, 154, 110, 188, 20, 159, 62, 125, 42, 59, 127, 19, 16, 0, 161, 236, 109}, //nolint:lll - err: wasmer.NewExportedFunctionError( - "rtm_ext_crypto_ecdsa_verify_version_2", - "running runtime function: Failed to call the `%s` exported function."), + err: fmt.Errorf("running runtime function: unreachable"), }, } for name, tc := range testCases { tc := tc t.Run(name, func(t *testing.T) { - t.Parallel() - inst := NewTestInstance(t, runtime.HOST_API_TEST_RUNTIME) - ret, err := inst.Exec("rtm_ext_crypto_ecdsa_verify_version_2", append(append(tc.sig, tc.msg...), tc.key...)) assert.Equal(t, tc.expected, ret) if tc.err != nil { @@ -979,7 +953,6 @@ func Test_ext_crypto_ecdsa_verify_version_2_Table(t *testing.T) { } func Test_ext_crypto_sr25519_generate_version_1(t *testing.T) { - t.Parallel() inst := NewTestInstance(t, runtime.HOST_API_TEST_RUNTIME) idData := []byte(keystore.AccoName) @@ -1012,7 +985,6 @@ func Test_ext_crypto_sr25519_generate_version_1(t *testing.T) { } func Test_ext_crypto_secp256k1_ecdsa_recover_version_1(t *testing.T) { - t.Parallel() inst := NewTestInstance(t, runtime.HOST_API_TEST_RUNTIME) msgData := []byte("Hello world!") @@ -1056,7 +1028,6 @@ func Test_ext_crypto_secp256k1_ecdsa_recover_version_1(t *testing.T) { } func Test_ext_crypto_secp256k1_ecdsa_recover_compressed_version_1(t *testing.T) { - t.Parallel() t.Skip("host API tester does not yet contain rtm_ext_crypto_secp256k1_ecdsa_recover_compressed_version_1") inst := NewTestInstance(t, runtime.HOST_API_TEST_RUNTIME) @@ -1100,7 +1071,6 @@ func Test_ext_crypto_secp256k1_ecdsa_recover_compressed_version_1(t *testing.T) } func Test_ext_crypto_sr25519_public_keys_version_1(t *testing.T) { - t.Parallel() inst := NewTestInstance(t, runtime.HOST_API_TEST_RUNTIME) idData := []byte(keystore.DumyName) @@ -1140,7 +1110,6 @@ func Test_ext_crypto_sr25519_public_keys_version_1(t *testing.T) { } func Test_ext_crypto_sr25519_sign_version_1(t *testing.T) { - t.Parallel() inst := NewTestInstance(t, runtime.HOST_API_TEST_RUNTIME) kp, err := sr25519.GenerateKeypair() @@ -1181,7 +1150,6 @@ func Test_ext_crypto_sr25519_sign_version_1(t *testing.T) { } func Test_ext_crypto_sr25519_verify_version_1(t *testing.T) { - t.Parallel() inst := NewTestInstance(t, runtime.HOST_API_TEST_RUNTIME) kp, err := sr25519.GenerateKeypair() @@ -1214,7 +1182,6 @@ func Test_ext_crypto_sr25519_verify_version_1(t *testing.T) { } func Test_ext_default_child_storage_read_version_1(t *testing.T) { - t.Parallel() inst := NewTestInstance(t, runtime.HOST_API_TEST_RUNTIME) err := inst.ctx.Storage.SetChild(testChildKey, trie.NewEmptyTrie()) @@ -1254,7 +1221,6 @@ func Test_ext_default_child_storage_read_version_1(t *testing.T) { } func Test_ext_default_child_storage_clear_version_1(t *testing.T) { - t.Parallel() inst := NewTestInstance(t, runtime.HOST_API_TEST_RUNTIME) err := inst.ctx.Storage.SetChild(testChildKey, trie.NewEmptyTrie()) @@ -1283,7 +1249,6 @@ func Test_ext_default_child_storage_clear_version_1(t *testing.T) { } func Test_ext_default_child_storage_clear_prefix_version_1(t *testing.T) { - t.Parallel() inst := NewTestInstance(t, runtime.HOST_API_TEST_RUNTIME) prefix := []byte("key") @@ -1325,7 +1290,6 @@ func Test_ext_default_child_storage_clear_prefix_version_1(t *testing.T) { } func Test_ext_default_child_storage_exists_version_1(t *testing.T) { - t.Parallel() inst := NewTestInstance(t, runtime.HOST_API_TEST_RUNTIME) err := inst.ctx.Storage.SetChild(testChildKey, trie.NewEmptyTrie()) @@ -1350,7 +1314,6 @@ func Test_ext_default_child_storage_exists_version_1(t *testing.T) { } func Test_ext_default_child_storage_get_version_1(t *testing.T) { - t.Parallel() inst := NewTestInstance(t, runtime.HOST_API_TEST_RUNTIME) err := inst.ctx.Storage.SetChild(testChildKey, trie.NewEmptyTrie()) @@ -1375,7 +1338,6 @@ func Test_ext_default_child_storage_get_version_1(t *testing.T) { } func Test_ext_default_child_storage_next_key_version_1(t *testing.T) { - t.Parallel() inst := NewTestInstance(t, runtime.HOST_API_TEST_RUNTIME) testKeyValuePair := []struct { @@ -1413,7 +1375,6 @@ func Test_ext_default_child_storage_next_key_version_1(t *testing.T) { } func Test_ext_default_child_storage_root_version_1(t *testing.T) { - t.Parallel() inst := NewTestInstance(t, runtime.HOST_API_TEST_RUNTIME) err := inst.ctx.Storage.SetChild(testChildKey, trie.NewEmptyTrie()) @@ -1446,7 +1407,6 @@ func Test_ext_default_child_storage_root_version_1(t *testing.T) { } func Test_ext_default_child_storage_set_version_1(t *testing.T) { - t.Parallel() inst := NewTestInstance(t, runtime.HOST_API_TEST_RUNTIME) err := inst.ctx.Storage.SetChild(testChildKey, trie.NewEmptyTrie()) @@ -1475,7 +1435,6 @@ func Test_ext_default_child_storage_set_version_1(t *testing.T) { } func Test_ext_default_child_storage_storage_kill_version_1(t *testing.T) { - t.Parallel() inst := NewTestInstance(t, runtime.HOST_API_TEST_RUNTIME) err := inst.ctx.Storage.SetChild(testChildKey, trie.NewEmptyTrie()) @@ -1497,7 +1456,6 @@ func Test_ext_default_child_storage_storage_kill_version_1(t *testing.T) { } func Test_ext_default_child_storage_storage_kill_version_2_limit_all(t *testing.T) { - t.Parallel() inst := NewTestInstance(t, runtime.HOST_API_TEST_RUNTIME) tr := trie.NewEmptyTrie() @@ -1531,7 +1489,6 @@ func Test_ext_default_child_storage_storage_kill_version_2_limit_all(t *testing. } func Test_ext_default_child_storage_storage_kill_version_2_limit_1(t *testing.T) { - t.Parallel() inst := NewTestInstance(t, runtime.HOST_API_TEST_RUNTIME) tr := trie.NewEmptyTrie() @@ -1565,7 +1522,6 @@ func Test_ext_default_child_storage_storage_kill_version_2_limit_1(t *testing.T) } func Test_ext_default_child_storage_storage_kill_version_2_limit_none(t *testing.T) { - t.Parallel() inst := NewTestInstance(t, runtime.HOST_API_TEST_RUNTIME) tr := trie.NewEmptyTrie() @@ -1596,7 +1552,6 @@ func Test_ext_default_child_storage_storage_kill_version_2_limit_none(t *testing } func Test_ext_default_child_storage_storage_kill_version_3(t *testing.T) { - t.Parallel() inst := NewTestInstance(t, runtime.HOST_API_TEST_RUNTIME) tr := trie.NewEmptyTrie() @@ -1620,8 +1575,7 @@ func Test_ext_default_child_storage_storage_kill_version_3(t *testing.T) { key: []byte(`fakekey`), limit: optLimit2, expected: []byte{0, 0, 0, 0, 0}, - errMsg: "running runtime function: " + - "Failed to call the `rtm_ext_default_child_storage_storage_kill_version_3` exported function.", + errMsg: "running runtime function: unreachable", }, {key: testChildKey, limit: optLimit2, expected: []byte{1, 2, 0, 0, 0}}, {key: testChildKey, limit: nil, expected: []byte{0, 1, 0, 0, 0}}, @@ -1649,7 +1603,6 @@ func Test_ext_default_child_storage_storage_kill_version_3(t *testing.T) { } func Test_ext_storage_append_version_1(t *testing.T) { - t.Parallel() inst := NewTestInstance(t, runtime.HOST_API_TEST_RUNTIME) testkey := []byte("noot") @@ -1698,7 +1651,6 @@ func Test_ext_storage_append_version_1(t *testing.T) { } func Test_ext_storage_append_version_1_again(t *testing.T) { - t.Parallel() DefaultTestLogLvl = 5 inst := NewTestInstance(t, runtime.HOST_API_TEST_RUNTIME) @@ -1748,7 +1700,6 @@ func Test_ext_storage_append_version_1_again(t *testing.T) { } func Test_ext_trie_blake2_256_ordered_root_version_1(t *testing.T) { - t.Parallel() inst := NewTestInstance(t, runtime.HOST_API_TEST_RUNTIME) testvalues := []string{"static", "even-keeled", "Future-proofed"} @@ -1767,7 +1718,6 @@ func Test_ext_trie_blake2_256_ordered_root_version_1(t *testing.T) { } func Test_ext_trie_blake2_256_root_version_1(t *testing.T) { - t.Parallel() inst := NewTestInstance(t, runtime.HOST_API_TEST_RUNTIME) testinput := []string{"noot", "was", "here", "??"} @@ -1791,8 +1741,6 @@ func Test_ext_trie_blake2_256_root_version_1(t *testing.T) { } func Test_ext_trie_blake2_256_verify_proof_version_1(t *testing.T) { - t.Parallel() - tmp := t.TempDir() memdb, err := chaindb.NewBadgerDB(&chaindb.Config{ @@ -1860,8 +1808,6 @@ func Test_ext_trie_blake2_256_verify_proof_version_1(t *testing.T) { for name, testcase := range testcases { testcase := testcase t.Run(name, func(t *testing.T) { - t.Parallel() - hashEnc, err := scale.Marshal(testcase.root) require.NoError(t, err) diff --git a/lib/runtime/wasmer/instance.go b/lib/runtime/wasmer/instance.go index f7aa63a835..fd4cd12c16 100644 --- a/lib/runtime/wasmer/instance.go +++ b/lib/runtime/wasmer/instance.go @@ -7,35 +7,39 @@ import ( "bytes" "errors" "fmt" + "os" + "path/filepath" "sync" "github.com/ChainSafe/gossamer/internal/log" "github.com/ChainSafe/gossamer/lib/common" + "github.com/ChainSafe/gossamer/lib/crypto" "github.com/ChainSafe/gossamer/lib/keystore" "github.com/ChainSafe/gossamer/lib/runtime" "github.com/ChainSafe/gossamer/lib/runtime/offchain" "github.com/ChainSafe/gossamer/lib/trie" - - "github.com/ChainSafe/gossamer/lib/crypto" - - wasm "github.com/wasmerio/go-ext-wasm/wasmer" - "github.com/klauspost/compress/zstd" + "github.com/wasmerio/wasmer-go/wasmer" ) // Name represents the name of the interpreter const Name = "wasmer" var ( + ErrCodeEmpty = errors.New("code is empty") + ErrWASMDecompress = errors.New("wasm decompression failed") + ErrInstanceIsStopped = errors.New("instance is stopped") + ErrExportFunctionNotFound = errors.New("export function not found") + logger = log.NewFromGlobal( log.AddContext("pkg", "runtime"), log.AddContext("module", "go-wasmer"), ) ) -// Instance represents a v0.8 runtime go-wasmer instance +// Instance represents a runtime go-wasmer instance type Instance struct { - vm wasm.Instance + vm *wasmer.Instance ctx *runtime.Context isClosed bool codeHash common.Hash @@ -69,26 +73,80 @@ func NewInstanceFromTrie(t *trie.Trie, cfg Config) (*Instance, error) { // NewInstanceFromFile instantiates a runtime from a .wasm file func NewInstanceFromFile(fp string, cfg Config) (*Instance, error) { // Reads the WebAssembly module as bytes. - bytes, err := wasm.ReadBytes(fp) + fileBytes, err := os.ReadFile(filepath.Clean(fp)) if err != nil { return nil, err } - return NewInstance(bytes, cfg) + return NewInstance(fileBytes, cfg) } // NewInstance instantiates a runtime from raw wasm bytecode -func NewInstance(code []byte, cfg Config) (instance *Instance, err error) { +func NewInstance(code []byte, cfg Config) (*Instance, error) { logger.Patch(log.SetLevel(cfg.LogLvl), log.SetCallerFunc(true)) + if len(code) == 0 { + return nil, ErrCodeEmpty + } - wasmInstance, allocator, err := setupVM(code) + code, err := decompressWasm(code) if err != nil { - return nil, fmt.Errorf("setting up VM: %w", err) + // Note the sentinel error is wrapped here since the ztsd Go library + // does not return any exported sentinel errors. + return nil, fmt.Errorf("%w: %s", ErrWASMDecompress, err) + } + + // Create engine and store with default values + engine := wasmer.NewEngine() + store := wasmer.NewStore(engine) + + // Compile the module + module, err := wasmer.NewModule(store, code) + if err != nil { + return nil, err + } + + // Get memory descriptor from module, if it imports memory + moduleImports := module.Imports() + var memImport *wasmer.ImportType + for _, im := range moduleImports { + if im.Name() == "memory" { + memImport = im + break + } + } + + var memoryType *wasmer.MemoryType + if memImport != nil { + memoryType = memImport.Type().IntoMemoryType() + } + + // Check if module exports memory + hasExportedMemory := false + moduleExports := module.Exports() + for _, export := range moduleExports { + if export.Name() == "memory" { + hasExportedMemory = true + break + } + } + + var memory *wasmer.Memory + // create memory to import, if it's expecting imported memory + if !hasExportedMemory { + if memoryType == nil { + // values from newer kusama/polkadot runtimes + lim, err := wasmer.NewLimits(23, 4294967295) + if err != nil { + return nil, err + } + memoryType = wasmer.NewMemoryType(lim) + } + + memory = wasmer.NewMemory(store, memoryType) } runtimeCtx := &runtime.Context{ Storage: cfg.Storage, - Allocator: allocator, Keystore: cfg.Keystore, Validator: cfg.Role == common.AuthorityRole, NodeStorage: cfg.NodeStorage, @@ -97,9 +155,38 @@ func NewInstance(code []byte, cfg Config) (instance *Instance, err error) { SigVerifier: crypto.NewSignatureVerifier(logger), OffchainHTTPSet: offchain.NewHTTPSet(), } - wasmInstance.SetContextData(runtimeCtx) - instance = &Instance{ + imports := importsNodeRuntime(store, memory, runtimeCtx) + if err != nil { + return nil, fmt.Errorf("creating node runtime imports: %w", err) + } + wasmInstance, err := wasmer.NewInstance(module, imports) + if err != nil { + return nil, err + } + + if hasExportedMemory { + memory, err = wasmInstance.Exports.GetMemory("memory") + if err != nil { + return nil, err + } + } + + runtimeCtx.Memory = Memory{memory} + + // set heap base for allocator, start allocating at heap base + heapBase, err := wasmInstance.Exports.Get("__heap_base") + if err != nil { + return nil, err + } + + hb, err := heapBase.IntoGlobal().Get() + if err != nil { + return nil, err + } + + runtimeCtx.Allocator = runtime.NewAllocator(runtimeCtx.Memory, uint32(hb.(int32))) + instance := &Instance{ vm: wasmInstance, ctx: runtimeCtx, codeHash: cfg.CodeHash, @@ -115,8 +202,6 @@ func NewInstance(code []byte, cfg Config) (instance *Instance, err error) { } } - wasmInstance.SetContextData(instance.ctx) - return instance, nil } @@ -146,36 +231,6 @@ func (in *Instance) GetContext() *runtime.Context { return in.ctx } -// UpdateRuntimeCode updates the runtime instance to run the given code -func (in *Instance) UpdateRuntimeCode(code []byte) (err error) { - wasmInstance, allocator, err := setupVM(code) - if err != nil { - return fmt.Errorf("setting up VM: %w", err) - } - - in.mutex.Lock() - defer in.mutex.Unlock() - - in.close() - - in.ctx.Allocator = allocator - wasmInstance.SetContextData(in.ctx) - - in.vm = wasmInstance - - // Find runtime instance version and cache it in its - // instance context. - version, err := in.version() - if err != nil { - in.close() - return fmt.Errorf("getting instance version: %w", err) - } - in.ctx.Version = version - wasmInstance.SetContextData(in.ctx) - - return nil -} - // GetRuntimeVersion finds the runtime version by initiating a temporary // runtime instance using the WASM code provided, and querying it. func GetRuntimeVersion(code []byte) (version runtime.Version, err error) { @@ -188,6 +243,8 @@ func GetRuntimeVersion(code []byte) (version runtime.Version, err error) { } defer instance.Stop() + logger.Info("instantiated runtime!!!") + version, err = instance.version() if err != nil { return version, fmt.Errorf("running runtime: %w", err) @@ -196,60 +253,77 @@ func GetRuntimeVersion(code []byte) (version runtime.Version, err error) { return version, nil } -var ( - ErrCodeEmpty = errors.New("code is empty") - ErrWASMDecompress = errors.New("wasm decompression failed") -) +// Exec calls the given function with the given data +func (in *Instance) Exec(function string, data []byte) (result []byte, err error) { + in.mutex.Lock() + defer in.mutex.Unlock() -func setupVM(code []byte) (instance wasm.Instance, - allocator *runtime.FreeingBumpHeapAllocator, err error) { - if len(code) == 0 { - return instance, nil, ErrCodeEmpty + if in.isClosed { + return nil, ErrInstanceIsStopped } - code, err = decompressWasm(code) + dataLength := uint32(len(data)) + inputPtr, err := in.ctx.Allocator.Allocate(dataLength) if err != nil { - // Note the sentinel error is wrapped here since the ztsd Go library - // does not return any exported sentinel errors. - return instance, nil, fmt.Errorf("%w: %s", ErrWASMDecompress, err) + return nil, fmt.Errorf("allocating input memory: %w", err) } - imports, err := importsNodeRuntime() + defer in.ctx.Allocator.Clear() + + // Store the data into memory + memory := in.ctx.Memory.Data() + copy(memory[inputPtr:inputPtr+dataLength], data) + + runtimeFunc, err := in.vm.Exports.GetFunction(function) if err != nil { - return instance, nil, fmt.Errorf("creating node runtime imports: %w", err) + return nil, fmt.Errorf("%w: %s", ErrExportFunctionNotFound, function) } - // Provide importable memory for newer runtimes - // TODO: determine memory descriptor size that the runtime wants from the wasm. - // should be doable w/ wasmer 1.0.0. (#1268) - memory, err := wasm.NewMemory(23, 0) + castedInputPointer, err := safeCastInt32(inputPtr) if err != nil { - return instance, nil, fmt.Errorf("creating web assembly memory: %w", err) + panic(err) } - _, err = imports.AppendMemory("memory", memory) + castedDataLength, err := safeCastInt32(dataLength) if err != nil { - return instance, nil, fmt.Errorf("appending memory to imports: %w", err) + panic(err) } - // Instantiates the WebAssembly module. - instance, err = wasm.NewInstanceWithImports(code, imports) + wasmValue, err := runtimeFunc(castedInputPointer, castedDataLength) if err != nil { - return instance, nil, fmt.Errorf("creating web assembly instance: %w", err) + if errors.Is(err, errMemoryValueOutOfBounds) { + panic(fmt.Errorf("executing runtime function: %v", err)) + } + return nil, fmt.Errorf("running runtime function: %w", err) } - // Assume imported memory is used if runtime does not export any - if !instance.HasMemory() { - instance.Memory = memory - } + wasmValueAsI64 := wasmer.NewI64(wasmValue) + outputPtr, outputLength := splitPointerSize(wasmValueAsI64.I64()) + memory = in.ctx.Memory.Data() // call Data() again to get larger slice + + allocatedData := make([]byte, outputLength) + copy(allocatedData[:], memory[outputPtr:outputPtr+outputLength]) + return allocatedData, nil +} - // TODO: get __heap_base exported value from runtime. - // wasmer 0.3.x does not support this, but wasmer 1.0.0 does (#1268) - heapBase := runtime.DefaultHeapBase +// NodeStorage to get reference to runtime node service +func (in *Instance) NodeStorage() runtime.NodeStorage { + return in.ctx.NodeStorage +} + +// NetworkService to get referernce to runtime network service +func (in *Instance) NetworkService() runtime.BasicNetwork { + return in.ctx.Network +} - allocator = runtime.NewAllocator(instance.Memory, heapBase) +// Keystore to get reference to runtime keystore +func (in *Instance) Keystore() *keystore.GlobalKeystore { + return in.ctx.Keystore +} - return instance, allocator, nil +// Validator returns the context's Validator +func (in *Instance) Validator() bool { + return in.ctx.Validator } // SetContextStorage sets the runtime's storage. @@ -280,64 +354,3 @@ func (in *Instance) close() { in.ctx.Allocator.Clear() in.isClosed = true } - -var ( - ErrInstanceIsStopped = errors.New("instance is stopped") - ErrExportFunctionNotFound = errors.New("export function not found") -) - -// Exec calls the given function with the given data -func (in *Instance) Exec(function string, data []byte) (result []byte, err error) { - in.mutex.Lock() - defer in.mutex.Unlock() - - if in.isClosed { - return nil, ErrInstanceIsStopped - } - - dataLength := uint32(len(data)) - inputPtr, err := in.ctx.Allocator.Allocate(dataLength) - if err != nil { - return nil, fmt.Errorf("allocating input memory: %w", err) - } - - defer in.ctx.Allocator.Clear() - - // Store the data into memory - memory := in.vm.Memory.Data() - copy(memory[inputPtr:inputPtr+dataLength], data) - - runtimeFunc, ok := in.vm.Exports[function] - if !ok { - return nil, fmt.Errorf("%w: %s", ErrExportFunctionNotFound, function) - } - - wasmValue, err := runtimeFunc(int32(inputPtr), int32(dataLength)) - if err != nil { - return nil, fmt.Errorf("running runtime function: %w", err) - } - - outputPtr, outputLength := splitPointerSize(wasmValue.ToI64()) - memory = in.vm.Memory.Data() // call Data() again to get larger slice - return memory[outputPtr : outputPtr+outputLength], nil -} - -// NodeStorage to get reference to runtime node service -func (in *Instance) NodeStorage() runtime.NodeStorage { - return in.ctx.NodeStorage -} - -// NetworkService to get referernce to runtime network service -func (in *Instance) NetworkService() runtime.BasicNetwork { - return in.ctx.Network -} - -// Keystore to get reference to runtime keystore -func (in *Instance) Keystore() *keystore.GlobalKeystore { - return in.ctx.Keystore -} - -// Validator returns the context's Validator -func (in *Instance) Validator() bool { - return in.ctx.Validator -} diff --git a/lib/runtime/wasmer/instance_test.go b/lib/runtime/wasmer/instance_test.go index 546cca7f83..e2f20d3410 100644 --- a/lib/runtime/wasmer/instance_test.go +++ b/lib/runtime/wasmer/instance_test.go @@ -9,12 +9,11 @@ import ( "testing" "github.com/ChainSafe/gossamer/lib/runtime" - "github.com/stretchr/testify/require" - "github.com/klauspost/compress/zstd" + "github.com/stretchr/testify/require" ) -// test used for ensuring runtime exec calls can me made concurrently +// test used for ensuring runtime exec calls can be made concurrently func TestConcurrentRuntimeCalls(t *testing.T) { instance := NewTestInstance(t, runtime.WESTEND_RUNTIME_v0929) diff --git a/lib/runtime/newWasmer/memory.go b/lib/runtime/wasmer/memory.go similarity index 98% rename from lib/runtime/newWasmer/memory.go rename to lib/runtime/wasmer/memory.go index e18f8856ee..13f1e0f460 100644 --- a/lib/runtime/newWasmer/memory.go +++ b/lib/runtime/wasmer/memory.go @@ -1,7 +1,7 @@ // Copyright 2023 ChainSafe Systems (ON) // SPDX-License-Identifier: LGPL-3.0-only -package latestwasmer +package wasmer import ( "errors" diff --git a/lib/runtime/newWasmer/memory_test.go b/lib/runtime/wasmer/memory_test.go similarity index 97% rename from lib/runtime/newWasmer/memory_test.go rename to lib/runtime/wasmer/memory_test.go index 6e3bfe94ec..5ec5b8b184 100644 --- a/lib/runtime/newWasmer/memory_test.go +++ b/lib/runtime/wasmer/memory_test.go @@ -1,7 +1,7 @@ // Copyright 2023 ChainSafe Systems (ON) // SPDX-License-Identifier: LGPL-3.0-only -package latestwasmer +package wasmer import ( "math" @@ -49,7 +49,6 @@ func createInstance(t *testing.T) (*wasmer.Instance, error) { } func TestMemory_Length(t *testing.T) { - t.Parallel() const pageLength uint32 = 65536 instance, err := createInstance(t) require.NoError(t, err) @@ -66,7 +65,6 @@ func TestMemory_Length(t *testing.T) { } func TestMemory_Grow(t *testing.T) { - t.Parallel() const pageLength uint32 = 65536 instance, err := createInstance(t) require.NoError(t, err) @@ -89,7 +87,6 @@ func TestMemory_Grow(t *testing.T) { } func TestMemory_Data(t *testing.T) { - t.Parallel() instance, err := createInstance(t) require.NoError(t, err) @@ -134,7 +131,6 @@ func TestMemory_Data(t *testing.T) { } func TestMemory_CheckBounds(t *testing.T) { - t.Parallel() testCases := []struct { name string value uint64 @@ -162,8 +158,6 @@ func TestMemory_CheckBounds(t *testing.T) { for _, test := range testCases { test := test t.Run(test.name, func(t *testing.T) { - t.Parallel() - res, err := checkBounds(test.value) assert.ErrorIs(t, err, test.expErr) if test.expErr != nil {