From 2ad89c437601b7afe95849266a8853604e518a8c Mon Sep 17 00:00:00 2001 From: Simon Warta Date: Tue, 13 Dec 2022 16:50:27 +0100 Subject: [PATCH 01/25] Add build_shared_library_windows --- .circleci/config.yml | 48 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) diff --git a/.circleci/config.yml b/.circleci/config.yml index 8a4c9584..dd7169b8 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -247,6 +247,53 @@ jobs: - libwasmvm/target/release/deps key: cargocache-v3-build_shared_library-rust:1.60.0-{{ checksum "libwasmvm/Cargo.lock" }} + # Analogue to build_shared_library this builds wasmvm.dll using a native Rust installation + # (i.e. no docker builders). In contrast to libwasmvm_sanity_windows this is a release build + # and gets its own build cache. + build_shared_library_windows: + executor: + name: win/default + shell: bash.exe + steps: + - checkout + - run: + name: Reset git config set by CircleCI to make Cargo work + command: git config --global --unset url.ssh://git@github.com.insteadof + - run: + name: Install make + command: | + set -o errexit + choco install -y make + - run: + name: Install Rust + command: | + set -o errexit + curl -sS --output rustup-init.exe https://static.rust-lang.org/rustup/dist/x86_64-pc-windows-msvc/rustup-init.exe + ./rustup-init.exe --no-modify-path --profile minimal --default-toolchain 1.60.0 -y + echo 'export PATH="$PATH;$USERPROFILE/.cargo/bin"' >> "$BASH_ENV" + - run: + name: Show Rust version information + command: rustc --version; cargo --version; rustup --version + - restore_cache: + keys: + - cachev4-build_shared_library_windows-rust:1.60.0-{{ checksum "libwasmvm/Cargo.lock" }} + - cachev4-build_shared_library_windows-rust:1.60.0- + - run: + name: Create release build of libwasmvm + command: make build-rust + - persist_to_workspace: + root: ./internal/api + paths: + - wasmvm.dll + - save_cache: + paths: + # ".." is the easiest way to get $HOME here (pwd is $HOME\project) + - ../.cargo/registry + - libwasmvm/target/release/.fingerprint + - libwasmvm/target/release/build + - libwasmvm/target/release/deps + key: cachev4-build_shared_library_windows-rust:1.60.0-{{ checksum "libwasmvm/Cargo.lock" }} + # Test the Go project wasmvm_test: docker: @@ -382,6 +429,7 @@ workflows: filters: # required since other jobs with tag filters require this one tags: only: /.*/ + - build_shared_library_windows - wasmvm_test: requires: - build_shared_library From 613b2266e877f63c7baa3ca8f1920f5b184e4d9e Mon Sep 17 00:00:00 2001 From: Simon Warta Date: Thu, 1 Dec 2022 13:10:18 +0100 Subject: [PATCH 02/25] Add wasmvm_test_windows CI job --- .circleci/config.yml | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/.circleci/config.yml b/.circleci/config.yml index dd7169b8..cbb65751 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -316,6 +316,36 @@ jobs: command: make test-safety - run: make build-go + # Test the Go project on Windows + wasmvm_test_windows: + executor: + name: win/default + shell: bash.exe + environment: + GORACE: "halt_on_error=1" + steps: + - checkout + - run: + name: Install make and mingw + # See https://github.com/docker/containerd-packaging/pull/294 for discussion around mingw version + command: | + set -o errexit + choco install -y make + choco install -y mingw --version 10.2.0 --allow-downgrade + - run: + name: Show Go version information + command: | + go version + make --version + - attach_workspace: + at: /c/builds + - run: + name: Copy .dll to system library path + command: cp /c/builds/wasmvm.dll /c/Windows/System32 + - run: + name: Run Go tests + command: make test + test_alpine_build: machine: image: ubuntu-2004:2022.10.1 @@ -433,6 +463,9 @@ workflows: - wasmvm_test: requires: - build_shared_library + - wasmvm_test_windows: + requires: + - build_shared_library_windows - build_static_lib: requires: - build_shared_library @@ -466,6 +499,7 @@ workflows: - format-scripts - lint-scripts - wasmvm_test + - wasmvm_test_windows filters: tags: ignore: From 7d6ba17131564fe5d3594948fa51915539a6ba6c Mon Sep 17 00:00:00 2001 From: Simon Warta Date: Thu, 1 Dec 2022 13:38:45 +0100 Subject: [PATCH 03/25] Avoid dot notation for relative paths in persist_to_workspace --- .circleci/config.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index cbb65751..786271a2 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -233,7 +233,7 @@ jobs: name: Create release build of libwasmvm command: make build-rust - persist_to_workspace: - root: ./internal/api + root: internal/api paths: - libwasmvm.x86_64.so - save_cache: @@ -282,7 +282,7 @@ jobs: name: Create release build of libwasmvm command: make build-rust - persist_to_workspace: - root: ./internal/api + root: internal/api paths: - wasmvm.dll - save_cache: From 3cb30197bec1d9634e33830373b956b6ca01ed4a Mon Sep 17 00:00:00 2001 From: Simon Warta Date: Thu, 1 Dec 2022 14:02:41 +0100 Subject: [PATCH 04/25] Increase build_shared_library_windows machine size --- .circleci/config.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.circleci/config.yml b/.circleci/config.yml index 786271a2..606bd7ae 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -253,6 +253,7 @@ jobs: build_shared_library_windows: executor: name: win/default + size: large shell: bash.exe steps: - checkout From 628b0f291bbdf8607aa34be06ee49caa313404b2 Mon Sep 17 00:00:00 2001 From: Simon Warta Date: Thu, 1 Dec 2022 14:03:51 +0100 Subject: [PATCH 05/25] Try windows path notation in persist_to_workspace of build_shared_library_windows --- .circleci/config.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 606bd7ae..07f74179 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -283,7 +283,7 @@ jobs: name: Create release build of libwasmvm command: make build-rust - persist_to_workspace: - root: internal/api + root: internal\api paths: - wasmvm.dll - save_cache: From 8934a025bcd8902a79a615cbccc6980b0ff2aaa6 Mon Sep 17 00:00:00 2001 From: Simon Warta Date: Thu, 1 Dec 2022 14:54:39 +0100 Subject: [PATCH 06/25] Attach workspace at C:/builds --- .circleci/config.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 07f74179..0e13e9cf 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -339,7 +339,7 @@ jobs: go version make --version - attach_workspace: - at: /c/builds + at: C:/builds - run: name: Copy .dll to system library path command: cp /c/builds/wasmvm.dll /c/Windows/System32 From 66865fd97662184a39d3bb98b167f268a80b73b1 Mon Sep 17 00:00:00 2001 From: Simon Warta Date: Thu, 1 Dec 2022 16:14:57 +0100 Subject: [PATCH 07/25] Harden ffiErrorWithMessage implementation --- internal/api/lib.go | 62 ++++++++++++++++++++++++++------------------- 1 file changed, 36 insertions(+), 26 deletions(-) diff --git a/internal/api/lib.go b/internal/api/lib.go index b4d96d26..d6f7d447 100644 --- a/internal/api/lib.go +++ b/internal/api/lib.go @@ -47,7 +47,7 @@ func InitCache(dataDir string, supportedFeatures string, cacheSize uint32, insta ptr, err := C.init_cache(d, f, cu32(cacheSize), cu32(instanceMemoryLimit), &errmsg) if err != nil { - return Cache{}, errorWithMessage(err, errmsg) + return Cache{}, ffiErrorWithMessage(err, errmsg) } return Cache{ptr: ptr}, nil } @@ -62,7 +62,7 @@ func StoreCode(cache Cache, wasm []byte) ([]byte, error) { errmsg := newUnmanagedVector(nil) checksum, err := C.save_wasm(cache.ptr, w, &errmsg) if err != nil { - return nil, errorWithMessage(err, errmsg) + return nil, ffiErrorWithMessage(err, errmsg) } return copyAndDestroyUnmanagedVector(checksum), nil } @@ -84,7 +84,7 @@ func GetCode(cache Cache, checksum []byte) ([]byte, error) { errmsg := newUnmanagedVector(nil) wasm, err := C.load_wasm(cache.ptr, cs, &errmsg) if err != nil { - return nil, errorWithMessage(err, errmsg) + return nil, ffiErrorWithMessage(err, errmsg) } return copyAndDestroyUnmanagedVector(wasm), nil } @@ -95,7 +95,7 @@ func Pin(cache Cache, checksum []byte) error { errmsg := newUnmanagedVector(nil) _, err := C.pin(cache.ptr, cs, &errmsg) if err != nil { - return errorWithMessage(err, errmsg) + return ffiErrorWithMessage(err, errmsg) } return nil } @@ -106,7 +106,7 @@ func Unpin(cache Cache, checksum []byte) error { errmsg := newUnmanagedVector(nil) _, err := C.unpin(cache.ptr, cs, &errmsg) if err != nil { - return errorWithMessage(err, errmsg) + return ffiErrorWithMessage(err, errmsg) } return nil } @@ -117,7 +117,7 @@ func AnalyzeCode(cache Cache, checksum []byte) (*types.AnalysisReport, error) { errmsg := newUnmanagedVector(nil) report, err := C.analyze_code(cache.ptr, cs, &errmsg) if err != nil { - return nil, errorWithMessage(err, errmsg) + return nil, ffiErrorWithMessage(err, errmsg) } requiredCapabilities := string(copyAndDestroyUnmanagedVector(report.required_capabilities)) res := types.AnalysisReport{ @@ -132,7 +132,7 @@ func GetMetrics(cache Cache) (*types.Metrics, error) { errmsg := newUnmanagedVector(nil) metrics, err := C.get_metrics(cache.ptr, &errmsg) if err != nil { - return nil, errorWithMessage(err, errmsg) + return nil, ffiErrorWithMessage(err, errmsg) } return &types.Metrics{ @@ -182,7 +182,7 @@ func Instantiate( res, err := C.instantiate(cache.ptr, cs, e, i, m, db, a, q, cu64(gasLimit), cbool(printDebug), &gasUsed, &errmsg) if err != nil && err.(syscall.Errno) != C.ErrnoValue_Success { // Depending on the nature of the error, `gasUsed` will either have a meaningful value, or just 0. - return nil, uint64(gasUsed), errorWithMessage(err, errmsg) + return nil, uint64(gasUsed), ffiErrorWithMessage(err, errmsg) } return copyAndDestroyUnmanagedVector(res), uint64(gasUsed), nil } @@ -222,7 +222,7 @@ func Execute( res, err := C.execute(cache.ptr, cs, e, i, m, db, a, q, cu64(gasLimit), cbool(printDebug), &gasUsed, &errmsg) if err != nil && err.(syscall.Errno) != C.ErrnoValue_Success { // Depending on the nature of the error, `gasUsed` will either have a meaningful value, or just 0. - return nil, uint64(gasUsed), errorWithMessage(err, errmsg) + return nil, uint64(gasUsed), ffiErrorWithMessage(err, errmsg) } return copyAndDestroyUnmanagedVector(res), uint64(gasUsed), nil } @@ -259,7 +259,7 @@ func Migrate( res, err := C.migrate(cache.ptr, cs, e, m, db, a, q, cu64(gasLimit), cbool(printDebug), &gasUsed, &errmsg) if err != nil && err.(syscall.Errno) != C.ErrnoValue_Success { // Depending on the nature of the error, `gasUsed` will either have a meaningful value, or just 0. - return nil, uint64(gasUsed), errorWithMessage(err, errmsg) + return nil, uint64(gasUsed), ffiErrorWithMessage(err, errmsg) } return copyAndDestroyUnmanagedVector(res), uint64(gasUsed), nil } @@ -296,7 +296,7 @@ func Sudo( res, err := C.sudo(cache.ptr, cs, e, m, db, a, q, cu64(gasLimit), cbool(printDebug), &gasUsed, &errmsg) if err != nil && err.(syscall.Errno) != C.ErrnoValue_Success { // Depending on the nature of the error, `gasUsed` will either have a meaningful value, or just 0. - return nil, uint64(gasUsed), errorWithMessage(err, errmsg) + return nil, uint64(gasUsed), ffiErrorWithMessage(err, errmsg) } return copyAndDestroyUnmanagedVector(res), uint64(gasUsed), nil } @@ -333,7 +333,7 @@ func Reply( res, err := C.reply(cache.ptr, cs, e, r, db, a, q, cu64(gasLimit), cbool(printDebug), &gasUsed, &errmsg) if err != nil && err.(syscall.Errno) != C.ErrnoValue_Success { // Depending on the nature of the error, `gasUsed` will either have a meaningful value, or just 0. - return nil, uint64(gasUsed), errorWithMessage(err, errmsg) + return nil, uint64(gasUsed), ffiErrorWithMessage(err, errmsg) } return copyAndDestroyUnmanagedVector(res), uint64(gasUsed), nil } @@ -370,7 +370,7 @@ func Query( res, err := C.query(cache.ptr, cs, e, m, db, a, q, cu64(gasLimit), cbool(printDebug), &gasUsed, &errmsg) if err != nil && err.(syscall.Errno) != C.ErrnoValue_Success { // Depending on the nature of the error, `gasUsed` will either have a meaningful value, or just 0. - return nil, uint64(gasUsed), errorWithMessage(err, errmsg) + return nil, uint64(gasUsed), ffiErrorWithMessage(err, errmsg) } return copyAndDestroyUnmanagedVector(res), uint64(gasUsed), nil } @@ -407,7 +407,7 @@ func IBCChannelOpen( res, err := C.ibc_channel_open(cache.ptr, cs, e, m, db, a, q, cu64(gasLimit), cbool(printDebug), &gasUsed, &errmsg) if err != nil && err.(syscall.Errno) != C.ErrnoValue_Success { // Depending on the nature of the error, `gasUsed` will either have a meaningful value, or just 0. - return nil, uint64(gasUsed), errorWithMessage(err, errmsg) + return nil, uint64(gasUsed), ffiErrorWithMessage(err, errmsg) } return copyAndDestroyUnmanagedVector(res), uint64(gasUsed), nil } @@ -444,7 +444,7 @@ func IBCChannelConnect( res, err := C.ibc_channel_connect(cache.ptr, cs, e, m, db, a, q, cu64(gasLimit), cbool(printDebug), &gasUsed, &errmsg) if err != nil && err.(syscall.Errno) != C.ErrnoValue_Success { // Depending on the nature of the error, `gasUsed` will either have a meaningful value, or just 0. - return nil, uint64(gasUsed), errorWithMessage(err, errmsg) + return nil, uint64(gasUsed), ffiErrorWithMessage(err, errmsg) } return copyAndDestroyUnmanagedVector(res), uint64(gasUsed), nil } @@ -481,7 +481,7 @@ func IBCChannelClose( res, err := C.ibc_channel_close(cache.ptr, cs, e, m, db, a, q, cu64(gasLimit), cbool(printDebug), &gasUsed, &errmsg) if err != nil && err.(syscall.Errno) != C.ErrnoValue_Success { // Depending on the nature of the error, `gasUsed` will either have a meaningful value, or just 0. - return nil, uint64(gasUsed), errorWithMessage(err, errmsg) + return nil, uint64(gasUsed), ffiErrorWithMessage(err, errmsg) } return copyAndDestroyUnmanagedVector(res), uint64(gasUsed), nil } @@ -518,7 +518,7 @@ func IBCPacketReceive( res, err := C.ibc_packet_receive(cache.ptr, cs, e, pa, db, a, q, cu64(gasLimit), cbool(printDebug), &gasUsed, &errmsg) if err != nil && err.(syscall.Errno) != C.ErrnoValue_Success { // Depending on the nature of the error, `gasUsed` will either have a meaningful value, or just 0. - return nil, uint64(gasUsed), errorWithMessage(err, errmsg) + return nil, uint64(gasUsed), ffiErrorWithMessage(err, errmsg) } return copyAndDestroyUnmanagedVector(res), uint64(gasUsed), nil } @@ -555,7 +555,7 @@ func IBCPacketAck( res, err := C.ibc_packet_ack(cache.ptr, cs, e, ac, db, a, q, cu64(gasLimit), cbool(printDebug), &gasUsed, &errmsg) if err != nil && err.(syscall.Errno) != C.ErrnoValue_Success { // Depending on the nature of the error, `gasUsed` will either have a meaningful value, or just 0. - return nil, uint64(gasUsed), errorWithMessage(err, errmsg) + return nil, uint64(gasUsed), ffiErrorWithMessage(err, errmsg) } return copyAndDestroyUnmanagedVector(res), uint64(gasUsed), nil } @@ -592,21 +592,31 @@ func IBCPacketTimeout( res, err := C.ibc_packet_timeout(cache.ptr, cs, e, pa, db, a, q, cu64(gasLimit), cbool(printDebug), &gasUsed, &errmsg) if err != nil && err.(syscall.Errno) != C.ErrnoValue_Success { // Depending on the nature of the error, `gasUsed` will either have a meaningful value, or just 0. - return nil, uint64(gasUsed), errorWithMessage(err, errmsg) + return nil, uint64(gasUsed), ffiErrorWithMessage(err, errmsg) } return copyAndDestroyUnmanagedVector(res), uint64(gasUsed), nil } -/**** To error module ***/ +// ffiErrorWithMessage takes a error, tries to read the error message +// written by the Rust code and returns a readable error. +// +// This function must only be called on `ffiErr`s of type syscall.Errno +// that are no 0 (no error). +func ffiErrorWithMessage(ffiErr error, errMsg C.UnmanagedVector) error { + errno := ffiErr.(syscall.Errno) // panics if conversion fails -func errorWithMessage(err error, b C.UnmanagedVector) error { - // this checks for out of gas as a special case - if errno, ok := err.(syscall.Errno); ok && int(errno) == 2 { + if errno == 0 { + panic("Called ffiErrorWithMessage with a 0 errno (no error)") + } + + // Checks for out of gas as a special case. See "ErrnoValue" in libwasmvm/src/error/rust.rs. + if errno == 2 { return types.OutOfGasError{} } - msg := copyAndDestroyUnmanagedVector(b) - if msg == nil { - return err + + msg := copyAndDestroyUnmanagedVector(errMsg) + if msg == nil || len(msg) == 0 { + return fmt.Errorf("FFI call errored with errno %#v and no error message.", errno) } return fmt.Errorf("%s", string(msg)) } From 020f347610bb84b139d28fa60dd714352d124f66 Mon Sep 17 00:00:00 2001 From: Simon Warta Date: Thu, 1 Dec 2022 16:57:56 +0100 Subject: [PATCH 08/25] Make void return types more explicit --- internal/api/lib.go | 6 +++--- internal/api/memory.go | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/internal/api/lib.go b/internal/api/lib.go index d6f7d447..d461475b 100644 --- a/internal/api/lib.go +++ b/internal/api/lib.go @@ -53,7 +53,7 @@ func InitCache(dataDir string, supportedFeatures string, cacheSize uint32, insta } func ReleaseCache(cache Cache) { - C.release_cache(cache.ptr) + C.release_cache(cache.ptr) // No error case that needs handling } func StoreCode(cache Cache, wasm []byte) ([]byte, error) { @@ -93,7 +93,7 @@ func Pin(cache Cache, checksum []byte) error { cs := makeView(checksum) defer runtime.KeepAlive(checksum) errmsg := newUnmanagedVector(nil) - _, err := C.pin(cache.ptr, cs, &errmsg) + _, err := C.pin(cache.ptr, cs, &errmsg) // returns (_Ctype_void, syscall.Errno) if err != nil { return ffiErrorWithMessage(err, errmsg) } @@ -104,7 +104,7 @@ func Unpin(cache Cache, checksum []byte) error { cs := makeView(checksum) defer runtime.KeepAlive(checksum) errmsg := newUnmanagedVector(nil) - _, err := C.unpin(cache.ptr, cs, &errmsg) + _, err := C.unpin(cache.ptr, cs, &errmsg) // returns (_Ctype_void, syscall.Errno) if err != nil { return ffiErrorWithMessage(err, errmsg) } diff --git a/internal/api/memory.go b/internal/api/memory.go index c7479c24..8f1352a6 100644 --- a/internal/api/memory.go +++ b/internal/api/memory.go @@ -65,7 +65,7 @@ func copyAndDestroyUnmanagedVector(v C.UnmanagedVector) []byte { // C.GoBytes create a copy (https://stackoverflow.com/a/40950744/2013738) out = C.GoBytes(unsafe.Pointer(v.ptr), cint(v.len)) } - C.destroy_unmanaged_vector(v) + C.destroy_unmanaged_vector(v) // No error case that needs handling return out } From f5954dcf006ebcebf6e27e5be008bfeb6bf58ea4 Mon Sep 17 00:00:00 2001 From: Simon Warta Date: Mon, 16 Jan 2023 17:19:39 +0100 Subject: [PATCH 09/25] Use errno-sys to set errnos --- libwasmvm/Cargo.lock | 27 ++++++-------------- libwasmvm/Cargo.toml | 2 +- libwasmvm/src/error/errno.rs | 16 ++++++++++++ libwasmvm/src/error/mod.rs | 1 + libwasmvm/src/error/rust.rs | 48 ++++++++++++++++++------------------ 5 files changed, 50 insertions(+), 44 deletions(-) create mode 100644 libwasmvm/src/error/errno.rs diff --git a/libwasmvm/Cargo.lock b/libwasmvm/Cargo.lock index 58c035ce..065f21ee 100644 --- a/libwasmvm/Cargo.lock +++ b/libwasmvm/Cargo.lock @@ -156,9 +156,9 @@ dependencies = [ [[package]] name = "cc" -version = "1.0.72" +version = "1.0.77" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22a9137b95ea06864e018375b72adfb7db6e6f68cfc8df5a04d00288050485ee" +checksum = "e9f73505338f7d905b19d18738976aae232eb46b8efc15554ffc56deb5d9ebe4" [[package]] name = "cfg-if" @@ -642,21 +642,10 @@ dependencies = [ ] [[package]] -name = "errno" -version = "0.2.8" +name = "errno-sys" +version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f639046355ee4f37944e44f60642c6f3a7efa3cf6b78c78a0d989a8ce6c396a1" -dependencies = [ - "errno-dragonfly", - "libc", - "winapi", -] - -[[package]] -name = "errno-dragonfly" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aa68f1b12764fab894d2755d2518754e71b4fd80ecfb822714a1206c2aab39bf" +checksum = "9c0007216af1525058024bc6dc15bbd2ffe8af877f0fbf754fbdb78c59d634e8" dependencies = [ "cc", "libc", @@ -850,9 +839,9 @@ checksum = "884e2677b40cc8c339eaefcb701c32ef1fd2493d71118dc0ca4b6a736c93bd67" [[package]] name = "libc" -version = "0.2.132" +version = "0.2.137" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8371e4e5341c3a96db127eb2465ac681ced4c433e01dd0e938adbef26ba93ba5" +checksum = "fc7fcc620a3bff7cdd7a365be3376c97191aeaccc2a603e600951e452615bf89" [[package]] name = "libloading" @@ -1929,7 +1918,7 @@ dependencies = [ "cbindgen", "cosmwasm-std", "cosmwasm-vm", - "errno", + "errno-sys", "hex", "serde", "serde_json", diff --git a/libwasmvm/Cargo.toml b/libwasmvm/Cargo.toml index 09b72c22..3625646a 100644 --- a/libwasmvm/Cargo.toml +++ b/libwasmvm/Cargo.toml @@ -28,7 +28,7 @@ backtraces = [] [dependencies] cosmwasm-std = { git = "https://github.com/CosmWasm/cosmwasm.git", rev = "v1.2.0-rc.1", features = ["staking", "stargate", "iterator"] } cosmwasm-vm = { git = "https://github.com/CosmWasm/cosmwasm.git", rev = "v1.2.0-rc.1", features = ["staking", "stargate", "iterator"] } -errno = "0.2" +errno-sys = "0.1.0" serde_json = "1.0" thiserror = "1.0" hex = "0.4" diff --git a/libwasmvm/src/error/errno.rs b/libwasmvm/src/error/errno.rs new file mode 100644 index 00000000..5c855df3 --- /dev/null +++ b/libwasmvm/src/error/errno.rs @@ -0,0 +1,16 @@ +// See https://github.com/rust-lang/libc/issues/1644 for why we have to implement that ourselves. +// https://github.com/lambda-fairy/rust-errno does not work with cgo +// on Windows as cgo does not use the SetLastError/GetLastError Windows APIs. + +use errno_sys::errno_location; + +#[allow(unused)] // used in tests +pub fn errno() -> i32 { + unsafe { *errno_location() } +} + +pub fn set_errno(errno: i32) { + unsafe { + *errno_location() = errno; + } +} diff --git a/libwasmvm/src/error/mod.rs b/libwasmvm/src/error/mod.rs index 96130ed8..1f64e919 100644 --- a/libwasmvm/src/error/mod.rs +++ b/libwasmvm/src/error/mod.rs @@ -1,3 +1,4 @@ +mod errno; mod go; mod rust; diff --git a/libwasmvm/src/error/rust.rs b/libwasmvm/src/error/rust.rs index 1938d3cb..01c5ea43 100644 --- a/libwasmvm/src/error/rust.rs +++ b/libwasmvm/src/error/rust.rs @@ -1,9 +1,9 @@ use cosmwasm_vm::VmError; -use errno::{set_errno, Errno}; #[cfg(feature = "backtraces")] use std::backtrace::Backtrace; use thiserror::Error; +use super::errno::set_errno; use crate::memory::UnmanagedVector; #[derive(Error, Debug)] @@ -123,7 +123,7 @@ enum ErrnoValue { } pub fn clear_error() { - set_errno(Errno(ErrnoValue::Success as i32)); + set_errno(ErrnoValue::Success as i32); } pub fn set_error(err: RustError, error_msg: Option<&mut UnmanagedVector>) { @@ -146,7 +146,7 @@ pub fn set_error(err: RustError, error_msg: Option<&mut UnmanagedVector>) { RustError::OutOfGas { .. } => ErrnoValue::OutOfGas, _ => ErrnoValue::Other, } as i32; - set_errno(Errno(errno)); + set_errno(errno); } /// If `result` is Ok, this returns the Ok value and clears [errno]. @@ -217,9 +217,9 @@ where #[cfg(test)] mod tests { + use super::super::errno::errno; use super::*; use cosmwasm_vm::{BackendError, Checksum}; - use errno::errno; use std::str; #[test] @@ -334,7 +334,7 @@ mod tests { let mut error_msg = UnmanagedVector::default(); let res: Result, RustError> = Ok(vec![0xF0, 0x0B, 0xAA]); let data = handle_c_error_binary(res, Some(&mut error_msg)); - assert_eq!(errno().0, ErrnoValue::Success as i32); + assert_eq!(errno(), ErrnoValue::Success as i32); assert!(error_msg.is_none()); assert_eq!(data, vec![0xF0, 0x0B, 0xAA]); let _ = error_msg.consume(); @@ -343,7 +343,7 @@ mod tests { let mut error_msg = UnmanagedVector::default(); let res: Result, RustError> = Ok(vec![]); let data = handle_c_error_binary(res, Some(&mut error_msg)); - assert_eq!(errno().0, ErrnoValue::Success as i32); + assert_eq!(errno(), ErrnoValue::Success as i32); assert!(error_msg.is_none()); assert_eq!(data, Vec::::new()); let _ = error_msg.consume(); @@ -352,7 +352,7 @@ mod tests { let mut error_msg = UnmanagedVector::default(); let res: Result<&[u8], RustError> = Ok(b"foobar"); let data = handle_c_error_binary(res, Some(&mut error_msg)); - assert_eq!(errno().0, ErrnoValue::Success as i32); + assert_eq!(errno(), ErrnoValue::Success as i32); assert!(error_msg.is_none()); assert_eq!(data, Vec::::from(b"foobar" as &[u8])); let _ = error_msg.consume(); @@ -361,7 +361,7 @@ mod tests { let mut error_msg = UnmanagedVector::default(); let res: Result<&[u8], RustError> = Ok(b""); let data = handle_c_error_binary(res, Some(&mut error_msg)); - assert_eq!(errno().0, ErrnoValue::Success as i32); + assert_eq!(errno(), ErrnoValue::Success as i32); assert!(error_msg.is_none()); assert_eq!(data, Vec::::new()); let _ = error_msg.consume(); @@ -374,7 +374,7 @@ mod tests { 0x84, 0x22, 0x71, 0x04, ])); let data = handle_c_error_binary(res, Some(&mut error_msg)); - assert_eq!(errno().0, ErrnoValue::Success as i32); + assert_eq!(errno(), ErrnoValue::Success as i32); assert!(error_msg.is_none()); assert_eq!( data, @@ -390,7 +390,7 @@ mod tests { let mut error_msg = UnmanagedVector::default(); let res: Result, RustError> = Err(RustError::panic()); let data = handle_c_error_binary(res, Some(&mut error_msg)); - assert_eq!(errno().0, ErrnoValue::Other as i32); + assert_eq!(errno(), ErrnoValue::Other as i32); assert!(error_msg.is_some()); assert_eq!(data, Vec::::new()); let _ = error_msg.consume(); @@ -399,7 +399,7 @@ mod tests { let mut error_msg = UnmanagedVector::default(); let res: Result<&[u8], RustError> = Err(RustError::panic()); let data = handle_c_error_binary(res, Some(&mut error_msg)); - assert_eq!(errno().0, ErrnoValue::Other as i32); + assert_eq!(errno(), ErrnoValue::Other as i32); assert!(error_msg.is_some()); assert_eq!(data, Vec::::new()); let _ = error_msg.consume(); @@ -408,7 +408,7 @@ mod tests { let mut error_msg = UnmanagedVector::default(); let res: Result = Err(RustError::panic()); let data = handle_c_error_binary(res, Some(&mut error_msg)); - assert_eq!(errno().0, ErrnoValue::Other as i32); + assert_eq!(errno(), ErrnoValue::Other as i32); assert!(error_msg.is_some()); assert_eq!(data, Vec::::new()); let _ = error_msg.consume(); @@ -420,7 +420,7 @@ mod tests { let mut error_msg = UnmanagedVector::default(); let res: Result, RustError> = Err(RustError::panic()); let data = handle_c_error_binary(res, Some(&mut error_msg)); - assert_eq!(errno().0, ErrnoValue::Other as i32); + assert_eq!(errno(), ErrnoValue::Other as i32); assert!(error_msg.is_some()); assert_eq!(data, Vec::::new()); let _ = error_msg.consume(); @@ -429,7 +429,7 @@ mod tests { let mut error_msg = UnmanagedVector::default(); let res: Result, RustError> = Ok(vec![0xF0, 0x0B, 0xAA]); let data = handle_c_error_binary(res, Some(&mut error_msg)); - assert_eq!(errno().0, ErrnoValue::Success as i32); + assert_eq!(errno(), ErrnoValue::Success as i32); assert!(error_msg.is_none()); assert_eq!(data, vec![0xF0, 0x0B, 0xAA]); let _ = error_msg.consume(); @@ -441,7 +441,7 @@ mod tests { let mut error_msg = UnmanagedVector::default(); let res: Result, RustError> = Ok(vec![0xF0, 0x0B, 0xAA]); let data = handle_c_error_default(res, Some(&mut error_msg)); - assert_eq!(errno().0, ErrnoValue::Success as i32); + assert_eq!(errno(), ErrnoValue::Success as i32); assert!(error_msg.is_none()); assert_eq!(data, vec![0xF0, 0x0B, 0xAA]); let _ = error_msg.consume(); @@ -450,7 +450,7 @@ mod tests { let mut error_msg = UnmanagedVector::default(); let res: Result, RustError> = Ok(vec![]); let data = handle_c_error_default(res, Some(&mut error_msg)); - assert_eq!(errno().0, ErrnoValue::Success as i32); + assert_eq!(errno(), ErrnoValue::Success as i32); assert!(error_msg.is_none()); assert_eq!(data, Vec::::new()); let _ = error_msg.consume(); @@ -459,7 +459,7 @@ mod tests { let mut error_msg = UnmanagedVector::default(); let res: Result<&[u8], RustError> = Ok(b"foobar"); let data = handle_c_error_default(res, Some(&mut error_msg)); - assert_eq!(errno().0, ErrnoValue::Success as i32); + assert_eq!(errno(), ErrnoValue::Success as i32); assert!(error_msg.is_none()); assert_eq!(data, Vec::::from(b"foobar" as &[u8])); let _ = error_msg.consume(); @@ -468,7 +468,7 @@ mod tests { let mut error_msg = UnmanagedVector::default(); let res: Result<&[u8], RustError> = Ok(b""); let data = handle_c_error_default(res, Some(&mut error_msg)); - assert_eq!(errno().0, ErrnoValue::Success as i32); + assert_eq!(errno(), ErrnoValue::Success as i32); assert!(error_msg.is_none()); assert_eq!(data, Vec::::new()); let _ = error_msg.consume(); @@ -477,7 +477,7 @@ mod tests { let mut error_msg = UnmanagedVector::default(); let res: Result<(), RustError> = Ok(()); let _data = handle_c_error_default(res, Some(&mut error_msg)); - assert_eq!(errno().0, ErrnoValue::Success as i32); + assert_eq!(errno(), ErrnoValue::Success as i32); assert!(error_msg.is_none()); let _ = error_msg.consume(); @@ -485,7 +485,7 @@ mod tests { let mut error_msg = UnmanagedVector::default(); let res: Result, RustError> = Err(RustError::panic()); let data = handle_c_error_default(res, Some(&mut error_msg)); - assert_eq!(errno().0, ErrnoValue::Other as i32); + assert_eq!(errno(), ErrnoValue::Other as i32); assert!(error_msg.is_some()); assert_eq!(data, Vec::::new()); let _ = error_msg.consume(); @@ -494,7 +494,7 @@ mod tests { let mut error_msg = UnmanagedVector::default(); let res: Result<&[u8], RustError> = Err(RustError::panic()); let data = handle_c_error_default(res, Some(&mut error_msg)); - assert_eq!(errno().0, ErrnoValue::Other as i32); + assert_eq!(errno(), ErrnoValue::Other as i32); assert!(error_msg.is_some()); assert_eq!(data, Vec::::new()); let _ = error_msg.consume(); @@ -503,7 +503,7 @@ mod tests { let mut error_msg = UnmanagedVector::default(); let res: Result<(), RustError> = Err(RustError::panic()); let _data = handle_c_error_default(res, Some(&mut error_msg)); - assert_eq!(errno().0, ErrnoValue::Other as i32); + assert_eq!(errno(), ErrnoValue::Other as i32); assert!(error_msg.is_some()); let _ = error_msg.consume(); } @@ -514,7 +514,7 @@ mod tests { let mut error_msg = UnmanagedVector::default(); let res: Result, RustError> = Err(RustError::panic()); let data = handle_c_error_default(res, Some(&mut error_msg)); - assert_eq!(errno().0, ErrnoValue::Other as i32); + assert_eq!(errno(), ErrnoValue::Other as i32); assert!(error_msg.is_some()); assert_eq!(data, Vec::::new()); let _ = error_msg.consume(); @@ -523,7 +523,7 @@ mod tests { let mut error_msg = UnmanagedVector::default(); let res: Result, RustError> = Ok(vec![0xF0, 0x0B, 0xAA]); let data = handle_c_error_default(res, Some(&mut error_msg)); - assert_eq!(errno().0, ErrnoValue::Success as i32); + assert_eq!(errno(), ErrnoValue::Success as i32); assert!(error_msg.is_none()); assert_eq!(data, vec![0xF0, 0x0B, 0xAA]); let _ = error_msg.consume(); From f498c33c1227f5aedb55cf302b88d66407851fdc Mon Sep 17 00:00:00 2001 From: Simon Warta Date: Thu, 1 Dec 2022 18:39:58 +0100 Subject: [PATCH 10/25] Try external linker --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 9c1c1438..917c1bb4 100644 --- a/Makefile +++ b/Makefile @@ -57,7 +57,7 @@ build-go: test: # Use package list mode to include all subdirectores. The -count=1 turns off caching. - RUST_BACKTRACE=1 go test -v -count=1 ./... + RUST_BACKTRACE=1 go test -v -count=1 -ldflags "-linkmode=external" ./... test-safety: # Use package list mode to include all subdirectores. The -count=1 turns off caching. From d2351bf982e40d18c9013ac29bea09a51a1415c0 Mon Sep 17 00:00:00 2001 From: Simon Warta Date: Mon, 5 Dec 2022 13:18:32 +0100 Subject: [PATCH 11/25] Make clippy happy --- libwasmvm/src/cache.rs | 4 ++-- libwasmvm/src/error/go.rs | 2 +- libwasmvm/src/memory.rs | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/libwasmvm/src/cache.rs b/libwasmvm/src/cache.rs index f55f4b6c..42ef9ebe 100644 --- a/libwasmvm/src/cache.rs +++ b/libwasmvm/src/cache.rs @@ -215,7 +215,7 @@ fn do_unpin( /// has to be destroyed exactly once. When calling `analyze_code` /// from Go this is done via `C.destroy_unmanaged_vector`. #[repr(C)] -#[derive(Copy, Clone, Default, Debug, PartialEq)] +#[derive(Copy, Clone, Default, Debug, PartialEq, Eq)] pub struct AnalysisReport { pub has_ibc_entry_points: bool, /// An UTF-8 encoded comma separated list of reqired capabilities. @@ -271,7 +271,7 @@ fn do_analyze_code( } #[repr(C)] -#[derive(Copy, Clone, Default, Debug, PartialEq)] +#[derive(Copy, Clone, Default, Debug, PartialEq, Eq)] pub struct Metrics { pub hits_pinned_memory_cache: u32, pub hits_memory_cache: u32, diff --git a/libwasmvm/src/error/go.rs b/libwasmvm/src/error/go.rs index 959212b4..1d8d65ed 100644 --- a/libwasmvm/src/error/go.rs +++ b/libwasmvm/src/error/go.rs @@ -14,7 +14,7 @@ use crate::memory::UnmanagedVector; // You have been warned. // #[repr(i32)] // This makes it so the enum looks like a simple i32 to Go -#[derive(PartialEq)] +#[derive(PartialEq, Eq)] pub enum GoError { None = 0, /// Go panicked for an unexpected reason. diff --git a/libwasmvm/src/memory.rs b/libwasmvm/src/memory.rs index 8abc01c2..24d6e91b 100644 --- a/libwasmvm/src/memory.rs +++ b/libwasmvm/src/memory.rs @@ -200,7 +200,7 @@ impl U8SliceView { /// // `output` is ready to be passed around /// ``` #[repr(C)] -#[derive(Copy, Clone, Debug, PartialEq)] +#[derive(Copy, Clone, Debug, PartialEq, Eq)] pub struct UnmanagedVector { /// True if and only if this is None. If this is true, the other fields must be ignored. is_none: bool, From 066dfa614afe07ed0113e60dca4fdaae4a75eb88 Mon Sep 17 00:00:00 2001 From: Simon Warta Date: Mon, 5 Dec 2022 13:38:18 +0100 Subject: [PATCH 12/25] Advoid explicit linker setting --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 917c1bb4..9c1c1438 100644 --- a/Makefile +++ b/Makefile @@ -57,7 +57,7 @@ build-go: test: # Use package list mode to include all subdirectores. The -count=1 turns off caching. - RUST_BACKTRACE=1 go test -v -count=1 -ldflags "-linkmode=external" ./... + RUST_BACKTRACE=1 go test -v -count=1 ./... test-safety: # Use package list mode to include all subdirectores. The -count=1 turns off caching. From 1716b61e123024a49b55405f56981af2cb0a4ffb Mon Sep 17 00:00:00 2001 From: Simon Warta Date: Mon, 16 Jan 2023 17:28:22 +0100 Subject: [PATCH 13/25] Return error as integer in save_wasm/remove_wasm/load_wasm/pin/unpin --- internal/api/bindings.h | 36 ++++++----- internal/api/lib.go | 58 ++++++++++++----- libwasmvm/bindings.h | 36 ++++++----- libwasmvm/src/cache.rs | 125 +++++++++++++++++++++++++----------- libwasmvm/src/error/mod.rs | 3 +- libwasmvm/src/error/rust.rs | 40 +++++++++++- 6 files changed, 210 insertions(+), 88 deletions(-) diff --git a/internal/api/bindings.h b/internal/api/bindings.h index 5f7e31f8..c585a640 100644 --- a/internal/api/bindings.h +++ b/internal/api/bindings.h @@ -309,21 +309,27 @@ struct cache_t *init_cache(struct ByteSliceView data_dir, uint32_t instance_memory_limit, struct UnmanagedVector *error_msg); -struct UnmanagedVector save_wasm(struct cache_t *cache, - struct ByteSliceView wasm, - struct UnmanagedVector *error_msg); - -void remove_wasm(struct cache_t *cache, - struct ByteSliceView checksum, - struct UnmanagedVector *error_msg); - -struct UnmanagedVector load_wasm(struct cache_t *cache, - struct ByteSliceView checksum, - struct UnmanagedVector *error_msg); - -void pin(struct cache_t *cache, struct ByteSliceView checksum, struct UnmanagedVector *error_msg); - -void unpin(struct cache_t *cache, struct ByteSliceView checksum, struct UnmanagedVector *error_msg); +int32_t save_wasm(struct cache_t *cache, + struct ByteSliceView wasm, + struct UnmanagedVector *error_msg, + struct UnmanagedVector *out); + +int32_t remove_wasm(struct cache_t *cache, + struct ByteSliceView checksum, + struct UnmanagedVector *error_msg); + +int32_t load_wasm(struct cache_t *cache, + struct ByteSliceView checksum, + struct UnmanagedVector *error_msg, + struct UnmanagedVector *out); + +int32_t pin(struct cache_t *cache, + struct ByteSliceView checksum, + struct UnmanagedVector *error_msg); + +int32_t unpin(struct cache_t *cache, + struct ByteSliceView checksum, + struct UnmanagedVector *error_msg); struct AnalysisReport analyze_code(struct cache_t *cache, struct ByteSliceView checksum, diff --git a/internal/api/lib.go b/internal/api/lib.go index d461475b..1db8bf02 100644 --- a/internal/api/lib.go +++ b/internal/api/lib.go @@ -56,24 +56,26 @@ func ReleaseCache(cache Cache) { C.release_cache(cache.ptr) // No error case that needs handling } +/// StoreCode stored the Wasm blob and returns the checksum func StoreCode(cache Cache, wasm []byte) ([]byte, error) { w := makeView(wasm) defer runtime.KeepAlive(wasm) errmsg := newUnmanagedVector(nil) - checksum, err := C.save_wasm(cache.ptr, w, &errmsg) - if err != nil { - return nil, ffiErrorWithMessage(err, errmsg) + out := newUnmanagedVector(nil) + err := C.save_wasm(cache.ptr, w, &errmsg, &out) + if err != 0 { + return nil, ffiErrorWithMessage2(err, errmsg) } - return copyAndDestroyUnmanagedVector(checksum), nil + return copyAndDestroyUnmanagedVector(out), nil } func RemoveCode(cache Cache, checksum []byte) error { cs := makeView(checksum) defer runtime.KeepAlive(checksum) errmsg := newUnmanagedVector(nil) - _, err := C.remove_wasm(cache.ptr, cs, &errmsg) - if err != nil { - return errorWithMessage(err, errmsg) + err := C.remove_wasm(cache.ptr, cs, &errmsg) + if err != 0 { + return ffiErrorWithMessage2(err, errmsg) } return nil } @@ -82,20 +84,21 @@ func GetCode(cache Cache, checksum []byte) ([]byte, error) { cs := makeView(checksum) defer runtime.KeepAlive(checksum) errmsg := newUnmanagedVector(nil) - wasm, err := C.load_wasm(cache.ptr, cs, &errmsg) - if err != nil { - return nil, ffiErrorWithMessage(err, errmsg) + out := newUnmanagedVector(nil) + err := C.load_wasm(cache.ptr, cs, &errmsg, &out) + if err != 0 { + return nil, ffiErrorWithMessage2(err, errmsg) } - return copyAndDestroyUnmanagedVector(wasm), nil + return copyAndDestroyUnmanagedVector(out), nil } func Pin(cache Cache, checksum []byte) error { cs := makeView(checksum) defer runtime.KeepAlive(checksum) errmsg := newUnmanagedVector(nil) - _, err := C.pin(cache.ptr, cs, &errmsg) // returns (_Ctype_void, syscall.Errno) - if err != nil { - return ffiErrorWithMessage(err, errmsg) + err := C.pin(cache.ptr, cs, &errmsg) + if err != 0 { + return ffiErrorWithMessage2(err, errmsg) } return nil } @@ -104,9 +107,9 @@ func Unpin(cache Cache, checksum []byte) error { cs := makeView(checksum) defer runtime.KeepAlive(checksum) errmsg := newUnmanagedVector(nil) - _, err := C.unpin(cache.ptr, cs, &errmsg) // returns (_Ctype_void, syscall.Errno) - if err != nil { - return ffiErrorWithMessage(err, errmsg) + err := C.unpin(cache.ptr, cs, &errmsg) + if err != 0 { + return ffiErrorWithMessage2(err, errmsg) } return nil } @@ -620,3 +623,24 @@ func ffiErrorWithMessage(ffiErr error, errMsg C.UnmanagedVector) error { } return fmt.Errorf("%s", string(msg)) } + +// ffiErrorWithMessage2 takes a error number, tries to read the error message +// written by the Rust code and returns a readable error. +// +// This function must only be called on non-zero error numbers. +func ffiErrorWithMessage2(errno cint, errMsg C.UnmanagedVector) error { + if errno == 0 { + panic("Called ffiErrorWithMessage2 with a 0 error number (no error)") + } + + // Checks for out of gas as a special case. See "ErrnoValue" in libwasmvm/src/error/rust.rs. + if errno == 2 { + return types.OutOfGasError{} + } + + msg := copyAndDestroyUnmanagedVector(errMsg) + if msg == nil || len(msg) == 0 { + return fmt.Errorf("FFI call errored with errno %#v and no error message.", errno) + } + return fmt.Errorf("%s", string(msg)) +} diff --git a/libwasmvm/bindings.h b/libwasmvm/bindings.h index 5f7e31f8..c585a640 100644 --- a/libwasmvm/bindings.h +++ b/libwasmvm/bindings.h @@ -309,21 +309,27 @@ struct cache_t *init_cache(struct ByteSliceView data_dir, uint32_t instance_memory_limit, struct UnmanagedVector *error_msg); -struct UnmanagedVector save_wasm(struct cache_t *cache, - struct ByteSliceView wasm, - struct UnmanagedVector *error_msg); - -void remove_wasm(struct cache_t *cache, - struct ByteSliceView checksum, - struct UnmanagedVector *error_msg); - -struct UnmanagedVector load_wasm(struct cache_t *cache, - struct ByteSliceView checksum, - struct UnmanagedVector *error_msg); - -void pin(struct cache_t *cache, struct ByteSliceView checksum, struct UnmanagedVector *error_msg); - -void unpin(struct cache_t *cache, struct ByteSliceView checksum, struct UnmanagedVector *error_msg); +int32_t save_wasm(struct cache_t *cache, + struct ByteSliceView wasm, + struct UnmanagedVector *error_msg, + struct UnmanagedVector *out); + +int32_t remove_wasm(struct cache_t *cache, + struct ByteSliceView checksum, + struct UnmanagedVector *error_msg); + +int32_t load_wasm(struct cache_t *cache, + struct ByteSliceView checksum, + struct UnmanagedVector *error_msg, + struct UnmanagedVector *out); + +int32_t pin(struct cache_t *cache, + struct ByteSliceView checksum, + struct UnmanagedVector *error_msg); + +int32_t unpin(struct cache_t *cache, + struct ByteSliceView checksum, + struct UnmanagedVector *error_msg); struct AnalysisReport analyze_code(struct cache_t *cache, struct ByteSliceView checksum, diff --git a/libwasmvm/src/cache.rs b/libwasmvm/src/cache.rs index 42ef9ebe..292fd205 100644 --- a/libwasmvm/src/cache.rs +++ b/libwasmvm/src/cache.rs @@ -7,7 +7,9 @@ use cosmwasm_vm::{capabilities_from_csv, Cache, CacheOptions, Checksum, Size}; use crate::api::GoApi; use crate::args::{AVAILABLE_CAPABILITIES_ARG, CACHE_ARG, CHECKSUM_ARG, DATA_DIR_ARG, WASM_ARG}; -use crate::error::{handle_c_error_binary, handle_c_error_default, handle_c_error_ptr, Error}; +use crate::error::{ + handle_c_error_default, handle_c_error_ptr, to_c_result_binary, to_c_result_unit, Error, +}; use crate::memory::{ByteSliceView, UnmanagedVector}; use crate::querier::GoQuerier; use crate::storage::GoStorage; @@ -81,18 +83,20 @@ fn do_init_cache( } #[no_mangle] +#[must_use] pub extern "C" fn save_wasm( cache: *mut cache_t, wasm: ByteSliceView, error_msg: Option<&mut UnmanagedVector>, -) -> UnmanagedVector { + out: Option<&mut UnmanagedVector>, +) -> i32 { let r = match to_cache(cache) { Some(c) => catch_unwind(AssertUnwindSafe(move || do_save_wasm(c, wasm))) .unwrap_or_else(|_| Err(Error::panic())), None => Err(Error::unset_arg(CACHE_ARG)), }; - let checksum = handle_c_error_binary(r, error_msg); - UnmanagedVector::new(Some(checksum)) + let r = r.map(UnmanagedVector::some); + to_c_result_binary(r, error_msg, out) } fn do_save_wasm( @@ -105,17 +109,18 @@ fn do_save_wasm( } #[no_mangle] +#[must_use] pub extern "C" fn remove_wasm( cache: *mut cache_t, checksum: ByteSliceView, error_msg: Option<&mut UnmanagedVector>, -) { +) -> i32 { let r = match to_cache(cache) { Some(c) => catch_unwind(AssertUnwindSafe(move || do_remove_wasm(c, checksum))) .unwrap_or_else(|_| Err(Error::panic())), None => Err(Error::unset_arg(CACHE_ARG)), }; - handle_c_error_default(r, error_msg) + to_c_result_unit(r, error_msg) } fn do_remove_wasm( @@ -131,18 +136,20 @@ fn do_remove_wasm( } #[no_mangle] +#[must_use] pub extern "C" fn load_wasm( cache: *mut cache_t, checksum: ByteSliceView, error_msg: Option<&mut UnmanagedVector>, -) -> UnmanagedVector { + out: Option<&mut UnmanagedVector>, +) -> i32 { let r = match to_cache(cache) { Some(c) => catch_unwind(AssertUnwindSafe(move || do_load_wasm(c, checksum))) .unwrap_or_else(|_| Err(Error::panic())), None => Err(Error::unset_arg(CACHE_ARG)), }; - let data = handle_c_error_binary(r, error_msg); - UnmanagedVector::new(Some(data)) + let r = r.map(UnmanagedVector::some); + to_c_result_binary(r, error_msg, out) } fn do_load_wasm( @@ -158,17 +165,18 @@ fn do_load_wasm( } #[no_mangle] +#[must_use] pub extern "C" fn pin( cache: *mut cache_t, checksum: ByteSliceView, error_msg: Option<&mut UnmanagedVector>, -) { +) -> i32 { let r = match to_cache(cache) { Some(c) => catch_unwind(AssertUnwindSafe(move || do_pin(c, checksum))) .unwrap_or_else(|_| Err(Error::panic())), None => Err(Error::unset_arg(CACHE_ARG)), }; - handle_c_error_default(r, error_msg) + to_c_result_unit(r, error_msg) } fn do_pin( @@ -184,17 +192,18 @@ fn do_pin( } #[no_mangle] +#[must_use] pub extern "C" fn unpin( cache: *mut cache_t, checksum: ByteSliceView, error_msg: Option<&mut UnmanagedVector>, -) { +) -> i32 { let r = match to_cache(cache) { Some(c) => catch_unwind(AssertUnwindSafe(move || do_unpin(c, checksum))) .unwrap_or_else(|_| Err(Error::panic())), None => Err(Error::unset_arg(CACHE_ARG)), }; - handle_c_error_default(r, error_msg) + to_c_result_unit(r, error_msg) } fn do_unpin( @@ -421,13 +430,18 @@ mod tests { let _ = error_msg.consume(); let mut error_msg = UnmanagedVector::default(); - save_wasm( + let mut out = UnmanagedVector::default(); + let error = save_wasm( cache_ptr, ByteSliceView::new(HACKATOM), Some(&mut error_msg), + Some(&mut out), ); + assert_eq!(error, 0); assert!(error_msg.is_none()); let _ = error_msg.consume(); + let checksum = out.consume().unwrap_or_default(); + assert_eq!(checksum.len(), 32); release_cache(cache_ptr); } @@ -449,32 +463,37 @@ mod tests { let _ = error_msg.consume(); let mut error_msg = UnmanagedVector::default(); - let checksum = save_wasm( + let mut out = UnmanagedVector::default(); + let error = save_wasm( cache_ptr, ByteSliceView::new(HACKATOM), Some(&mut error_msg), + Some(&mut out), ); + assert_eq!(error, 0); assert!(error_msg.is_none()); let _ = error_msg.consume(); - let checksum = checksum.consume().unwrap_or_default(); + let checksum = out.consume().unwrap_or_default(); // Removing once works let mut error_msg = UnmanagedVector::default(); - remove_wasm( + let error = remove_wasm( cache_ptr, ByteSliceView::new(&checksum), Some(&mut error_msg), ); + assert_eq!(error, 0); assert!(error_msg.is_none()); let _ = error_msg.consume(); // Removing again fails let mut error_msg = UnmanagedVector::default(); - remove_wasm( + let error = remove_wasm( cache_ptr, ByteSliceView::new(&checksum), Some(&mut error_msg), ); + assert_eq!(error, 1); let error_msg = error_msg .consume() .map(|e| String::from_utf8_lossy(&e).into_owned()); @@ -503,24 +522,30 @@ mod tests { let _ = error_msg.consume(); let mut error_msg = UnmanagedVector::default(); - let checksum = save_wasm( + let mut out = UnmanagedVector::default(); + let error = save_wasm( cache_ptr, ByteSliceView::new(HACKATOM), Some(&mut error_msg), + Some(&mut out), ); + assert_eq!(error, 0); assert!(error_msg.is_none()); let _ = error_msg.consume(); - let checksum = checksum.consume().unwrap_or_default(); + let checksum = out.consume().unwrap_or_default(); let mut error_msg = UnmanagedVector::default(); - let wasm = load_wasm( + let mut out = UnmanagedVector::default(); + let error = load_wasm( cache_ptr, ByteSliceView::new(&checksum), Some(&mut error_msg), + Some(&mut out), ); + assert_eq!(error, 0); assert!(error_msg.is_none()); let _ = error_msg.consume(); - let wasm = wasm.consume().unwrap_or_default(); + let wasm = out.consume().unwrap_or_default(); assert_eq!(wasm, HACKATOM); release_cache(cache_ptr); @@ -543,31 +568,36 @@ mod tests { let _ = error_msg.consume(); let mut error_msg = UnmanagedVector::default(); - let checksum = save_wasm( + let mut out = UnmanagedVector::default(); + let error = save_wasm( cache_ptr, ByteSliceView::new(HACKATOM), Some(&mut error_msg), + Some(&mut out), ); + assert_eq!(error, 0); assert!(error_msg.is_none()); let _ = error_msg.consume(); - let checksum = checksum.consume().unwrap_or_default(); + let checksum = out.consume().unwrap_or_default(); let mut error_msg = UnmanagedVector::default(); - pin( + let error = pin( cache_ptr, ByteSliceView::new(&checksum), Some(&mut error_msg), ); + assert_eq!(error, 0); assert!(error_msg.is_none()); let _ = error_msg.consume(); // pinning again has no effect let mut error_msg = UnmanagedVector::default(); - pin( + let error = pin( cache_ptr, ByteSliceView::new(&checksum), Some(&mut error_msg), ); + assert_eq!(error, 0); assert!(error_msg.is_none()); let _ = error_msg.consume(); @@ -591,40 +621,46 @@ mod tests { let _ = error_msg.consume(); let mut error_msg = UnmanagedVector::default(); - let checksum = save_wasm( + let mut out = UnmanagedVector::default(); + let error = save_wasm( cache_ptr, ByteSliceView::new(HACKATOM), Some(&mut error_msg), + Some(&mut out), ); + assert_eq!(error, 0); assert!(error_msg.is_none()); let _ = error_msg.consume(); - let checksum = checksum.consume().unwrap_or_default(); + let checksum = out.consume().unwrap_or_default(); let mut error_msg = UnmanagedVector::default(); - pin( + let error = pin( cache_ptr, ByteSliceView::new(&checksum), Some(&mut error_msg), ); + assert_eq!(error, 0); assert!(error_msg.is_none()); let _ = error_msg.consume(); let mut error_msg = UnmanagedVector::default(); - unpin( + let error = unpin( cache_ptr, ByteSliceView::new(&checksum), Some(&mut error_msg), ); + assert_eq!(error, 0); assert!(error_msg.is_none()); let _ = error_msg.consume(); // Unpinning again has no effect let mut error_msg = UnmanagedVector::default(); - unpin( + let error = unpin( cache_ptr, ByteSliceView::new(&checksum), Some(&mut error_msg), ); + assert_eq!(error, 0); assert!(error_msg.is_none()); let _ = error_msg.consume(); @@ -648,24 +684,30 @@ mod tests { let _ = error_msg.consume(); let mut error_msg = UnmanagedVector::default(); - let checksum_hackatom = save_wasm( + let mut out = UnmanagedVector::default(); + let error = save_wasm( cache_ptr, ByteSliceView::new(HACKATOM), Some(&mut error_msg), + Some(&mut out), ); + assert_eq!(error, 0); assert!(error_msg.is_none()); let _ = error_msg.consume(); - let checksum_hackatom = checksum_hackatom.consume().unwrap_or_default(); + let checksum_hackatom = out.consume().unwrap_or_default(); let mut error_msg = UnmanagedVector::default(); - let checksum_ibc_reflect = save_wasm( + let mut out = UnmanagedVector::default(); + let error = save_wasm( cache_ptr, ByteSliceView::new(IBC_REFLECT), Some(&mut error_msg), + Some(&mut out), ); + assert_eq!(error, 0); assert!(error_msg.is_none()); let _ = error_msg.consume(); - let checksum_ibc_reflect = checksum_ibc_reflect.consume().unwrap_or_default(); + let checksum_ibc_reflect = out.consume().unwrap_or_default(); let mut error_msg = UnmanagedVector::default(); let hackatom_report = analyze_code( @@ -751,14 +793,17 @@ mod tests { // Save wasm let mut error_msg = UnmanagedVector::default(); - let checksum_hackatom = save_wasm( + let mut out = UnmanagedVector::default(); + let error = save_wasm( cache_ptr, ByteSliceView::new(HACKATOM), Some(&mut error_msg), + Some(&mut out), ); + assert_eq!(error, 0); assert!(error_msg.is_none()); let _ = error_msg.consume(); - let checksum = checksum_hackatom.consume().unwrap_or_default(); + let checksum = out.consume().unwrap_or_default(); // Get metrics 2 let mut error_msg = UnmanagedVector::default(); @@ -768,11 +813,12 @@ mod tests { // Pin let mut error_msg = UnmanagedVector::default(); - pin( + let error = pin( cache_ptr, ByteSliceView::new(&checksum), Some(&mut error_msg), ); + assert_eq!(error, 0); assert!(error_msg.is_none()); let _ = error_msg.consume(); @@ -806,11 +852,12 @@ mod tests { // Unpin let mut error_msg = UnmanagedVector::default(); - unpin( + let error = unpin( cache_ptr, ByteSliceView::new(&checksum), Some(&mut error_msg), ); + assert_eq!(error, 0); assert!(error_msg.is_none()); let _ = error_msg.consume(); diff --git a/libwasmvm/src/error/mod.rs b/libwasmvm/src/error/mod.rs index 1f64e919..4980365f 100644 --- a/libwasmvm/src/error/mod.rs +++ b/libwasmvm/src/error/mod.rs @@ -4,5 +4,6 @@ mod rust; pub use go::GoError; pub use rust::{ - handle_c_error_binary, handle_c_error_default, handle_c_error_ptr, RustError as Error, + handle_c_error_binary, handle_c_error_default, handle_c_error_ptr, to_c_result_binary, + to_c_result_unit, RustError as Error, }; diff --git a/libwasmvm/src/error/rust.rs b/libwasmvm/src/error/rust.rs index 01c5ea43..8c8fd494 100644 --- a/libwasmvm/src/error/rust.rs +++ b/libwasmvm/src/error/rust.rs @@ -126,7 +126,7 @@ pub fn clear_error() { set_errno(ErrnoValue::Success as i32); } -pub fn set_error(err: RustError, error_msg: Option<&mut UnmanagedVector>) { +pub fn set_error(err: RustError, error_msg: Option<&mut UnmanagedVector>) -> i32 { if let Some(error_msg) = error_msg { if error_msg.is_some() { panic!( @@ -147,6 +147,16 @@ pub fn set_error(err: RustError, error_msg: Option<&mut UnmanagedVector>) { _ => ErrnoValue::Other, } as i32; set_errno(errno); + errno +} + +pub fn set_out(value: T, out_ptr: Option<&mut T>) { + if let Some(out_ref) = out_ptr { + *out_ref = value; + } else { + // The caller provided a nil pointer for the output message. + // That's not nice but we can live with it. + } } /// If `result` is Ok, this returns the Ok value and clears [errno]. @@ -215,6 +225,34 @@ where } } +/// If `result` is Ok, this writes the Ok value to `out` and returns 0. +/// Otherwise it writes the error message to `error_msg` and returns the error code. +pub fn to_c_result_binary( + result: Result, + error_msg_ptr: Option<&mut UnmanagedVector>, + out_ptr: Option<&mut UnmanagedVector>, +) -> i32 { + match result { + Ok(value) => { + set_out(value, out_ptr); + 0 + } + Err(error) => set_error(error, error_msg_ptr), + } +} + +/// If `result` is Ok, this writes the Ok value to `out` and returns 0. +/// Otherwise it writes the error message to `error_msg` and returns the error code. +pub fn to_c_result_unit( + result: Result<(), RustError>, + error_msg_ptr: Option<&mut UnmanagedVector>, +) -> i32 { + match result { + Ok(_) => 0, + Err(error) => set_error(error, error_msg_ptr), + } +} + #[cfg(test)] mod tests { use super::super::errno::errno; From 1be079d447ce39e7fad2481fb08f99149fc6ccbe Mon Sep 17 00:00:00 2001 From: Simon Warta Date: Mon, 5 Dec 2022 13:45:55 +0100 Subject: [PATCH 14/25] Start NO_ERRNO docs --- docs/NO_ERRNO.md | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 docs/NO_ERRNO.md diff --git a/docs/NO_ERRNO.md b/docs/NO_ERRNO.md new file mode 100644 index 00000000..d88ac1b0 --- /dev/null +++ b/docs/NO_ERRNO.md @@ -0,0 +1,21 @@ +# Why we are not using errno anymore + +wasmvm up until 1.1.1 used errno to communicate errors over the FFI that +happened in the Rust code. The [errno](https://crates.io/crates/errno) crate was +used to set error values in Rust and +[cgo automatically read them](https://utcc.utoronto.ca/~cks/space/blog/programming/GoCgoErrorReturns) +and made them available in the error return value of +`ptr, err := C.init_cache(...)`. + +Unfortunately errno does not work well for us when trying to support Windows. On +Windows, `errno` +[uses a Windows API](https://github.com/lambda-fairy/rust-errno/blob/v0.2.8/src/windows.rs#L60-L70) +which then is not what cgo expects. Also Rust's +[libc does not help us](https://github.com/rust-lang/libc/issues/1644) solving +the issue. Using the C errno variable via +[rust-errno](https://github.com/lambda-fairy/rust-errno) caused linker errors +using the Go "internal" linker. + +In order to avoid wasting more time and remaining flexible when it comes to the +linker we use, we let all FFI functions return their error as an integer. The +result then goes into an output pointer. From 32a63f430b24348bd5016c8c810e318b87ce401e Mon Sep 17 00:00:00 2001 From: Simon Warta Date: Mon, 5 Dec 2022 14:12:17 +0100 Subject: [PATCH 15/25] Let analyze_code return error --- internal/api/bindings.h | 7 ++++--- internal/api/lib.go | 11 ++++++----- libwasmvm/bindings.h | 7 ++++--- libwasmvm/src/cache.rs | 31 ++++++++++++++++++------------- libwasmvm/src/error/mod.rs | 4 ++-- libwasmvm/src/error/rust.rs | 16 ++++++++++++++++ 6 files changed, 50 insertions(+), 26 deletions(-) diff --git a/internal/api/bindings.h b/internal/api/bindings.h index c585a640..7b51a772 100644 --- a/internal/api/bindings.h +++ b/internal/api/bindings.h @@ -331,9 +331,10 @@ int32_t unpin(struct cache_t *cache, struct ByteSliceView checksum, struct UnmanagedVector *error_msg); -struct AnalysisReport analyze_code(struct cache_t *cache, - struct ByteSliceView checksum, - struct UnmanagedVector *error_msg); +int32_t analyze_code(struct cache_t *cache, + struct ByteSliceView checksum, + struct UnmanagedVector *error_msg, + struct AnalysisReport *out); struct Metrics get_metrics(struct cache_t *cache, struct UnmanagedVector *error_msg); diff --git a/internal/api/lib.go b/internal/api/lib.go index 1db8bf02..20dc4f55 100644 --- a/internal/api/lib.go +++ b/internal/api/lib.go @@ -118,13 +118,14 @@ func AnalyzeCode(cache Cache, checksum []byte) (*types.AnalysisReport, error) { cs := makeView(checksum) defer runtime.KeepAlive(checksum) errmsg := newUnmanagedVector(nil) - report, err := C.analyze_code(cache.ptr, cs, &errmsg) - if err != nil { - return nil, ffiErrorWithMessage(err, errmsg) + out := C.AnalysisReport{} + err := C.analyze_code(cache.ptr, cs, &errmsg, &out) + if err != 0 { + return nil, ffiErrorWithMessage2(err, errmsg) } - requiredCapabilities := string(copyAndDestroyUnmanagedVector(report.required_capabilities)) + requiredCapabilities := string(copyAndDestroyUnmanagedVector(out.required_capabilities)) res := types.AnalysisReport{ - HasIBCEntryPoints: bool(report.has_ibc_entry_points), + HasIBCEntryPoints: bool(out.has_ibc_entry_points), RequiredFeatures: requiredCapabilities, RequiredCapabilities: requiredCapabilities, } diff --git a/libwasmvm/bindings.h b/libwasmvm/bindings.h index c585a640..7b51a772 100644 --- a/libwasmvm/bindings.h +++ b/libwasmvm/bindings.h @@ -331,9 +331,10 @@ int32_t unpin(struct cache_t *cache, struct ByteSliceView checksum, struct UnmanagedVector *error_msg); -struct AnalysisReport analyze_code(struct cache_t *cache, - struct ByteSliceView checksum, - struct UnmanagedVector *error_msg); +int32_t analyze_code(struct cache_t *cache, + struct ByteSliceView checksum, + struct UnmanagedVector *error_msg, + struct AnalysisReport *out); struct Metrics get_metrics(struct cache_t *cache, struct UnmanagedVector *error_msg); diff --git a/libwasmvm/src/cache.rs b/libwasmvm/src/cache.rs index 292fd205..69b14f27 100644 --- a/libwasmvm/src/cache.rs +++ b/libwasmvm/src/cache.rs @@ -8,7 +8,8 @@ use cosmwasm_vm::{capabilities_from_csv, Cache, CacheOptions, Checksum, Size}; use crate::api::GoApi; use crate::args::{AVAILABLE_CAPABILITIES_ARG, CACHE_ARG, CHECKSUM_ARG, DATA_DIR_ARG, WASM_ARG}; use crate::error::{ - handle_c_error_default, handle_c_error_ptr, to_c_result_binary, to_c_result_unit, Error, + handle_c_error_default, handle_c_error_ptr, to_c_result, to_c_result_binary, to_c_result_unit, + Error, }; use crate::memory::{ByteSliceView, UnmanagedVector}; use crate::querier::GoQuerier; @@ -254,17 +255,19 @@ fn set_to_csv(set: HashSet) -> String { } #[no_mangle] +#[must_use] pub extern "C" fn analyze_code( cache: *mut cache_t, checksum: ByteSliceView, error_msg: Option<&mut UnmanagedVector>, -) -> AnalysisReport { + out: Option<&mut AnalysisReport>, +) -> i32 { let r = match to_cache(cache) { Some(c) => catch_unwind(AssertUnwindSafe(move || do_analyze_code(c, checksum))) .unwrap_or_else(|_| Err(Error::panic())), None => Err(Error::unset_arg(CACHE_ARG)), }; - handle_c_error_default(r, error_msg) + to_c_result(r, error_msg, out) } fn do_analyze_code( @@ -710,29 +713,31 @@ mod tests { let checksum_ibc_reflect = out.consume().unwrap_or_default(); let mut error_msg = UnmanagedVector::default(); - let hackatom_report = analyze_code( + let mut out = AnalysisReport::default(); + let error = analyze_code( cache_ptr, ByteSliceView::new(&checksum_hackatom), Some(&mut error_msg), + Some(&mut out), ); + assert_eq!(error, 0); let _ = error_msg.consume(); - assert!(!hackatom_report.has_ibc_entry_points); - assert_eq!( - hackatom_report.required_capabilities.consume().unwrap(), - b"" - ); + assert!(!out.has_ibc_entry_points); + assert_eq!(out.required_capabilities.consume().unwrap(), b""); let mut error_msg = UnmanagedVector::default(); - let ibc_reflect_report = analyze_code( + let mut out = AnalysisReport::default(); + let error = analyze_code( cache_ptr, ByteSliceView::new(&checksum_ibc_reflect), Some(&mut error_msg), + Some(&mut out), ); + assert_eq!(error, 0); let _ = error_msg.consume(); - assert!(ibc_reflect_report.has_ibc_entry_points); + assert!(out.has_ibc_entry_points); let required_capabilities = - String::from_utf8_lossy(&ibc_reflect_report.required_capabilities.consume().unwrap()) - .to_string(); + String::from_utf8_lossy(&out.required_capabilities.consume().unwrap()).to_string(); assert_eq!(required_capabilities, "iterator,stargate"); release_cache(cache_ptr); diff --git a/libwasmvm/src/error/mod.rs b/libwasmvm/src/error/mod.rs index 4980365f..2a13db65 100644 --- a/libwasmvm/src/error/mod.rs +++ b/libwasmvm/src/error/mod.rs @@ -4,6 +4,6 @@ mod rust; pub use go::GoError; pub use rust::{ - handle_c_error_binary, handle_c_error_default, handle_c_error_ptr, to_c_result_binary, - to_c_result_unit, RustError as Error, + handle_c_error_binary, handle_c_error_default, handle_c_error_ptr, to_c_result, + to_c_result_binary, to_c_result_unit, RustError as Error, }; diff --git a/libwasmvm/src/error/rust.rs b/libwasmvm/src/error/rust.rs index 8c8fd494..0a73f278 100644 --- a/libwasmvm/src/error/rust.rs +++ b/libwasmvm/src/error/rust.rs @@ -241,6 +241,22 @@ pub fn to_c_result_binary( } } +/// If `result` is Ok, this writes the Ok value to `out` and returns 0. +/// Otherwise it writes the error message to `error_msg` and returns the error code. +pub fn to_c_result( + result: Result, + error_msg_ptr: Option<&mut UnmanagedVector>, + out_ptr: Option<&mut T>, +) -> i32 { + match result { + Ok(value) => { + set_out(value, out_ptr); + 0 + } + Err(error) => set_error(error, error_msg_ptr), + } +} + /// If `result` is Ok, this writes the Ok value to `out` and returns 0. /// Otherwise it writes the error message to `error_msg` and returns the error code. pub fn to_c_result_unit( From 61143fc9f2e8fd1d9cb9da620c4781f276fb0de7 Mon Sep 17 00:00:00 2001 From: Simon Warta Date: Mon, 5 Dec 2022 14:21:30 +0100 Subject: [PATCH 16/25] Let get_metrics return error directly --- internal/api/bindings.h | 2 +- internal/api/lib.go | 9 +-- libwasmvm/bindings.h | 2 +- libwasmvm/src/cache.rs | 35 ++++++----- libwasmvm/src/error/mod.rs | 4 +- libwasmvm/src/error/rust.rs | 117 ------------------------------------ 6 files changed, 30 insertions(+), 139 deletions(-) diff --git a/internal/api/bindings.h b/internal/api/bindings.h index 7b51a772..afeeb878 100644 --- a/internal/api/bindings.h +++ b/internal/api/bindings.h @@ -336,7 +336,7 @@ int32_t analyze_code(struct cache_t *cache, struct UnmanagedVector *error_msg, struct AnalysisReport *out); -struct Metrics get_metrics(struct cache_t *cache, struct UnmanagedVector *error_msg); +int32_t get_metrics(struct cache_t *cache, struct UnmanagedVector *error_msg, struct Metrics *out); /** * frees a cache reference diff --git a/internal/api/lib.go b/internal/api/lib.go index 20dc4f55..a81b9de4 100644 --- a/internal/api/lib.go +++ b/internal/api/lib.go @@ -56,7 +56,7 @@ func ReleaseCache(cache Cache) { C.release_cache(cache.ptr) // No error case that needs handling } -/// StoreCode stored the Wasm blob and returns the checksum +// / StoreCode stored the Wasm blob and returns the checksum func StoreCode(cache Cache, wasm []byte) ([]byte, error) { w := makeView(wasm) defer runtime.KeepAlive(wasm) @@ -134,9 +134,10 @@ func AnalyzeCode(cache Cache, checksum []byte) (*types.AnalysisReport, error) { func GetMetrics(cache Cache) (*types.Metrics, error) { errmsg := newUnmanagedVector(nil) - metrics, err := C.get_metrics(cache.ptr, &errmsg) - if err != nil { - return nil, ffiErrorWithMessage(err, errmsg) + metrics := C.Metrics{} + err := C.get_metrics(cache.ptr, &errmsg, &metrics) + if err != 0 { + return nil, ffiErrorWithMessage2(err, errmsg) } return &types.Metrics{ diff --git a/libwasmvm/bindings.h b/libwasmvm/bindings.h index 7b51a772..afeeb878 100644 --- a/libwasmvm/bindings.h +++ b/libwasmvm/bindings.h @@ -336,7 +336,7 @@ int32_t analyze_code(struct cache_t *cache, struct UnmanagedVector *error_msg, struct AnalysisReport *out); -struct Metrics get_metrics(struct cache_t *cache, struct UnmanagedVector *error_msg); +int32_t get_metrics(struct cache_t *cache, struct UnmanagedVector *error_msg, struct Metrics *out); /** * frees a cache reference diff --git a/libwasmvm/src/cache.rs b/libwasmvm/src/cache.rs index 69b14f27..fecf8e01 100644 --- a/libwasmvm/src/cache.rs +++ b/libwasmvm/src/cache.rs @@ -7,10 +7,7 @@ use cosmwasm_vm::{capabilities_from_csv, Cache, CacheOptions, Checksum, Size}; use crate::api::GoApi; use crate::args::{AVAILABLE_CAPABILITIES_ARG, CACHE_ARG, CHECKSUM_ARG, DATA_DIR_ARG, WASM_ARG}; -use crate::error::{ - handle_c_error_default, handle_c_error_ptr, to_c_result, to_c_result_binary, to_c_result_unit, - Error, -}; +use crate::error::{handle_c_error_ptr, to_c_result, to_c_result_binary, to_c_result_unit, Error}; use crate::memory::{ByteSliceView, UnmanagedVector}; use crate::querier::GoQuerier; use crate::storage::GoStorage; @@ -333,16 +330,18 @@ impl From for Metrics { } #[no_mangle] +#[must_use] pub extern "C" fn get_metrics( cache: *mut cache_t, error_msg: Option<&mut UnmanagedVector>, -) -> Metrics { + out: Option<&mut Metrics>, +) -> i32 { let r = match to_cache(cache) { Some(c) => catch_unwind(AssertUnwindSafe(move || do_get_metrics(c))) .unwrap_or_else(|_| Err(Error::panic())), None => Err(Error::unset_arg(CACHE_ARG)), }; - handle_c_error_default(r, error_msg) + to_c_result(r, error_msg, out) } #[allow(clippy::unnecessary_wraps)] // Keep unused Result for consistent boilerplate for all fn do_* @@ -792,9 +791,11 @@ mod tests { // Get metrics 1 let mut error_msg = UnmanagedVector::default(); - let metrics = get_metrics(cache_ptr, Some(&mut error_msg)); + let mut out = Metrics::default(); + let error = get_metrics(cache_ptr, Some(&mut error_msg), Some(&mut out)); + assert_eq!(error, 0); let _ = error_msg.consume(); - assert_eq!(metrics, Metrics::default()); + assert_eq!(out, Metrics::default()); // Save wasm let mut error_msg = UnmanagedVector::default(); @@ -812,9 +813,11 @@ mod tests { // Get metrics 2 let mut error_msg = UnmanagedVector::default(); - let metrics = get_metrics(cache_ptr, Some(&mut error_msg)); + let mut out = Metrics::default(); + let error = get_metrics(cache_ptr, Some(&mut error_msg), Some(&mut out)); + assert_eq!(error, 0); let _ = error_msg.consume(); - assert_eq!(metrics, Metrics::default()); + assert_eq!(out, Metrics::default()); // Pin let mut error_msg = UnmanagedVector::default(); @@ -829,7 +832,9 @@ mod tests { // Get metrics 3 let mut error_msg = UnmanagedVector::default(); - let metrics = get_metrics(cache_ptr, Some(&mut error_msg)); + let mut out = Metrics::default(); + let error = get_metrics(cache_ptr, Some(&mut error_msg), Some(&mut out)); + assert_eq!(error, 0); let _ = error_msg.consume(); let Metrics { hits_pinned_memory_cache, @@ -840,7 +845,7 @@ mod tests { elements_memory_cache, size_pinned_memory_cache, size_memory_cache, - } = metrics; + } = out; assert_eq!(hits_pinned_memory_cache, 0); assert_eq!(hits_memory_cache, 0); assert_eq!(hits_fs_cache, 1); @@ -868,10 +873,12 @@ mod tests { // Get metrics 4 let mut error_msg = UnmanagedVector::default(); - let metrics = get_metrics(cache_ptr, Some(&mut error_msg)); + let mut out = Metrics::default(); + let error = get_metrics(cache_ptr, Some(&mut error_msg), Some(&mut out)); + assert_eq!(error, 0); let _ = error_msg.consume(); assert_eq!( - metrics, + out, Metrics { hits_pinned_memory_cache: 0, hits_memory_cache: 0, diff --git a/libwasmvm/src/error/mod.rs b/libwasmvm/src/error/mod.rs index 2a13db65..bc21ad9f 100644 --- a/libwasmvm/src/error/mod.rs +++ b/libwasmvm/src/error/mod.rs @@ -4,6 +4,6 @@ mod rust; pub use go::GoError; pub use rust::{ - handle_c_error_binary, handle_c_error_default, handle_c_error_ptr, to_c_result, - to_c_result_binary, to_c_result_unit, RustError as Error, + handle_c_error_binary, handle_c_error_ptr, to_c_result, to_c_result_binary, to_c_result_unit, + RustError as Error, }; diff --git a/libwasmvm/src/error/rust.rs b/libwasmvm/src/error/rust.rs index 0a73f278..510bdd56 100644 --- a/libwasmvm/src/error/rust.rs +++ b/libwasmvm/src/error/rust.rs @@ -202,29 +202,6 @@ where } } -/// If `result` is Ok, this returns the Ok value and clears [errno]. -/// Otherwise it returns the default value, writes the error message to `error_msg` and sets [errno]. -/// -/// [errno]: https://utcc.utoronto.ca/~cks/space/blog/programming/GoCgoErrorReturns -pub fn handle_c_error_default( - result: Result, - error_msg: Option<&mut UnmanagedVector>, -) -> T -where - T: Default, -{ - match result { - Ok(value) => { - clear_error(); - value - } - Err(error) => { - set_error(error, error_msg); - Default::default() - } - } -} - /// If `result` is Ok, this writes the Ok value to `out` and returns 0. /// Otherwise it writes the error message to `error_msg` and returns the error code. pub fn to_c_result_binary( @@ -488,98 +465,4 @@ mod tests { assert_eq!(data, vec![0xF0, 0x0B, 0xAA]); let _ = error_msg.consume(); } - - #[test] - fn handle_c_error_default_works() { - // Ok (non-empty vector) - let mut error_msg = UnmanagedVector::default(); - let res: Result, RustError> = Ok(vec![0xF0, 0x0B, 0xAA]); - let data = handle_c_error_default(res, Some(&mut error_msg)); - assert_eq!(errno(), ErrnoValue::Success as i32); - assert!(error_msg.is_none()); - assert_eq!(data, vec![0xF0, 0x0B, 0xAA]); - let _ = error_msg.consume(); - - // Ok (empty vector) - let mut error_msg = UnmanagedVector::default(); - let res: Result, RustError> = Ok(vec![]); - let data = handle_c_error_default(res, Some(&mut error_msg)); - assert_eq!(errno(), ErrnoValue::Success as i32); - assert!(error_msg.is_none()); - assert_eq!(data, Vec::::new()); - let _ = error_msg.consume(); - - // Ok (non-empty slice) - let mut error_msg = UnmanagedVector::default(); - let res: Result<&[u8], RustError> = Ok(b"foobar"); - let data = handle_c_error_default(res, Some(&mut error_msg)); - assert_eq!(errno(), ErrnoValue::Success as i32); - assert!(error_msg.is_none()); - assert_eq!(data, Vec::::from(b"foobar" as &[u8])); - let _ = error_msg.consume(); - - // Ok (empty slice) - let mut error_msg = UnmanagedVector::default(); - let res: Result<&[u8], RustError> = Ok(b""); - let data = handle_c_error_default(res, Some(&mut error_msg)); - assert_eq!(errno(), ErrnoValue::Success as i32); - assert!(error_msg.is_none()); - assert_eq!(data, Vec::::new()); - let _ = error_msg.consume(); - - // Ok (unit) - let mut error_msg = UnmanagedVector::default(); - let res: Result<(), RustError> = Ok(()); - let _data = handle_c_error_default(res, Some(&mut error_msg)); - assert_eq!(errno(), ErrnoValue::Success as i32); - assert!(error_msg.is_none()); - let _ = error_msg.consume(); - - // Err (vector) - let mut error_msg = UnmanagedVector::default(); - let res: Result, RustError> = Err(RustError::panic()); - let data = handle_c_error_default(res, Some(&mut error_msg)); - assert_eq!(errno(), ErrnoValue::Other as i32); - assert!(error_msg.is_some()); - assert_eq!(data, Vec::::new()); - let _ = error_msg.consume(); - - // Err (slice) - let mut error_msg = UnmanagedVector::default(); - let res: Result<&[u8], RustError> = Err(RustError::panic()); - let data = handle_c_error_default(res, Some(&mut error_msg)); - assert_eq!(errno(), ErrnoValue::Other as i32); - assert!(error_msg.is_some()); - assert_eq!(data, Vec::::new()); - let _ = error_msg.consume(); - - // Err (unit) - let mut error_msg = UnmanagedVector::default(); - let res: Result<(), RustError> = Err(RustError::panic()); - let _data = handle_c_error_default(res, Some(&mut error_msg)); - assert_eq!(errno(), ErrnoValue::Other as i32); - assert!(error_msg.is_some()); - let _ = error_msg.consume(); - } - - #[test] - fn handle_c_error_default_clears_an_old_error() { - // Err - let mut error_msg = UnmanagedVector::default(); - let res: Result, RustError> = Err(RustError::panic()); - let data = handle_c_error_default(res, Some(&mut error_msg)); - assert_eq!(errno(), ErrnoValue::Other as i32); - assert!(error_msg.is_some()); - assert_eq!(data, Vec::::new()); - let _ = error_msg.consume(); - - // Ok - let mut error_msg = UnmanagedVector::default(); - let res: Result, RustError> = Ok(vec![0xF0, 0x0B, 0xAA]); - let data = handle_c_error_default(res, Some(&mut error_msg)); - assert_eq!(errno(), ErrnoValue::Success as i32); - assert!(error_msg.is_none()); - assert_eq!(data, vec![0xF0, 0x0B, 0xAA]); - let _ = error_msg.consume(); - } } From 5862e3f613357a51695b955eb8a41acd4afe9903 Mon Sep 17 00:00:00 2001 From: Simon Warta Date: Mon, 5 Dec 2022 14:47:01 +0100 Subject: [PATCH 17/25] Let init_cache return error directly --- internal/api/bindings.h | 31 ++++++++---- internal/api/lib.go | 9 ++-- libwasmvm/bindings.h | 31 ++++++++---- libwasmvm/src/cache.rs | 97 +++++++++++++++++++++++++++++++------ libwasmvm/src/error/mod.rs | 3 +- libwasmvm/src/error/rust.rs | 20 -------- 6 files changed, 133 insertions(+), 58 deletions(-) diff --git a/internal/api/bindings.h b/internal/api/bindings.h index afeeb878..53a4165d 100644 --- a/internal/api/bindings.h +++ b/internal/api/bindings.h @@ -53,10 +53,6 @@ enum GoError { }; typedef int32_t GoError; -typedef struct cache_t { - -} cache_t; - /** * A view into an externally owned byte slice (Go `[]byte`). * Use this for the current call only. A view cannot be copied for safety reasons. @@ -193,6 +189,22 @@ typedef struct UnmanagedVector { uintptr_t cap; } UnmanagedVector; +typedef struct cache_t { + +} cache_t; + +/** + * A struct that holds a pointer to the cache. This struct can be + * copied freely. + * + * In case of `init_cache` we need a pointer to a pointer for the output + * and in order to be able to do this consistently with e.g. `AnalysisReport` + * and `Metrics`, we use thiy type. + */ +typedef struct CachePtr { + struct cache_t *ptr; +} CachePtr; + /** * The result type of the FFI function analyze_code. * @@ -303,11 +315,12 @@ typedef struct GoQuerier { struct Querier_vtable vtable; } GoQuerier; -struct cache_t *init_cache(struct ByteSliceView data_dir, - struct ByteSliceView available_capabilities, - uint32_t cache_size, - uint32_t instance_memory_limit, - struct UnmanagedVector *error_msg); +int32_t init_cache(struct ByteSliceView data_dir, + struct ByteSliceView available_capabilities, + uint32_t cache_size, + uint32_t instance_memory_limit, + struct UnmanagedVector *error_msg, + struct CachePtr *out); int32_t save_wasm(struct cache_t *cache, struct ByteSliceView wasm, diff --git a/internal/api/lib.go b/internal/api/lib.go index a81b9de4..aa360ef7 100644 --- a/internal/api/lib.go +++ b/internal/api/lib.go @@ -44,12 +44,13 @@ func InitCache(dataDir string, supportedFeatures string, cacheSize uint32, insta defer runtime.KeepAlive(supportedFeaturesBytes) errmsg := newUnmanagedVector(nil) + out := C.CachePtr{} - ptr, err := C.init_cache(d, f, cu32(cacheSize), cu32(instanceMemoryLimit), &errmsg) - if err != nil { - return Cache{}, ffiErrorWithMessage(err, errmsg) + err := C.init_cache(d, f, cu32(cacheSize), cu32(instanceMemoryLimit), &errmsg, &out) + if err != 0 { + return Cache{}, ffiErrorWithMessage2(err, errmsg) } - return Cache{ptr: ptr}, nil + return Cache{ptr: out.ptr}, nil } func ReleaseCache(cache Cache) { diff --git a/libwasmvm/bindings.h b/libwasmvm/bindings.h index afeeb878..53a4165d 100644 --- a/libwasmvm/bindings.h +++ b/libwasmvm/bindings.h @@ -53,10 +53,6 @@ enum GoError { }; typedef int32_t GoError; -typedef struct cache_t { - -} cache_t; - /** * A view into an externally owned byte slice (Go `[]byte`). * Use this for the current call only. A view cannot be copied for safety reasons. @@ -193,6 +189,22 @@ typedef struct UnmanagedVector { uintptr_t cap; } UnmanagedVector; +typedef struct cache_t { + +} cache_t; + +/** + * A struct that holds a pointer to the cache. This struct can be + * copied freely. + * + * In case of `init_cache` we need a pointer to a pointer for the output + * and in order to be able to do this consistently with e.g. `AnalysisReport` + * and `Metrics`, we use thiy type. + */ +typedef struct CachePtr { + struct cache_t *ptr; +} CachePtr; + /** * The result type of the FFI function analyze_code. * @@ -303,11 +315,12 @@ typedef struct GoQuerier { struct Querier_vtable vtable; } GoQuerier; -struct cache_t *init_cache(struct ByteSliceView data_dir, - struct ByteSliceView available_capabilities, - uint32_t cache_size, - uint32_t instance_memory_limit, - struct UnmanagedVector *error_msg); +int32_t init_cache(struct ByteSliceView data_dir, + struct ByteSliceView available_capabilities, + uint32_t cache_size, + uint32_t instance_memory_limit, + struct UnmanagedVector *error_msg, + struct CachePtr *out); int32_t save_wasm(struct cache_t *cache, struct ByteSliceView wasm, diff --git a/libwasmvm/src/cache.rs b/libwasmvm/src/cache.rs index fecf8e01..172cc16f 100644 --- a/libwasmvm/src/cache.rs +++ b/libwasmvm/src/cache.rs @@ -7,7 +7,7 @@ use cosmwasm_vm::{capabilities_from_csv, Cache, CacheOptions, Checksum, Size}; use crate::api::GoApi; use crate::args::{AVAILABLE_CAPABILITIES_ARG, CACHE_ARG, CHECKSUM_ARG, DATA_DIR_ARG, WASM_ARG}; -use crate::error::{handle_c_error_ptr, to_c_result, to_c_result_binary, to_c_result_unit, Error}; +use crate::error::{to_c_result, to_c_result_binary, to_c_result_unit, Error}; use crate::memory::{ByteSliceView, UnmanagedVector}; use crate::querier::GoQuerier; use crate::storage::GoStorage; @@ -15,6 +15,39 @@ use crate::storage::GoStorage; #[repr(C)] pub struct cache_t {} +/// A struct that holds a pointer to the cache. This struct can be +/// copied freely. +/// +/// In case of `init_cache` we need a pointer to a pointer for the output +/// and in order to be able to do this consistently with e.g. `AnalysisReport` +/// and `Metrics`, we use thiy type. +#[repr(C)] +#[derive(Copy, Clone, Debug, PartialEq, Eq)] +pub struct CachePtr { + pub ptr: *mut cache_t, +} + +impl Default for CachePtr { + fn default() -> Self { + Self { + ptr: std::ptr::null_mut(), + } + } +} + +impl CachePtr { + pub fn new(rust_ptr: *mut Cache) -> Self { + Self { + ptr: rust_ptr as *mut cache_t, + } + } + + #[cfg(test)] + pub fn is_null(self) -> bool { + self.ptr.is_null() + } +} + pub fn to_cache(ptr: *mut cache_t) -> Option<&'static mut Cache> { if ptr.is_null() { None @@ -31,7 +64,8 @@ pub extern "C" fn init_cache( cache_size: u32, // in MiB instance_memory_limit: u32, // in MiB error_msg: Option<&mut UnmanagedVector>, -) -> *mut cache_t { + out: Option<&mut CachePtr>, +) -> i32 { let r = catch_unwind(|| { do_init_cache( data_dir, @@ -41,7 +75,8 @@ pub extern "C" fn init_cache( ) }) .unwrap_or_else(|_| Err(Error::panic())); - handle_c_error_ptr(r, error_msg) as *mut cache_t + let r = r.map(CachePtr::new); + to_c_result(r, error_msg, out) } fn do_init_cache( @@ -380,17 +415,20 @@ mod tests { let capabilities = b"staking"; let mut error_msg = UnmanagedVector::default(); - let cache_ptr = init_cache( + let mut out = CachePtr::default(); + let error = init_cache( ByteSliceView::new(dir.as_bytes()), ByteSliceView::new(capabilities), 512, 32, Some(&mut error_msg), + Some(&mut out), ); + assert_eq!(error, 0); assert!(error_msg.is_none()); let _ = error_msg.consume(); - release_cache(cache_ptr); + release_cache(out.ptr); } #[test] @@ -399,14 +437,17 @@ mod tests { let capabilities = b"staking"; let mut error_msg = UnmanagedVector::default(); - let cache_ptr = init_cache( + let mut out = CachePtr::default(); + let error = init_cache( ByteSliceView::new(dir.as_bytes()), ByteSliceView::new(capabilities), 512, 32, Some(&mut error_msg), + Some(&mut out), ); - assert!(cache_ptr.is_null()); + assert_ne!(error, 0); + assert!(out.is_null()); assert!(error_msg.is_some()); let msg = String::from_utf8(error_msg.consume().unwrap()).unwrap(); assert_eq!( @@ -421,15 +462,19 @@ mod tests { let capabilities = b"staking"; let mut error_msg = UnmanagedVector::default(); - let cache_ptr = init_cache( + let mut out = CachePtr::default(); + let error = init_cache( ByteSliceView::new(dir.as_bytes()), ByteSliceView::new(capabilities), 512, 32, Some(&mut error_msg), + Some(&mut out), ); + assert_eq!(error, 0); assert!(error_msg.is_none()); let _ = error_msg.consume(); + let cache_ptr = out.ptr; let mut error_msg = UnmanagedVector::default(); let mut out = UnmanagedVector::default(); @@ -454,15 +499,19 @@ mod tests { let capabilities = b"staking"; let mut error_msg = UnmanagedVector::default(); - let cache_ptr = init_cache( + let mut out = CachePtr::default(); + let error = init_cache( ByteSliceView::new(dir.as_bytes()), ByteSliceView::new(capabilities), 512, 32, Some(&mut error_msg), + Some(&mut out), ); + assert_eq!(error, 0); assert!(error_msg.is_none()); let _ = error_msg.consume(); + let cache_ptr = out.ptr; let mut error_msg = UnmanagedVector::default(); let mut out = UnmanagedVector::default(); @@ -513,15 +562,19 @@ mod tests { let capabilities = b"staking"; let mut error_msg = UnmanagedVector::default(); - let cache_ptr = init_cache( + let mut out = CachePtr::default(); + let error = init_cache( ByteSliceView::new(dir.as_bytes()), ByteSliceView::new(capabilities), 512, 32, Some(&mut error_msg), + Some(&mut out), ); + assert_eq!(error, 0); assert!(error_msg.is_none()); let _ = error_msg.consume(); + let cache_ptr = out.ptr; let mut error_msg = UnmanagedVector::default(); let mut out = UnmanagedVector::default(); @@ -559,15 +612,19 @@ mod tests { let capabilities = b"staking"; let mut error_msg = UnmanagedVector::default(); - let cache_ptr = init_cache( + let mut out = CachePtr::default(); + let error = init_cache( ByteSliceView::new(dir.as_bytes()), ByteSliceView::new(capabilities), 512, 32, Some(&mut error_msg), + Some(&mut out), ); + assert_eq!(error, 0); assert!(error_msg.is_none()); let _ = error_msg.consume(); + let cache_ptr = out.ptr; let mut error_msg = UnmanagedVector::default(); let mut out = UnmanagedVector::default(); @@ -612,15 +669,19 @@ mod tests { let capabilities = b"staking"; let mut error_msg = UnmanagedVector::default(); - let cache_ptr = init_cache( + let mut out = CachePtr::default(); + let error = init_cache( ByteSliceView::new(dir.as_bytes()), ByteSliceView::new(capabilities), 512, 32, Some(&mut error_msg), + Some(&mut out), ); + assert_eq!(error, 0); assert!(error_msg.is_none()); let _ = error_msg.consume(); + let cache_ptr = out.ptr; let mut error_msg = UnmanagedVector::default(); let mut out = UnmanagedVector::default(); @@ -675,15 +736,19 @@ mod tests { let capabilities = b"staking,stargate,iterator"; let mut error_msg = UnmanagedVector::default(); - let cache_ptr = init_cache( + let mut out = CachePtr::default(); + let error = init_cache( ByteSliceView::new(dir.as_bytes()), ByteSliceView::new(capabilities), 512, 32, Some(&mut error_msg), + Some(&mut out), ); + assert_eq!(error, 0); assert!(error_msg.is_none()); let _ = error_msg.consume(); + let cache_ptr = out.ptr; let mut error_msg = UnmanagedVector::default(); let mut out = UnmanagedVector::default(); @@ -779,15 +844,19 @@ mod tests { // Init cache let mut error_msg = UnmanagedVector::default(); - let cache_ptr = init_cache( + let mut out = CachePtr::default(); + let error = init_cache( ByteSliceView::new(dir.as_bytes()), ByteSliceView::new(capabilities), 512, 32, Some(&mut error_msg), + Some(&mut out), ); + assert_eq!(error, 0); assert!(error_msg.is_none()); let _ = error_msg.consume(); + let cache_ptr = out.ptr; // Get metrics 1 let mut error_msg = UnmanagedVector::default(); diff --git a/libwasmvm/src/error/mod.rs b/libwasmvm/src/error/mod.rs index bc21ad9f..5f3748fd 100644 --- a/libwasmvm/src/error/mod.rs +++ b/libwasmvm/src/error/mod.rs @@ -4,6 +4,5 @@ mod rust; pub use go::GoError; pub use rust::{ - handle_c_error_binary, handle_c_error_ptr, to_c_result, to_c_result_binary, to_c_result_unit, - RustError as Error, + handle_c_error_binary, to_c_result, to_c_result_binary, to_c_result_unit, RustError as Error, }; diff --git a/libwasmvm/src/error/rust.rs b/libwasmvm/src/error/rust.rs index 510bdd56..01a3c53e 100644 --- a/libwasmvm/src/error/rust.rs +++ b/libwasmvm/src/error/rust.rs @@ -159,26 +159,6 @@ pub fn set_out(value: T, out_ptr: Option<&mut T>) { } } -/// If `result` is Ok, this returns the Ok value and clears [errno]. -/// Otherwise it returns a null pointer, writes the error message to `error_msg` and sets [errno]. -/// -/// [errno]: https://utcc.utoronto.ca/~cks/space/blog/programming/GoCgoErrorReturns -pub fn handle_c_error_ptr( - result: Result<*mut T, RustError>, - error_msg: Option<&mut UnmanagedVector>, -) -> *mut T { - match result { - Ok(value) => { - clear_error(); - value - } - Err(error) => { - set_error(error, error_msg); - std::ptr::null_mut() - } - } -} - /// If `result` is Ok, this returns the binary representation of the Ok value and clears [errno]. /// Otherwise it returns an empty vector, writes the error message to `error_msg` and sets [errno]. /// From fd19fd64868502541d6a5684e8e7e454cd0257f7 Mon Sep 17 00:00:00 2001 From: Simon Warta Date: Mon, 16 Jan 2023 17:31:18 +0100 Subject: [PATCH 18/25] Use CachePtr consistently and remove cache_t --- internal/api/bindings.h | 52 +++++++++++++++++++---------------------- internal/api/lib.go | 49 +++++++++++++++++++++----------------- libwasmvm/bindings.h | 52 +++++++++++++++++++---------------------- libwasmvm/src/cache.rs | 50 ++++++++++++++++++--------------------- libwasmvm/src/calls.rs | 30 ++++++++++++------------ libwasmvm/src/lib.rs | 2 +- libwasmvm/src/memory.rs | 4 ++-- 7 files changed, 117 insertions(+), 122 deletions(-) diff --git a/internal/api/bindings.h b/internal/api/bindings.h index 53a4165d..b5edc2c7 100644 --- a/internal/api/bindings.h +++ b/internal/api/bindings.h @@ -108,10 +108,10 @@ typedef struct ByteSliceView { * Transferring ownership from Rust to Go using return values of FFI calls: * * ``` - * # use wasmvm::{cache_t, ByteSliceView, UnmanagedVector}; + * # use wasmvm::{CachePtr, ByteSliceView, UnmanagedVector}; * #[no_mangle] * pub extern "C" fn save_wasm_to_cache( - * cache: *mut cache_t, + * cache: CachePtr, * wasm: ByteSliceView, * error_msg: Option<&mut UnmanagedVector>, * ) -> UnmanagedVector { @@ -189,10 +189,6 @@ typedef struct UnmanagedVector { uintptr_t cap; } UnmanagedVector; -typedef struct cache_t { - -} cache_t; - /** * A struct that holds a pointer to the cache. This struct can be * copied freely. @@ -202,7 +198,7 @@ typedef struct cache_t { * and `Metrics`, we use thiy type. */ typedef struct CachePtr { - struct cache_t *ptr; + void *ptr; } CachePtr; /** @@ -322,46 +318,46 @@ int32_t init_cache(struct ByteSliceView data_dir, struct UnmanagedVector *error_msg, struct CachePtr *out); -int32_t save_wasm(struct cache_t *cache, +int32_t save_wasm(struct CachePtr cache, struct ByteSliceView wasm, struct UnmanagedVector *error_msg, struct UnmanagedVector *out); -int32_t remove_wasm(struct cache_t *cache, +int32_t remove_wasm(struct CachePtr cache, struct ByteSliceView checksum, struct UnmanagedVector *error_msg); -int32_t load_wasm(struct cache_t *cache, +int32_t load_wasm(struct CachePtr cache, struct ByteSliceView checksum, struct UnmanagedVector *error_msg, struct UnmanagedVector *out); -int32_t pin(struct cache_t *cache, +int32_t pin(struct CachePtr cache, struct ByteSliceView checksum, struct UnmanagedVector *error_msg); -int32_t unpin(struct cache_t *cache, +int32_t unpin(struct CachePtr cache, struct ByteSliceView checksum, struct UnmanagedVector *error_msg); -int32_t analyze_code(struct cache_t *cache, +int32_t analyze_code(struct CachePtr cache, struct ByteSliceView checksum, struct UnmanagedVector *error_msg, struct AnalysisReport *out); -int32_t get_metrics(struct cache_t *cache, struct UnmanagedVector *error_msg, struct Metrics *out); +int32_t get_metrics(struct CachePtr cache, struct UnmanagedVector *error_msg, struct Metrics *out); /** * frees a cache reference * * # Safety * - * This must be called exactly once for any `*cache_t` returned by `init_cache` + * This must be called exactly once for any `CachePtr` returned by `init_cache` * and cannot be called on any other pointer. */ -void release_cache(struct cache_t *cache); +void release_cache(struct CachePtr cache); -struct UnmanagedVector instantiate(struct cache_t *cache, +struct UnmanagedVector instantiate(struct CachePtr cache, struct ByteSliceView checksum, struct ByteSliceView env, struct ByteSliceView info, @@ -374,7 +370,7 @@ struct UnmanagedVector instantiate(struct cache_t *cache, uint64_t *gas_used, struct UnmanagedVector *error_msg); -struct UnmanagedVector execute(struct cache_t *cache, +struct UnmanagedVector execute(struct CachePtr cache, struct ByteSliceView checksum, struct ByteSliceView env, struct ByteSliceView info, @@ -387,7 +383,7 @@ struct UnmanagedVector execute(struct cache_t *cache, uint64_t *gas_used, struct UnmanagedVector *error_msg); -struct UnmanagedVector migrate(struct cache_t *cache, +struct UnmanagedVector migrate(struct CachePtr cache, struct ByteSliceView checksum, struct ByteSliceView env, struct ByteSliceView msg, @@ -399,7 +395,7 @@ struct UnmanagedVector migrate(struct cache_t *cache, uint64_t *gas_used, struct UnmanagedVector *error_msg); -struct UnmanagedVector sudo(struct cache_t *cache, +struct UnmanagedVector sudo(struct CachePtr cache, struct ByteSliceView checksum, struct ByteSliceView env, struct ByteSliceView msg, @@ -411,7 +407,7 @@ struct UnmanagedVector sudo(struct cache_t *cache, uint64_t *gas_used, struct UnmanagedVector *error_msg); -struct UnmanagedVector reply(struct cache_t *cache, +struct UnmanagedVector reply(struct CachePtr cache, struct ByteSliceView checksum, struct ByteSliceView env, struct ByteSliceView msg, @@ -423,7 +419,7 @@ struct UnmanagedVector reply(struct cache_t *cache, uint64_t *gas_used, struct UnmanagedVector *error_msg); -struct UnmanagedVector query(struct cache_t *cache, +struct UnmanagedVector query(struct CachePtr cache, struct ByteSliceView checksum, struct ByteSliceView env, struct ByteSliceView msg, @@ -435,7 +431,7 @@ struct UnmanagedVector query(struct cache_t *cache, uint64_t *gas_used, struct UnmanagedVector *error_msg); -struct UnmanagedVector ibc_channel_open(struct cache_t *cache, +struct UnmanagedVector ibc_channel_open(struct CachePtr cache, struct ByteSliceView checksum, struct ByteSliceView env, struct ByteSliceView msg, @@ -447,7 +443,7 @@ struct UnmanagedVector ibc_channel_open(struct cache_t *cache, uint64_t *gas_used, struct UnmanagedVector *error_msg); -struct UnmanagedVector ibc_channel_connect(struct cache_t *cache, +struct UnmanagedVector ibc_channel_connect(struct CachePtr cache, struct ByteSliceView checksum, struct ByteSliceView env, struct ByteSliceView msg, @@ -459,7 +455,7 @@ struct UnmanagedVector ibc_channel_connect(struct cache_t *cache, uint64_t *gas_used, struct UnmanagedVector *error_msg); -struct UnmanagedVector ibc_channel_close(struct cache_t *cache, +struct UnmanagedVector ibc_channel_close(struct CachePtr cache, struct ByteSliceView checksum, struct ByteSliceView env, struct ByteSliceView msg, @@ -471,7 +467,7 @@ struct UnmanagedVector ibc_channel_close(struct cache_t *cache, uint64_t *gas_used, struct UnmanagedVector *error_msg); -struct UnmanagedVector ibc_packet_receive(struct cache_t *cache, +struct UnmanagedVector ibc_packet_receive(struct CachePtr cache, struct ByteSliceView checksum, struct ByteSliceView env, struct ByteSliceView msg, @@ -483,7 +479,7 @@ struct UnmanagedVector ibc_packet_receive(struct cache_t *cache, uint64_t *gas_used, struct UnmanagedVector *error_msg); -struct UnmanagedVector ibc_packet_ack(struct cache_t *cache, +struct UnmanagedVector ibc_packet_ack(struct CachePtr cache, struct ByteSliceView checksum, struct ByteSliceView env, struct ByteSliceView msg, @@ -495,7 +491,7 @@ struct UnmanagedVector ibc_packet_ack(struct cache_t *cache, uint64_t *gas_used, struct UnmanagedVector *error_msg); -struct UnmanagedVector ibc_packet_timeout(struct cache_t *cache, +struct UnmanagedVector ibc_packet_timeout(struct CachePtr cache, struct ByteSliceView checksum, struct ByteSliceView env, struct ByteSliceView msg, diff --git a/internal/api/lib.go b/internal/api/lib.go index aa360ef7..bc1d287a 100644 --- a/internal/api/lib.go +++ b/internal/api/lib.go @@ -8,6 +8,7 @@ import ( "fmt" "runtime" "syscall" + "unsafe" "github.com/CosmWasm/wasmvm/types" ) @@ -29,7 +30,13 @@ type ( type cu8_ptr = *C.uint8_t type Cache struct { - ptr *C.cache_t + ptr unsafe.Pointer +} + +func toCachePtr(cache Cache) C.CachePtr { + return C.CachePtr{ + ptr: cache.ptr, + } } type Querier = types.Querier @@ -54,7 +61,7 @@ func InitCache(dataDir string, supportedFeatures string, cacheSize uint32, insta } func ReleaseCache(cache Cache) { - C.release_cache(cache.ptr) // No error case that needs handling + C.release_cache(toCachePtr(cache)) // No error case that needs handling } // / StoreCode stored the Wasm blob and returns the checksum @@ -63,7 +70,7 @@ func StoreCode(cache Cache, wasm []byte) ([]byte, error) { defer runtime.KeepAlive(wasm) errmsg := newUnmanagedVector(nil) out := newUnmanagedVector(nil) - err := C.save_wasm(cache.ptr, w, &errmsg, &out) + err := C.save_wasm(toCachePtr(cache), w, &errmsg, &out) if err != 0 { return nil, ffiErrorWithMessage2(err, errmsg) } @@ -74,7 +81,7 @@ func RemoveCode(cache Cache, checksum []byte) error { cs := makeView(checksum) defer runtime.KeepAlive(checksum) errmsg := newUnmanagedVector(nil) - err := C.remove_wasm(cache.ptr, cs, &errmsg) + err := C.remove_wasm(toCachePtr(cache), cs, &errmsg) if err != 0 { return ffiErrorWithMessage2(err, errmsg) } @@ -86,7 +93,7 @@ func GetCode(cache Cache, checksum []byte) ([]byte, error) { defer runtime.KeepAlive(checksum) errmsg := newUnmanagedVector(nil) out := newUnmanagedVector(nil) - err := C.load_wasm(cache.ptr, cs, &errmsg, &out) + err := C.load_wasm(toCachePtr(cache), cs, &errmsg, &out) if err != 0 { return nil, ffiErrorWithMessage2(err, errmsg) } @@ -97,7 +104,7 @@ func Pin(cache Cache, checksum []byte) error { cs := makeView(checksum) defer runtime.KeepAlive(checksum) errmsg := newUnmanagedVector(nil) - err := C.pin(cache.ptr, cs, &errmsg) + err := C.pin(toCachePtr(cache), cs, &errmsg) if err != 0 { return ffiErrorWithMessage2(err, errmsg) } @@ -108,7 +115,7 @@ func Unpin(cache Cache, checksum []byte) error { cs := makeView(checksum) defer runtime.KeepAlive(checksum) errmsg := newUnmanagedVector(nil) - err := C.unpin(cache.ptr, cs, &errmsg) + err := C.unpin(toCachePtr(cache), cs, &errmsg) if err != 0 { return ffiErrorWithMessage2(err, errmsg) } @@ -120,7 +127,7 @@ func AnalyzeCode(cache Cache, checksum []byte) (*types.AnalysisReport, error) { defer runtime.KeepAlive(checksum) errmsg := newUnmanagedVector(nil) out := C.AnalysisReport{} - err := C.analyze_code(cache.ptr, cs, &errmsg, &out) + err := C.analyze_code(toCachePtr(cache), cs, &errmsg, &out) if err != 0 { return nil, ffiErrorWithMessage2(err, errmsg) } @@ -136,7 +143,7 @@ func AnalyzeCode(cache Cache, checksum []byte) (*types.AnalysisReport, error) { func GetMetrics(cache Cache) (*types.Metrics, error) { errmsg := newUnmanagedVector(nil) metrics := C.Metrics{} - err := C.get_metrics(cache.ptr, &errmsg, &metrics) + err := C.get_metrics(toCachePtr(cache), &errmsg, &metrics) if err != 0 { return nil, ffiErrorWithMessage2(err, errmsg) } @@ -185,7 +192,7 @@ func Instantiate( var gasUsed cu64 errmsg := newUnmanagedVector(nil) - res, err := C.instantiate(cache.ptr, cs, e, i, m, db, a, q, cu64(gasLimit), cbool(printDebug), &gasUsed, &errmsg) + res, err := C.instantiate(toCachePtr(cache), cs, e, i, m, db, a, q, cu64(gasLimit), cbool(printDebug), &gasUsed, &errmsg) if err != nil && err.(syscall.Errno) != C.ErrnoValue_Success { // Depending on the nature of the error, `gasUsed` will either have a meaningful value, or just 0. return nil, uint64(gasUsed), ffiErrorWithMessage(err, errmsg) @@ -225,7 +232,7 @@ func Execute( var gasUsed cu64 errmsg := newUnmanagedVector(nil) - res, err := C.execute(cache.ptr, cs, e, i, m, db, a, q, cu64(gasLimit), cbool(printDebug), &gasUsed, &errmsg) + res, err := C.execute(toCachePtr(cache), cs, e, i, m, db, a, q, cu64(gasLimit), cbool(printDebug), &gasUsed, &errmsg) if err != nil && err.(syscall.Errno) != C.ErrnoValue_Success { // Depending on the nature of the error, `gasUsed` will either have a meaningful value, or just 0. return nil, uint64(gasUsed), ffiErrorWithMessage(err, errmsg) @@ -262,7 +269,7 @@ func Migrate( var gasUsed cu64 errmsg := newUnmanagedVector(nil) - res, err := C.migrate(cache.ptr, cs, e, m, db, a, q, cu64(gasLimit), cbool(printDebug), &gasUsed, &errmsg) + res, err := C.migrate(toCachePtr(cache), cs, e, m, db, a, q, cu64(gasLimit), cbool(printDebug), &gasUsed, &errmsg) if err != nil && err.(syscall.Errno) != C.ErrnoValue_Success { // Depending on the nature of the error, `gasUsed` will either have a meaningful value, or just 0. return nil, uint64(gasUsed), ffiErrorWithMessage(err, errmsg) @@ -299,7 +306,7 @@ func Sudo( var gasUsed cu64 errmsg := newUnmanagedVector(nil) - res, err := C.sudo(cache.ptr, cs, e, m, db, a, q, cu64(gasLimit), cbool(printDebug), &gasUsed, &errmsg) + res, err := C.sudo(toCachePtr(cache), cs, e, m, db, a, q, cu64(gasLimit), cbool(printDebug), &gasUsed, &errmsg) if err != nil && err.(syscall.Errno) != C.ErrnoValue_Success { // Depending on the nature of the error, `gasUsed` will either have a meaningful value, or just 0. return nil, uint64(gasUsed), ffiErrorWithMessage(err, errmsg) @@ -336,7 +343,7 @@ func Reply( var gasUsed cu64 errmsg := newUnmanagedVector(nil) - res, err := C.reply(cache.ptr, cs, e, r, db, a, q, cu64(gasLimit), cbool(printDebug), &gasUsed, &errmsg) + res, err := C.reply(toCachePtr(cache), cs, e, r, db, a, q, cu64(gasLimit), cbool(printDebug), &gasUsed, &errmsg) if err != nil && err.(syscall.Errno) != C.ErrnoValue_Success { // Depending on the nature of the error, `gasUsed` will either have a meaningful value, or just 0. return nil, uint64(gasUsed), ffiErrorWithMessage(err, errmsg) @@ -373,7 +380,7 @@ func Query( var gasUsed cu64 errmsg := newUnmanagedVector(nil) - res, err := C.query(cache.ptr, cs, e, m, db, a, q, cu64(gasLimit), cbool(printDebug), &gasUsed, &errmsg) + res, err := C.query(toCachePtr(cache), cs, e, m, db, a, q, cu64(gasLimit), cbool(printDebug), &gasUsed, &errmsg) if err != nil && err.(syscall.Errno) != C.ErrnoValue_Success { // Depending on the nature of the error, `gasUsed` will either have a meaningful value, or just 0. return nil, uint64(gasUsed), ffiErrorWithMessage(err, errmsg) @@ -410,7 +417,7 @@ func IBCChannelOpen( var gasUsed cu64 errmsg := newUnmanagedVector(nil) - res, err := C.ibc_channel_open(cache.ptr, cs, e, m, db, a, q, cu64(gasLimit), cbool(printDebug), &gasUsed, &errmsg) + res, err := C.ibc_channel_open(toCachePtr(cache), cs, e, m, db, a, q, cu64(gasLimit), cbool(printDebug), &gasUsed, &errmsg) if err != nil && err.(syscall.Errno) != C.ErrnoValue_Success { // Depending on the nature of the error, `gasUsed` will either have a meaningful value, or just 0. return nil, uint64(gasUsed), ffiErrorWithMessage(err, errmsg) @@ -447,7 +454,7 @@ func IBCChannelConnect( var gasUsed cu64 errmsg := newUnmanagedVector(nil) - res, err := C.ibc_channel_connect(cache.ptr, cs, e, m, db, a, q, cu64(gasLimit), cbool(printDebug), &gasUsed, &errmsg) + res, err := C.ibc_channel_connect(toCachePtr(cache), cs, e, m, db, a, q, cu64(gasLimit), cbool(printDebug), &gasUsed, &errmsg) if err != nil && err.(syscall.Errno) != C.ErrnoValue_Success { // Depending on the nature of the error, `gasUsed` will either have a meaningful value, or just 0. return nil, uint64(gasUsed), ffiErrorWithMessage(err, errmsg) @@ -484,7 +491,7 @@ func IBCChannelClose( var gasUsed cu64 errmsg := newUnmanagedVector(nil) - res, err := C.ibc_channel_close(cache.ptr, cs, e, m, db, a, q, cu64(gasLimit), cbool(printDebug), &gasUsed, &errmsg) + res, err := C.ibc_channel_close(toCachePtr(cache), cs, e, m, db, a, q, cu64(gasLimit), cbool(printDebug), &gasUsed, &errmsg) if err != nil && err.(syscall.Errno) != C.ErrnoValue_Success { // Depending on the nature of the error, `gasUsed` will either have a meaningful value, or just 0. return nil, uint64(gasUsed), ffiErrorWithMessage(err, errmsg) @@ -521,7 +528,7 @@ func IBCPacketReceive( var gasUsed cu64 errmsg := newUnmanagedVector(nil) - res, err := C.ibc_packet_receive(cache.ptr, cs, e, pa, db, a, q, cu64(gasLimit), cbool(printDebug), &gasUsed, &errmsg) + res, err := C.ibc_packet_receive(toCachePtr(cache), cs, e, pa, db, a, q, cu64(gasLimit), cbool(printDebug), &gasUsed, &errmsg) if err != nil && err.(syscall.Errno) != C.ErrnoValue_Success { // Depending on the nature of the error, `gasUsed` will either have a meaningful value, or just 0. return nil, uint64(gasUsed), ffiErrorWithMessage(err, errmsg) @@ -558,7 +565,7 @@ func IBCPacketAck( var gasUsed cu64 errmsg := newUnmanagedVector(nil) - res, err := C.ibc_packet_ack(cache.ptr, cs, e, ac, db, a, q, cu64(gasLimit), cbool(printDebug), &gasUsed, &errmsg) + res, err := C.ibc_packet_ack(toCachePtr(cache), cs, e, ac, db, a, q, cu64(gasLimit), cbool(printDebug), &gasUsed, &errmsg) if err != nil && err.(syscall.Errno) != C.ErrnoValue_Success { // Depending on the nature of the error, `gasUsed` will either have a meaningful value, or just 0. return nil, uint64(gasUsed), ffiErrorWithMessage(err, errmsg) @@ -595,7 +602,7 @@ func IBCPacketTimeout( var gasUsed cu64 errmsg := newUnmanagedVector(nil) - res, err := C.ibc_packet_timeout(cache.ptr, cs, e, pa, db, a, q, cu64(gasLimit), cbool(printDebug), &gasUsed, &errmsg) + res, err := C.ibc_packet_timeout(toCachePtr(cache), cs, e, pa, db, a, q, cu64(gasLimit), cbool(printDebug), &gasUsed, &errmsg) if err != nil && err.(syscall.Errno) != C.ErrnoValue_Success { // Depending on the nature of the error, `gasUsed` will either have a meaningful value, or just 0. return nil, uint64(gasUsed), ffiErrorWithMessage(err, errmsg) diff --git a/libwasmvm/bindings.h b/libwasmvm/bindings.h index 53a4165d..b5edc2c7 100644 --- a/libwasmvm/bindings.h +++ b/libwasmvm/bindings.h @@ -108,10 +108,10 @@ typedef struct ByteSliceView { * Transferring ownership from Rust to Go using return values of FFI calls: * * ``` - * # use wasmvm::{cache_t, ByteSliceView, UnmanagedVector}; + * # use wasmvm::{CachePtr, ByteSliceView, UnmanagedVector}; * #[no_mangle] * pub extern "C" fn save_wasm_to_cache( - * cache: *mut cache_t, + * cache: CachePtr, * wasm: ByteSliceView, * error_msg: Option<&mut UnmanagedVector>, * ) -> UnmanagedVector { @@ -189,10 +189,6 @@ typedef struct UnmanagedVector { uintptr_t cap; } UnmanagedVector; -typedef struct cache_t { - -} cache_t; - /** * A struct that holds a pointer to the cache. This struct can be * copied freely. @@ -202,7 +198,7 @@ typedef struct cache_t { * and `Metrics`, we use thiy type. */ typedef struct CachePtr { - struct cache_t *ptr; + void *ptr; } CachePtr; /** @@ -322,46 +318,46 @@ int32_t init_cache(struct ByteSliceView data_dir, struct UnmanagedVector *error_msg, struct CachePtr *out); -int32_t save_wasm(struct cache_t *cache, +int32_t save_wasm(struct CachePtr cache, struct ByteSliceView wasm, struct UnmanagedVector *error_msg, struct UnmanagedVector *out); -int32_t remove_wasm(struct cache_t *cache, +int32_t remove_wasm(struct CachePtr cache, struct ByteSliceView checksum, struct UnmanagedVector *error_msg); -int32_t load_wasm(struct cache_t *cache, +int32_t load_wasm(struct CachePtr cache, struct ByteSliceView checksum, struct UnmanagedVector *error_msg, struct UnmanagedVector *out); -int32_t pin(struct cache_t *cache, +int32_t pin(struct CachePtr cache, struct ByteSliceView checksum, struct UnmanagedVector *error_msg); -int32_t unpin(struct cache_t *cache, +int32_t unpin(struct CachePtr cache, struct ByteSliceView checksum, struct UnmanagedVector *error_msg); -int32_t analyze_code(struct cache_t *cache, +int32_t analyze_code(struct CachePtr cache, struct ByteSliceView checksum, struct UnmanagedVector *error_msg, struct AnalysisReport *out); -int32_t get_metrics(struct cache_t *cache, struct UnmanagedVector *error_msg, struct Metrics *out); +int32_t get_metrics(struct CachePtr cache, struct UnmanagedVector *error_msg, struct Metrics *out); /** * frees a cache reference * * # Safety * - * This must be called exactly once for any `*cache_t` returned by `init_cache` + * This must be called exactly once for any `CachePtr` returned by `init_cache` * and cannot be called on any other pointer. */ -void release_cache(struct cache_t *cache); +void release_cache(struct CachePtr cache); -struct UnmanagedVector instantiate(struct cache_t *cache, +struct UnmanagedVector instantiate(struct CachePtr cache, struct ByteSliceView checksum, struct ByteSliceView env, struct ByteSliceView info, @@ -374,7 +370,7 @@ struct UnmanagedVector instantiate(struct cache_t *cache, uint64_t *gas_used, struct UnmanagedVector *error_msg); -struct UnmanagedVector execute(struct cache_t *cache, +struct UnmanagedVector execute(struct CachePtr cache, struct ByteSliceView checksum, struct ByteSliceView env, struct ByteSliceView info, @@ -387,7 +383,7 @@ struct UnmanagedVector execute(struct cache_t *cache, uint64_t *gas_used, struct UnmanagedVector *error_msg); -struct UnmanagedVector migrate(struct cache_t *cache, +struct UnmanagedVector migrate(struct CachePtr cache, struct ByteSliceView checksum, struct ByteSliceView env, struct ByteSliceView msg, @@ -399,7 +395,7 @@ struct UnmanagedVector migrate(struct cache_t *cache, uint64_t *gas_used, struct UnmanagedVector *error_msg); -struct UnmanagedVector sudo(struct cache_t *cache, +struct UnmanagedVector sudo(struct CachePtr cache, struct ByteSliceView checksum, struct ByteSliceView env, struct ByteSliceView msg, @@ -411,7 +407,7 @@ struct UnmanagedVector sudo(struct cache_t *cache, uint64_t *gas_used, struct UnmanagedVector *error_msg); -struct UnmanagedVector reply(struct cache_t *cache, +struct UnmanagedVector reply(struct CachePtr cache, struct ByteSliceView checksum, struct ByteSliceView env, struct ByteSliceView msg, @@ -423,7 +419,7 @@ struct UnmanagedVector reply(struct cache_t *cache, uint64_t *gas_used, struct UnmanagedVector *error_msg); -struct UnmanagedVector query(struct cache_t *cache, +struct UnmanagedVector query(struct CachePtr cache, struct ByteSliceView checksum, struct ByteSliceView env, struct ByteSliceView msg, @@ -435,7 +431,7 @@ struct UnmanagedVector query(struct cache_t *cache, uint64_t *gas_used, struct UnmanagedVector *error_msg); -struct UnmanagedVector ibc_channel_open(struct cache_t *cache, +struct UnmanagedVector ibc_channel_open(struct CachePtr cache, struct ByteSliceView checksum, struct ByteSliceView env, struct ByteSliceView msg, @@ -447,7 +443,7 @@ struct UnmanagedVector ibc_channel_open(struct cache_t *cache, uint64_t *gas_used, struct UnmanagedVector *error_msg); -struct UnmanagedVector ibc_channel_connect(struct cache_t *cache, +struct UnmanagedVector ibc_channel_connect(struct CachePtr cache, struct ByteSliceView checksum, struct ByteSliceView env, struct ByteSliceView msg, @@ -459,7 +455,7 @@ struct UnmanagedVector ibc_channel_connect(struct cache_t *cache, uint64_t *gas_used, struct UnmanagedVector *error_msg); -struct UnmanagedVector ibc_channel_close(struct cache_t *cache, +struct UnmanagedVector ibc_channel_close(struct CachePtr cache, struct ByteSliceView checksum, struct ByteSliceView env, struct ByteSliceView msg, @@ -471,7 +467,7 @@ struct UnmanagedVector ibc_channel_close(struct cache_t *cache, uint64_t *gas_used, struct UnmanagedVector *error_msg); -struct UnmanagedVector ibc_packet_receive(struct cache_t *cache, +struct UnmanagedVector ibc_packet_receive(struct CachePtr cache, struct ByteSliceView checksum, struct ByteSliceView env, struct ByteSliceView msg, @@ -483,7 +479,7 @@ struct UnmanagedVector ibc_packet_receive(struct cache_t *cache, uint64_t *gas_used, struct UnmanagedVector *error_msg); -struct UnmanagedVector ibc_packet_ack(struct cache_t *cache, +struct UnmanagedVector ibc_packet_ack(struct CachePtr cache, struct ByteSliceView checksum, struct ByteSliceView env, struct ByteSliceView msg, @@ -495,7 +491,7 @@ struct UnmanagedVector ibc_packet_ack(struct cache_t *cache, uint64_t *gas_used, struct UnmanagedVector *error_msg); -struct UnmanagedVector ibc_packet_timeout(struct cache_t *cache, +struct UnmanagedVector ibc_packet_timeout(struct CachePtr cache, struct ByteSliceView checksum, struct ByteSliceView env, struct ByteSliceView msg, diff --git a/libwasmvm/src/cache.rs b/libwasmvm/src/cache.rs index 172cc16f..ad94a48e 100644 --- a/libwasmvm/src/cache.rs +++ b/libwasmvm/src/cache.rs @@ -12,9 +12,6 @@ use crate::memory::{ByteSliceView, UnmanagedVector}; use crate::querier::GoQuerier; use crate::storage::GoStorage; -#[repr(C)] -pub struct cache_t {} - /// A struct that holds a pointer to the cache. This struct can be /// copied freely. /// @@ -24,7 +21,7 @@ pub struct cache_t {} #[repr(C)] #[derive(Copy, Clone, Debug, PartialEq, Eq)] pub struct CachePtr { - pub ptr: *mut cache_t, + pub ptr: *mut std::ffi::c_void, } impl Default for CachePtr { @@ -38,21 +35,20 @@ impl Default for CachePtr { impl CachePtr { pub fn new(rust_ptr: *mut Cache) -> Self { Self { - ptr: rust_ptr as *mut cache_t, + ptr: rust_ptr as *mut std::ffi::c_void, } } - #[cfg(test)] pub fn is_null(self) -> bool { self.ptr.is_null() } } -pub fn to_cache(ptr: *mut cache_t) -> Option<&'static mut Cache> { - if ptr.is_null() { +pub fn to_cache(cache: CachePtr) -> Option<&'static mut Cache> { + if cache.is_null() { None } else { - let c = unsafe { &mut *(ptr as *mut Cache) }; + let c = unsafe { &mut *(cache.ptr as *mut Cache) }; Some(c) } } @@ -118,7 +114,7 @@ fn do_init_cache( #[no_mangle] #[must_use] pub extern "C" fn save_wasm( - cache: *mut cache_t, + cache: CachePtr, wasm: ByteSliceView, error_msg: Option<&mut UnmanagedVector>, out: Option<&mut UnmanagedVector>, @@ -144,7 +140,7 @@ fn do_save_wasm( #[no_mangle] #[must_use] pub extern "C" fn remove_wasm( - cache: *mut cache_t, + cache: CachePtr, checksum: ByteSliceView, error_msg: Option<&mut UnmanagedVector>, ) -> i32 { @@ -171,7 +167,7 @@ fn do_remove_wasm( #[no_mangle] #[must_use] pub extern "C" fn load_wasm( - cache: *mut cache_t, + cache: CachePtr, checksum: ByteSliceView, error_msg: Option<&mut UnmanagedVector>, out: Option<&mut UnmanagedVector>, @@ -200,7 +196,7 @@ fn do_load_wasm( #[no_mangle] #[must_use] pub extern "C" fn pin( - cache: *mut cache_t, + cache: CachePtr, checksum: ByteSliceView, error_msg: Option<&mut UnmanagedVector>, ) -> i32 { @@ -227,7 +223,7 @@ fn do_pin( #[no_mangle] #[must_use] pub extern "C" fn unpin( - cache: *mut cache_t, + cache: CachePtr, checksum: ByteSliceView, error_msg: Option<&mut UnmanagedVector>, ) -> i32 { @@ -289,7 +285,7 @@ fn set_to_csv(set: HashSet) -> String { #[no_mangle] #[must_use] pub extern "C" fn analyze_code( - cache: *mut cache_t, + cache: CachePtr, checksum: ByteSliceView, error_msg: Option<&mut UnmanagedVector>, out: Option<&mut AnalysisReport>, @@ -367,7 +363,7 @@ impl From for Metrics { #[no_mangle] #[must_use] pub extern "C" fn get_metrics( - cache: *mut cache_t, + cache: CachePtr, error_msg: Option<&mut UnmanagedVector>, out: Option<&mut Metrics>, ) -> i32 { @@ -388,13 +384,13 @@ fn do_get_metrics(cache: &mut Cache) -> Result) }; + let _ = unsafe { Box::from_raw(cache.ptr as *mut Cache) }; } } @@ -428,7 +424,7 @@ mod tests { assert!(error_msg.is_none()); let _ = error_msg.consume(); - release_cache(out.ptr); + release_cache(out); } #[test] @@ -474,7 +470,7 @@ mod tests { assert_eq!(error, 0); assert!(error_msg.is_none()); let _ = error_msg.consume(); - let cache_ptr = out.ptr; + let cache_ptr = out; let mut error_msg = UnmanagedVector::default(); let mut out = UnmanagedVector::default(); @@ -511,7 +507,7 @@ mod tests { assert_eq!(error, 0); assert!(error_msg.is_none()); let _ = error_msg.consume(); - let cache_ptr = out.ptr; + let cache_ptr = out; let mut error_msg = UnmanagedVector::default(); let mut out = UnmanagedVector::default(); @@ -574,7 +570,7 @@ mod tests { assert_eq!(error, 0); assert!(error_msg.is_none()); let _ = error_msg.consume(); - let cache_ptr = out.ptr; + let cache_ptr = out; let mut error_msg = UnmanagedVector::default(); let mut out = UnmanagedVector::default(); @@ -624,7 +620,7 @@ mod tests { assert_eq!(error, 0); assert!(error_msg.is_none()); let _ = error_msg.consume(); - let cache_ptr = out.ptr; + let cache_ptr = out; let mut error_msg = UnmanagedVector::default(); let mut out = UnmanagedVector::default(); @@ -681,7 +677,7 @@ mod tests { assert_eq!(error, 0); assert!(error_msg.is_none()); let _ = error_msg.consume(); - let cache_ptr = out.ptr; + let cache_ptr = out; let mut error_msg = UnmanagedVector::default(); let mut out = UnmanagedVector::default(); @@ -748,7 +744,7 @@ mod tests { assert_eq!(error, 0); assert!(error_msg.is_none()); let _ = error_msg.consume(); - let cache_ptr = out.ptr; + let cache_ptr = out; let mut error_msg = UnmanagedVector::default(); let mut out = UnmanagedVector::default(); @@ -856,7 +852,7 @@ mod tests { assert_eq!(error, 0); assert!(error_msg.is_none()); let _ = error_msg.consume(); - let cache_ptr = out.ptr; + let cache_ptr = out; // Get metrics 1 let mut error_msg = UnmanagedVector::default(); diff --git a/libwasmvm/src/calls.rs b/libwasmvm/src/calls.rs index c0622409..5c5c7ce5 100644 --- a/libwasmvm/src/calls.rs +++ b/libwasmvm/src/calls.rs @@ -12,7 +12,7 @@ use cosmwasm_vm::{ use crate::api::GoApi; use crate::args::{ARG1, ARG2, ARG3, CACHE_ARG, CHECKSUM_ARG, GAS_USED_ARG}; -use crate::cache::{cache_t, to_cache}; +use crate::cache::{to_cache, CachePtr}; use crate::db::Db; use crate::error::{handle_c_error_binary, Error}; use crate::memory::{ByteSliceView, UnmanagedVector}; @@ -29,7 +29,7 @@ fn into_backend(db: Db, api: GoApi, querier: GoQuerier) -> Backend, /// ) -> UnmanagedVector { From aa3811e0736c53c9b049675cca855f1543c44f0e Mon Sep 17 00:00:00 2001 From: Simon Warta Date: Mon, 5 Dec 2022 16:06:31 +0100 Subject: [PATCH 19/25] Let C.instantiate and C.execute return error code directly --- internal/api/bindings.h | 52 +++++++++++++++++++++-------------------- internal/api/lib.go | 18 +++++++------- libwasmvm/bindings.h | 52 +++++++++++++++++++++-------------------- libwasmvm/clippy.toml | 2 +- libwasmvm/src/calls.rs | 20 +++++++++++----- 5 files changed, 79 insertions(+), 65 deletions(-) diff --git a/internal/api/bindings.h b/internal/api/bindings.h index b5edc2c7..dd8583cf 100644 --- a/internal/api/bindings.h +++ b/internal/api/bindings.h @@ -357,31 +357,33 @@ int32_t get_metrics(struct CachePtr cache, struct UnmanagedVector *error_msg, st */ void release_cache(struct CachePtr cache); -struct UnmanagedVector instantiate(struct CachePtr cache, - struct ByteSliceView checksum, - struct ByteSliceView env, - struct ByteSliceView info, - struct ByteSliceView msg, - struct Db db, - struct GoApi api, - struct GoQuerier querier, - uint64_t gas_limit, - bool print_debug, - uint64_t *gas_used, - struct UnmanagedVector *error_msg); - -struct UnmanagedVector execute(struct CachePtr cache, - struct ByteSliceView checksum, - struct ByteSliceView env, - struct ByteSliceView info, - struct ByteSliceView msg, - struct Db db, - struct GoApi api, - struct GoQuerier querier, - uint64_t gas_limit, - bool print_debug, - uint64_t *gas_used, - struct UnmanagedVector *error_msg); +int32_t instantiate(struct CachePtr cache, + struct ByteSliceView checksum, + struct ByteSliceView env, + struct ByteSliceView info, + struct ByteSliceView msg, + struct Db db, + struct GoApi api, + struct GoQuerier querier, + uint64_t gas_limit, + bool print_debug, + uint64_t *gas_used, + struct UnmanagedVector *error_msg, + struct UnmanagedVector *out); + +int32_t execute(struct CachePtr cache, + struct ByteSliceView checksum, + struct ByteSliceView env, + struct ByteSliceView info, + struct ByteSliceView msg, + struct Db db, + struct GoApi api, + struct GoQuerier querier, + uint64_t gas_limit, + bool print_debug, + uint64_t *gas_used, + struct UnmanagedVector *error_msg, + struct UnmanagedVector *out); struct UnmanagedVector migrate(struct CachePtr cache, struct ByteSliceView checksum, diff --git a/internal/api/lib.go b/internal/api/lib.go index bc1d287a..ad35df4c 100644 --- a/internal/api/lib.go +++ b/internal/api/lib.go @@ -191,13 +191,14 @@ func Instantiate( q := buildQuerier(querier) var gasUsed cu64 errmsg := newUnmanagedVector(nil) + out := newUnmanagedVector(nil) - res, err := C.instantiate(toCachePtr(cache), cs, e, i, m, db, a, q, cu64(gasLimit), cbool(printDebug), &gasUsed, &errmsg) - if err != nil && err.(syscall.Errno) != C.ErrnoValue_Success { + err := C.instantiate(toCachePtr(cache), cs, e, i, m, db, a, q, cu64(gasLimit), cbool(printDebug), &gasUsed, &errmsg, &out) + if err != 0 { // Depending on the nature of the error, `gasUsed` will either have a meaningful value, or just 0. - return nil, uint64(gasUsed), ffiErrorWithMessage(err, errmsg) + return nil, uint64(gasUsed), ffiErrorWithMessage2(err, errmsg) } - return copyAndDestroyUnmanagedVector(res), uint64(gasUsed), nil + return copyAndDestroyUnmanagedVector(out), uint64(gasUsed), nil } func Execute( @@ -231,13 +232,14 @@ func Execute( q := buildQuerier(querier) var gasUsed cu64 errmsg := newUnmanagedVector(nil) + out := newUnmanagedVector(nil) - res, err := C.execute(toCachePtr(cache), cs, e, i, m, db, a, q, cu64(gasLimit), cbool(printDebug), &gasUsed, &errmsg) - if err != nil && err.(syscall.Errno) != C.ErrnoValue_Success { + err := C.execute(toCachePtr(cache), cs, e, i, m, db, a, q, cu64(gasLimit), cbool(printDebug), &gasUsed, &errmsg, &out) + if err != 0 { // Depending on the nature of the error, `gasUsed` will either have a meaningful value, or just 0. - return nil, uint64(gasUsed), ffiErrorWithMessage(err, errmsg) + return nil, uint64(gasUsed), ffiErrorWithMessage2(err, errmsg) } - return copyAndDestroyUnmanagedVector(res), uint64(gasUsed), nil + return copyAndDestroyUnmanagedVector(out), uint64(gasUsed), nil } func Migrate( diff --git a/libwasmvm/bindings.h b/libwasmvm/bindings.h index b5edc2c7..dd8583cf 100644 --- a/libwasmvm/bindings.h +++ b/libwasmvm/bindings.h @@ -357,31 +357,33 @@ int32_t get_metrics(struct CachePtr cache, struct UnmanagedVector *error_msg, st */ void release_cache(struct CachePtr cache); -struct UnmanagedVector instantiate(struct CachePtr cache, - struct ByteSliceView checksum, - struct ByteSliceView env, - struct ByteSliceView info, - struct ByteSliceView msg, - struct Db db, - struct GoApi api, - struct GoQuerier querier, - uint64_t gas_limit, - bool print_debug, - uint64_t *gas_used, - struct UnmanagedVector *error_msg); - -struct UnmanagedVector execute(struct CachePtr cache, - struct ByteSliceView checksum, - struct ByteSliceView env, - struct ByteSliceView info, - struct ByteSliceView msg, - struct Db db, - struct GoApi api, - struct GoQuerier querier, - uint64_t gas_limit, - bool print_debug, - uint64_t *gas_used, - struct UnmanagedVector *error_msg); +int32_t instantiate(struct CachePtr cache, + struct ByteSliceView checksum, + struct ByteSliceView env, + struct ByteSliceView info, + struct ByteSliceView msg, + struct Db db, + struct GoApi api, + struct GoQuerier querier, + uint64_t gas_limit, + bool print_debug, + uint64_t *gas_used, + struct UnmanagedVector *error_msg, + struct UnmanagedVector *out); + +int32_t execute(struct CachePtr cache, + struct ByteSliceView checksum, + struct ByteSliceView env, + struct ByteSliceView info, + struct ByteSliceView msg, + struct Db db, + struct GoApi api, + struct GoQuerier querier, + uint64_t gas_limit, + bool print_debug, + uint64_t *gas_used, + struct UnmanagedVector *error_msg, + struct UnmanagedVector *out); struct UnmanagedVector migrate(struct CachePtr cache, struct ByteSliceView checksum, diff --git a/libwasmvm/clippy.toml b/libwasmvm/clippy.toml index 85355417..6f40f2cd 100644 --- a/libwasmvm/clippy.toml +++ b/libwasmvm/clippy.toml @@ -1 +1 @@ -too-many-arguments-threshold = 13 +too-many-arguments-threshold = 14 diff --git a/libwasmvm/src/calls.rs b/libwasmvm/src/calls.rs index 5c5c7ce5..d91e66bb 100644 --- a/libwasmvm/src/calls.rs +++ b/libwasmvm/src/calls.rs @@ -14,7 +14,7 @@ use crate::api::GoApi; use crate::args::{ARG1, ARG2, ARG3, CACHE_ARG, CHECKSUM_ARG, GAS_USED_ARG}; use crate::cache::{to_cache, CachePtr}; use crate::db::Db; -use crate::error::{handle_c_error_binary, Error}; +use crate::error::{handle_c_error_binary, to_c_result, Error}; use crate::memory::{ByteSliceView, UnmanagedVector}; use crate::querier::GoQuerier; use crate::storage::GoStorage; @@ -28,6 +28,7 @@ fn into_backend(db: Db, api: GoApi, querier: GoQuerier) -> Backend, error_msg: Option<&mut UnmanagedVector>, -) -> UnmanagedVector { + out: Option<&mut UnmanagedVector>, +) -> i32 { call_3_args( call_instantiate_raw, cache, @@ -56,10 +58,12 @@ pub extern "C" fn instantiate( print_debug, gas_used, error_msg, + out, ) } #[no_mangle] +#[must_use] pub extern "C" fn execute( cache: CachePtr, checksum: ByteSliceView, @@ -73,7 +77,8 @@ pub extern "C" fn execute( print_debug: bool, gas_used: Option<&mut u64>, error_msg: Option<&mut UnmanagedVector>, -) -> UnmanagedVector { + out: Option<&mut UnmanagedVector>, +) -> i32 { call_3_args( call_execute_raw, cache, @@ -88,6 +93,7 @@ pub extern "C" fn execute( print_debug, gas_used, error_msg, + out, ) } @@ -482,6 +488,7 @@ type VmFn3Args = fn( // This wraps all error handling and ffi for instantiate, execute and migrate // (and anything else that takes env, info and msg arguments). // The only difference is which low-level function they dispatch to. +#[must_use] fn call_3_args( vm_fn: VmFn3Args, cache: CachePtr, @@ -496,7 +503,8 @@ fn call_3_args( print_debug: bool, gas_used: Option<&mut u64>, error_msg: Option<&mut UnmanagedVector>, -) -> UnmanagedVector { + out: Option<&mut UnmanagedVector>, +) -> i32 { let r = match to_cache(cache) { Some(c) => catch_unwind(AssertUnwindSafe(move || { do_call_3_args( @@ -517,8 +525,8 @@ fn call_3_args( .unwrap_or_else(|_| Err(Error::panic())), None => Err(Error::unset_arg(CACHE_ARG)), }; - let data = handle_c_error_binary(r, error_msg); - UnmanagedVector::new(Some(data)) + let r = r.map(UnmanagedVector::some); + to_c_result(r, error_msg, out) } fn do_call_3_args( From e9349e4d0c555c4fd019e7058a7d0f8c42a6f3f1 Mon Sep 17 00:00:00 2001 From: Simon Warta Date: Mon, 5 Dec 2022 16:19:12 +0100 Subject: [PATCH 20/25] Let 2 arg C calls return error directly --- internal/api/bindings.h | 230 +++++++++++++++++++----------------- internal/api/lib.go | 90 +++++++------- libwasmvm/bindings.h | 230 +++++++++++++++++++----------------- libwasmvm/src/calls.rs | 60 +++++++--- libwasmvm/src/error/mod.rs | 4 +- libwasmvm/src/error/rust.rs | 138 +--------------------- 6 files changed, 339 insertions(+), 413 deletions(-) diff --git a/internal/api/bindings.h b/internal/api/bindings.h index dd8583cf..c15e740f 100644 --- a/internal/api/bindings.h +++ b/internal/api/bindings.h @@ -385,19 +385,72 @@ int32_t execute(struct CachePtr cache, struct UnmanagedVector *error_msg, struct UnmanagedVector *out); -struct UnmanagedVector migrate(struct CachePtr cache, - struct ByteSliceView checksum, - struct ByteSliceView env, - struct ByteSliceView msg, - struct Db db, - struct GoApi api, - struct GoQuerier querier, - uint64_t gas_limit, - bool print_debug, - uint64_t *gas_used, - struct UnmanagedVector *error_msg); - -struct UnmanagedVector sudo(struct CachePtr cache, +int32_t migrate(struct CachePtr cache, + struct ByteSliceView checksum, + struct ByteSliceView env, + struct ByteSliceView msg, + struct Db db, + struct GoApi api, + struct GoQuerier querier, + uint64_t gas_limit, + bool print_debug, + uint64_t *gas_used, + struct UnmanagedVector *error_msg, + struct UnmanagedVector *out); + +int32_t sudo(struct CachePtr cache, + struct ByteSliceView checksum, + struct ByteSliceView env, + struct ByteSliceView msg, + struct Db db, + struct GoApi api, + struct GoQuerier querier, + uint64_t gas_limit, + bool print_debug, + uint64_t *gas_used, + struct UnmanagedVector *error_msg, + struct UnmanagedVector *out); + +int32_t reply(struct CachePtr cache, + struct ByteSliceView checksum, + struct ByteSliceView env, + struct ByteSliceView msg, + struct Db db, + struct GoApi api, + struct GoQuerier querier, + uint64_t gas_limit, + bool print_debug, + uint64_t *gas_used, + struct UnmanagedVector *error_msg, + struct UnmanagedVector *out); + +int32_t query(struct CachePtr cache, + struct ByteSliceView checksum, + struct ByteSliceView env, + struct ByteSliceView msg, + struct Db db, + struct GoApi api, + struct GoQuerier querier, + uint64_t gas_limit, + bool print_debug, + uint64_t *gas_used, + struct UnmanagedVector *error_msg, + struct UnmanagedVector *out); + +int32_t ibc_channel_open(struct CachePtr cache, + struct ByteSliceView checksum, + struct ByteSliceView env, + struct ByteSliceView msg, + struct Db db, + struct GoApi api, + struct GoQuerier querier, + uint64_t gas_limit, + bool print_debug, + uint64_t *gas_used, + struct UnmanagedVector *error_msg, + struct UnmanagedVector *out); + +int32_t ibc_channel_connect(struct CachePtr cache, struct ByteSliceView checksum, struct ByteSliceView env, struct ByteSliceView msg, @@ -407,103 +460,60 @@ struct UnmanagedVector sudo(struct CachePtr cache, uint64_t gas_limit, bool print_debug, uint64_t *gas_used, - struct UnmanagedVector *error_msg); - -struct UnmanagedVector reply(struct CachePtr cache, - struct ByteSliceView checksum, - struct ByteSliceView env, - struct ByteSliceView msg, - struct Db db, - struct GoApi api, - struct GoQuerier querier, - uint64_t gas_limit, - bool print_debug, - uint64_t *gas_used, - struct UnmanagedVector *error_msg); - -struct UnmanagedVector query(struct CachePtr cache, - struct ByteSliceView checksum, - struct ByteSliceView env, - struct ByteSliceView msg, - struct Db db, - struct GoApi api, - struct GoQuerier querier, - uint64_t gas_limit, - bool print_debug, - uint64_t *gas_used, - struct UnmanagedVector *error_msg); - -struct UnmanagedVector ibc_channel_open(struct CachePtr cache, - struct ByteSliceView checksum, - struct ByteSliceView env, - struct ByteSliceView msg, - struct Db db, - struct GoApi api, - struct GoQuerier querier, - uint64_t gas_limit, - bool print_debug, - uint64_t *gas_used, - struct UnmanagedVector *error_msg); - -struct UnmanagedVector ibc_channel_connect(struct CachePtr cache, - struct ByteSliceView checksum, - struct ByteSliceView env, - struct ByteSliceView msg, - struct Db db, - struct GoApi api, - struct GoQuerier querier, - uint64_t gas_limit, - bool print_debug, - uint64_t *gas_used, - struct UnmanagedVector *error_msg); - -struct UnmanagedVector ibc_channel_close(struct CachePtr cache, - struct ByteSliceView checksum, - struct ByteSliceView env, - struct ByteSliceView msg, - struct Db db, - struct GoApi api, - struct GoQuerier querier, - uint64_t gas_limit, - bool print_debug, - uint64_t *gas_used, - struct UnmanagedVector *error_msg); - -struct UnmanagedVector ibc_packet_receive(struct CachePtr cache, - struct ByteSliceView checksum, - struct ByteSliceView env, - struct ByteSliceView msg, - struct Db db, - struct GoApi api, - struct GoQuerier querier, - uint64_t gas_limit, - bool print_debug, - uint64_t *gas_used, - struct UnmanagedVector *error_msg); - -struct UnmanagedVector ibc_packet_ack(struct CachePtr cache, - struct ByteSliceView checksum, - struct ByteSliceView env, - struct ByteSliceView msg, - struct Db db, - struct GoApi api, - struct GoQuerier querier, - uint64_t gas_limit, - bool print_debug, - uint64_t *gas_used, - struct UnmanagedVector *error_msg); - -struct UnmanagedVector ibc_packet_timeout(struct CachePtr cache, - struct ByteSliceView checksum, - struct ByteSliceView env, - struct ByteSliceView msg, - struct Db db, - struct GoApi api, - struct GoQuerier querier, - uint64_t gas_limit, - bool print_debug, - uint64_t *gas_used, - struct UnmanagedVector *error_msg); + struct UnmanagedVector *error_msg, + struct UnmanagedVector *out); + +int32_t ibc_channel_close(struct CachePtr cache, + struct ByteSliceView checksum, + struct ByteSliceView env, + struct ByteSliceView msg, + struct Db db, + struct GoApi api, + struct GoQuerier querier, + uint64_t gas_limit, + bool print_debug, + uint64_t *gas_used, + struct UnmanagedVector *error_msg, + struct UnmanagedVector *out); + +int32_t ibc_packet_receive(struct CachePtr cache, + struct ByteSliceView checksum, + struct ByteSliceView env, + struct ByteSliceView msg, + struct Db db, + struct GoApi api, + struct GoQuerier querier, + uint64_t gas_limit, + bool print_debug, + uint64_t *gas_used, + struct UnmanagedVector *error_msg, + struct UnmanagedVector *out); + +int32_t ibc_packet_ack(struct CachePtr cache, + struct ByteSliceView checksum, + struct ByteSliceView env, + struct ByteSliceView msg, + struct Db db, + struct GoApi api, + struct GoQuerier querier, + uint64_t gas_limit, + bool print_debug, + uint64_t *gas_used, + struct UnmanagedVector *error_msg, + struct UnmanagedVector *out); + +int32_t ibc_packet_timeout(struct CachePtr cache, + struct ByteSliceView checksum, + struct ByteSliceView env, + struct ByteSliceView msg, + struct Db db, + struct GoApi api, + struct GoQuerier querier, + uint64_t gas_limit, + bool print_debug, + uint64_t *gas_used, + struct UnmanagedVector *error_msg, + struct UnmanagedVector *out); struct UnmanagedVector new_unmanaged_vector(bool nil, const uint8_t *ptr, uintptr_t length); diff --git a/internal/api/lib.go b/internal/api/lib.go index ad35df4c..e88522d4 100644 --- a/internal/api/lib.go +++ b/internal/api/lib.go @@ -270,13 +270,14 @@ func Migrate( q := buildQuerier(querier) var gasUsed cu64 errmsg := newUnmanagedVector(nil) + out := newUnmanagedVector(nil) - res, err := C.migrate(toCachePtr(cache), cs, e, m, db, a, q, cu64(gasLimit), cbool(printDebug), &gasUsed, &errmsg) - if err != nil && err.(syscall.Errno) != C.ErrnoValue_Success { + err := C.migrate(toCachePtr(cache), cs, e, m, db, a, q, cu64(gasLimit), cbool(printDebug), &gasUsed, &errmsg, &out) + if err != 0 { // Depending on the nature of the error, `gasUsed` will either have a meaningful value, or just 0. - return nil, uint64(gasUsed), ffiErrorWithMessage(err, errmsg) + return nil, uint64(gasUsed), ffiErrorWithMessage2(err, errmsg) } - return copyAndDestroyUnmanagedVector(res), uint64(gasUsed), nil + return copyAndDestroyUnmanagedVector(out), uint64(gasUsed), nil } func Sudo( @@ -307,13 +308,14 @@ func Sudo( q := buildQuerier(querier) var gasUsed cu64 errmsg := newUnmanagedVector(nil) + out := newUnmanagedVector(nil) - res, err := C.sudo(toCachePtr(cache), cs, e, m, db, a, q, cu64(gasLimit), cbool(printDebug), &gasUsed, &errmsg) - if err != nil && err.(syscall.Errno) != C.ErrnoValue_Success { + err := C.sudo(toCachePtr(cache), cs, e, m, db, a, q, cu64(gasLimit), cbool(printDebug), &gasUsed, &errmsg, &out) + if err != 0 { // Depending on the nature of the error, `gasUsed` will either have a meaningful value, or just 0. - return nil, uint64(gasUsed), ffiErrorWithMessage(err, errmsg) + return nil, uint64(gasUsed), ffiErrorWithMessage2(err, errmsg) } - return copyAndDestroyUnmanagedVector(res), uint64(gasUsed), nil + return copyAndDestroyUnmanagedVector(out), uint64(gasUsed), nil } func Reply( @@ -344,13 +346,14 @@ func Reply( q := buildQuerier(querier) var gasUsed cu64 errmsg := newUnmanagedVector(nil) + out := newUnmanagedVector(nil) - res, err := C.reply(toCachePtr(cache), cs, e, r, db, a, q, cu64(gasLimit), cbool(printDebug), &gasUsed, &errmsg) - if err != nil && err.(syscall.Errno) != C.ErrnoValue_Success { + err := C.reply(toCachePtr(cache), cs, e, r, db, a, q, cu64(gasLimit), cbool(printDebug), &gasUsed, &errmsg, &out) + if err != 0 { // Depending on the nature of the error, `gasUsed` will either have a meaningful value, or just 0. - return nil, uint64(gasUsed), ffiErrorWithMessage(err, errmsg) + return nil, uint64(gasUsed), ffiErrorWithMessage2(err, errmsg) } - return copyAndDestroyUnmanagedVector(res), uint64(gasUsed), nil + return copyAndDestroyUnmanagedVector(out), uint64(gasUsed), nil } func Query( @@ -381,13 +384,14 @@ func Query( q := buildQuerier(querier) var gasUsed cu64 errmsg := newUnmanagedVector(nil) + out := newUnmanagedVector(nil) - res, err := C.query(toCachePtr(cache), cs, e, m, db, a, q, cu64(gasLimit), cbool(printDebug), &gasUsed, &errmsg) - if err != nil && err.(syscall.Errno) != C.ErrnoValue_Success { + err := C.query(toCachePtr(cache), cs, e, m, db, a, q, cu64(gasLimit), cbool(printDebug), &gasUsed, &errmsg, &out) + if err != 0 { // Depending on the nature of the error, `gasUsed` will either have a meaningful value, or just 0. - return nil, uint64(gasUsed), ffiErrorWithMessage(err, errmsg) + return nil, uint64(gasUsed), ffiErrorWithMessage2(err, errmsg) } - return copyAndDestroyUnmanagedVector(res), uint64(gasUsed), nil + return copyAndDestroyUnmanagedVector(out), uint64(gasUsed), nil } func IBCChannelOpen( @@ -418,13 +422,14 @@ func IBCChannelOpen( q := buildQuerier(querier) var gasUsed cu64 errmsg := newUnmanagedVector(nil) + out := newUnmanagedVector(nil) - res, err := C.ibc_channel_open(toCachePtr(cache), cs, e, m, db, a, q, cu64(gasLimit), cbool(printDebug), &gasUsed, &errmsg) - if err != nil && err.(syscall.Errno) != C.ErrnoValue_Success { + err := C.ibc_channel_open(toCachePtr(cache), cs, e, m, db, a, q, cu64(gasLimit), cbool(printDebug), &gasUsed, &errmsg, &out) + if err != 0 { // Depending on the nature of the error, `gasUsed` will either have a meaningful value, or just 0. - return nil, uint64(gasUsed), ffiErrorWithMessage(err, errmsg) + return nil, uint64(gasUsed), ffiErrorWithMessage2(err, errmsg) } - return copyAndDestroyUnmanagedVector(res), uint64(gasUsed), nil + return copyAndDestroyUnmanagedVector(out), uint64(gasUsed), nil } func IBCChannelConnect( @@ -455,13 +460,14 @@ func IBCChannelConnect( q := buildQuerier(querier) var gasUsed cu64 errmsg := newUnmanagedVector(nil) + out := newUnmanagedVector(nil) - res, err := C.ibc_channel_connect(toCachePtr(cache), cs, e, m, db, a, q, cu64(gasLimit), cbool(printDebug), &gasUsed, &errmsg) - if err != nil && err.(syscall.Errno) != C.ErrnoValue_Success { + err := C.ibc_channel_connect(toCachePtr(cache), cs, e, m, db, a, q, cu64(gasLimit), cbool(printDebug), &gasUsed, &errmsg, &out) + if err != 0 { // Depending on the nature of the error, `gasUsed` will either have a meaningful value, or just 0. - return nil, uint64(gasUsed), ffiErrorWithMessage(err, errmsg) + return nil, uint64(gasUsed), ffiErrorWithMessage2(err, errmsg) } - return copyAndDestroyUnmanagedVector(res), uint64(gasUsed), nil + return copyAndDestroyUnmanagedVector(out), uint64(gasUsed), nil } func IBCChannelClose( @@ -492,13 +498,14 @@ func IBCChannelClose( q := buildQuerier(querier) var gasUsed cu64 errmsg := newUnmanagedVector(nil) + out := newUnmanagedVector(nil) - res, err := C.ibc_channel_close(toCachePtr(cache), cs, e, m, db, a, q, cu64(gasLimit), cbool(printDebug), &gasUsed, &errmsg) - if err != nil && err.(syscall.Errno) != C.ErrnoValue_Success { + err := C.ibc_channel_close(toCachePtr(cache), cs, e, m, db, a, q, cu64(gasLimit), cbool(printDebug), &gasUsed, &errmsg, &out) + if err != 0 { // Depending on the nature of the error, `gasUsed` will either have a meaningful value, or just 0. - return nil, uint64(gasUsed), ffiErrorWithMessage(err, errmsg) + return nil, uint64(gasUsed), ffiErrorWithMessage2(err, errmsg) } - return copyAndDestroyUnmanagedVector(res), uint64(gasUsed), nil + return copyAndDestroyUnmanagedVector(out), uint64(gasUsed), nil } func IBCPacketReceive( @@ -529,13 +536,14 @@ func IBCPacketReceive( q := buildQuerier(querier) var gasUsed cu64 errmsg := newUnmanagedVector(nil) + out := newUnmanagedVector(nil) - res, err := C.ibc_packet_receive(toCachePtr(cache), cs, e, pa, db, a, q, cu64(gasLimit), cbool(printDebug), &gasUsed, &errmsg) - if err != nil && err.(syscall.Errno) != C.ErrnoValue_Success { + err := C.ibc_packet_receive(toCachePtr(cache), cs, e, pa, db, a, q, cu64(gasLimit), cbool(printDebug), &gasUsed, &errmsg, &out) + if err != 0 { // Depending on the nature of the error, `gasUsed` will either have a meaningful value, or just 0. - return nil, uint64(gasUsed), ffiErrorWithMessage(err, errmsg) + return nil, uint64(gasUsed), ffiErrorWithMessage2(err, errmsg) } - return copyAndDestroyUnmanagedVector(res), uint64(gasUsed), nil + return copyAndDestroyUnmanagedVector(out), uint64(gasUsed), nil } func IBCPacketAck( @@ -566,13 +574,14 @@ func IBCPacketAck( q := buildQuerier(querier) var gasUsed cu64 errmsg := newUnmanagedVector(nil) + out := newUnmanagedVector(nil) - res, err := C.ibc_packet_ack(toCachePtr(cache), cs, e, ac, db, a, q, cu64(gasLimit), cbool(printDebug), &gasUsed, &errmsg) - if err != nil && err.(syscall.Errno) != C.ErrnoValue_Success { + err := C.ibc_packet_ack(toCachePtr(cache), cs, e, ac, db, a, q, cu64(gasLimit), cbool(printDebug), &gasUsed, &errmsg, &out) + if err != 0 { // Depending on the nature of the error, `gasUsed` will either have a meaningful value, or just 0. - return nil, uint64(gasUsed), ffiErrorWithMessage(err, errmsg) + return nil, uint64(gasUsed), ffiErrorWithMessage2(err, errmsg) } - return copyAndDestroyUnmanagedVector(res), uint64(gasUsed), nil + return copyAndDestroyUnmanagedVector(out), uint64(gasUsed), nil } func IBCPacketTimeout( @@ -603,13 +612,14 @@ func IBCPacketTimeout( q := buildQuerier(querier) var gasUsed cu64 errmsg := newUnmanagedVector(nil) + out := newUnmanagedVector(nil) - res, err := C.ibc_packet_timeout(toCachePtr(cache), cs, e, pa, db, a, q, cu64(gasLimit), cbool(printDebug), &gasUsed, &errmsg) - if err != nil && err.(syscall.Errno) != C.ErrnoValue_Success { + err := C.ibc_packet_timeout(toCachePtr(cache), cs, e, pa, db, a, q, cu64(gasLimit), cbool(printDebug), &gasUsed, &errmsg, &out) + if err != 0 { // Depending on the nature of the error, `gasUsed` will either have a meaningful value, or just 0. - return nil, uint64(gasUsed), ffiErrorWithMessage(err, errmsg) + return nil, uint64(gasUsed), ffiErrorWithMessage2(err, errmsg) } - return copyAndDestroyUnmanagedVector(res), uint64(gasUsed), nil + return copyAndDestroyUnmanagedVector(out), uint64(gasUsed), nil } // ffiErrorWithMessage takes a error, tries to read the error message diff --git a/libwasmvm/bindings.h b/libwasmvm/bindings.h index dd8583cf..c15e740f 100644 --- a/libwasmvm/bindings.h +++ b/libwasmvm/bindings.h @@ -385,19 +385,72 @@ int32_t execute(struct CachePtr cache, struct UnmanagedVector *error_msg, struct UnmanagedVector *out); -struct UnmanagedVector migrate(struct CachePtr cache, - struct ByteSliceView checksum, - struct ByteSliceView env, - struct ByteSliceView msg, - struct Db db, - struct GoApi api, - struct GoQuerier querier, - uint64_t gas_limit, - bool print_debug, - uint64_t *gas_used, - struct UnmanagedVector *error_msg); - -struct UnmanagedVector sudo(struct CachePtr cache, +int32_t migrate(struct CachePtr cache, + struct ByteSliceView checksum, + struct ByteSliceView env, + struct ByteSliceView msg, + struct Db db, + struct GoApi api, + struct GoQuerier querier, + uint64_t gas_limit, + bool print_debug, + uint64_t *gas_used, + struct UnmanagedVector *error_msg, + struct UnmanagedVector *out); + +int32_t sudo(struct CachePtr cache, + struct ByteSliceView checksum, + struct ByteSliceView env, + struct ByteSliceView msg, + struct Db db, + struct GoApi api, + struct GoQuerier querier, + uint64_t gas_limit, + bool print_debug, + uint64_t *gas_used, + struct UnmanagedVector *error_msg, + struct UnmanagedVector *out); + +int32_t reply(struct CachePtr cache, + struct ByteSliceView checksum, + struct ByteSliceView env, + struct ByteSliceView msg, + struct Db db, + struct GoApi api, + struct GoQuerier querier, + uint64_t gas_limit, + bool print_debug, + uint64_t *gas_used, + struct UnmanagedVector *error_msg, + struct UnmanagedVector *out); + +int32_t query(struct CachePtr cache, + struct ByteSliceView checksum, + struct ByteSliceView env, + struct ByteSliceView msg, + struct Db db, + struct GoApi api, + struct GoQuerier querier, + uint64_t gas_limit, + bool print_debug, + uint64_t *gas_used, + struct UnmanagedVector *error_msg, + struct UnmanagedVector *out); + +int32_t ibc_channel_open(struct CachePtr cache, + struct ByteSliceView checksum, + struct ByteSliceView env, + struct ByteSliceView msg, + struct Db db, + struct GoApi api, + struct GoQuerier querier, + uint64_t gas_limit, + bool print_debug, + uint64_t *gas_used, + struct UnmanagedVector *error_msg, + struct UnmanagedVector *out); + +int32_t ibc_channel_connect(struct CachePtr cache, struct ByteSliceView checksum, struct ByteSliceView env, struct ByteSliceView msg, @@ -407,103 +460,60 @@ struct UnmanagedVector sudo(struct CachePtr cache, uint64_t gas_limit, bool print_debug, uint64_t *gas_used, - struct UnmanagedVector *error_msg); - -struct UnmanagedVector reply(struct CachePtr cache, - struct ByteSliceView checksum, - struct ByteSliceView env, - struct ByteSliceView msg, - struct Db db, - struct GoApi api, - struct GoQuerier querier, - uint64_t gas_limit, - bool print_debug, - uint64_t *gas_used, - struct UnmanagedVector *error_msg); - -struct UnmanagedVector query(struct CachePtr cache, - struct ByteSliceView checksum, - struct ByteSliceView env, - struct ByteSliceView msg, - struct Db db, - struct GoApi api, - struct GoQuerier querier, - uint64_t gas_limit, - bool print_debug, - uint64_t *gas_used, - struct UnmanagedVector *error_msg); - -struct UnmanagedVector ibc_channel_open(struct CachePtr cache, - struct ByteSliceView checksum, - struct ByteSliceView env, - struct ByteSliceView msg, - struct Db db, - struct GoApi api, - struct GoQuerier querier, - uint64_t gas_limit, - bool print_debug, - uint64_t *gas_used, - struct UnmanagedVector *error_msg); - -struct UnmanagedVector ibc_channel_connect(struct CachePtr cache, - struct ByteSliceView checksum, - struct ByteSliceView env, - struct ByteSliceView msg, - struct Db db, - struct GoApi api, - struct GoQuerier querier, - uint64_t gas_limit, - bool print_debug, - uint64_t *gas_used, - struct UnmanagedVector *error_msg); - -struct UnmanagedVector ibc_channel_close(struct CachePtr cache, - struct ByteSliceView checksum, - struct ByteSliceView env, - struct ByteSliceView msg, - struct Db db, - struct GoApi api, - struct GoQuerier querier, - uint64_t gas_limit, - bool print_debug, - uint64_t *gas_used, - struct UnmanagedVector *error_msg); - -struct UnmanagedVector ibc_packet_receive(struct CachePtr cache, - struct ByteSliceView checksum, - struct ByteSliceView env, - struct ByteSliceView msg, - struct Db db, - struct GoApi api, - struct GoQuerier querier, - uint64_t gas_limit, - bool print_debug, - uint64_t *gas_used, - struct UnmanagedVector *error_msg); - -struct UnmanagedVector ibc_packet_ack(struct CachePtr cache, - struct ByteSliceView checksum, - struct ByteSliceView env, - struct ByteSliceView msg, - struct Db db, - struct GoApi api, - struct GoQuerier querier, - uint64_t gas_limit, - bool print_debug, - uint64_t *gas_used, - struct UnmanagedVector *error_msg); - -struct UnmanagedVector ibc_packet_timeout(struct CachePtr cache, - struct ByteSliceView checksum, - struct ByteSliceView env, - struct ByteSliceView msg, - struct Db db, - struct GoApi api, - struct GoQuerier querier, - uint64_t gas_limit, - bool print_debug, - uint64_t *gas_used, - struct UnmanagedVector *error_msg); + struct UnmanagedVector *error_msg, + struct UnmanagedVector *out); + +int32_t ibc_channel_close(struct CachePtr cache, + struct ByteSliceView checksum, + struct ByteSliceView env, + struct ByteSliceView msg, + struct Db db, + struct GoApi api, + struct GoQuerier querier, + uint64_t gas_limit, + bool print_debug, + uint64_t *gas_used, + struct UnmanagedVector *error_msg, + struct UnmanagedVector *out); + +int32_t ibc_packet_receive(struct CachePtr cache, + struct ByteSliceView checksum, + struct ByteSliceView env, + struct ByteSliceView msg, + struct Db db, + struct GoApi api, + struct GoQuerier querier, + uint64_t gas_limit, + bool print_debug, + uint64_t *gas_used, + struct UnmanagedVector *error_msg, + struct UnmanagedVector *out); + +int32_t ibc_packet_ack(struct CachePtr cache, + struct ByteSliceView checksum, + struct ByteSliceView env, + struct ByteSliceView msg, + struct Db db, + struct GoApi api, + struct GoQuerier querier, + uint64_t gas_limit, + bool print_debug, + uint64_t *gas_used, + struct UnmanagedVector *error_msg, + struct UnmanagedVector *out); + +int32_t ibc_packet_timeout(struct CachePtr cache, + struct ByteSliceView checksum, + struct ByteSliceView env, + struct ByteSliceView msg, + struct Db db, + struct GoApi api, + struct GoQuerier querier, + uint64_t gas_limit, + bool print_debug, + uint64_t *gas_used, + struct UnmanagedVector *error_msg, + struct UnmanagedVector *out); struct UnmanagedVector new_unmanaged_vector(bool nil, const uint8_t *ptr, uintptr_t length); diff --git a/libwasmvm/src/calls.rs b/libwasmvm/src/calls.rs index d91e66bb..feebf536 100644 --- a/libwasmvm/src/calls.rs +++ b/libwasmvm/src/calls.rs @@ -14,7 +14,7 @@ use crate::api::GoApi; use crate::args::{ARG1, ARG2, ARG3, CACHE_ARG, CHECKSUM_ARG, GAS_USED_ARG}; use crate::cache::{to_cache, CachePtr}; use crate::db::Db; -use crate::error::{handle_c_error_binary, to_c_result, Error}; +use crate::error::{to_c_result, Error}; use crate::memory::{ByteSliceView, UnmanagedVector}; use crate::querier::GoQuerier; use crate::storage::GoStorage; @@ -98,6 +98,7 @@ pub extern "C" fn execute( } #[no_mangle] +#[must_use] pub extern "C" fn migrate( cache: CachePtr, checksum: ByteSliceView, @@ -110,7 +111,8 @@ pub extern "C" fn migrate( print_debug: bool, gas_used: Option<&mut u64>, error_msg: Option<&mut UnmanagedVector>, -) -> UnmanagedVector { + out: Option<&mut UnmanagedVector>, +) -> i32 { call_2_args( call_migrate_raw, cache, @@ -124,10 +126,12 @@ pub extern "C" fn migrate( print_debug, gas_used, error_msg, + out, ) } #[no_mangle] +#[must_use] pub extern "C" fn sudo( cache: CachePtr, checksum: ByteSliceView, @@ -140,7 +144,8 @@ pub extern "C" fn sudo( print_debug: bool, gas_used: Option<&mut u64>, error_msg: Option<&mut UnmanagedVector>, -) -> UnmanagedVector { + out: Option<&mut UnmanagedVector>, +) -> i32 { call_2_args( call_sudo_raw, cache, @@ -154,10 +159,12 @@ pub extern "C" fn sudo( print_debug, gas_used, error_msg, + out, ) } #[no_mangle] +#[must_use] pub extern "C" fn reply( cache: CachePtr, checksum: ByteSliceView, @@ -170,7 +177,8 @@ pub extern "C" fn reply( print_debug: bool, gas_used: Option<&mut u64>, error_msg: Option<&mut UnmanagedVector>, -) -> UnmanagedVector { + out: Option<&mut UnmanagedVector>, +) -> i32 { call_2_args( call_reply_raw, cache, @@ -184,10 +192,12 @@ pub extern "C" fn reply( print_debug, gas_used, error_msg, + out, ) } #[no_mangle] +#[must_use] pub extern "C" fn query( cache: CachePtr, checksum: ByteSliceView, @@ -200,7 +210,8 @@ pub extern "C" fn query( print_debug: bool, gas_used: Option<&mut u64>, error_msg: Option<&mut UnmanagedVector>, -) -> UnmanagedVector { + out: Option<&mut UnmanagedVector>, +) -> i32 { call_2_args( call_query_raw, cache, @@ -214,10 +225,12 @@ pub extern "C" fn query( print_debug, gas_used, error_msg, + out, ) } #[no_mangle] +#[must_use] pub extern "C" fn ibc_channel_open( cache: CachePtr, checksum: ByteSliceView, @@ -230,7 +243,8 @@ pub extern "C" fn ibc_channel_open( print_debug: bool, gas_used: Option<&mut u64>, error_msg: Option<&mut UnmanagedVector>, -) -> UnmanagedVector { + out: Option<&mut UnmanagedVector>, +) -> i32 { call_2_args( call_ibc_channel_open_raw, cache, @@ -244,10 +258,12 @@ pub extern "C" fn ibc_channel_open( print_debug, gas_used, error_msg, + out, ) } #[no_mangle] +#[must_use] pub extern "C" fn ibc_channel_connect( cache: CachePtr, checksum: ByteSliceView, @@ -260,7 +276,8 @@ pub extern "C" fn ibc_channel_connect( print_debug: bool, gas_used: Option<&mut u64>, error_msg: Option<&mut UnmanagedVector>, -) -> UnmanagedVector { + out: Option<&mut UnmanagedVector>, +) -> i32 { call_2_args( call_ibc_channel_connect_raw, cache, @@ -274,10 +291,12 @@ pub extern "C" fn ibc_channel_connect( print_debug, gas_used, error_msg, + out, ) } #[no_mangle] +#[must_use] pub extern "C" fn ibc_channel_close( cache: CachePtr, checksum: ByteSliceView, @@ -290,7 +309,8 @@ pub extern "C" fn ibc_channel_close( print_debug: bool, gas_used: Option<&mut u64>, error_msg: Option<&mut UnmanagedVector>, -) -> UnmanagedVector { + out: Option<&mut UnmanagedVector>, +) -> i32 { call_2_args( call_ibc_channel_close_raw, cache, @@ -304,10 +324,12 @@ pub extern "C" fn ibc_channel_close( print_debug, gas_used, error_msg, + out, ) } #[no_mangle] +#[must_use] pub extern "C" fn ibc_packet_receive( cache: CachePtr, checksum: ByteSliceView, @@ -320,7 +342,8 @@ pub extern "C" fn ibc_packet_receive( print_debug: bool, gas_used: Option<&mut u64>, error_msg: Option<&mut UnmanagedVector>, -) -> UnmanagedVector { + out: Option<&mut UnmanagedVector>, +) -> i32 { call_2_args( call_ibc_packet_receive_raw, cache, @@ -334,10 +357,12 @@ pub extern "C" fn ibc_packet_receive( print_debug, gas_used, error_msg, + out, ) } #[no_mangle] +#[must_use] pub extern "C" fn ibc_packet_ack( cache: CachePtr, checksum: ByteSliceView, @@ -350,7 +375,8 @@ pub extern "C" fn ibc_packet_ack( print_debug: bool, gas_used: Option<&mut u64>, error_msg: Option<&mut UnmanagedVector>, -) -> UnmanagedVector { + out: Option<&mut UnmanagedVector>, +) -> i32 { call_2_args( call_ibc_packet_ack_raw, cache, @@ -364,10 +390,12 @@ pub extern "C" fn ibc_packet_ack( print_debug, gas_used, error_msg, + out, ) } #[no_mangle] +#[must_use] pub extern "C" fn ibc_packet_timeout( cache: CachePtr, checksum: ByteSliceView, @@ -380,7 +408,8 @@ pub extern "C" fn ibc_packet_timeout( print_debug: bool, gas_used: Option<&mut u64>, error_msg: Option<&mut UnmanagedVector>, -) -> UnmanagedVector { + out: Option<&mut UnmanagedVector>, +) -> i32 { call_2_args( call_ibc_packet_timeout_raw, cache, @@ -394,6 +423,7 @@ pub extern "C" fn ibc_packet_timeout( print_debug, gas_used, error_msg, + out, ) } @@ -406,6 +436,7 @@ type VmFn2Args = fn( // this wraps all error handling and ffi for the 6 ibc entry points and query. // (all of which take env and one "msg" argument). // the only difference is which low-level function they dispatch to. +#[must_use] fn call_2_args( vm_fn: VmFn2Args, cache: CachePtr, @@ -419,7 +450,8 @@ fn call_2_args( print_debug: bool, gas_used: Option<&mut u64>, error_msg: Option<&mut UnmanagedVector>, -) -> UnmanagedVector { + out: Option<&mut UnmanagedVector>, +) -> i32 { let r = match to_cache(cache) { Some(c) => catch_unwind(AssertUnwindSafe(move || { do_call_2_args( @@ -439,8 +471,8 @@ fn call_2_args( .unwrap_or_else(|_| Err(Error::panic())), None => Err(Error::unset_arg(CACHE_ARG)), }; - let data = handle_c_error_binary(r, error_msg); - UnmanagedVector::new(Some(data)) + let r = r.map(UnmanagedVector::some); + to_c_result(r, error_msg, out) } // this is internal processing, same for all the 6 ibc entry points diff --git a/libwasmvm/src/error/mod.rs b/libwasmvm/src/error/mod.rs index 5f3748fd..b15935de 100644 --- a/libwasmvm/src/error/mod.rs +++ b/libwasmvm/src/error/mod.rs @@ -3,6 +3,4 @@ mod go; mod rust; pub use go::GoError; -pub use rust::{ - handle_c_error_binary, to_c_result, to_c_result_binary, to_c_result_unit, RustError as Error, -}; +pub use rust::{to_c_result, to_c_result_binary, to_c_result_unit, RustError as Error}; diff --git a/libwasmvm/src/error/rust.rs b/libwasmvm/src/error/rust.rs index 01a3c53e..81284621 100644 --- a/libwasmvm/src/error/rust.rs +++ b/libwasmvm/src/error/rust.rs @@ -117,15 +117,12 @@ impl From for RustError { /// cbindgen:prefix-with-name #[repr(i32)] enum ErrnoValue { + #[allow(dead_code)] Success = 0, Other = 1, OutOfGas = 2, } -pub fn clear_error() { - set_errno(ErrnoValue::Success as i32); -} - pub fn set_error(err: RustError, error_msg: Option<&mut UnmanagedVector>) -> i32 { if let Some(error_msg) = error_msg { if error_msg.is_some() { @@ -159,29 +156,6 @@ pub fn set_out(value: T, out_ptr: Option<&mut T>) { } } -/// If `result` is Ok, this returns the binary representation of the Ok value and clears [errno]. -/// Otherwise it returns an empty vector, writes the error message to `error_msg` and sets [errno]. -/// -/// [errno]: https://utcc.utoronto.ca/~cks/space/blog/programming/GoCgoErrorReturns -pub fn handle_c_error_binary( - result: Result, - error_msg: Option<&mut UnmanagedVector>, -) -> Vec -where - T: Into>, -{ - match result { - Ok(value) => { - clear_error(); - value.into() - } - Err(error) => { - set_error(error, error_msg); - Vec::new() - } - } -} - /// If `result` is Ok, this writes the Ok value to `out` and returns 0. /// Otherwise it writes the error message to `error_msg` and returns the error code. pub fn to_c_result_binary( @@ -228,9 +202,8 @@ pub fn to_c_result_unit( #[cfg(test)] mod tests { - use super::super::errno::errno; use super::*; - use cosmwasm_vm::{BackendError, Checksum}; + use cosmwasm_vm::BackendError; use std::str; #[test] @@ -338,111 +311,4 @@ mod tests { _ => panic!("expect different error"), } } - - #[test] - fn handle_c_error_binary_works() { - // Ok (non-empty vector) - let mut error_msg = UnmanagedVector::default(); - let res: Result, RustError> = Ok(vec![0xF0, 0x0B, 0xAA]); - let data = handle_c_error_binary(res, Some(&mut error_msg)); - assert_eq!(errno(), ErrnoValue::Success as i32); - assert!(error_msg.is_none()); - assert_eq!(data, vec![0xF0, 0x0B, 0xAA]); - let _ = error_msg.consume(); - - // Ok (empty vector) - let mut error_msg = UnmanagedVector::default(); - let res: Result, RustError> = Ok(vec![]); - let data = handle_c_error_binary(res, Some(&mut error_msg)); - assert_eq!(errno(), ErrnoValue::Success as i32); - assert!(error_msg.is_none()); - assert_eq!(data, Vec::::new()); - let _ = error_msg.consume(); - - // Ok (non-empty slice) - let mut error_msg = UnmanagedVector::default(); - let res: Result<&[u8], RustError> = Ok(b"foobar"); - let data = handle_c_error_binary(res, Some(&mut error_msg)); - assert_eq!(errno(), ErrnoValue::Success as i32); - assert!(error_msg.is_none()); - assert_eq!(data, Vec::::from(b"foobar" as &[u8])); - let _ = error_msg.consume(); - - // Ok (empty slice) - let mut error_msg = UnmanagedVector::default(); - let res: Result<&[u8], RustError> = Ok(b""); - let data = handle_c_error_binary(res, Some(&mut error_msg)); - assert_eq!(errno(), ErrnoValue::Success as i32); - assert!(error_msg.is_none()); - assert_eq!(data, Vec::::new()); - let _ = error_msg.consume(); - - // Ok (checksum) - let mut error_msg = UnmanagedVector::default(); - let res: Result = Ok(Checksum::from([ - 0x72, 0x2c, 0x8c, 0x99, 0x3f, 0xd7, 0x5a, 0x76, 0x27, 0xd6, 0x9e, 0xd9, 0x41, 0x34, - 0x4f, 0xe2, 0xa1, 0x42, 0x3a, 0x3e, 0x75, 0xef, 0xd3, 0xe6, 0x77, 0x8a, 0x14, 0x28, - 0x84, 0x22, 0x71, 0x04, - ])); - let data = handle_c_error_binary(res, Some(&mut error_msg)); - assert_eq!(errno(), ErrnoValue::Success as i32); - assert!(error_msg.is_none()); - assert_eq!( - data, - vec![ - 0x72, 0x2c, 0x8c, 0x99, 0x3f, 0xd7, 0x5a, 0x76, 0x27, 0xd6, 0x9e, 0xd9, 0x41, 0x34, - 0x4f, 0xe2, 0xa1, 0x42, 0x3a, 0x3e, 0x75, 0xef, 0xd3, 0xe6, 0x77, 0x8a, 0x14, 0x28, - 0x84, 0x22, 0x71, 0x04, - ] - ); - let _ = error_msg.consume(); - - // Err (vector) - let mut error_msg = UnmanagedVector::default(); - let res: Result, RustError> = Err(RustError::panic()); - let data = handle_c_error_binary(res, Some(&mut error_msg)); - assert_eq!(errno(), ErrnoValue::Other as i32); - assert!(error_msg.is_some()); - assert_eq!(data, Vec::::new()); - let _ = error_msg.consume(); - - // Err (slice) - let mut error_msg = UnmanagedVector::default(); - let res: Result<&[u8], RustError> = Err(RustError::panic()); - let data = handle_c_error_binary(res, Some(&mut error_msg)); - assert_eq!(errno(), ErrnoValue::Other as i32); - assert!(error_msg.is_some()); - assert_eq!(data, Vec::::new()); - let _ = error_msg.consume(); - - // Err (checksum) - let mut error_msg = UnmanagedVector::default(); - let res: Result = Err(RustError::panic()); - let data = handle_c_error_binary(res, Some(&mut error_msg)); - assert_eq!(errno(), ErrnoValue::Other as i32); - assert!(error_msg.is_some()); - assert_eq!(data, Vec::::new()); - let _ = error_msg.consume(); - } - - #[test] - fn handle_c_error_binary_clears_an_old_error() { - // Err - let mut error_msg = UnmanagedVector::default(); - let res: Result, RustError> = Err(RustError::panic()); - let data = handle_c_error_binary(res, Some(&mut error_msg)); - assert_eq!(errno(), ErrnoValue::Other as i32); - assert!(error_msg.is_some()); - assert_eq!(data, Vec::::new()); - let _ = error_msg.consume(); - - // Ok - let mut error_msg = UnmanagedVector::default(); - let res: Result, RustError> = Ok(vec![0xF0, 0x0B, 0xAA]); - let data = handle_c_error_binary(res, Some(&mut error_msg)); - assert_eq!(errno(), ErrnoValue::Success as i32); - assert!(error_msg.is_none()); - assert_eq!(data, vec![0xF0, 0x0B, 0xAA]); - let _ = error_msg.consume(); - } } From 2230a936bfd6b65af81e98194c6451b60b43ef50 Mon Sep 17 00:00:00 2001 From: Simon Warta Date: Mon, 5 Dec 2022 16:20:00 +0100 Subject: [PATCH 21/25] Remove unused ffiErrorWithMessage --- internal/api/lib.go | 25 ------------------------- 1 file changed, 25 deletions(-) diff --git a/internal/api/lib.go b/internal/api/lib.go index e88522d4..85e5d6d8 100644 --- a/internal/api/lib.go +++ b/internal/api/lib.go @@ -7,7 +7,6 @@ import "C" import ( "fmt" "runtime" - "syscall" "unsafe" "github.com/CosmWasm/wasmvm/types" @@ -622,30 +621,6 @@ func IBCPacketTimeout( return copyAndDestroyUnmanagedVector(out), uint64(gasUsed), nil } -// ffiErrorWithMessage takes a error, tries to read the error message -// written by the Rust code and returns a readable error. -// -// This function must only be called on `ffiErr`s of type syscall.Errno -// that are no 0 (no error). -func ffiErrorWithMessage(ffiErr error, errMsg C.UnmanagedVector) error { - errno := ffiErr.(syscall.Errno) // panics if conversion fails - - if errno == 0 { - panic("Called ffiErrorWithMessage with a 0 errno (no error)") - } - - // Checks for out of gas as a special case. See "ErrnoValue" in libwasmvm/src/error/rust.rs. - if errno == 2 { - return types.OutOfGasError{} - } - - msg := copyAndDestroyUnmanagedVector(errMsg) - if msg == nil || len(msg) == 0 { - return fmt.Errorf("FFI call errored with errno %#v and no error message.", errno) - } - return fmt.Errorf("%s", string(msg)) -} - // ffiErrorWithMessage2 takes a error number, tries to read the error message // written by the Rust code and returns a readable error. // From 9c168f57e5979591d1fdf531c396da98d1990122 Mon Sep 17 00:00:00 2001 From: Simon Warta Date: Mon, 16 Jan 2023 17:32:05 +0100 Subject: [PATCH 22/25] Remove errno --- libwasmvm/Cargo.lock | 11 ----------- libwasmvm/Cargo.toml | 1 - libwasmvm/src/error/errno.rs | 16 ---------------- libwasmvm/src/error/mod.rs | 1 - libwasmvm/src/error/rust.rs | 8 +++----- 5 files changed, 3 insertions(+), 34 deletions(-) delete mode 100644 libwasmvm/src/error/errno.rs diff --git a/libwasmvm/Cargo.lock b/libwasmvm/Cargo.lock index 065f21ee..06070187 100644 --- a/libwasmvm/Cargo.lock +++ b/libwasmvm/Cargo.lock @@ -641,16 +641,6 @@ dependencies = [ "syn", ] -[[package]] -name = "errno-sys" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c0007216af1525058024bc6dc15bbd2ffe8af877f0fbf754fbdb78c59d634e8" -dependencies = [ - "cc", - "libc", -] - [[package]] name = "fallible-iterator" version = "0.2.0" @@ -1918,7 +1908,6 @@ dependencies = [ "cbindgen", "cosmwasm-std", "cosmwasm-vm", - "errno-sys", "hex", "serde", "serde_json", diff --git a/libwasmvm/Cargo.toml b/libwasmvm/Cargo.toml index 3625646a..385f7e28 100644 --- a/libwasmvm/Cargo.toml +++ b/libwasmvm/Cargo.toml @@ -28,7 +28,6 @@ backtraces = [] [dependencies] cosmwasm-std = { git = "https://github.com/CosmWasm/cosmwasm.git", rev = "v1.2.0-rc.1", features = ["staking", "stargate", "iterator"] } cosmwasm-vm = { git = "https://github.com/CosmWasm/cosmwasm.git", rev = "v1.2.0-rc.1", features = ["staking", "stargate", "iterator"] } -errno-sys = "0.1.0" serde_json = "1.0" thiserror = "1.0" hex = "0.4" diff --git a/libwasmvm/src/error/errno.rs b/libwasmvm/src/error/errno.rs deleted file mode 100644 index 5c855df3..00000000 --- a/libwasmvm/src/error/errno.rs +++ /dev/null @@ -1,16 +0,0 @@ -// See https://github.com/rust-lang/libc/issues/1644 for why we have to implement that ourselves. -// https://github.com/lambda-fairy/rust-errno does not work with cgo -// on Windows as cgo does not use the SetLastError/GetLastError Windows APIs. - -use errno_sys::errno_location; - -#[allow(unused)] // used in tests -pub fn errno() -> i32 { - unsafe { *errno_location() } -} - -pub fn set_errno(errno: i32) { - unsafe { - *errno_location() = errno; - } -} diff --git a/libwasmvm/src/error/mod.rs b/libwasmvm/src/error/mod.rs index b15935de..1c2767a6 100644 --- a/libwasmvm/src/error/mod.rs +++ b/libwasmvm/src/error/mod.rs @@ -1,4 +1,3 @@ -mod errno; mod go; mod rust; diff --git a/libwasmvm/src/error/rust.rs b/libwasmvm/src/error/rust.rs index 81284621..de30e8d3 100644 --- a/libwasmvm/src/error/rust.rs +++ b/libwasmvm/src/error/rust.rs @@ -3,7 +3,6 @@ use cosmwasm_vm::VmError; use std::backtrace::Backtrace; use thiserror::Error; -use super::errno::set_errno; use crate::memory::UnmanagedVector; #[derive(Error, Debug)] @@ -139,12 +138,11 @@ pub fn set_error(err: RustError, error_msg: Option<&mut UnmanagedVector>) -> i32 // That's not nice but we can live with it. } - let errno = match err { + let errno: ErrnoValue = match err { RustError::OutOfGas { .. } => ErrnoValue::OutOfGas, _ => ErrnoValue::Other, - } as i32; - set_errno(errno); - errno + }; + errno as i32 } pub fn set_out(value: T, out_ptr: Option<&mut T>) { From 92f47b5651fad8ce6b127e1beabcb1c270e73680 Mon Sep 17 00:00:00 2001 From: Simon Warta Date: Mon, 5 Dec 2022 16:37:57 +0100 Subject: [PATCH 23/25] Refactor ErrorCode --- internal/api/bindings.h | 14 ++++++---- internal/api/lib.go | 52 ++++++++++++++++++------------------- libwasmvm/bindings.h | 14 ++++++---- libwasmvm/cbindgen.toml | 2 +- libwasmvm/src/error/rust.rs | 43 ++++++++++++++++++------------ 5 files changed, 72 insertions(+), 53 deletions(-) diff --git a/internal/api/bindings.h b/internal/api/bindings.h index c15e740f..3458e32d 100644 --- a/internal/api/bindings.h +++ b/internal/api/bindings.h @@ -9,12 +9,16 @@ #include #include -enum ErrnoValue { - ErrnoValue_Success = 0, - ErrnoValue_Other = 1, - ErrnoValue_OutOfGas = 2, +/** + * An error code used to communicate the errors of FFI calls. + * Similar to shell codes and errno, 0 means no error. + */ +enum ErrorCode { + ErrorCode_Success = 0, + ErrorCode_Other = 1, + ErrorCode_OutOfGas = 2, }; -typedef int32_t ErrnoValue; +typedef int32_t ErrorCode; /** * This enum gives names to the status codes returned from Go callbacks to Rust. diff --git a/internal/api/lib.go b/internal/api/lib.go index 85e5d6d8..7919321e 100644 --- a/internal/api/lib.go +++ b/internal/api/lib.go @@ -53,7 +53,7 @@ func InitCache(dataDir string, supportedFeatures string, cacheSize uint32, insta out := C.CachePtr{} err := C.init_cache(d, f, cu32(cacheSize), cu32(instanceMemoryLimit), &errmsg, &out) - if err != 0 { + if err != C.ErrorCode_Success { return Cache{}, ffiErrorWithMessage2(err, errmsg) } return Cache{ptr: out.ptr}, nil @@ -70,7 +70,7 @@ func StoreCode(cache Cache, wasm []byte) ([]byte, error) { errmsg := newUnmanagedVector(nil) out := newUnmanagedVector(nil) err := C.save_wasm(toCachePtr(cache), w, &errmsg, &out) - if err != 0 { + if err != C.ErrorCode_Success { return nil, ffiErrorWithMessage2(err, errmsg) } return copyAndDestroyUnmanagedVector(out), nil @@ -93,7 +93,7 @@ func GetCode(cache Cache, checksum []byte) ([]byte, error) { errmsg := newUnmanagedVector(nil) out := newUnmanagedVector(nil) err := C.load_wasm(toCachePtr(cache), cs, &errmsg, &out) - if err != 0 { + if err != C.ErrorCode_Success { return nil, ffiErrorWithMessage2(err, errmsg) } return copyAndDestroyUnmanagedVector(out), nil @@ -104,7 +104,7 @@ func Pin(cache Cache, checksum []byte) error { defer runtime.KeepAlive(checksum) errmsg := newUnmanagedVector(nil) err := C.pin(toCachePtr(cache), cs, &errmsg) - if err != 0 { + if err != C.ErrorCode_Success { return ffiErrorWithMessage2(err, errmsg) } return nil @@ -115,7 +115,7 @@ func Unpin(cache Cache, checksum []byte) error { defer runtime.KeepAlive(checksum) errmsg := newUnmanagedVector(nil) err := C.unpin(toCachePtr(cache), cs, &errmsg) - if err != 0 { + if err != C.ErrorCode_Success { return ffiErrorWithMessage2(err, errmsg) } return nil @@ -127,7 +127,7 @@ func AnalyzeCode(cache Cache, checksum []byte) (*types.AnalysisReport, error) { errmsg := newUnmanagedVector(nil) out := C.AnalysisReport{} err := C.analyze_code(toCachePtr(cache), cs, &errmsg, &out) - if err != 0 { + if err != C.ErrorCode_Success { return nil, ffiErrorWithMessage2(err, errmsg) } requiredCapabilities := string(copyAndDestroyUnmanagedVector(out.required_capabilities)) @@ -143,7 +143,7 @@ func GetMetrics(cache Cache) (*types.Metrics, error) { errmsg := newUnmanagedVector(nil) metrics := C.Metrics{} err := C.get_metrics(toCachePtr(cache), &errmsg, &metrics) - if err != 0 { + if err != C.ErrorCode_Success { return nil, ffiErrorWithMessage2(err, errmsg) } @@ -193,7 +193,7 @@ func Instantiate( out := newUnmanagedVector(nil) err := C.instantiate(toCachePtr(cache), cs, e, i, m, db, a, q, cu64(gasLimit), cbool(printDebug), &gasUsed, &errmsg, &out) - if err != 0 { + if err != C.ErrorCode_Success { // Depending on the nature of the error, `gasUsed` will either have a meaningful value, or just 0. return nil, uint64(gasUsed), ffiErrorWithMessage2(err, errmsg) } @@ -234,7 +234,7 @@ func Execute( out := newUnmanagedVector(nil) err := C.execute(toCachePtr(cache), cs, e, i, m, db, a, q, cu64(gasLimit), cbool(printDebug), &gasUsed, &errmsg, &out) - if err != 0 { + if err != C.ErrorCode_Success { // Depending on the nature of the error, `gasUsed` will either have a meaningful value, or just 0. return nil, uint64(gasUsed), ffiErrorWithMessage2(err, errmsg) } @@ -272,7 +272,7 @@ func Migrate( out := newUnmanagedVector(nil) err := C.migrate(toCachePtr(cache), cs, e, m, db, a, q, cu64(gasLimit), cbool(printDebug), &gasUsed, &errmsg, &out) - if err != 0 { + if err != C.ErrorCode_Success { // Depending on the nature of the error, `gasUsed` will either have a meaningful value, or just 0. return nil, uint64(gasUsed), ffiErrorWithMessage2(err, errmsg) } @@ -310,7 +310,7 @@ func Sudo( out := newUnmanagedVector(nil) err := C.sudo(toCachePtr(cache), cs, e, m, db, a, q, cu64(gasLimit), cbool(printDebug), &gasUsed, &errmsg, &out) - if err != 0 { + if err != C.ErrorCode_Success { // Depending on the nature of the error, `gasUsed` will either have a meaningful value, or just 0. return nil, uint64(gasUsed), ffiErrorWithMessage2(err, errmsg) } @@ -348,7 +348,7 @@ func Reply( out := newUnmanagedVector(nil) err := C.reply(toCachePtr(cache), cs, e, r, db, a, q, cu64(gasLimit), cbool(printDebug), &gasUsed, &errmsg, &out) - if err != 0 { + if err != C.ErrorCode_Success { // Depending on the nature of the error, `gasUsed` will either have a meaningful value, or just 0. return nil, uint64(gasUsed), ffiErrorWithMessage2(err, errmsg) } @@ -386,7 +386,7 @@ func Query( out := newUnmanagedVector(nil) err := C.query(toCachePtr(cache), cs, e, m, db, a, q, cu64(gasLimit), cbool(printDebug), &gasUsed, &errmsg, &out) - if err != 0 { + if err != C.ErrorCode_Success { // Depending on the nature of the error, `gasUsed` will either have a meaningful value, or just 0. return nil, uint64(gasUsed), ffiErrorWithMessage2(err, errmsg) } @@ -424,7 +424,7 @@ func IBCChannelOpen( out := newUnmanagedVector(nil) err := C.ibc_channel_open(toCachePtr(cache), cs, e, m, db, a, q, cu64(gasLimit), cbool(printDebug), &gasUsed, &errmsg, &out) - if err != 0 { + if err != C.ErrorCode_Success { // Depending on the nature of the error, `gasUsed` will either have a meaningful value, or just 0. return nil, uint64(gasUsed), ffiErrorWithMessage2(err, errmsg) } @@ -462,7 +462,7 @@ func IBCChannelConnect( out := newUnmanagedVector(nil) err := C.ibc_channel_connect(toCachePtr(cache), cs, e, m, db, a, q, cu64(gasLimit), cbool(printDebug), &gasUsed, &errmsg, &out) - if err != 0 { + if err != C.ErrorCode_Success { // Depending on the nature of the error, `gasUsed` will either have a meaningful value, or just 0. return nil, uint64(gasUsed), ffiErrorWithMessage2(err, errmsg) } @@ -500,7 +500,7 @@ func IBCChannelClose( out := newUnmanagedVector(nil) err := C.ibc_channel_close(toCachePtr(cache), cs, e, m, db, a, q, cu64(gasLimit), cbool(printDebug), &gasUsed, &errmsg, &out) - if err != 0 { + if err != C.ErrorCode_Success { // Depending on the nature of the error, `gasUsed` will either have a meaningful value, or just 0. return nil, uint64(gasUsed), ffiErrorWithMessage2(err, errmsg) } @@ -538,7 +538,7 @@ func IBCPacketReceive( out := newUnmanagedVector(nil) err := C.ibc_packet_receive(toCachePtr(cache), cs, e, pa, db, a, q, cu64(gasLimit), cbool(printDebug), &gasUsed, &errmsg, &out) - if err != 0 { + if err != C.ErrorCode_Success { // Depending on the nature of the error, `gasUsed` will either have a meaningful value, or just 0. return nil, uint64(gasUsed), ffiErrorWithMessage2(err, errmsg) } @@ -576,7 +576,7 @@ func IBCPacketAck( out := newUnmanagedVector(nil) err := C.ibc_packet_ack(toCachePtr(cache), cs, e, ac, db, a, q, cu64(gasLimit), cbool(printDebug), &gasUsed, &errmsg, &out) - if err != 0 { + if err != C.ErrorCode_Success { // Depending on the nature of the error, `gasUsed` will either have a meaningful value, or just 0. return nil, uint64(gasUsed), ffiErrorWithMessage2(err, errmsg) } @@ -614,30 +614,30 @@ func IBCPacketTimeout( out := newUnmanagedVector(nil) err := C.ibc_packet_timeout(toCachePtr(cache), cs, e, pa, db, a, q, cu64(gasLimit), cbool(printDebug), &gasUsed, &errmsg, &out) - if err != 0 { + if err != C.ErrorCode_Success { // Depending on the nature of the error, `gasUsed` will either have a meaningful value, or just 0. return nil, uint64(gasUsed), ffiErrorWithMessage2(err, errmsg) } return copyAndDestroyUnmanagedVector(out), uint64(gasUsed), nil } -// ffiErrorWithMessage2 takes a error number, tries to read the error message +// ffiErrorWithMessage2 takes an error code, tries to read the error message // written by the Rust code and returns a readable error. // -// This function must only be called on non-zero error numbers. -func ffiErrorWithMessage2(errno cint, errMsg C.UnmanagedVector) error { - if errno == 0 { - panic("Called ffiErrorWithMessage2 with a 0 error number (no error)") +// This function must only be called on non-zero error codes. +func ffiErrorWithMessage2(errorCode cint, errMsg C.UnmanagedVector) error { + if errorCode == 0 { + panic("Called ffiErrorWithMessage2 with a 0 error code (no error)") } // Checks for out of gas as a special case. See "ErrnoValue" in libwasmvm/src/error/rust.rs. - if errno == 2 { + if errorCode == C.ErrorCode_OutOfGas { return types.OutOfGasError{} } msg := copyAndDestroyUnmanagedVector(errMsg) if msg == nil || len(msg) == 0 { - return fmt.Errorf("FFI call errored with errno %#v and no error message.", errno) + return fmt.Errorf("FFI call errored with error code %#v and no error message.", errorCode) } return fmt.Errorf("%s", string(msg)) } diff --git a/libwasmvm/bindings.h b/libwasmvm/bindings.h index c15e740f..3458e32d 100644 --- a/libwasmvm/bindings.h +++ b/libwasmvm/bindings.h @@ -9,12 +9,16 @@ #include #include -enum ErrnoValue { - ErrnoValue_Success = 0, - ErrnoValue_Other = 1, - ErrnoValue_OutOfGas = 2, +/** + * An error code used to communicate the errors of FFI calls. + * Similar to shell codes and errno, 0 means no error. + */ +enum ErrorCode { + ErrorCode_Success = 0, + ErrorCode_Other = 1, + ErrorCode_OutOfGas = 2, }; -typedef int32_t ErrnoValue; +typedef int32_t ErrorCode; /** * This enum gives names to the status codes returned from Go callbacks to Rust. diff --git a/libwasmvm/cbindgen.toml b/libwasmvm/cbindgen.toml index 4c3f41ca..9d524169 100644 --- a/libwasmvm/cbindgen.toml +++ b/libwasmvm/cbindgen.toml @@ -51,7 +51,7 @@ style = "both" [export] include = [ "GoError", - "ErrnoValue", + "ErrorCode", ] exclude = [] # prefix = "CAPI_" diff --git a/libwasmvm/src/error/rust.rs b/libwasmvm/src/error/rust.rs index de30e8d3..4269707d 100644 --- a/libwasmvm/src/error/rust.rs +++ b/libwasmvm/src/error/rust.rs @@ -113,16 +113,24 @@ impl From for RustError { } } +/// An error code used to communicate the errors of FFI calls. +/// Similar to shell codes and errno, 0 means no error. /// cbindgen:prefix-with-name #[repr(i32)] -enum ErrnoValue { - #[allow(dead_code)] +#[derive(Debug, Clone, Copy)] +pub enum ErrorCode { Success = 0, Other = 1, OutOfGas = 2, } -pub fn set_error(err: RustError, error_msg: Option<&mut UnmanagedVector>) -> i32 { +impl ErrorCode { + pub fn to_int(self) -> i32 { + self as i32 + } +} + +pub fn set_error(err: RustError, error_msg: Option<&mut UnmanagedVector>) -> ErrorCode { if let Some(error_msg) = error_msg { if error_msg.is_some() { panic!( @@ -138,11 +146,11 @@ pub fn set_error(err: RustError, error_msg: Option<&mut UnmanagedVector>) -> i32 // That's not nice but we can live with it. } - let errno: ErrnoValue = match err { - RustError::OutOfGas { .. } => ErrnoValue::OutOfGas, - _ => ErrnoValue::Other, + let errno: ErrorCode = match err { + RustError::OutOfGas { .. } => ErrorCode::OutOfGas, + _ => ErrorCode::Other, }; - errno as i32 + errno } pub fn set_out(value: T, out_ptr: Option<&mut T>) { @@ -161,13 +169,14 @@ pub fn to_c_result_binary( error_msg_ptr: Option<&mut UnmanagedVector>, out_ptr: Option<&mut UnmanagedVector>, ) -> i32 { - match result { + let code = match result { Ok(value) => { set_out(value, out_ptr); - 0 + ErrorCode::Success } Err(error) => set_error(error, error_msg_ptr), - } + }; + code.to_int() } /// If `result` is Ok, this writes the Ok value to `out` and returns 0. @@ -177,13 +186,14 @@ pub fn to_c_result( error_msg_ptr: Option<&mut UnmanagedVector>, out_ptr: Option<&mut T>, ) -> i32 { - match result { + let code = match result { Ok(value) => { set_out(value, out_ptr); - 0 + ErrorCode::Success } Err(error) => set_error(error, error_msg_ptr), - } + }; + code.to_int() } /// If `result` is Ok, this writes the Ok value to `out` and returns 0. @@ -192,10 +202,11 @@ pub fn to_c_result_unit( result: Result<(), RustError>, error_msg_ptr: Option<&mut UnmanagedVector>, ) -> i32 { - match result { - Ok(_) => 0, + let code = match result { + Ok(_) => ErrorCode::Success, Err(error) => set_error(error, error_msg_ptr), - } + }; + code.to_int() } #[cfg(test)] From c083a37686fcef99d95a4b12e7d6ef07069b0bab Mon Sep 17 00:00:00 2001 From: Simon Warta Date: Mon, 5 Dec 2022 17:01:02 +0100 Subject: [PATCH 24/25] Avoid FFI calls for errmsg, out that are not used --- internal/api/lib.go | 66 ++++++++++++++++++------------------- internal/api/memory.go | 6 ++++ libwasmvm/src/error/rust.rs | 21 +++++------- 3 files changed, 47 insertions(+), 46 deletions(-) diff --git a/internal/api/lib.go b/internal/api/lib.go index 7919321e..659f90be 100644 --- a/internal/api/lib.go +++ b/internal/api/lib.go @@ -49,7 +49,7 @@ func InitCache(dataDir string, supportedFeatures string, cacheSize uint32, insta f := makeView(supportedFeaturesBytes) defer runtime.KeepAlive(supportedFeaturesBytes) - errmsg := newUnmanagedVector(nil) + errmsg := uninitializedUnmanagedVector() out := C.CachePtr{} err := C.init_cache(d, f, cu32(cacheSize), cu32(instanceMemoryLimit), &errmsg, &out) @@ -67,8 +67,8 @@ func ReleaseCache(cache Cache) { func StoreCode(cache Cache, wasm []byte) ([]byte, error) { w := makeView(wasm) defer runtime.KeepAlive(wasm) - errmsg := newUnmanagedVector(nil) - out := newUnmanagedVector(nil) + errmsg := uninitializedUnmanagedVector() + out := uninitializedUnmanagedVector() err := C.save_wasm(toCachePtr(cache), w, &errmsg, &out) if err != C.ErrorCode_Success { return nil, ffiErrorWithMessage2(err, errmsg) @@ -90,8 +90,8 @@ func RemoveCode(cache Cache, checksum []byte) error { func GetCode(cache Cache, checksum []byte) ([]byte, error) { cs := makeView(checksum) defer runtime.KeepAlive(checksum) - errmsg := newUnmanagedVector(nil) - out := newUnmanagedVector(nil) + errmsg := uninitializedUnmanagedVector() + out := uninitializedUnmanagedVector() err := C.load_wasm(toCachePtr(cache), cs, &errmsg, &out) if err != C.ErrorCode_Success { return nil, ffiErrorWithMessage2(err, errmsg) @@ -102,7 +102,7 @@ func GetCode(cache Cache, checksum []byte) ([]byte, error) { func Pin(cache Cache, checksum []byte) error { cs := makeView(checksum) defer runtime.KeepAlive(checksum) - errmsg := newUnmanagedVector(nil) + errmsg := uninitializedUnmanagedVector() err := C.pin(toCachePtr(cache), cs, &errmsg) if err != C.ErrorCode_Success { return ffiErrorWithMessage2(err, errmsg) @@ -113,7 +113,7 @@ func Pin(cache Cache, checksum []byte) error { func Unpin(cache Cache, checksum []byte) error { cs := makeView(checksum) defer runtime.KeepAlive(checksum) - errmsg := newUnmanagedVector(nil) + errmsg := uninitializedUnmanagedVector() err := C.unpin(toCachePtr(cache), cs, &errmsg) if err != C.ErrorCode_Success { return ffiErrorWithMessage2(err, errmsg) @@ -124,7 +124,7 @@ func Unpin(cache Cache, checksum []byte) error { func AnalyzeCode(cache Cache, checksum []byte) (*types.AnalysisReport, error) { cs := makeView(checksum) defer runtime.KeepAlive(checksum) - errmsg := newUnmanagedVector(nil) + errmsg := uninitializedUnmanagedVector() out := C.AnalysisReport{} err := C.analyze_code(toCachePtr(cache), cs, &errmsg, &out) if err != C.ErrorCode_Success { @@ -140,7 +140,7 @@ func AnalyzeCode(cache Cache, checksum []byte) (*types.AnalysisReport, error) { } func GetMetrics(cache Cache) (*types.Metrics, error) { - errmsg := newUnmanagedVector(nil) + errmsg := uninitializedUnmanagedVector() metrics := C.Metrics{} err := C.get_metrics(toCachePtr(cache), &errmsg, &metrics) if err != C.ErrorCode_Success { @@ -189,8 +189,8 @@ func Instantiate( a := buildAPI(api) q := buildQuerier(querier) var gasUsed cu64 - errmsg := newUnmanagedVector(nil) - out := newUnmanagedVector(nil) + errmsg := uninitializedUnmanagedVector() + out := uninitializedUnmanagedVector() err := C.instantiate(toCachePtr(cache), cs, e, i, m, db, a, q, cu64(gasLimit), cbool(printDebug), &gasUsed, &errmsg, &out) if err != C.ErrorCode_Success { @@ -230,8 +230,8 @@ func Execute( a := buildAPI(api) q := buildQuerier(querier) var gasUsed cu64 - errmsg := newUnmanagedVector(nil) - out := newUnmanagedVector(nil) + errmsg := uninitializedUnmanagedVector() + out := uninitializedUnmanagedVector() err := C.execute(toCachePtr(cache), cs, e, i, m, db, a, q, cu64(gasLimit), cbool(printDebug), &gasUsed, &errmsg, &out) if err != C.ErrorCode_Success { @@ -268,8 +268,8 @@ func Migrate( a := buildAPI(api) q := buildQuerier(querier) var gasUsed cu64 - errmsg := newUnmanagedVector(nil) - out := newUnmanagedVector(nil) + errmsg := uninitializedUnmanagedVector() + out := uninitializedUnmanagedVector() err := C.migrate(toCachePtr(cache), cs, e, m, db, a, q, cu64(gasLimit), cbool(printDebug), &gasUsed, &errmsg, &out) if err != C.ErrorCode_Success { @@ -306,8 +306,8 @@ func Sudo( a := buildAPI(api) q := buildQuerier(querier) var gasUsed cu64 - errmsg := newUnmanagedVector(nil) - out := newUnmanagedVector(nil) + errmsg := uninitializedUnmanagedVector() + out := uninitializedUnmanagedVector() err := C.sudo(toCachePtr(cache), cs, e, m, db, a, q, cu64(gasLimit), cbool(printDebug), &gasUsed, &errmsg, &out) if err != C.ErrorCode_Success { @@ -344,8 +344,8 @@ func Reply( a := buildAPI(api) q := buildQuerier(querier) var gasUsed cu64 - errmsg := newUnmanagedVector(nil) - out := newUnmanagedVector(nil) + errmsg := uninitializedUnmanagedVector() + out := uninitializedUnmanagedVector() err := C.reply(toCachePtr(cache), cs, e, r, db, a, q, cu64(gasLimit), cbool(printDebug), &gasUsed, &errmsg, &out) if err != C.ErrorCode_Success { @@ -382,8 +382,8 @@ func Query( a := buildAPI(api) q := buildQuerier(querier) var gasUsed cu64 - errmsg := newUnmanagedVector(nil) - out := newUnmanagedVector(nil) + errmsg := uninitializedUnmanagedVector() + out := uninitializedUnmanagedVector() err := C.query(toCachePtr(cache), cs, e, m, db, a, q, cu64(gasLimit), cbool(printDebug), &gasUsed, &errmsg, &out) if err != C.ErrorCode_Success { @@ -420,8 +420,8 @@ func IBCChannelOpen( a := buildAPI(api) q := buildQuerier(querier) var gasUsed cu64 - errmsg := newUnmanagedVector(nil) - out := newUnmanagedVector(nil) + errmsg := uninitializedUnmanagedVector() + out := uninitializedUnmanagedVector() err := C.ibc_channel_open(toCachePtr(cache), cs, e, m, db, a, q, cu64(gasLimit), cbool(printDebug), &gasUsed, &errmsg, &out) if err != C.ErrorCode_Success { @@ -458,8 +458,8 @@ func IBCChannelConnect( a := buildAPI(api) q := buildQuerier(querier) var gasUsed cu64 - errmsg := newUnmanagedVector(nil) - out := newUnmanagedVector(nil) + errmsg := uninitializedUnmanagedVector() + out := uninitializedUnmanagedVector() err := C.ibc_channel_connect(toCachePtr(cache), cs, e, m, db, a, q, cu64(gasLimit), cbool(printDebug), &gasUsed, &errmsg, &out) if err != C.ErrorCode_Success { @@ -496,8 +496,8 @@ func IBCChannelClose( a := buildAPI(api) q := buildQuerier(querier) var gasUsed cu64 - errmsg := newUnmanagedVector(nil) - out := newUnmanagedVector(nil) + errmsg := uninitializedUnmanagedVector() + out := uninitializedUnmanagedVector() err := C.ibc_channel_close(toCachePtr(cache), cs, e, m, db, a, q, cu64(gasLimit), cbool(printDebug), &gasUsed, &errmsg, &out) if err != C.ErrorCode_Success { @@ -534,8 +534,8 @@ func IBCPacketReceive( a := buildAPI(api) q := buildQuerier(querier) var gasUsed cu64 - errmsg := newUnmanagedVector(nil) - out := newUnmanagedVector(nil) + errmsg := uninitializedUnmanagedVector() + out := uninitializedUnmanagedVector() err := C.ibc_packet_receive(toCachePtr(cache), cs, e, pa, db, a, q, cu64(gasLimit), cbool(printDebug), &gasUsed, &errmsg, &out) if err != C.ErrorCode_Success { @@ -572,8 +572,8 @@ func IBCPacketAck( a := buildAPI(api) q := buildQuerier(querier) var gasUsed cu64 - errmsg := newUnmanagedVector(nil) - out := newUnmanagedVector(nil) + errmsg := uninitializedUnmanagedVector() + out := uninitializedUnmanagedVector() err := C.ibc_packet_ack(toCachePtr(cache), cs, e, ac, db, a, q, cu64(gasLimit), cbool(printDebug), &gasUsed, &errmsg, &out) if err != C.ErrorCode_Success { @@ -610,8 +610,8 @@ func IBCPacketTimeout( a := buildAPI(api) q := buildQuerier(querier) var gasUsed cu64 - errmsg := newUnmanagedVector(nil) - out := newUnmanagedVector(nil) + errmsg := uninitializedUnmanagedVector() + out := uninitializedUnmanagedVector() err := C.ibc_packet_timeout(toCachePtr(cache), cs, e, pa, db, a, q, cu64(gasLimit), cbool(printDebug), &gasUsed, &errmsg, &out) if err != C.ErrorCode_Success { diff --git a/internal/api/memory.go b/internal/api/memory.go index 8f1352a6..549e221f 100644 --- a/internal/api/memory.go +++ b/internal/api/memory.go @@ -39,6 +39,12 @@ func constructUnmanagedVector(is_none cbool, ptr cu8_ptr, len cusize, cap cusize } } +// uninitializedUnmanagedVector returns an invalid C.UnmanagedVector +// instance. Only use then after someone wrote an instance to it. +func uninitializedUnmanagedVector() C.UnmanagedVector { + return C.UnmanagedVector{} +} + func newUnmanagedVector(data []byte) C.UnmanagedVector { if data == nil { return C.new_unmanaged_vector(cbool(true), cu8_ptr(nil), cusize(0)) diff --git a/libwasmvm/src/error/rust.rs b/libwasmvm/src/error/rust.rs index 4269707d..14c3ee9a 100644 --- a/libwasmvm/src/error/rust.rs +++ b/libwasmvm/src/error/rust.rs @@ -130,15 +130,10 @@ impl ErrorCode { } } -pub fn set_error(err: RustError, error_msg: Option<&mut UnmanagedVector>) -> ErrorCode { +/// Takes the `RustError`, writes the error message to +/// the `error_msg` pointer and returns an Error code. +pub fn set_error_msg(err: RustError, error_msg: Option<&mut UnmanagedVector>) -> ErrorCode { if let Some(error_msg) = error_msg { - if error_msg.is_some() { - panic!( - "There is an old error message in the given pointer that has not been \ - cleaned up. Error message pointers should not be reused for multiple calls." - ) - } - let msg: Vec = err.to_string().into(); *error_msg = UnmanagedVector::new(Some(msg)); } else { @@ -146,11 +141,11 @@ pub fn set_error(err: RustError, error_msg: Option<&mut UnmanagedVector>) -> Err // That's not nice but we can live with it. } - let errno: ErrorCode = match err { + let code: ErrorCode = match err { RustError::OutOfGas { .. } => ErrorCode::OutOfGas, _ => ErrorCode::Other, }; - errno + code } pub fn set_out(value: T, out_ptr: Option<&mut T>) { @@ -174,7 +169,7 @@ pub fn to_c_result_binary( set_out(value, out_ptr); ErrorCode::Success } - Err(error) => set_error(error, error_msg_ptr), + Err(error) => set_error_msg(error, error_msg_ptr), }; code.to_int() } @@ -191,7 +186,7 @@ pub fn to_c_result( set_out(value, out_ptr); ErrorCode::Success } - Err(error) => set_error(error, error_msg_ptr), + Err(error) => set_error_msg(error, error_msg_ptr), }; code.to_int() } @@ -204,7 +199,7 @@ pub fn to_c_result_unit( ) -> i32 { let code = match result { Ok(_) => ErrorCode::Success, - Err(error) => set_error(error, error_msg_ptr), + Err(error) => set_error_msg(error, error_msg_ptr), }; code.to_int() } From 425cc113365b7681cce23d0d40327d4a66f34069 Mon Sep 17 00:00:00 2001 From: Simon Warta Date: Tue, 6 Dec 2022 15:42:43 +0100 Subject: [PATCH 25/25] Get CPU info of Windows machine --- .circleci/config.yml | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/.circleci/config.yml b/.circleci/config.yml index 0e13e9cf..fddf2c32 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -3,6 +3,17 @@ version: 2.1 orbs: win: circleci/windows@5.0 +commands: + show_cpu_info: + steps: + - run: + name: Show CPU info + command: | + set -o errexit + curl -sS -L --output py-cpuinfo.zip https://github.com/workhorsy/py-cpuinfo/archive/refs/tags/v9.0.0.zip + unzip -q py-cpuinfo.zip + python py-cpuinfo-*/cpuinfo/cpuinfo.py + jobs: # All checks on the codebase that can run in parallel to build_shared_library libwasmvm_sanity: @@ -79,6 +90,7 @@ jobs: - run: name: Reset git config set by CircleCI to make Cargo work command: git config --global --unset url.ssh://git@github.com.insteadof + - show_cpu_info - run: name: Install Rust command: | @@ -260,6 +272,7 @@ jobs: - run: name: Reset git config set by CircleCI to make Cargo work command: git config --global --unset url.ssh://git@github.com.insteadof + - show_cpu_info - run: name: Install make command: | @@ -326,6 +339,7 @@ jobs: GORACE: "halt_on_error=1" steps: - checkout + - show_cpu_info - run: name: Install make and mingw # See https://github.com/docker/containerd-packaging/pull/294 for discussion around mingw version