diff --git a/docs/developer-guides/building-a-blended-app/start-solidity-contract.md b/docs/developer-guides/building-a-blended-app/start-solidity-contract.md index f5c94ef..62f53dc 100644 --- a/docs/developer-guides/building-a-blended-app/start-solidity-contract.md +++ b/docs/developer-guides/building-a-blended-app/start-solidity-contract.md @@ -8,7 +8,6 @@ Step 2: Start Solidity Contract This guide is based off of the template blended application in this [Github repo](https://github.com/fluentlabs-xyz/blended-template-foundry-cli). - ## Solidity Contract with Interface Solidity interfaces are useful for calling external contracts that might diff --git a/docs/knowledge-base/architecture/README.md b/docs/knowledge-base/architecture/README.md new file mode 100644 index 0000000..c1e8657 --- /dev/null +++ b/docs/knowledge-base/architecture/README.md @@ -0,0 +1,29 @@ +--- +title: Architecture +--- + +Architecture +--- + +Fluent is an Ethereum Layer L2 rollup designed to natively execute EVM, SVM and Wasm-based programs. +Fluent exists as a unified state machine, +where all contracts can call each other, regardless of which VM they were originally built for. + +As a rollup, Fluent supports scalable and efficient execution by committing state changes to Ethereum L1. +This process involves compressing the state changes using ZK proofs, specifically SNARKs. + +![Fluent base architecture](../../../static/img/kb/fluent-arch.png) + +The Fluent operates on a modified version of [Reth](https://github.com/fluentlabs-xyz/fluent), +using its own execution engine that replaces [Revm](https://github.com/fluentlabs-xyz/revm-rwasm). +It maintains backward compatibility with most existing Ethereum standards, such as transaction and block structures. +However, Fluent is not confined to Reth exclusively, as it features an independent execution runtime. + +Furthermore, +Fluent enables a fork-less runtime upgrade model +by incorporating the most critical and upgradable runtime execution codebase within the genesis state. +The only persistent element within the runtime is the transaction format. + +Additionally, Fluent is always post-Prague compatible and does not support any EIPs implemented before the Prague fork. +Maintaining backward compatibility with all previous forks is unnecessary. +The EVM runtime can be upgraded to retain compatibility with EVM. diff --git a/docs/knowledge-base/architecture/_category_.json b/docs/knowledge-base/architecture/_category_.json new file mode 100644 index 0000000..2b96ba3 --- /dev/null +++ b/docs/knowledge-base/architecture/_category_.json @@ -0,0 +1,5 @@ +{ + "label": "Architecture", + "position": 4, + "collapsed": true + } \ No newline at end of file diff --git a/docs/knowledge-base/architecture/abi-format.md b/docs/knowledge-base/architecture/abi-format.md new file mode 100644 index 0000000..021d670 --- /dev/null +++ b/docs/knowledge-base/architecture/abi-format.md @@ -0,0 +1,178 @@ +--- +title: ABI +sidebar_position: 3 +--- +ABI +--- + +In the realm of EVM applications, +the Solidity ABI has become the predominant encoding format, +effectively establishing itself as a primary standard for on-chain interactions today. +This encoding and decoding schema, +primarily driven by the Solidity language, is widely used across Ethereum and other EVM-compatible platforms. + +However, in the Web2 domain, +developers opt for ABI encoding/decoding schemes that best fit their specific needs and tasks. +Notably, Ethereum includes several system precompiles that do not conform to a Solidity-compatible ABI schema. + +Blended VM Fluent distinguishes itself by supporting a variety of execution environments, such as EVM and Solana's VM, +using distinct ABI schemes tailored to each environment. +In Solana, for instance, there isn't a standardized ABI format, +granting developers the flexibility to choose any format that suits their requirements. + +This flexibility is a hallmark of Fluent, as it does not mandate a single encoding/decoding standard for applications. +Instead, it empowers developers to select the most suitable option. +The Fluentbase SDK accommodates this by implementing the necessary ABI encoding/decoding standards, +allowing developers to freely use any ABI format they prefer. + +## Fluentbase Codec + +Fluent employs a custom codec for ABI encoding/decoding tailored to various ABIs. +This Codec includes compatibility modes such as Solidity ABI, +and is designed to efficiently encode and decode parameters across different VMs. + +Fluent Codec is a lightweight library, compatible with no-std environments, and optimized for random reads. +Although it shares similarities with Solidity ABI encoding, +it incorporates several optimizations and features +to enhance efficient data access and handle nested structures more effectively. + +The Codec leverages a header/body encoding mode: + +- **Header**: Contains all static information. +- **Body**: Contains all dynamic information. + +Key Features: + +- **No-std Compatible**: Operates in environments without the standard library. +- **Configurable Byte Order and Alignment**: Allows customization according to requirements. +- **Solidity ABI Compatibility Mode**: Seamlessly integrates with Solidity ABI. +- **Random Access**: Accesses first-level information without requiring full decoding. +- **Support for Nested Structures**: Encodes nested structures recursively. +- **Derive Macro Support**: Facilitates custom type encoding/decoding via derive macros. + +## Encoding Modes + +The library supports two primary encoding modes: + +- **SolidityABI**: Applied for external cross-contract calls to handle input parameters and decode outputs effectively. +- **FluentABI**: Utilized for internal cross-system calls, benefiting from 4-byte stack alignment for efficiency without compromising the developer experience. + +### SolidityABI Mode + +Parameters: + +- Big-endian byte order +- 32-byte alignment (Solidity compatible) +- Dynamic structure encoding: + - Header + - offset (u256) - a position in the structure + - Body + - length (u256) - a number of elements + - recursively encoded elements + +Usage example: + +```rust +use fluentbase_codec::SolidityABI; +SolidityABI::encode(&value, &mut buf, 0) +``` + +### FluentABI Mode + +Parameters: + +- Little-endian byte order +- 4-byte alignment +- Dynamic structure encoding: + - Header + - length (u32) - a total number of elements in the dynamic data + - offset (u32) - a position in the buffer + - size (u32) - a total number of encoded elements bytes + - Body + - recursively encoded elements + +Usage example: + +```rust +use fluentbase_codec::FluentABI; +FluentABI::encode(&value, &mut buf, 0) +``` + +## Type System + +### Primitive Types + +Primitive types are encoded directly without any additional metadata, +offering zero-cost encoding when their alignment matches the stack size. + +TODO: add all types + +- Integer types: `u8`, `i8`, `u16`, `i16`, `u32`, `i32`, `u64`, `i64` +- Static arrays: `[T; N]` + +### Non-Primitive Types + +These types require additional metadata for encoding: + +- `Vec`: Dynamic array of encodable elements +- `HashMap`: Hash map with encodable keys and values +- `HashSet`: Hash set with encodable elements + +For dynamic types, the codec stores metadata that enables partial reading. For example: + +- Vectors store offset and length information +- HashMaps store separate metadata for keys and values, allowing independent access + +## Important Notes + +### Determinism + +The encoded binary is not deterministic and should only be used for parameter passing. +The encoding order of non-primitive fields affects the data layout after the header, +though decoding will produce the same result regardless of encoding order. + +### Order Sensitivity + +The order of encoding operations is significant, especially for non-primitive types, +as it affects the final binary layout. +For non-ordered set/map data structures, ordering by key is applied. + +## Usage Examples + +### Basic Structure + +```rust +use fluentbase_codec::{Codec, FluentABI}; +use bytes::BytesMut; + +#[derive(Codec)] +struct Point { + x: u32, + y: u32, +} + +// Encoding +let point = Point { x: 10, y: 20 }; +let mut buf = BytesMut::new(); +FluentABI::encode(&point, &mut buf, 0).unwrap(); + +// Decoding +let decoded: Point = FluentABI::decode(&buf, 0).unwrap(); +``` + +### Dynamic Array Example + +```rust +// Vector encoding with metadata +let numbers = vec![1, 2, 3]; + +// FluentABI encoding (with full metadata) +let mut fluent_buf = BytesMut::new(); +FluentABI::encode(&numbers, &mut fluent_buf, 0).unwrap(); +// Format: [length:3][offset:12][size:12][1][2][3] + +// SolidityABI encoding +let mut solidity_buf = BytesMut::new(); +SolidityABI::encode(&numbers, &mut solidity_buf, 0).unwrap(); +// Format: [offset:32][length:3][1][2][3] +``` diff --git a/docs/knowledge-base/architecture/account-trie.md b/docs/knowledge-base/architecture/account-trie.md new file mode 100644 index 0000000..40101b9 --- /dev/null +++ b/docs/knowledge-base/architecture/account-trie.md @@ -0,0 +1,41 @@ +--- +title: Account Trie +sidebar_position: 4 +--- +Account Trie +--- + +The account structure in rWASM is designed to be as simple as possible, containing only the most essential fields. +It's fully compatible with an original Ethereum account structure. + +```rust +pub struct Account { + pub address: Address, + pub balance: U256, + pub nonce: u64, + pub code_hash: B256, + pub code_size: u64, +} +``` + +Fields description: + +- **`address`**: This transient field holds the account address. Currently, a 20-byte address is used to ensure compatibility with the EVM account structure. However, there is a possibility of extending this to 32 bytes in the future to align with the state trie account path, thereby enhancing interoperability. +- **`balance`**: Represents the account balance as a 256-bit element. This is consistently expressed as a 256-bit Big Endian value, although future changes may be considered. +- **`nonce`**: Indicates the number of transactions initiated by this account. It increments with each transaction, call, or contract creation, regardless of the operation's success. +- **`code_hash`**: A Poseidon hash representing the translated bytecode in rWASM format. +- **`code_size`**: Denotes the size of the compiled bytecode in rWASM IR binary format. This bytecode has successfully passed all static validations and is optimized for ZK proofs. + +## State Trie + +Fluent operates with state tries through a pure functional approach, +where every smart contract and root-STF can be represented as a function. +In this model, the input provides a list of dependencies, +and the output yields an execution result along with a number of logs. + +However, this isn't entirely feasible due to cold storage reads and external storage dependencies, +such as CODEHASH-like EVM opcodes. +To address this, Fluent employs an interruption system to "request" missing information from the root-STF. +This is particularly useful for operations involving cold storage or invalidated warm storage. + +The same concept is also used to handle nested calls without incurring additional simulation overhead. diff --git a/docs/knowledge-base/architecture/address-format.md b/docs/knowledge-base/architecture/address-format.md new file mode 100644 index 0000000..bd267b3 --- /dev/null +++ b/docs/knowledge-base/architecture/address-format.md @@ -0,0 +1,58 @@ +--- +title: Address Format +sidebar_position: 5 +--- +Address Format +--- + +Address format is used to compute paths inside the tree, +making interoperability between different EEs almost impossible without additional pre-compiled contracts and/or adapters. + +| Chain | Address Format | Curve | Size | +|-------|------------------------------------------|-----------|----------| +| EVM | `keccak256(uncompressed(G^x)[1:])[12..]` | secp256k1 | 160 bits | +| SVM | `G^SHA512(x)[..32]` | ed25519 | 256 bits | +| FVM | `SHA256(uncompressed(G^x))` | secp256k1 | 256 bits | + +*Table 1. Different blockchains use different address schemes and elliptic curves.* + +Mapping addresses is not a viable solution, +as there is no straightforward way to prove the mapping due to different curves and Solana's use of hashed private keys. +This would introduce additional challenges and might require developing our versions of Ethereum and Solana wallets, +which is unlikely. + +Our account/state system leverages a Sparse Merkle Binary Trie (SMBT) powered by the Poseidon hashing function. +This implementation utilizes 254-bit elliptic curve points +to compute paths within the trie by hashing addresses with Poseidon. + +Let’s examine how trie keys are calculated for Ethereum and Solana blockchains: + +- For an Ethereum address, it pads to 20 bytes with zeros to achieve a 32-byte size, then splits into two elements to calculate the binary path. +- For a Solana address, it calculates the path using a 32-byte address, which is longer than the Ethereum’s 20-byte address. + +The current function cannot handle Ethereum and Solana addresses simultaneously +because they occupy different trie spaces due to Ethereum's 20-byte padding. +This issue also affects Fuel address formats and other blockchain systems, such as Polkadot, +which employs the Ristretto curve. +Consequently, +native interoperability across these platforms is not feasible +without altering blockchain address formats and cryptographic methods. + +## Solution + +### Fully Isolated EE + +For **Fully Isolated Execution Environments (EE)**, address projection (also known as account emulation) is employed. +In this model, +an account is stored within a special EE smart contract (or executor) responsible for managing all balance operations. +This setup ensures that all balances of the isolated EE coexist in the same account space +and can interact with external EEs only through specific system calls. + +### Partially Compatible EE + +For **Partially Compatible Execution Environments (EE)**, +the same address format and derivation standards as used by Ethereum must be followed. +The address derivation is as follows: + +- **`CREATE` (contract deployment)**: `h(address || nonce)` +- **`CREATE2`**: `h(deployer, salt, init_code_hash)` diff --git a/docs/knowledge-base/architecture/blended-vm/README.md b/docs/knowledge-base/architecture/blended-vm/README.md new file mode 100644 index 0000000..624445b --- /dev/null +++ b/docs/knowledge-base/architecture/blended-vm/README.md @@ -0,0 +1,10 @@ +--- +title: Blended VM +--- +Blended VM +--- + +Blended VM implements Blended Execution concepts inside Fluent. +It works on the top of rWasm VM, the runtime system bindings and interruption system. +rWasm VM represents all state transitions within the VM, including Wasm instructions. +The interruption system efficiently manages interruptions during system calls or cross-contract calls. diff --git a/docs/knowledge-base/architecture/blended-vm/_category_.json b/docs/knowledge-base/architecture/blended-vm/_category_.json new file mode 100644 index 0000000..f8e5e17 --- /dev/null +++ b/docs/knowledge-base/architecture/blended-vm/_category_.json @@ -0,0 +1,5 @@ +{ + "label": "Blended VM", + "position": 2, + "collapsed": true + } \ No newline at end of file diff --git a/docs/knowledge-base/architecture/blended-vm/evm.md b/docs/knowledge-base/architecture/blended-vm/evm.md new file mode 100644 index 0000000..693fd24 --- /dev/null +++ b/docs/knowledge-base/architecture/blended-vm/evm.md @@ -0,0 +1,24 @@ +--- +title: EVM +sidebar_position: 2 +--- +EVM +--- + +Fluent integrates with the EVM by leveraging special EVM precompiled contracts. +These contracts facilitate the execution of EVM bytecode, +enabling the deployment and operation of smart contracts designed for the EVM ecosystem. +This allows developers to seamlessly deploy their applications built for EVM platforms using languages like Solidity or +Viper. + +The EVM executor, a Rust-based smart contract, provides two key functions: + +1. **`deploy`**: Deploys the EVM application and stores the bytecode state. +2. **`main`**: Executes the already deployed EVM application. + +During deployment, a specialized rWasm proxy is deployed under the smart contract address. +This proxy redirects all deployment and execution calls to the EVM executor. + +The deployment process is identical to that of Ethereum and other Ethereum-compatible platforms. +Additionally, there are no differences in calling conventions or contract interactions. +This consistency ensures a smooth app migration process for developers. diff --git a/docs/knowledge-base/architecture/blended-vm/precompiled-contracts.md b/docs/knowledge-base/architecture/blended-vm/precompiled-contracts.md new file mode 100644 index 0000000..45487e8 --- /dev/null +++ b/docs/knowledge-base/architecture/blended-vm/precompiled-contracts.md @@ -0,0 +1,56 @@ +--- +title: Precompiled Contracts +sidebar_position: 6 +--- +Native Precompiled Contracts +--- + +Fluent allows extending any contract with additional functionality through precompiled WASM modules. +For example, by implementing a multicall precompiled contract, +any contract can process batched transactions when called with the multicall selector +(`0xac9650d8`). +This system-wide extension mechanism doesn't require modifying the original contracts. + +## Architecture + +The implementation is based on function selector matching during bytecode execution. +When the BlendedRuntime executes bytecode, +it checks the first four bytes of the input data (function selector) against known precompiled contract selectors. +If there's a match, execution is redirected to the corresponding precompiled contract. + +### Precompile Address + +Each precompiled contract has a deterministic address generated from: `keccak256("precompile")[..16] + function_selector[..4]` + +## Available Precompiles + +### Multicall + +Multicall enables batching multiple calls into a single transaction for any contract in the system. +The implementation is compatible with OpenZeppelin's [Multicall](https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/utils/Multicall.sol). + +The key feature is +that multicall works with any contract address—the system automatically detects the multicall selector +and routes the call through the precompiled contract while preserving the original contract's context. + +#### Interface + +```rust +#[function_id("multicall(bytes[])")] // 0xac9650d8 +pub fn multicall(&mut self, data: Vec) -> Vec {} +``` + +Parameters: + +- `data`: Array of encoded function calls to be executed +- `results`: Array of return data from each call + +#### How It Works + +When a call with the Multicall selector (0xac9650d8) is made to any contract: + +1. System detects the selector in the first four bytes of input data +2. Redirects execution to the Multicall precompile +3. Uses delegate_call for each batched call to preserve the original contract's context +4. Reverts the entire transaction if any call fails +5. Returns results from all calls on success diff --git a/docs/knowledge-base/architecture/blended-vm/rwasm.md b/docs/knowledge-base/architecture/blended-vm/rwasm.md new file mode 100644 index 0000000..398f27d --- /dev/null +++ b/docs/knowledge-base/architecture/blended-vm/rwasm.md @@ -0,0 +1,173 @@ +--- +title: rWASM +sidebar_position: 1 +--- +rWASM +--- + +rWasm (reduced WebAssembly) is an EIP-3540 compatible binary IR of Wasm. It is designed to simplify the execution +process of Wasm binaries while maintaining 99% compatibility with original Wasm features. + +rWasm is a specially modified binary IR of Wasm execution. It retains 99% compatibility with the original Wasm bytecode +and instruction set but features a modified binary structure that avoids the pitfalls of non-zk friendly elements, +without altering opcode behavior. + +The main issue with Wasm is its use of relative offsets for type mappings, function mappings, and block/loop statements, +which complicates the proving process. rWasm addresses this by adopting a more flattened binary structure without +relative offsets and eliminating the need for a type mapping validator, allowing for straightforward execution. + +The flattened structure of rWasm simplifies the process of proving the correctness of each opcode execution and places +several verification steps in the hands of the developer. This modification makes rWasm a more efficient and zk-friendly +option for integrating Web2 developers into the Web3 ecosystem. + +## Technology + +Key Differences between rWasm and Wasm: + +- **Deterministic Function Order**: Functions are ordered based on their position in the codebase. +- **Block/Loop Replacement**: Blocks and loops are replaced with Br-family instructions. +- **Redesigned Break Instructions**: Break instructions now support program counter (PC) offsets instead of depth-level. +- **Simplified Binary Verification**: Most sections are removed to streamline binary verification. +- **Unified Memory Segment Section**: Implements all Wasm memory standards in one place. +- **Removed Global Variables Section**: A global variables section is eliminated. +- **Eliminated Type Mapping**: Type mapping is no longer necessary as the code is fully validated. +- **Special Entrypoint Function**: A unique entry point function encompasses all segments. + +The new binary representation ensures a fully equivalently compatible Wasm runtime module from the binary. +Some features are no longer supported by the rWasm runtime: module imports; global variables; memory imports; +global variables export. +These features are unnecessary as Fluent does not utilize them. + +## Structure + +The rWasm binary format supports the following sections: + +- **Bytecode Section**: Replaces the function/code/entrypoint sections. +- **Memory Section**: Replaces memory/data sections for all active/passive/declare section types. + +The following sections, currently implemented, are scheduled for removal: + +- **Function Section**: This section determines the size of each function and is used to properly allocate functions in + memory. Once the `CallInternal` opcode is eliminated, this section can be dropped as well. +- **Element Section**: This section defines allocations for tables used in indirect calls. The `CallIndirect` + instruction is being phased out, and once this process is complete, the section will also be removed. + +### Bytecode Section + +This section consolidates Wasm's original function, code, and start sections. It contains all instructions for the +entire binary without any additional separators for functions. Functions are recovered from the bytecode by reading the +function section, which contains function lengths. The entrypoint function is injected at the end, which is used to +initialize all segments according to Wasm constraints. + +> Note: The function section is planned to be removed and entrypoint stored at offset 0. To achieve this, eliminating +> stack calls must be achieved while implementing indirect breaks. Although Fluent has an implementation for this, it is +> not yet satisfactory, and a migration is planned to a register-based IR before finalizing it. + +### Memory & Data Section + +In Wasm, memory and data sections are handled separately. In rWasm, the Memory section defines memory bounds (lower and +upper limits), and data sections, which can be either active or passive, and specify data to be mapped inside memory. +Unlike Wasm, rWasm eliminates the separate memory section, modifies the corresponding instruction logic, and merges all +data sections. + +Here's an example of a WAT file that initializes memory with minimum and maximum memory bounds (default allocated memory +is one page, and the maximum possible allocated pages are two): + +```wat +(module + (memory 1 2) +) +``` + +To support this, the `memory.grow` instruction is injected into the entrypoint to initialize the default memory. +A special preamble is also added to all `memory.grow` instructions to perform upper bound checks. + +Here is an example of the resulting entrypoint injection: + +```wat +(module + (func $__entrypoint + i32.const $_init_pages + memory.init + drop) +) +``` + +According to Wasm standards, a memory overflow causes `u32::MAX` to be placed on the stack. +For upper-bound checks, the `memory.size` opcode can be used. Here is an example of such an injection: + +```wat +(module + (func $_func_uses_memory_grow + (block + local.get 1 + memory.size + i32.add + i32.const $_max_pages + i32.gts + drop + i32.const 4294967295 + br 0 + memory.grow) + ) +) +``` + +These injections fully comply with Wasm standards, allowing Fluent to support official Wasm memory constraint checks for +the memory section. + +For the data section, the process is more complex because Fluent needs to support three different data section types: + +- **Active**: Has a pre-defined compile-time offset. +- **Passive**: Can be initialized dynamically at runtime. + +To address this, all sections are merged. If the memory is active, it is initialized inside the entrypoint with +re-mapped offsets. Otherwise, the offset is remembered in a special mapping to adjust passive segments when the user +calls `memory.init` manually. + +Here is an example of an entrypoint injection for an active data segment: + +```wat +(module + (func $__entrypoint + i32.const $_relative_offset + i64.const $_data_offset + i64.const $_data_length // or u64::MAX in case of overflow + memory.init 0 + data.drop $segment_index+1 + ) +) +``` + +The data segment must be dropped finally. According to Wasm standards, once the segment is initialized, it must be +entirely removed from memory. To simulate this behavior, Fluent uses zero segments as a default and stores special data +segment flags to know which segments are still active. + +For passive data segments, the logic is similar, but data segment offsets must be recalculated on the fly. + +```wat +(module + (func $_func_uses_memory_init + // adjust length + (block + local.get 1 + local.get 3 + i32.add + i32.const $_data_len + i32.gts + br_if_eqz 0 + i32.const 4294967295 // an error + local.set 1 + ) + // adjust offset + i32.const $_data_offset + local.get 3 + i32.add + local.set 2 + // do init + memory.init $_segment_index+1 + ) +) +``` + +*The provided injections are examples and may vary based on specific requirements.* diff --git a/docs/knowledge-base/architecture/blended-vm/solana.md b/docs/knowledge-base/architecture/blended-vm/solana.md new file mode 100644 index 0000000..8f5285f --- /dev/null +++ b/docs/knowledge-base/architecture/blended-vm/solana.md @@ -0,0 +1,47 @@ +--- +title: Solana Integration +sidebar_position: 4 +--- +Solana Integration +--- + +Solana natively supports composability with both EVM and Wasm applications. This is made possible because Fluent +addresses Solana applications by mapping them into Fluent's account space. To achieve SVM support, a special rPBF +executor is employed, which defines the execution of Solana binaries and specifies a list of mapped system bindings and +calls. Native support for rPBF bytecode is achieved by mapping each operation into the Fluent EE space. + +## Address Format + +Solana uses a 32-byte address format, while Fluent operates with a 20-byte format. Instead of storing a mapping from the +32-byte to the 20-byte format, Fluent employs a special address convention to convert addresses between formats. A +unique magic prefix is attached to Solana addresses to make them convertible into the same binary representation within +the 20-byte Fluent account trie. + +The first 12 bytes of the address are used to route transfers and calls between SVM and EVM+Wasm accounts. This routing +is necessary to achieve full EE compatibility and perform additional containment checks when required. For example, +while a simple transfer without invoking callee bytecode is not allowed in EVM, it is possible in SVM. Therefore, +differentiating between SVM and EVM accounts is essential. + +## Transaction Type + +Fluent does not support Solana transactions directly; instead, EIP-1559 transactions must be used. During deployment, +Fluent automatically detects Solana applications (EFL+rPBF) and specifies a special proxy that refers to the SVM +executor system's precompiled contract. + +Currently, Fluent does not support an additional transaction type for Solana transactions. However, this feature could +be added in the future if there is enough demand. + +## PDA (Program-Derivable Address) + +Program Derived Addresses (PDA) are a core feature of Solana, allowing for the management of nested contracts with +dedicated storage. Fluent leverages various derivation schemes for Solana programs, ensuring that the migration process +remains seamless for developers. The `CREATE2` derivation scheme is used to replicate the PDA functionality. + +To maintain an identical storage layout, Fluent offers supplementary storage interfaces. These interfaces enable Solana +applications to efficiently manage data chunks without incurring extra overhead. + +## Accounts + +Fluent employs account projection, also known as EE simulation, to integrate Solana accounts into the unified Fluent +account space. This approach ensures that all EVM, Wasm, and SVM accounts are treated uniformly, leveraging the same +rWasm VM. Consequently, this enables seamless interoperability and balance transfers between various account types. diff --git a/docs/knowledge-base/architecture/blended-vm/system-calls.md b/docs/knowledge-base/architecture/blended-vm/system-calls.md new file mode 100644 index 0000000..82a1dac --- /dev/null +++ b/docs/knowledge-base/architecture/blended-vm/system-calls.md @@ -0,0 +1,148 @@ +--- +title: System Calls +sidebar_position: 5 +--- +System Calls +--- + +A collection of system functions provides access to low-level operations, +serving both our VM runtime and our circuit definitions. +Each system function is replaced with a specialized ZK-gadget to speed up the proving process. +These functions can include hashing algorithms, I/O operations, and nested call functions. + +> **WARNING**: The system functions API/ABI are still under development and may change in the future. + +```rust +#[link(wasm_import_module = "fluentbase_v1preview")] +extern "C" { + /// Functions that provide access to crypto elements, right now we support following: + /// - Keccak256 + /// - Poseidon (two modes, message hash and two elements hash) + /// - Ecrecover + pub fn _keccak256(data_offset: *const u8, data_len: u32, output32_offset: *mut u8); + pub fn _poseidon(data_offset: *const u8, data_len: u32, output32_offset: *mut u8); + pub fn _poseidon_hash( + fa32_offset: *const u8, + fb32_offset: *const u8, + fd32_offset: *const u8, + output32_offset: *mut u8, + ); + pub fn _ecrecover( + digest32_offset: *const u8, + sig64_offset: *const u8, + output65_offset: *mut u8, + rec_id: u32, + ); + + /// Basic system methods that are available for every app (shared and sovereign) + pub fn _exit(code: i32) -> !; + pub fn _write(offset: *const u8, length: u32); + pub fn _input_size() -> u32; + pub fn _read(target: *mut u8, offset: u32, length: u32); + pub fn _output_size() -> u32; + pub fn _read_output(target: *mut u8, offset: u32, length: u32); + pub fn _forward_output(offset: u32, len: u32); + pub fn _state() -> u32; + pub fn _read_context(target_ptr: *mut u8, offset: u32, length: u32); + + /// Executes a nested call with specified bytecode poseidon hash. + /// + /// # Parameters + /// - `hash32_ptr`: A pointer to a 254-bit poseidon hash of a contract to be called. + /// - `input_ptr`: A pointer to the input data (const u8). + /// - `input_len`: The length of the input data (u32). + /// - `fuel_ptr`: A mutable pointer to a fuel value (u64), consumed fuel is stored in the same + /// pointer after execution. + /// - `state`: A state value (u32), used internally to maintain function state. + /// + /// Fuel ptr can be set to zero if you want to delegate all remaining gas. + /// In this case sender won't get consumed gas result. + /// + /// # Returns + /// - An `i32` value indicating the result of the execution, + /// negative or zero result stands for terminated execution, + /// but positive code stands for interrupted execution (works only for root execution level) + pub fn _exec( + hash32_ptr: *const u8, + input_ptr: *const u8, + input_len: u32, + fuel_ptr: *mut u64, + state: u32, + ) -> i32; + + /// Resumes the execution of a previously suspended function call. + /// + /// This function is designed to handle the resumption of a function call + /// that was previously paused. + /// It takes several parameters that provide + /// the necessary context and data for resuming the call. + /// + /// # Parameters + /// + /// * `call_id` - A unique identifier for the call that needs to be resumed. + /// * `return_data_ptr` - A pointer to the return data that needs to be passed back to the + /// resuming function. + /// This should point to a byte array. + /// * `return_data_len` - The length of the return data in bytes. + /// * `exit_code` - An integer code that represents the exit status of the resuming function. + /// Typically, this might be 0 for success or an error code for failure. + /// * `fuel_ptr` - A mutable pointer to a 64-bit unsigned integer representing the fuel need to + /// be charged, also it puts a consumed fuel result into the same pointer + pub fn _resume( + call_id: u32, + return_data_ptr: *const u8, + return_data_len: u32, + exit_code: i32, + fuel_ptr: *mut u64, + ) -> i32; + + pub fn _charge_fuel(delta: u64) -> u64; + pub fn _fuel() -> u64; + + /// Journaled ZK Trie methods to work with blockchain state + pub fn _preimage_size(hash32_ptr: *const u8) -> u32; + pub fn _preimage_copy(hash32_ptr: *const u8, preimage_ptr: *mut u8); + + pub fn _debug_log(msg_ptr: *const u8, msg_len: u32); +} +``` + +For each system function, a unique identifier is assigned. +During the rWASM translation, every function call is replaced with a `Call(SysCallIdx)` instruction. +This approach significantly enhances the efficiency and simplicity of the proving process. + +```rust +#[repr(u32)] +#[allow(non_camel_case_types)] +pub enum SysFuncIdx { + #[default] + UNKNOWN = 0x0000, + + // crypto + KECCAK256 = 0x0101, + POSEIDON = 0x0102, + POSEIDON_HASH = 0x0103, + ECRECOVER = 0x0104, + + // SYS host + EXIT = 0x0001, + STATE = 0x0002, + READ = 0x0003, + INPUT_SIZE = 0x0004, + WRITE = 0x0005, + OUTPUT_SIZE = 0x0006, + READ_OUTPUT = 0x0007, + EXEC = 0x0009, + RESUME = 0x000a, + FORWARD_OUTPUT = 0x000b, + CHARGE_FUEL = 0x000c, + FUEL = 0x000d, + READ_CONTEXT = 0x000e, + + // preimage + PREIMAGE_SIZE = 0x070D, + PREIMAGE_COPY = 0x070E, + + DEBUG_LOG = 0x0901, +} +``` diff --git a/docs/knowledge-base/architecture/blended-vm/wasm.md b/docs/knowledge-base/architecture/blended-vm/wasm.md new file mode 100644 index 0000000..8de37ea --- /dev/null +++ b/docs/knowledge-base/architecture/blended-vm/wasm.md @@ -0,0 +1,15 @@ +--- +title: WebAssembly +sidebar_position: 3 +--- +WebAssembly +--- + +Fluent offers near-native support for Wasm, with the primary distinction being that, during deployment, it's compiled +into rWasm. +A Wasm application can use the same system calls as EVM applications without any restrictions. + +During the deployment process, +Fluent enhances the rWasm codebase with additional checks for gas measurement and modifies certain instructions or +segment structures when necessary. +For more details, refer to the [rWasm section](rwasm.md). diff --git a/docs/knowledge-base/architecture/execution-environment/README.md b/docs/knowledge-base/architecture/execution-environment/README.md new file mode 100644 index 0000000..da93ab5 --- /dev/null +++ b/docs/knowledge-base/architecture/execution-environment/README.md @@ -0,0 +1,29 @@ +--- +title: Execution Environment +--- +Execution Environment +--- + +The Fluent EE is designed to be universal, supporting various VMs and EEs. +This universality is achieved through the rWasm VM, which executes and simulates different EEs. +By using rWasm, Fluent translates all applications into a single execution language, +enabling different EEs to share the same state trie. +This shared state trie facilitates seamless interoperability among applications. + +Given that each EE/VM can introduce unique execution standards, various integration challenges may arise. +Let's explore the most significant ones. + +1. **Incompatible Cryptography**: EEs can consume an entire transaction as an input, requiring the use of system bindings to verify signature correctness. Fluent supports pre-compiled contracts for a range of commonly used cryptographic functions (e.g., secp256k1, ed25519, bn254, bls384). Any missing cryptographic functions can be implemented as custom precompiled contracts. + +2. **Different Address Format**: Fluent uses an Ethereum-compatible 20-byte address format. If an address uses a different derivation format or has more bytes than a contract can store, there needs to be a way to handle this. Such addresses can be stored as so-called projected addresses, which are calculated using any hashing function. + +3. **Varying Gas Calculation Policies**: EEs/VMs may use different gas calculation policies compared to Fluent. To address this, Fluent has two distinct gas calculation policies: + + - *Standard Gas Calculation*: Applies to typical operations, assigning a specific gas cost to each rWasm opcode. + - *Manual Gas Calculation*: Available exclusively for genesis precompiled smart contracts on Fluent. + + This approach ensures flexibility and maintains the integrity of operations across different environments. + +4. **Custom Bytecode Storage**: There is a need to store immutable data like custom bytecode or some EE-specific context information. Fluent provides special metadata accounts that can be used to store immutable data, including custom bytecode or other data. + +5. **Variable Storage Size**: Some EEs implement variable storage key/value lengths. For instance, Solana uses 10kB chunks, while Cosmos utilizes variable key/value lengths with certain constraints. Storing these datasets within Ethereum's standard 32-byte storage format may lead to significant performance issues and increased gas consumption. To address this, Fluent offers a metadata API that allows developers to use custom storage solutions for varying data lengths efficiently. diff --git a/docs/knowledge-base/architecture/execution-environment/_category_.json b/docs/knowledge-base/architecture/execution-environment/_category_.json new file mode 100644 index 0000000..188315e --- /dev/null +++ b/docs/knowledge-base/architecture/execution-environment/_category_.json @@ -0,0 +1,5 @@ +{ + "label": "Execution Environment", + "position": 1, + "collapsed": true + } \ No newline at end of file diff --git a/docs/knowledge-base/architecture/execution-environment/account-ownership.md b/docs/knowledge-base/architecture/execution-environment/account-ownership.md new file mode 100644 index 0000000..0072807 --- /dev/null +++ b/docs/knowledge-base/architecture/execution-environment/account-ownership.md @@ -0,0 +1,83 @@ +--- +title: Account Ownership +sidebar_position: 1 +--- +Account Ownership +--- + +Fluent extends the original EVM account structure to support **account ownership**. +Account ownership is a special modification of an [EIP-7702](https://eips.ethereum.org/EIPS/eip-7702) account. Instead of delegating an account to a contract, you assign it an **owner**. + +At first glance the idea looks similar, but it enables managing **metadata storage** directly within the account. +This metadata can store arbitrary data as linear storage and is used by both the EVM and SVM runtimes to keep track of information such as bytecode, code hashes, and other account metadata. + +Ownable accounts begin with a special `0xEF44` prefix and follow the structure below: + +```rust +/// Ownable account bytecode representation +/// +/// Format: +/// `0xEF44` (MAGIC) + `0x00` (VERSION) + 20 bytes of owner address + metadata. +pub struct OwnableAccountBytecode { + /// The owner of this account. + pub owner_address: Address, + /// Account version. + pub version: u8, + /// Extra bytes stored by the runtime. + pub metadata: Bytes, +} +``` + +The concept is simple but unlocks powerful new features for **EVM extensibility**. + +## Account Delegation + +This mechanism is similar to EIP-7702, but with one key difference: +**ownership cannot be revoked** by the runtime, since the metadata structure is strictly bound to runtime logic. + +Once a smart contract is deployed, its ownership is permanently assigned—every contract has an owner. + +The runtime resolution logic is straightforward: + +```rust +pub fn resolve_precompiled_runtime_from_input(input: &[u8]) -> Address { + if input.len() > WASM_MAGIC_BYTES.len() + && input[..WASM_MAGIC_BYTES.len()] == WASM_MAGIC_BYTES + { + PRECOMPILE_WASM_RUNTIME + } else if input.len() > SVM_ELF_MAGIC_BYTES.len() + && input[..SVM_ELF_MAGIC_BYTES.len()] == SVM_ELF_MAGIC_BYTES + { + PRECOMPILE_SVM_RUNTIME + } else if input.len() > ERC20_MAGIC_BYTES.len() + && input[..ERC20_MAGIC_BYTES.len()] == ERC20_MAGIC_BYTES + { + PRECOMPILE_ERC20_RUNTIME + } else { + PRECOMPILE_EVM_RUNTIME + } +} +``` + +Currently, Fluent supports the following runtime formats: + +1. **WASM** — for compiling Wasm into rWasm. +2. **SVM** — rPBF (ELF) binaries for running Solana applications. +3. **ERC20** — a specialized runtime for fast ERC20 token transfers. +4. **EVM** — for running EVM applications. + +## Account Derivation + +Ownable accounts can also **derive new accounts** within the same runtime. +This process is similar to `CREATE2`, but it differs in two key ways: + +* It does **not** use bytecode as input (the runtime is fixed). +* It allows runtimes themselves to spawn new accounts. + +This mechanism resembles **Program Derived Addresses (PDA)** in Solana, where subaccounts can be deterministically created. + +To avoid collisions with the `CREATE2` scheme, Fluent uses a **custom hashing function** for deriving ownable accounts: + +``` +0x44 || account_owner || salt +``` diff --git a/docs/knowledge-base/architecture/execution-environment/composability.md b/docs/knowledge-base/architecture/execution-environment/composability.md new file mode 100644 index 0000000..1a1cccd --- /dev/null +++ b/docs/knowledge-base/architecture/execution-environment/composability.md @@ -0,0 +1,45 @@ +--- +title: Composability +sidebar_position: 2 +--- +Composability +--- + +Blended EEs within Fluent operating as execution proxies. +Since Fluent only supports rWasm bytecode, then every operation inside Fluent must be represented using rWasm ISA. + +![Blended Composability](../../../../static/img/kb/blended-composability.png) + +There are two main options for this approach: + +1. **Translation**: A translation from one binary format into rWasm. This concept is used for Wasm application deployment where runtime is a Wasm → rWasm compiler. + +2. **Runtime**: An precompiled execution runtime developed using Wasm and compiled into machine code. This concept is used by EVM, SVM, ERC20 runtimes. + +For example, Fluent presently incorporates the EVM/SVM using the account ownership method (aka runtime proxy). +A proxy with a delegate call forwards execution to a unique EVM/SVM loader smart contract. +This setup eliminates the need for address mapping or transaction verification. +ABI encoding/decoding format can be used, and contracts can be managed using default EVM/SVM-compatible data structures, +such as storage, block/transaction structures. + +To achieve native composability on Fluent, an EE must coexist within the same trie space as the default EVM+Wasm EEs. +It should adhere to established EVM standards, including address formatting and derivation strategies +(for example, CREATE/CREATE2 for smart contract deployment). +The EE must not execute arbitrary account or state modifications +and can only manage basic Ethereum-compatible accounts. + +As a result, apps built with the proxy model can natively interoperate with other native-compatible EEs. +Since they share the same address space, isolation isn't required. +Consequently, Wasm apps can directly interact with EVM apps and vice versa. + +## State Access + +Fluent operates with state tries through a pure functional approach, +where every smart contract and root-STF can be represented as a function. +In this model, the input provides a list of dependencies, +and the output yields an execution result along with a number of logs. + +However, this isn't entirely feasible due to cold storage reads and external storage dependencies, +such as CODEHASH-like EVM opcodes. +To address this, Fluent employs an interruption system to "request" missing information from the root-STF. +This is particularly useful for operations involving cold storage or invalidated warm storage. diff --git a/docs/knowledge-base/architecture/execution-environment/interruption-system.md b/docs/knowledge-base/architecture/execution-environment/interruption-system.md new file mode 100644 index 0000000..51ad0d7 --- /dev/null +++ b/docs/knowledge-base/architecture/execution-environment/interruption-system.md @@ -0,0 +1,181 @@ +--- +title: Interruption System +sidebar_position: 3 +--- +Interruption System +--- + +Fluent interoperability relies heavily on its interruption system. +Smart contracts on Fluent are limited to pure functions, +preventing system calls from accessing external resources such as bytecodes, cold or invalidated storage slots, +or performing nested calls. +Including system calls imposes additional proving overhead, +as proving gadgets must be developed for each call, complicating system development. +This also impacts the flexibility in managing rights or extending contracts, +making the system less sustainable for the fork-less concept. +In such a scenario, system contracts cannot be upgraded without updating the circuits. + +Fluent solves this problem by enabling an interruption system that helps manage context switching between nested apps +and the so-called STF that stands for context management. + +For simplicity, let's assume that STF, smart contracts and EEs are all functions +(since they are essentially state transition functions or a part of STF). +Functions can be categorized as either root or non-root. +A root function is defined as a function where the depth level is equal to 0. +The root function is pivotal because it handles all context switching and cross-contract accesses, +serving as a security layer. + +The root function has the ultimate authority over all state transitions within the blockchain. +Additionally, the root function is in charge of managing and executing system calls. +The root function cannot be interrupted, but it is capable of handling interruptions. + +## System Bindings + +The system bindings manage context switching in a Fluent interruption system. +Functions signatures are provided below. +These functions maintain the entire flow of an interruption system. + +```rust +/// Low-level function that terminates the execution of the program and exits with the specified +/// exit code. +/// +/// This function is typically used to perform an immediate and final exit of a program, +/// bypassing Rust's standard teardown mechanisms. +/// It effectively stops execution and prevents further operations, including cleanup or +/// unwinding. +/// +/// # Parameters +/// - `code` (i32): The non-positive exit code indicating the reason for termination. +/// +/// # Notes +/// - This function is generally invoked in specialized environments, such as WebAssembly +/// runtimes, or through higher-level abstractions. +/// - Consider alternatives in standard applications, such as returning control to the caller or +/// using Rust's standard exit mechanisms, for safer options. +pub fn _exit(code: i32) -> !; + +/// Executes a nested call with specified bytecode poseidon hash. +/// +/// # Parameters +/// - `hash32_ptr`: A pointer to a 254-bit poseidon hash of a contract to be called. +/// - `input_ptr`: A pointer to the input data (const u8). +/// - `input_len`: The length of the input data (u32). +/// - `fuel16_ptr`: A 16 byte array of elements where [fuel_limit/fuel_used, fuel_refunded] +/// - `state`: A state value (u32), used internally to maintain function state. +/// +/// Fuel ptr can be set to zero if you want to delegate all remaining gas. +/// In this case sender won't get the consumed gas result. +/// +/// # Returns +/// - An `i32` value indicating the result of the execution, negative or zero result stands for +/// terminated execution, but positive code stands for interrupted execution (works only for +/// root execution level) +pub fn _exec( + hash32_ptr: *const u8, + input_ptr: *const u8, + input_len: u32, + fuel16_ptr: *mut [i64; 2], + state: u32, +) -> i32; + +/// Resumes the execution of a previously suspended function call. +/// +/// This function is designed to handle the resumption of a function call +/// that was previously paused. +/// It takes several parameters that provide +/// the necessary context and data for resuming the call. +/// +/// # Parameters +/// +/// * `call_id` - A unique identifier for the call that needs to be resumed. +/// * `return_data_ptr` - A pointer to the return data that needs to be passed back to the resuming function. This should point to a byte array. +/// * `return_data_len` - The length of the return data in bytes. +/// * `exit_code` - An integer code that represents the exit status of the resuming function. Typically, this might be 0 for success or an error code for failure. +/// * `fuel_limit` - A fuel used representing the fuel need to be charged, also it puts a consumed fuel result into the same pointer +pub fn _resume( + call_id: u32, + return_data_ptr: *const u8, + return_data_len: u32, + exit_code: i32, + fuel16_ptr: *mut [i64; 2], +) -> i32; +``` + +During execution, once shared resources are requested, it pauses the execution and forwards params into the STF. +Once the interruption is over, it resumes the previous frame. + +Here is the basic flow of an interruption: + +![Interruption Flow](../../../../static/img/kb/interruption-flow.png) + +## Application Exit + +The application exit binding terminates function execution with the specified exit code. The function is designed to +exit from any smart contract or application. It immediately halts the contract execution and forwards all execution +results, including the exit code and return data, to the caller contract. + +**Constraints:** +The exit code must always be a negative 32-bit integer. +Supplying a positive exit code will result in a `NonNegativeExitCode` execution error. +Positive exit codes indicate interrupted execution and are exclusive to the `_exec` or `_resume` functions. + +## Exec & Resume + +During execution, once shared resources are requested, it pauses the execution and forwards params into the STF. + +Interrupted params contain the following items: + +- `hash32_ptr`: A pointer to a 32-byte code hash of a contract to be called (bytecode hash for STF or syscall code + hash). +- `input`: An input parameter for smart contract or input for interruption. +- `fuel_ptr`: A mutable pointer to a fuel value. The consumed and refunded fuel is stored in the same pointer after + execution. +- `state`: A state value (u32), used internally to maintain function state (main or deploy). + +This binding executes a nested call or sends an interruption to the parent execution call though context switching. If +the depth level is greater than 0 (non STF), then an interruption occurs; otherwise, bytecode is executed. + +Once the interruption is resolved, it resumes the execution of a previously suspended function call by specifying return +data, resulting exit code and fuel consumed. + +The resume function operates similarly to exec, +but it requires an interrupted call ID and the interruption result (including return data and exit code). +Interruption events may also occur during the resume process, +requiring an execution loop capable of handling and correctly processing these interruptions. + +## System Calls + +System calls use the same approach as an interruption system. +Since the root-STF function is responsible for all state transitions, including cold/warm storage reads, then a syscall +can be represented as an interruption to the ephemeral smart contract. + +For accessing state data, Fluent uses special ephemeral smart contracts to access information located outside a smart +contract. For example, in case of storage cache invalidation, the contract must request the newest info from the root +call instead of reading invalidated cache. Also, nested calls to other contracts require ACL checks that must be checked +and verified by the root-STF. + +Here is an example of what the system call looks like for Rust contracts. + +```rust +fn syscall_storage_read(native_sdk: &mut SDK, slot: &U256) -> U256 { + // do a call to the root-STF to request some storage slot + let (_, exit_code) = native_sdk.exec( + &SYSCALL_ID_STORAGE_READ, // an unique storage read code hash + slot.as_le_slice(), // a requesting slice with data (aka call-input) + GAS_LIMIT_SYSCALL_STORAGE_READ, // a gas limit for this call (max threshold) + STATE_MAIN, // state of the call (must always be 0, except some special tricky cases) + ); + // make sure returning result is zero (Ok) + assert_eq!(exit_code, 0); + // read output from the return data (storage slot value is always 32 bytes) + let mut output: [u8; 32] = [0u8; 32]; + native_sdk.read_output(&mut output, 0); + // convert return data to the U256 value + U256::from_le_bytes(output) +} +``` + +For example, if smart contract **A** needs to send a message to smart contract **B**, it can trigger a special system +call interruption. +Upon interruption, the STF processes the interruption, performs ACL checks, executes the target application, and then +resumes the previous context with the appropriate exit code and return data. diff --git a/docs/knowledge-base/architecture/genesis.md b/docs/knowledge-base/architecture/genesis.md new file mode 100644 index 0000000..8998e52 --- /dev/null +++ b/docs/knowledge-base/architecture/genesis.md @@ -0,0 +1,81 @@ +--- +title: Genesis +sidebar_position: 6 +--- +Genesis +--- + +The Genesis block, numbered 0, serves as the initial block in the blockchain. It defines fundamental blockchain +parameters, the genesis hash, and stores the initial blockchain state, including system contracts. + +## Fluent Precompiled Contracts + +Fluent provides the following genesis contracts: + +- **EVM**: `0x0000000000000000000000000000000000005210` +- **WASM**: `0x0000000000000000000000000000000000005220` +- **SVM**: `0x0000000000000000000000000000000000005230` + +### EVM + +EVM precompiled contract is responsible for managing EVM deployment and execution. +It embeds EVM virtual machine with ISA. + +The contract defines two methods: + +- `deploy` - for deploying EVM smart contract using EVM constructor (aka init code) +- `main` - for executing already deployed EVM contract + +Keccak256 compatible code hash is stored inside special constant storage slot +calculated using function `keccak256("_evm_bytecode_hash")`. +The EVM bytecode is stored in the special preimage storage that uses CREATE2 for storing custom immutable data. + +- EVM_BYTECODE_HASH_SLOT: `0xfd8a2cf66e0f80fe20ebc0e96c0e08e69c883c792a0409d4f4f92413fb66e980` + +### WASM + +> The contract is disabled for now, WASM support is achieved natively + +### SVM + +> TBD + +## EVM-compatible Precompiled Contracts + +EVM precompiled contracts are fully compatible with the original EVM contracts +and are maintained with the following addresses: + +- **SECP256K1_ECRECOVER** (`0x0000000000000000000000000000000000000001`): Used for recovering the public key from a + given signature. +- **SHA256** (`0x0000000000000000000000000000000000000002`): Computes the SHA-256 hash of the input data. +- **RIPEMD160** (`0x0000000000000000000000000000000000000003`): Computes the RIPEMD-160 hash of the input data. +- **IDENTITY** (`0x0000000000000000000000000000000000000004`): Returns the input as the output without any + modifications. +- **MODEXP** (`0x0000000000000000000000000000000000000005`): Performs modular exponentiation. +- **BN128_ADD** (`0x0000000000000000000000000000000000000006`): Adds two points on the BN128 elliptic curve. +- **BN128_MUL** (`0x0000000000000000000000000000000000000007`): Multiplies a point on the BN128 elliptic curve by a + scalar. +- **BN128_PAIR** (`0x0000000000000000000000000000000000000008`): Performs a pairing check on the BN128 elliptic curve. +- **BLAKE2** (`0x0000000000000000000000000000000000000009`): Computes the BLAKE2 cryptographic hash of the input data. +- **KZG_POINT_EVALUATION** (`0x000000000000000000000000000000000000000a`): Evaluates a KZG commitment at a given point. +- **BLS12_381_G1_ADD** (`0x000000000000000000000000000000000000000b`): Adds two points in the G1 group on the BLS12-381 + elliptic curve. +- **BLS12_381_G1_MUL** (`0x000000000000000000000000000000000000000c`): Multiplies a point in the G1 group on the + BLS12-381 elliptic curve by a scalar. +- **BLS12_381_G1_MSM** (`0x000000000000000000000000000000000000000d`): Performs a multi-scalar multiplication in the G1 + group on the BLS12-381 elliptic curve. +- **BLS12_381_G2_ADD** (`0x000000000000000000000000000000000000000e`): Adds two points in the G2 group on the BLS12-381 + elliptic curve. +- **BLS12_381_G2_MUL** (`0x000000000000000000000000000000000000000f`): Multiplies a point in the G2 group on the + BLS12-381 elliptic curve by a scalar. +- **BLS12_381_G2_MSM** (`0x0000000000000000000000000000000000000010`): Performs a multi-scalar multiplication in the G2 + group on the BLS12-381 elliptic curve. +- **BLS12_381_PAIRING** (`0x0000000000000000000000000000000000000011`): Performs a pairing check on the BLS12-381 + elliptic curve. +- **BLS12_381_MAP_FP_TO_G1** (`0x0000000000000000000000000000000000000012`): Maps an element of the base field to a + point in the G1 group on the BLS12-381 elliptic curve. +- **BLS12_381_MAP_FP2_TO_G2** (`0x0000000000000000000000000000000000000013`): Maps an element of the quadratic extension + field to a point in the G2 group on the BLS12-381 elliptic curve. +- **SECP256R1_VERIFY** (`0x0000000000000000000000000000000000000100`): Verifies an ECDSA signature on the SECP256R1 + elliptic curve. + \ No newline at end of file diff --git a/docs/knowledge-base/introduction/README.md b/docs/knowledge-base/introduction/README.md new file mode 100644 index 0000000..8f0dfa8 --- /dev/null +++ b/docs/knowledge-base/introduction/README.md @@ -0,0 +1,16 @@ +--- +title: Introduction +--- +Introduction +--- + +> **Note:** This document is a work in progress. Its structure is not yet finalized, and significant changes may still +> be made to the content. + +Fluent is the +first [blended execution network](https://mirror.xyz/fluentlabs.eth/8IelEprNblwr1HENCzbp9WFEc7FieEapD5SAiBNUBGA) - an +Ethereum L2 and framework that blends Wasm, EVM and (soon) SVM-based smart contracts into a unified execution +environment. + +Smart contracts from different VM targets can directly call each other on Fluent. Fluent is in public devnet and +currently supports apps composed of Solidity, Vyper, and Rust contracts. diff --git a/docs/knowledge-base/introduction/_category_.json b/docs/knowledge-base/introduction/_category_.json new file mode 100644 index 0000000..f92aebc --- /dev/null +++ b/docs/knowledge-base/introduction/_category_.json @@ -0,0 +1,5 @@ +{ + "label": "Introduction", + "position": 3, + "collapsed": true + } \ No newline at end of file diff --git a/docs/knowledge-base/introduction/blended-execution.md b/docs/knowledge-base/introduction/blended-execution.md new file mode 100644 index 0000000..db2a5b7 --- /dev/null +++ b/docs/knowledge-base/introduction/blended-execution.md @@ -0,0 +1,45 @@ +--- +title: Blended Execution +sidebar_position: 3 +--- +Blended Execution +--- + +Blended Execution \- is an approach that aims to increase the efficiency of executing smart contracts from diverse VMs +by utilizing a unified IR known as rWasm. +rWasm facilitates the expansion of system functionality by leveraging native composability across different execution +environments. +This innovative approach enables seamless execution of smart contracts, optimizing performance and enhancing the overall +capabilities of the system. + +This system allows for the verification of all state transitions within a unified execution environment, +thereby minimizing emulation overhead typically associated with nested execution in various VMs. +By employing rWasm, which retains full compatibility with standard Wasm, +developers can seamlessly deploy and integrate smart contracts across multiple programming languages and execution +environments. +Fluent features native, real-time composability, as the different applications the network supports share the same +execution space. +The use of compilation software allows for efficient integration of various VMs, such as the EVM and SVM, +while maintaining optimal proving infrastructure. + +Ultimately, blended execution serves as a state verification function, streamlining the development process and +broadening the capabilities of builders on Ethereum the Fluent ecosystem without affecting developer experience. + +## BlendedVM vs MultiVM + +MultiVM is an execution layer that provides multiple VMs for running user applications. +It offers developers the opportunity to create new types of applications and combine different programming languages in +a single platform. +However, MultiVM requires developers to manage these VMs within the execution layer. +Most of these VMs use varying ISAs, which impact execution costs and supported functionality. +Developers must carefully handle these parameters to avoid miscalculations or vulnerabilities that could lead to +malicious state trie modifications. + +BlendedVM takes a similar approach to MultiVM, but instead of having multiple VMs, it uses a single VM to represent all +VM operations. +This is achieved by employing compilation and emulation software to translate user applications into native instructions +for BlendedVM. +This approach enhances security by preventing malicious state access outside the single VM, even in the event of a +vulnerability in the AOT compiler. +Furthermore, BlendedVM offers system extensibility, allowing developers to incorporate support for additional VMs or EEs +in a trusted or trustless manner. diff --git a/docs/knowledge-base/introduction/glossary.md b/docs/knowledge-base/introduction/glossary.md new file mode 100644 index 0000000..7dcdc4d --- /dev/null +++ b/docs/knowledge-base/introduction/glossary.md @@ -0,0 +1,29 @@ +--- +title: Glossary +sidebar_position: 1 +--- +Glossary +--- + +**IR** (Intermediary Representation) — An intermediary representation of some bytecode, that is usually used to +represent and optimized and execution-ready application state. + +**ZK** (Zero Knowledge) — A cryptographic method where one party (the prover) can prove to another party (the verifier) +that they know a value without conveying any information apart from the fact that they know the value. + +**STF** (State Transition Function) — A function used to ensure the correctness of a system's state transition. + +**ISA** (Instruction Set Architecture) — The part of the computer architecture related to programming, which includes +the instruction set, word size, memory address modes, processor registers, and address and data formats. + +**AOT** (Ahead Of Time) — A type of compilation that converts high-level code to a lower-level code or machine code +before execution. + +**JIT** (Just In Time) — A type of compilation that converts high-level code to intermediate or machine code at runtime, +typically to enhance performance during execution. + +**EVM** (Ethereum Virtual Machine) — The runtime environment for smart contracts in Ethereum, allowing code to be +executed exactly as intended. + +**DA** (Data Availability) — Refers to the accessibility and correctness of the data required to reconstruct the state +of a blockchain. diff --git a/docs/knowledge-base/introduction/vision.md b/docs/knowledge-base/introduction/vision.md new file mode 100644 index 0000000..df9444d --- /dev/null +++ b/docs/knowledge-base/introduction/vision.md @@ -0,0 +1,87 @@ +--- +title: Our Vision +sidebar_position: 2 +--- +Our Vision +--- + +While developing a zkVM for an EVM-compatible, Wasm based rollup on Ethereum, Fluent explored methods to optimize the +proving process of smart contracts. +A major challenge lies in the fact that using a zkVM to support multiple VMs only allows for the proof of the root STF, +while the remaining nested execution of other VMs requires emulation. + +To address this issue, Fluent proposes a VM capable of performing nested execution without incurring additional +emulation overhead. +This is achieved through a hardware acceleration process similar to the translation of smart contracts, applications, +and precompiled contracts into a specialized low-level intermediary representation (IR) binary structure known as rWasm. +This structure can be proven much more efficient compared to running emulator software. + +With its unique interruption system, rWasm emerged as an innovative solution for handling nested calls and compiling +diverse smart contracts, revolutionizing the landscape of efficient zk-Wasm based applications on Ethereum. + +## Meet Blended Execution + +With blended execution on Fluent, developers can create applications using languages and tools from various VMs yet +coexisting in the same execution space. +This is possible because all smart contracts share the same account space. +As a result, native composability is achieved for anything within Fluent that can be represented as rWasm (which relies +on Wasm and LLVM, making 17+ languages available for development). + +Different VMs can be supported using an AOT translation process (directly into Rwasm) or an emulation process. +Fluent can enable execution environments like the EVM, bringing Solidity and Vyper support. +Similarly, the new language Sway from Fuel can be integrated by running an FVM execution precompile. + +Both users and developers obtain major benefits from blended execution because it enhances the experience of developers +who are ready to expand the Fluent ecosystem by bringing more development languages and execution environments on board. +Additionally, it bridges the gap between Web2 and Web3 users by providing a shared set of tools and new ways to interact +with applications through account abstraction backed by EIP-7702 and modules such as OAuth 2.0 and WebAuthn. + +## Product Vision + +The Fluent Blended Execution Layer will revolutionize the way developers create, deploy, and prove smart contracts by +unifying multiple VMs into a single, highly efficient execution environment. At the heart of this vision is rWasm, a +unique IR language designed to bridge the gap between various VMs and EEs such as the EVM, SVM, and Wasm. By eliminating +the emulation overhead typically associated with nested execution, Fluent enables faster, more secure, and more scalable +smart contract execution. + +Key features: + +1. **Unified Execution Environment**: Support for multiple VMs and EEs through a single execution environment, enabling + native composability between different smart contracts, tools, and languages. +2. **rWasm Integration**: Full compatibility with standard Wasm and support for over 17+ traditional programming + languages, allowing developers to use familiar tools such as Rust, C, Solidity, TinyGo, and AssemblyScript without + sacrificing performance. +3. **Optimized Proving Infrastructure**: Efficient proving through rWasm that drastically reduces overhead and + complexity, providing optimal performance for ZK circuits. +4. **Seamless Expansion**: Advanced JIT/AOT compilers to integrate new VMs and EEs, ensuring extensibility for + future-proofing and scalability. +5. **Security and Extensibility**: BlendedVM unifies the execution space, providing enhanced security and preventing + vulnerabilities that arise from managing multiple VMs while enabling new VMs to be added. + +The Fluent Blended Execution Layer empowers developers to build diverse applications without managing disparate systems, +optimizing their experience and fostering rapid growth in the Ethereum ecosystem. + +## Technical Vision + +Extracting traces is crucial for proving. It involves obtaining snapshots of stack and memory operations to feed into zk +circuits. Aligning the IR language with the trace structure and ensuring its compatibility with zk is essential to +minimize circuit size, ultimately improving proving speed and reducing code complexity. rWasm, as an IR binary language, +combines execution concepts and maps its execution trace to the zkVM circuit structure. This approach aims to achieve +optimal performance, minimizing both proving and execution overhead. + +Blended execution natively supports multiple VMs and EEs within a single execution environment, and within Fluent, is +enabled by employing a single IR known as rWasm, which serves as its primary VM. This IR enables the verification of all +state transitions occurring within the system, encompassing various VMs and EEs. In the case of the Fluent L2, the EVM, +SVM, and Wasm are supported. As a result, developers familiar with any of these primitives can leverage circuits +designed for rWasm and effortlessly obtain the necessary optimal proving infrastructure for their applications. In +essence, blended execution acts as a state verification function responsible for representing every operation within the +Fluent execution layer. + +Given that rWasm serves as the IR language for Fluent, it has the potential to represent not only Wasm or EVM but also +other VMs and EEs. This is facilitated by providing dedicated compilation or emulation software for these platforms or +in some cases utilizing emulation software. + +rWasm is a derivative of the Wasm assembly language that keeps 100% backward compatibility with original Wasm standards. +Leveraging the extensive adoption and support of Wasm, rWasm enables blockchain developers to effortlessly create new +applications in traditional languages like Rust and C. Fluent's advanced AOT compilers handle all IR compilation tasks, +simplifying the development and deployment process of Wasm-based blockchain applications in the Ethereum ecosystem. diff --git a/docs/knowledge-base/rwasm/README.md b/docs/knowledge-base/rwasm/README.md new file mode 100644 index 0000000..95922f2 --- /dev/null +++ b/docs/knowledge-base/rwasm/README.md @@ -0,0 +1,20 @@ +--- +title: rWASM +--- + +rWASM +--- + +rWASM (reduced WebAssembly) is an EIP-3540 compatible binary intermediary representation (IR) of WASM (WebAssembly). +It is designed +to simplify the execution process of WASM binaries while maintaining 99% compatibility with original WASM features. + +## Key Features + +- **ZK-Friendliness**: rWASM achieves Zero-Knowledge (ZK) friendliness by having a more flattened binary structure and a simplified instruction set. +- **Compatibility**: rWASM retains full compatibility with WASM, ensuring that all original WASM features are preserved. + +## Important Notice + +rWASM is a trusted execution runtime and should not be run without proper validation. +It is safe to translate WASM to rWASM and execute, as rWASM injects all necessary validations into the entrypoint. diff --git a/docs/knowledge-base/rwasm/_category_.json b/docs/knowledge-base/rwasm/_category_.json new file mode 100644 index 0000000..0eef572 --- /dev/null +++ b/docs/knowledge-base/rwasm/_category_.json @@ -0,0 +1,5 @@ +{ + "label": "rWASM", + "position": 6, + "collapsed": true + } \ No newline at end of file diff --git a/docs/knowledge-base/rwasm/motivation.md b/docs/knowledge-base/rwasm/motivation.md new file mode 100644 index 0000000..5db3d1d --- /dev/null +++ b/docs/knowledge-base/rwasm/motivation.md @@ -0,0 +1,39 @@ +--- +title: Motivation +sidebar_position: 1 +--- +Motivation +--- + +WebAssembly (WASM) is an interpreted language and binary format favored by many Web2 developers. +Our approach aims to seamlessly integrate these developers into the Web3 world, +despite the challenges this integration presents. +We prefer WASM over RISC-V or other binary formats due to its well-established and widely adopted standard, +which developers appreciate and support. +Moreover, WASM includes a self-described binary format (covering memory structure, type mapping, and more), +unlike RISC-V/AMD/Intel binary formats, +which require binary wrappers like EXE or ELF. + +However, WASM is not without its drawbacks, +particularly its non-ZK friendly structures that complicate the proving process. +This is where rWASM (Reduced WebAssembly) comes into play. + +## Introducing rWASM + +rWASM is a specially modified binary intermediary representation (IR) of WASM execution. +It retains 99% compatibility with the original WASM bytecode and instruction set +but features a modified binary structure that avoids the pitfalls of non-ZK friendly elements, +without altering opcode behavior. + +The main issue with WASM is its use of relative offsets for type mappings, function mappings, and block/loop statements, +which complicates the proving process. +rWASM addresses this by adopting a more flattened binary structure without relative offsets +and eliminating the need for a type mapping validator, +allowing for straightforward execution. + +## Benefits of rWASM + +The flattened structure of rWASM simplifies the process of proving the correctness of each opcode execution +and places several verification steps in the hands of the developer. +This modification makes rWASM a more efficient and ZK-friendly option +for integrating Web2 developers into the Web3 ecosystem. diff --git a/docs/knowledge-base/rwasm/technology.md b/docs/knowledge-base/rwasm/technology.md new file mode 100644 index 0000000..ffb5657 --- /dev/null +++ b/docs/knowledge-base/rwasm/technology.md @@ -0,0 +1,187 @@ +--- +title: Technology +sidebar_position: 2 +--- +Technology +--- + +rWASM is built on WASMi's intermediate representation (IR), +originally developed by [Parity Tech](https://github.com/wasmi-labs/wasmi) and now under Robin Freyler's ownership. +We chose the WASMi virtual machine because its IR is fully consistent with the original WebAssembly (WASM), +ensuring compatibility and stability. +For rWASM, we adhere to the same principles, +making no changes to WASMi's IR and only modifying the binary representation to enhance ZK +(ZK) friendliness. + +### Key Differences: + +1. **Deterministic Function Order**: Functions are ordered based on their position in the codebase. +2. **Block/Loop Replacement**: Blocks and loops are replaced with Br-family instructions. +3. **Redesigned Break Instructions**: Break instructions now support program counter (PC) offsets instead of depth-level. +4. **Simplified Binary Verification**: Most sections are removed to streamline binary verification. +5. **Unified Memory Segment Section**: Implements all WASM memory standards in one place. +6. **Removed Global Variables Section**: Global variables section is eliminated. +7. **Eliminated Type Mapping**: Type mapping is no longer necessary as the code is fully validated. +8. **Special Entrypoint Function**: A unique entry point function encompasses all segments. + +The new binary representation ensures a fully equivalently compatible WASMi runtime module from the binary. +Some features are no longer supported but are not required by the rWASM runtime: + +- Module imports, global variables, and memory imports +- Global variables exports + +## Structure + +The rWASM binary format supports the following sections: + +1. **Bytecode Section**: Replaces the function/code/entrypoint sections. +2. **Memory Section**: Replaces memory/data sections for all active/passive/declare section types. +3. **Function Section**: A temporary solution for the code section, planned for removal. +4. **Element Section**: Replaces the table/elem sections, also planned for removal. + +### Bytecode Section + +This section consolidates WASM's original function, code, and start sections. +It contains all instructions for the entire binary without any additional separators for functions. +Functions are recovered from the bytecode by reading the function section, which contains function lengths. +We inject the entrypoint function at the end, which is used to initialize all segments according to WASM constraints. + +> **Note**: We plan to remove the function section and store the entrypoint at offset 0. To achieve this, we need to eliminate stack calls and implement indirect breaks. Although we have an implementation for this, it is not yet satisfactory, and we plan to migrate to a register-based IR before finalizing it. + +### Memory Section + +In WASM, memory and data sections are handled separately. +In rWASM, the Memory section defines memory bounds (lower and upper limits), and data sections, +which can be either active or passive, specify data to be mapped inside the memory. +Unlike WASM, rWASM eliminates the separate memory section, +modifies the corresponding instruction logic, and merges all data sections. + +Here's an example of a WAT file that initializes memory with minimum and maximum memory bounds +(default allocated memory is one page, and the maximum possible allocated pages are two): + +```wat +(module + (memory 1 2) +) +``` + +To support this, we inject the `memory.grow` instruction into the entrypoint to initialize the default memory. +We also add a special preamble to all `memory.grow` instructions to perform upper bound checks. + +Here is an example of the resulting entrypoint injection: + +```wat +(module + (func $__entrypoint + i32.const $_init_pages + memory.init + drop) +) +``` + +According to WASM standards, a memory overflow causes `u32::MAX` to be placed on the stack. +For upper-bound checks, we can use the `memory.size` opcode. +Here is an example of such an injection: + +```wat +(module + (func $_func_uses_memory_grow + (block + local.get 1 + memory.size + i32.add + i32.const $_max_pages + i32.gts + drop + i32.const 4294967295 + br 0 + memory.grow) + ) +) +``` + +These injections fully comply with WASM standards, +allowing us to support official WASM memory constraint checks for the memory section. + +For the data section, the process is more complex because we need to support three different data section types: + +- **Active**: Has a pre-defined compile-time offset. +- **Passive**: Can be initialized dynamically at runtime. + +To address this, we merge all sections. +If the memory is active, we initialize it inside the entrypoint with re-mapped offsets. +Otherwise, +we remember the offset in a special mapping to adjust passive segments when the user calls `memory.init` manually. + +Here is an example of an entrypoint injection for an active data segment: + +```wat +(module + (func $__entrypoint + i32.const $_relative_offset + i64.const $_data_offset + i64.const $_data_length // or u64::MAX in case of overflow + memory.init 0 + data.drop $segment_index+1 + ) +) +``` + +We need to drop the data segment finally. +According to WASM standards, once the segment is initialized, it must be entirely removed from memory. +To simulate this behavior, +we use zero segments as a default and store special data segment flags to know which segments are still active. + +For passive data segments, the logic is similar, but we must recalculate data segment offsets on the fly. + +```wat +(module + (func $_func_uses_memory_init + // adjust length + (block + local.get 1 + local.get 3 + i32.add + i32.const $_data_len + i32.gts + br_if_eqz 0 + i32.const 4294967295 // an error + local.set 1 + ) + // adjust offset + i32.const $_data_offset + local.get 3 + i32.add + local.set 2 + // do init + memory.init $_segment_index+1 + ) +) +``` + +The provided injections are examples and may vary based on specific requirements. + +### Function Sections (Temporary) + +The function section is a temporary measure used to store information about function lengths. +This section will be removed once we move the entrypoint function to the beginning of the module. + +Currently, removing functions requires significant refactoring and modifications to our codebase, including: + +1. Replacing all functions with breaks (e.g., `br` instructions). +2. Removing stack calls and using indirect breaks or tables. + +We plan to migrate to a register-based VM in the future. + +### Element Section (Temporary) + +The element section uses the same translation logic as the memory/data sections +but operates with tables and elements instead of memory and data. + +This section is also temporary and will eventually be replaced with memory operations. +Doing so can reduce the number of read/write operations and the size of our circuits. +The main challenge is managing memory securely to avoid mixing system and user memory spaces. +We aim to support original WASM binaries, regardless of how they are compiled, +without resorting to a custom WASM compilation target. + +This approach is still under research. diff --git a/static/img/kb/blended-composability.png b/static/img/kb/blended-composability.png new file mode 100644 index 0000000..4223af5 Binary files /dev/null and b/static/img/kb/blended-composability.png differ diff --git a/static/img/kb/blended-ee.png b/static/img/kb/blended-ee.png new file mode 100644 index 0000000..ecc5f59 Binary files /dev/null and b/static/img/kb/blended-ee.png differ diff --git a/static/img/kb/evm-flow.svg b/static/img/kb/evm-flow.svg new file mode 100644 index 0000000..147c6da --- /dev/null +++ b/static/img/kb/evm-flow.svg @@ -0,0 +1 @@ +title%20EVM%20deployment%2Fcall%20flow%0A%0Aactivate%20User%0AUser-%3EUser%3A%20compile%20solidity%5Cnapplication%20and%20sign%5Cntransaction%0AUser-%3EFluent%3A%20send%20signed%5Cntransaction%0Aactivate%20Fluent%0AFluent-%3EFluent%3A%20save%20proxy%20into%20the%5Cndeployed%20account%0AFluent-%3EProxy%3A%20call%20%60deploy%60%20stage%0Aactivate%20Proxy%0AProxy-%3EEVM%3A%20delegate%20call%20into%5Cnthe%20EVM%20executor%0AEVM-%3EEVM%3A%20execute%20EVM%20bytecode%20and%5Cnstore%20result%20in%20the%20state%0AEVM--%3EProxy%3A%20return%20deployment%20result%0AProxy--%3EFluent%3A%20forward%20deployment%20result%0Adeactivate%20Proxy%0Adeactivate%20Fluent%0AFluent--%3EUser%3A%20return%20deployment%20result%0A%0AUser-%3EFluent%3A%20call%20just%20deployed%20contract%0Aactivate%20Fluent%0AFluent-%3EProxy%3A%20call%20%60main%60%20stage%0Aactivate%20Proxy%0AProxy-%3EEVM%3A%20delegate%20call%20into%5Cnthe%20EVM%20executor%0AEVM-%3EEVM%3A%20execute%20EVM%20bytecode%20and%5Cnstore%20result%20in%20the%20state%0AEVM--%3EProxy%3A%20return%20deployment%20result%0AProxy--%3EFluent%3A%20forward%20deployment%20result%0Adeactivate%20Proxy%0AFluent--%3EUser%3A%20return%20deployment%20result%0Adeactivate%20Fluent%0Adeactivate%20UserUserFluentProxyEVMEVM deployment/call flowcompile solidityapplication and signtransactionsend signedtransactionsave proxy into thedeployed accountcall `deploy` stagedelegate call intothe EVM executorexecute EVM bytecode andstore result in the statereturn deployment resultforward deployment resultreturn deployment resultcall just deployed contractcall `main` stagedelegate call intothe EVM executorexecute EVM bytecode andstore result in the statereturn deployment resultforward deployment resultreturn deployment result \ No newline at end of file diff --git a/static/img/kb/exec-flow.png b/static/img/kb/exec-flow.png new file mode 100644 index 0000000..dab3306 Binary files /dev/null and b/static/img/kb/exec-flow.png differ diff --git a/static/img/kb/exit-flow.png b/static/img/kb/exit-flow.png new file mode 100644 index 0000000..d20a30c Binary files /dev/null and b/static/img/kb/exit-flow.png differ diff --git a/static/img/kb/fluent-arch.png b/static/img/kb/fluent-arch.png new file mode 100644 index 0000000..955102e Binary files /dev/null and b/static/img/kb/fluent-arch.png differ diff --git a/static/img/kb/fluent-arch.svg b/static/img/kb/fluent-arch.svg new file mode 100644 index 0000000..b3c52c4 --- /dev/null +++ b/static/img/kb/fluent-arch.svg @@ -0,0 +1,6 @@ +
 Fluentbase
Core Contracts
SVM
WASM
EVM
Runtime
SDK
Revm
Reth
(Fluent L2)
Fluent STF
rWASM (blended VM)
\ No newline at end of file diff --git a/static/img/kb/interruption-flow.png b/static/img/kb/interruption-flow.png new file mode 100644 index 0000000..25ff762 Binary files /dev/null and b/static/img/kb/interruption-flow.png differ diff --git a/static/img/kb/isolated-ee.svg b/static/img/kb/isolated-ee.svg new file mode 100644 index 0000000..f7967db --- /dev/null +++ b/static/img/kb/isolated-ee.svg @@ -0,0 +1,6 @@ +
 Fluent L2
EVM Runtime
(native)
proxy call
EVM Contract
EE Runtime
(simulated)
EE Contract
bytecode storage
 RPC Relayer
FuelRPC Proxy
proxy call
SolanaRPC Proxy
... Proxy
wallet call
\ No newline at end of file diff --git a/static/img/kb/storage-flow.png b/static/img/kb/storage-flow.png new file mode 100644 index 0000000..a373a54 Binary files /dev/null and b/static/img/kb/storage-flow.png differ