Skip to content

Commit

Permalink
Forkless state transition with upgradable WASM executor (#1716)
Browse files Browse the repository at this point in the history
Closes #1547

## Change overview

The change adds the WASM version of the `fuel_core_executor::Executor`
and the upgradable executor that works with native(std) and WASM(no-std)
versions of the executor. Currently, it uses either the WASM or the std
version. But in the follow-up PRs it will decide which version to use
based on the block header. For now, this behavior is controlled by the
"wasm-executor" feature. The CI runs tests two times, one with the WASM
executor and the second with std, to verify that behaviors are the same.

## Details on how WASM integration is done

The `fuel-core-upgradable-executor` uses the `wasmtime` library to
compile and run the WASM bytecode. The `wastime::Engine` allows
customization of how the `wastime::Module` compiles the bytecode. For
simplicity, we are using the default configuration that works on all
platforms for now, but later, it is possible to do more specific
compilation.

We are using `wastime::Linker` to add host functions that can be called
from the WASM runtime via `extern "C"` API:

```rust
#[link(wasm_import_module = "host_v0")]
extern "C" {
    /// Returns the size of the value from the storage.
    pub(crate) fn storage_size_of_value(
        key_ptr: Ptr32<[u8]>,
        key_len: u32,
        column: u32,
    ) -> u64;

    /// Returns the value from the storage.
    pub(crate) fn storage_get(
        key_ptr: Ptr32<[u8]>,
        key_len: u32,
        column: u32,
        out_ptr: Ptr32Mut<[u8]>,
        out_len: u32,
    ) -> ReturnResult;
}
```

The host functions are closures that capture data required for the work,
such as the storage or relayer. Host functions have access to the
`ExecutionState`, which accumulates intermediate data.

Data is passed between the host and runtime through memory, where one
side gives the pointer where data should be stored, and another side
writes the memory using this pointer and the size. The host is not
responsible for allocating and deallocating memory; the memory
management is done within WASM runtime. Currently, when we return
something from the runtime to the host, we "leak" it to avoid
deallocation. It allows the host to read the value from the memory.

Side changes:
- The coinbase contract id is not a part of the `Config` anymore. It is
part of the `Components` and seats along with the `gas_price` because it
is defined by the block producer and can always be changed on the fly.
- The usage of `anyhow::Error` in the `ExecutorError` was replaced by
`String` because it doesn't implement `serde` ser/des.
- The `ExecutionOptions`, `WriteOperation`, `ExecutionResult`,
`TransactionExecutionResult`, `TransactionExecutionStatus`,
`ExecutorError`, and `TransactionValidityError` support `serde` ser/des.
- The `fuel-core-executor` only provides the `ExecutionInstance` without
`Executor`. The logic of the `Executor` was moved to the
`fuel-core-upgradable-executor`.

---------

Co-authored-by: Voxelot <[email protected]>
  • Loading branch information
xgreenx and Voxelot authored Mar 26, 2024
1 parent fb79894 commit a5faa1f
Show file tree
Hide file tree
Showing 46 changed files with 2,394 additions and 660 deletions.
4 changes: 4 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,8 @@ jobs:
strategy:
matrix:
include:
- command: clippy
args: -p fuel-core-wasm-executor --target wasm32-unknown-unknown --no-default-features
- command: clippy
args: --all-targets --all-features
- command: check
Expand All @@ -122,6 +124,8 @@ jobs:
args: --all-features --workspace --no-deps
- command: make
args: check --locked
- command: test
args: --workspace
- command: test
args: --all-features --workspace
- command: test
Expand Down
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ Description of the upcoming release here.

### Added

- [#1716](https://github.com/FuelLabs/fuel-core/pull/1716): Added support of WASM state transition along with upgradable execution that works with native(std) and WASM(non-std) executors. The `fuel-core` now requires a `wasm32-unknown-unknown` target to build.
- [#1770](https://github.com/FuelLabs/fuel-core/pull/1770): Add the new L1 event type for forced transactions.
- [#1767](https://github.com/FuelLabs/fuel-core/pull/1767): Added consensus parameters version and state transition version to the `ApplicationHeader` to describe what was used to produce this block.
- [#1760](https://github.com/FuelLabs/fuel-core/pull/1760): Added tests to verify that the network operates with a custom chain id and base asset id.
Expand Down
Loading

0 comments on commit a5faa1f

Please sign in to comment.