From 2a4209ec4157acfbc44bf4310f399020160e5a05 Mon Sep 17 00:00:00 2001 From: Thomas Niederberger <781000+Niederb@users.noreply.github.com> Date: Thu, 4 Jul 2024 11:52:54 +0200 Subject: [PATCH] Wasm test (#772) * Scaffolding for wasm test * Fix command to build wasm example * State os for running job statically * Run example with wasmtime * Try different approach for a build with a wasm test * Add missing comma * Fix toml formatting * Adjust path * Test a failing example * Return an Err * Improve wasm example * Working on example * Implement functionality * Improve example * Cleanup example * Revert "Implement functionality" This reverts commit 69005747926830e37e97af08479d84f51f26c9b1. * Add test documentation * Incorporate review feedback --- .github/workflows/ci.yml | 37 ++++++++++++++++++- Cargo.lock | 10 ++++++ Cargo.toml | 1 + examples/wasm/Cargo.toml | 11 ++++++ examples/wasm/examples/wasm_example.rs | 50 ++++++++++++++++++++++++++ 5 files changed, 108 insertions(+), 1 deletion(-) create mode 100644 examples/wasm/Cargo.toml create mode 100644 examples/wasm/examples/wasm_example.rs diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index bd6f6fe07..55d4f55b6 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -54,6 +54,7 @@ jobs: # Test for 32 bit and wasm32-unknown-unknown compatibility cargo build --target wasm32-unknown-unknown --no-default-features --features sync-api, + cargo build --release -p ac-examples-wasm --examples --target wasm32-unknown-unknown, # Test for 32 bit and wasm32-wasip1 compatibility cargo build --target wasm32-wasip1 --no-default-features --features std --features staking-xt --features contracts-xt --features sync-api, @@ -120,6 +121,14 @@ jobs: !target/release/examples/*.d !target/release/examples/*-* + - name: Upload wasm examples + uses: actions/upload-artifact@v4 + if: contains(matrix.check, 'examples-wasm') + with: + name: examples-wasm + path: | + target/wasm32-unknown-unknown/release/examples/*.wasm + - name: Upload async testing examples uses: actions/upload-artifact@v4 if: contains(matrix.check, 'testing-async') @@ -235,9 +244,35 @@ jobs: nc -z -v 127.0.0.1 9944 chmod +x ${{ matrix.example }} ./${{ matrix.example }} + + wasm_examples: + runs-on: ${{ matrix.os }} + needs: build + strategy: + fail-fast: false + matrix: + os: [ ubuntu-latest ] + example: [ + wasm_example, + ] + steps: + - uses: actions/checkout@v4 + + - name: Download examples from previous run + uses: actions/download-artifact@v4 + with: + pattern: examples-wasm + merge-multiple: true + + - name: Setup `wasmtime` + uses: bytecodealliance/actions/wasmtime/setup@v1 + + - name: Run wasm example + run: wasmtime --invoke main ${{ matrix.example }}.wasm 0 0 + merge: runs-on: ubuntu-latest - needs: examples + needs: [examples, wasm_examples] steps: - name: Merge Artifacts uses: actions/upload-artifact/merge@v4 diff --git a/Cargo.lock b/Cargo.lock index 915dd2861..53936dc01 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -61,6 +61,16 @@ dependencies = [ "substrate-api-client", ] +[[package]] +name = "ac-examples-wasm" +version = "0.5.0" +dependencies = [ + "pallet-balances", + "sp-core", + "sp-runtime", + "substrate-api-client", +] + [[package]] name = "ac-keystore" version = "0.10.0" diff --git a/Cargo.toml b/Cargo.toml index 9ffeacb61..6078ee20c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -18,6 +18,7 @@ members = [ "compose-macros", "examples/async", "examples/sync", + "examples/wasm", "node-api", "test-no-std", "testing/async", diff --git a/examples/wasm/Cargo.toml b/examples/wasm/Cargo.toml new file mode 100644 index 000000000..e620f1e94 --- /dev/null +++ b/examples/wasm/Cargo.toml @@ -0,0 +1,11 @@ +[package] +name = "ac-examples-wasm" +version = "0.5.0" +license = "Apache-2.0" +edition = "2021" + +[dev-dependencies] +sp-core = { default-features = false, features = ["full_crypto", "serde"], git = "https://github.com/paritytech/polkadot-sdk.git", branch = "master" } +sp-runtime = { default-features = false, git = "https://github.com/paritytech/polkadot-sdk.git", branch = "master" } +substrate-api-client = { default-features = false, path = "../..", version = "0.17" } +pallet-balances = { default-features = false, git = "https://github.com/paritytech/polkadot-sdk.git", branch = "master" } diff --git a/examples/wasm/examples/wasm_example.rs b/examples/wasm/examples/wasm_example.rs new file mode 100644 index 000000000..d25262393 --- /dev/null +++ b/examples/wasm/examples/wasm_example.rs @@ -0,0 +1,50 @@ +/* + Copyright 2024 Supercomputing Systems AG + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + http://www.apache.org/licenses/LICENSE-2.0 + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +//! Example that some basic functions that can be executed in WebAssembly. + +pub use pallet_balances::Call as BalancesCall; +use sp_core::{ + crypto::{AccountId32, Ss58Codec}, + sr25519, Pair, +}; +use sp_runtime::MultiAddress; +pub use sp_runtime::OpaqueExtrinsic as UncheckedExtrinsic; +use std::process::ExitCode; +use substrate_api_client::ac_primitives::{AssetRuntimeConfig, ExtrinsicSigner}; + +fn main() -> Result { + // This test is not yet very sophisticated and not exhaustive. + // Still it shows how some basic data structures can be constructed and used. + let alice: sr25519::Pair = Pair::from_string( + "0xe5be9a5092b81bca64be81d212e7f2f9eba183bb7a90954f7b76361f6edb5c0a", + None, + ) + .unwrap(); + + let bob_account: AccountId32 = + sr25519::Public::from_ss58check("5FHneW46xGXgs5mUiveU4sbTyGBzmstUspZC92UhjJM694ty") + .unwrap() + .into(); + let _bob: MultiAddress = MultiAddress::Id(bob_account); + let es_converted: ExtrinsicSigner = alice.clone().into(); + let es_new = ExtrinsicSigner::::new(alice.clone()); + assert_eq!(es_converted.signer().public(), es_new.signer().public()); + + let extrinsic = UncheckedExtrinsic::from_bytes(&[]); + match extrinsic { + Ok(_) => panic!("Extrinsic should be invalid"), + Err(_) => (), + } + Ok(ExitCode::from(0)) +}