Instrument and transform wasm modules.

Overview

wasm-instrument

A Rust library containing a collection of wasm module instrumentations and transformations mainly useful for wasm based block chains and smart contracts.

Provided functionality

This is a non exhaustive list of provided functionality. Please check out the documentation for details.

Gas Metering

Add gas metering to your platform by injecting the necessary code directly into the wasm module. This allows having a uniform gas metering implementation across different execution engines (interpreters, JIT compilers).

Stack Height Limiter

Neither the wasm standard nor any sufficiently complex execution engine specifies how many items on the wasm stack are supported before the execution aborts or malfunctions. Even the same execution engine on different operating systems or host architectures could support a different number of stack items and be well within its rights.

This is the kind of indeterminism that can lead to consensus failures when used in a blockchain context.

To address this issue we can inject some code that meters the stack height at runtime and aborts the execution when it reaches a predefined limit. Choosing this limit suffciently small so that it is smaller than what any reasonably parameterized execution engine would support solves the issue: All execution engines would reach the injected limit before hitting any implementation specific limitation.

License

wasm-instrument is distributed under the terms of both the MIT license and the Apache License (Version 2.0), at your choice.

See LICENSE-APACHE, and LICENSE-MIT for details.

Contribution

Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in wasm-instrument by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.

Comments
  • handle debug info

    handle debug info

    Fixes https://github.com/paritytech/wasm-instrument/issues/15.

    Waiting on https://github.com/paritytech/parity-wasm/pull/328 to be merged to update the Cargo.toml on this PR

    opened by mangas 9
  • Handle overflows while calculating cost of the block in gas-metering algorithm

    Handle overflows while calculating cost of the block in gas-metering algorithm

    A possibility of the overflow while calculating cost of the block in gas-metering algorithm depends on 2 factors: the cost of each instruction defined by the caller, i.e. user of the wasm-instrument crate, and the size of the wasm module (amount of instructions). Some projects can face overflow error while injecting gas calls, because of specific for them parameters of wasm module size or cost of each instruction. I believe handling overflows while cost (gas) calculation can give more freedom to wasm-instrument users.

    The suggested in the PR solution:

    1. Enable overflows counter while metering blocks
    2. When injecting gas calls, push several gas call instructions instead of one as it is now.
    opened by SabaunT 8
  • Add new gas metering method: mutable global + local `gas` function

    Add new gas metering method: mutable global + local `gas` function

    Solves #11

    In addition to method used beforehand (i.e. injection of calls to an imported gas function into metering blocks), this new method now available too, which:

    • Injects an exported mutable global into the module, which tracks the gas left.
    • Injects the local gas function which subtracts the gas spent from the global, and drops unreachable if out of gas.

    This new method should make the resulting module more efficient in terms of execution time, as invoking an imported gas host function every metering block adds an overhead. Synchronization between the global and the runtime should be implemented on the execution engine side.

    opened by agryaznov 7
  • Stack depth instrumentation fails to account for the full function activation stack frame

    Stack depth instrumentation fails to account for the full function activation stack frame

    The stack depth calculation for the call and call_indirect instruction here

    https://github.com/paritytech/wasm-utils/blob/b22696aaa516212284f2d94a28d8d292afe27859/src/stack_height/max_height.rs#L268-L293

    fails to account for the full function activation frames as described in the specification.

    For that reason it is possible to write a WASM program which, when instrumented, could place frames onto the stack and overflow it regardless of the limit imposed.

    Most straightforward such WASM module may look like this

    (module
      (type (;0;) (func))
      (func (;0;) (type 0)
        call 0)
      (func (;1;) (type 0)
        call 0)
      (export "main" (func 1)))
    

    which after instrumentation becomes

    (module
      (type (;0;) (func))
      (func (;0;) (type 0)
        call 0)
      (func (;1;) (type 0)
        call 0)
      (global (;0;) (mut i32) (i32.const 0))
      (export "main" (func 1)))
    

    today.

    The correct model should be:

    1. Pop the function address (for call_indirect);
    2. Pop the arguments;
    3. Push a function activation frame (this includes space for arguments, locals, return values and a reference to the module instance);

    Module instance reference here in particular is something that would make stack depth accounting accurate in absence of the arguments, locals and return values.

    opened by nagisa 5
  • Update debug information when injecting gas metering

    Update debug information when injecting gas metering

    Injecting the gas metering causes the function indices to shift. This causes any stacktraces using the name section to be wrong for any function with an index higher than the injected gas meter functions.

    opened by mangas 4
  • WIP: Weighted stack metering

    WIP: Weighted stack metering

    This is work-in-progress. No multi-value support yet, some tests are failing. I'm working on it.

    The purpose of PR is to bring stack metering closer to the real world. Although Wasm values always take one abstract position on stack, real-world values do not work like that. For a legit code the difference is negligible, however, more care is needed to mitigate risks of potentially abusive code where an attacker may use that difference to abuse stack cost calculation (e.g. providing a function with several hundreds of wide f64 parameters).

    opened by s0me0ne-unkn0wn 3
  • Expose more features from parity-wasm

    Expose more features from parity-wasm

    Only sign_ext feature is supported from parity-wasm, the following aren't, but might be useful:

    • atomics
    • bulk
    • multi_value
    • simd

    I wanted to do some experiments with enabling various features, but it fails with errors like this:

    170 |         match opcode {
        |               ^^^^^^ pattern `&Simd(_)` not covered
    
    opened by nazar-pc 3
  • Update wasmparser requirement from 0.92 to 0.93

    Update wasmparser requirement from 0.92 to 0.93

    Updates the requirements on wasmparser to permit the latest version.

    Commits

    Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting @dependabot rebase.


    Dependabot commands and options

    You can trigger Dependabot actions by commenting on this PR:

    • @dependabot rebase will rebase this PR
    • @dependabot recreate will recreate this PR, overwriting any edits that have been made to it
    • @dependabot merge will merge this PR after your CI passes on it
    • @dependabot squash and merge will squash and merge this PR after your CI passes on it
    • @dependabot cancel merge will cancel a previously requested merge and block automerging
    • @dependabot reopen will reopen this PR if it is closed
    • @dependabot close will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually
    • @dependabot ignore this major version will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this minor version will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this dependency will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
    opened by dependabot[bot] 1
  • Update wasmparser requirement from 0.90 to 0.91

    Update wasmparser requirement from 0.90 to 0.91

    Updates the requirements on wasmparser to permit the latest version.

    Commits
    • 4e14cec Bump crate versions (#772)
    • f9a5709 Update the spec test suite submodule (#763)
    • 3dfb643 Update some crate README.mds a bit (#771)
    • 84a09c2 wasm-tools: update for latest component model changes. (#770)
    • 589ff55 Fix wasm-encoder encodings for new relaxed instructions (#768)
    • 6dee72f OperatorVisitor: qualify index param names (#767)
    • 5db14d0 Update relaxed simd instructions (#766)
    • 3755661 fix typo in for_each_operator macro expansion (#765)
    • 609dc15 wasmparser: self-contain for_each_operator! (#764)
    • 95883ff Add the ability to share allocations during validation (#760)
    • Additional commits viewable in compare view

    Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting @dependabot rebase.


    Dependabot commands and options

    You can trigger Dependabot actions by commenting on this PR:

    • @dependabot rebase will rebase this PR
    • @dependabot recreate will recreate this PR, overwriting any edits that have been made to it
    • @dependabot merge will merge this PR after your CI passes on it
    • @dependabot squash and merge will squash and merge this PR after your CI passes on it
    • @dependabot cancel merge will cancel a previously requested merge and block automerging
    • @dependabot reopen will reopen this PR if it is closed
    • @dependabot close will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually
    • @dependabot ignore this major version will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this minor version will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this dependency will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
    opened by dependabot[bot] 1
  • Update parity-wasm requirement from 0.42 to 0.45

    Update parity-wasm requirement from 0.42 to 0.45

    Updates the requirements on parity-wasm to permit the latest version.

    Commits

    Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting @dependabot rebase.


    Dependabot commands and options

    You can trigger Dependabot actions by commenting on this PR:

    • @dependabot rebase will rebase this PR
    • @dependabot recreate will recreate this PR, overwriting any edits that have been made to it
    • @dependabot merge will merge this PR after your CI passes on it
    • @dependabot squash and merge will squash and merge this PR after your CI passes on it
    • @dependabot cancel merge will cancel a previously requested merge and block automerging
    • @dependabot reopen will reopen this PR if it is closed
    • @dependabot close will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually
    • @dependabot ignore this major version will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this minor version will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this dependency will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
    opened by dependabot[bot] 1
  • Update wasmparser requirement from 0.84 to 0.85

    Update wasmparser requirement from 0.84 to 0.85

    Updates the requirements on wasmparser to permit the latest version.

    Commits
    • fcb052f Bump crate versions (#616)
    • 9d4a730 Refactor the wast component resolver (#614)
    • 0d7b191 Fix a failing test on main (#615)
    • 16af83e wasm-encoder: remove iterator-based encoders. (#612)
    • cf92a1e Refactor interface type representation in wast (#607)
    • 5f3d593 Remove ItemRef and IndexOrRef from core wast support (#608)
    • 12427be Add more tests exercising the component model (#606)
    • 32770aa Fix parsing (assert_trap (component ...)) (#611)
    • 105b51f wasm-encoder: introduce an Encode trait implemented on all encodable types ...
    • e359e1e Add more tests for components parsing (#602)
    • Additional commits viewable in compare view

    Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting @dependabot rebase.


    Dependabot commands and options

    You can trigger Dependabot actions by commenting on this PR:

    • @dependabot rebase will rebase this PR
    • @dependabot recreate will recreate this PR, overwriting any edits that have been made to it
    • @dependabot merge will merge this PR after your CI passes on it
    • @dependabot squash and merge will squash and merge this PR after your CI passes on it
    • @dependabot cancel merge will cancel a previously requested merge and block automerging
    • @dependabot reopen will reopen this PR if it is closed
    • @dependabot close will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually
    • @dependabot ignore this major version will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this minor version will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this dependency will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
    opened by dependabot[bot] 1
  • How to get the remaining gas once execution has ran out of gas?

    How to get the remaining gas once execution has ran out of gas?

    Hi, guys. As I can see here https://github.com/paritytech/wasm-instrument/blob/6a79d1d4b803c66c92ed91c0ee42d07f8e03c27f/src/gas_metering/backend.rs#L106-L110 Global is explicitly set to u64::MAX. I'd like to know the value of leftover gas instead of u64::MAX, is there a way to do it in the current version of your library?

    opened by mralexes 1
  • Switch to `wasmparser` and `wasm-encoder`

    Switch to `wasmparser` and `wasm-encoder`

    Currently, we use parity-wasm both as a parser and encoder library for web assembly. However, this library is kind of outdated and only supports the wasm MVP properly.

    The plan is to switch to the battle tested libraries wasmparser (for parsing) and wasm-encoder (for writing out the modified wasm). The main problem here is that those libraries don't have the required no_std support. So this is blocked until they have that or until an up-to-date fork exists. @Robbepop maintains such a fork here. However, it only added no_std support for wasmparser but it should be easy to support it for wasm-encoder (in the same repo) in a similar manner: https://github.com/Robbepop/wasm-tools/pull/1

    Right now we re-export the parity-wasm crate so that our users can directly interact with those types. Some users (pallet-contract) even use those types implement some constraints and checks themselves on wasm modules. The same concept won't be possible because wasmparser is event driven and has no in-memory representation of a whole module like parity-wasm does.

    Another hurdle is that we currently rely on the inability of parity-wasm to parse anything more than the wasm MVP to guard us against wasm modules that make use of features we don't want to support. I think this is a mistake: The parser should support everything that is standardized and this crate should represent the bottle neck of what we want to support. This is a natural place because we need to deal with all features in detail in order to implement a proper instrumentation.

    This switch should shift the overall design so that we can accomplish all the checking and instrumentation steps in one pass over the module: We expose a single entry point like fn process<C: Config>(config: C). This Config will configure what is to be done in this single pass:

    • Which wasm features to support or reject (MVP only/list of features)
    • Which exports with which signatures are allowed
    • Which imports with which signatures are allowed
    • Check of memories (size and if imported or exported)
    • Which instructions are supported (disallow floating point)
    • Limit number of function parameters
    • Limit the size of tables
    • Limit the number of global variables
    • Should we inject gas metering?
    • Should we inject stack height limiting?
    • Should we expose certain global variables?

    The points listed above are basically what pallet-contracts is doing right now by directly depending on parity-wasm directly: https://github.com/paritytech/substrate/blob/master/frame/contracts/src/wasm/prepare.rs . We want to get rid of that code and move it to wasm-instrument through the Config we described above.

    Doing this all in one pass and possibly in parallel (for std builds) could yield massive speedups. Right now the pallet-contracts needs multiple passes over a module to achieve all of that.

    opened by athei 2
Owner
Parity Technologies
Solutions for a trust-free world
Parity Technologies
Distribute a wasm SPA as HTML by wrapping it as a polyglot "html+wasm+zip"

A packer that adds a webpage to WASM module, making it self-hosted! Motivation At the moment, Browsers can not execute WebAssembly as a native single

Andreas Molzer 3 Jan 2, 2023
Rust bindings for writing safe and fast native Node.js modules.

Rust bindings for writing safe and fast native Node.js modules. Getting started Once you have the platform dependencies installed, getting started is

The Neon Project 7k Jan 4, 2023
A weekly dive into commonly used modules in the Rust ecosystem, with story flavor!

Rust Module of the Week A weekly dive into commonly used modules in the Rust ecosystem, with story flavor! Build status Release Draft The goal The goa

Scott Lyons 20 Aug 26, 2022
Rust Python modules for interacting with Metaplex's NFT standard.

Simple Metaplex Metadata Decoder Install the correct Python wheel for your Python version with pip: pip install metaplex_decoder-0.1.0-cp39-cp39-manyl

Samuel Vanderwaal 11 Mar 31, 2022
Zinnia is a runtime for Filecoin Station modules. It provides a sandboxed environment to execute untrusted code on consumer-grade computers.

?? Zinnia Zinnia is a runtime for Filecoin Station modules. It provides a sandboxed environment to execute untrusted code on consumer-grade computers.

Filecoin Station 5 Jan 25, 2023
Parametric surfaces drawn using the Rust + WASM toolchain with WebGL, React, and TypeScript.

Parametric Surfaces in the Browser My.Movie.3.mp4 Wanted to experiment with WebGL using the Rust + WASM toolchain, with React and TypeScript to glue e

Benji Nguyen 45 Oct 21, 2022
Rust implementation of the Mina protocol, targeting Wasm and ARM architectures.

Mina-rs An implementation of Mina protocol in Rust, with focus on web and Wasm compatibility ** As you can probably tell this is a WIP! Don't use for

ChainSafe 157 Dec 12, 2022
WASM bindings for React - enables you to write and use React components in Rust

This library enables you to write and use React components in Rust, which then can be exported to JS to be reused or rendered.

Yichuan Shen 55 Dec 24, 2022
TSS of GG18 by WASM, for Confidential Transaction Generation and Signing

TSS WASM portable lightweight client application for threshold ECDSA (based on GG18), built on&for multi-party-ecdsa : Wasm HW friendly Dev yarn build

Eigen Labs 24 Dec 28, 2022
Lunatic based webserver embedding WASM. Supports scaling down to zero and up to infinity.

Frenezulo A WASM-embedding webserver build on top of submillisecond and lunatic. Build to serve as an entry point for microservices compiled to WASM.

Kai Jellinghaus 13 Oct 23, 2022
Spine runtime for Rust (and wasm!) transpiled from the official C Runtime.

rusty_spine Spine runtime for Rust (and wasm!) transpiled from the official C Runtime. Supports Spine 4.1. [dependencies] rusty_spine = "0.4.0" Onlin

jabu 12 Dec 17, 2022
zzhack-cli is a Command Tool to help you quickly generate a WASM WebApp with simple configuration and zero code

English | δΈ­ζ–‡ζ–‡ζ‘£ zzhack-cli is a Command Tool that can help you quickly generate a WASM WebApp with simple configuration and zero code. It's worth menti

null 17 Feb 9, 2023
2D particle system with custom material traits. Works well in wasm webgl2 and mobile

Bevy Enoki Enoki - A 2D particle system for the Bevy game engine. Overview The Enoki particle system is a CPU calculate particle system, that uses GPU

Lorenz 28 Jul 7, 2024
πŸ“¦βœ¨ your favorite rust -> wasm workflow tool!

?? ✨ wasm-pack Your favorite Rust β†’ Wasm workflow tool! Docs | Contributing | Chat Built with ?? ?? by The Rust and WebAssembly Working Group About Th

Rust and WebAssembly 4.8k Jan 5, 2023
Gun port in rust & wasm

gun-rs-wasm Rust & WASM port of Gun. For a non-wasm version, check out gun-rs Example (source) Use npm install rusty-gun import { Node as Gun } from "

Martti Malmi 39 Dec 19, 2022
Install `wasm-pack` by downloading the executable

wasm-pack-action Install wasm-pack by downloading the executable (much faster than cargo install wasm-pack, seconds vs minutes). Usage - uses: jetli/w

Jet Li 33 Nov 23, 2022
`wasm-snip` replaces a WebAssembly function's body with an `unreachable`

wasm-snip wasm-snip replaces a Wasm function's body with an unreachable instruction. API Docs | Contributing | Chat Built with ?? ?? by The Rust and W

Rust and WebAssembly 177 Dec 28, 2022
gc-sections for wasm

wasm-gc Note: you probably don't need to use this project. This project is no longer necessary to run by hand, nor do you need the wasm-gc executable

Alex Crichton 245 Oct 22, 2022
List the symbols within a wasm file

wasm-nm List the symbols within a wasm file. Library Executable License Contributing Executable To install the wasm-nm executable, run $ cargo install

Nick Fitzgerald 38 Nov 6, 2022