From 3c11dedfd7f129e90eb3e27d3cd937127afd85cf Mon Sep 17 00:00:00 2001 From: rakita Date: Fri, 14 Feb 2025 20:46:06 +0100 Subject: [PATCH] feat: book structure (#2082) * book: wip * wip book * structure of the book * ci book, note about wip book * git ignore * rm generated book * fix book links * ignore incomplete codes * Change perm for readme.md * fix * test * test * chmod 777 * 777 folder * 777 folder * change mod of root folder * move file for mdbook test * base link * base link --- .github/workflows/book.yml | 13 +- .gitignore | 6 +- README.md | 170 +++++------------ book.toml | 6 +- book/src/SUMMARY.md | 13 ++ book/src/architecture.md | 55 ++++++ book/src/architecture/crates.md | 39 ++++ book/src/architecture/dependencies.md | 18 ++ book/src/architecture/overview.md | 24 +++ book/src/awesome.md | 38 ++++ book/src/contact.md | 17 ++ book/src/dev.md | 69 +++++++ book/src/examples.md | 10 + book/src/framework.md | 16 ++ book/src/release_procedure.md | 5 + .../src/crates/revm => book/src}/state.md | 0 book/src/testing.md | 11 ++ documentation/src/SUMMARY.md | 36 ---- documentation/src/bins/revm-test.md | 1 - documentation/src/bins/revme.md | 1 - documentation/src/crates/interpreter.md | 27 --- documentation/src/crates/interpreter/gas.md | 29 --- documentation/src/crates/interpreter/host.md | 24 --- .../crates/interpreter/instruction_result.md | 19 -- .../src/crates/interpreter/instructions.md | 15 -- .../crates/interpreter/interpreter_action.md | 39 ---- .../src/crates/interpreter/memory.md | 35 ---- documentation/src/crates/precompile.md | 47 ----- documentation/src/crates/precompile/blake2.md | 47 ----- documentation/src/crates/precompile/bn128.md | 13 -- documentation/src/crates/precompile/hash.md | 7 - .../src/crates/precompile/identity.md | 7 - documentation/src/crates/precompile/modexp.md | 9 - .../src/crates/precompile/point_evaluation.md | 5 - .../src/crates/precompile/secp256k1.md | 9 - documentation/src/crates/primitives.md | 40 ---- documentation/src/crates/primitives/bits.md | 17 -- .../src/crates/primitives/bytecode.md | 9 - .../src/crates/primitives/constants.md | 7 - .../src/crates/primitives/database.md | 12 -- .../src/crates/primitives/environment.md | 5 - documentation/src/crates/primitives/kzg.md | 12 -- documentation/src/crates/primitives/log.md | 11 -- .../src/crates/primitives/precompile.md | 9 - documentation/src/crates/primitives/result.md | 11 -- .../src/crates/primitives/specifications.md | 15 -- documentation/src/crates/primitives/state.md | 15 -- documentation/src/crates/primitives/utils.md | 7 - documentation/src/crates/revm.md | 39 ---- documentation/src/crates/revm/builder.md | 171 ------------------ documentation/src/crates/revm/evm.md | 56 ------ documentation/src/crates/revm/handler.md | 120 ------------ documentation/src/crates/revm/inspector.md | 37 ---- .../src/crates/revm/journaled_state.md | 147 --------------- documentation/src/introduction.md | 30 --- 55 files changed, 374 insertions(+), 1276 deletions(-) create mode 100644 book/src/SUMMARY.md create mode 100644 book/src/architecture.md create mode 100644 book/src/architecture/crates.md create mode 100644 book/src/architecture/dependencies.md create mode 100644 book/src/architecture/overview.md create mode 100644 book/src/awesome.md create mode 100644 book/src/contact.md create mode 100644 book/src/dev.md create mode 100644 book/src/examples.md create mode 100644 book/src/framework.md create mode 100644 book/src/release_procedure.md rename {documentation/src/crates/revm => book/src}/state.md (100%) create mode 100644 book/src/testing.md delete mode 100644 documentation/src/SUMMARY.md delete mode 100644 documentation/src/bins/revm-test.md delete mode 100644 documentation/src/bins/revme.md delete mode 100644 documentation/src/crates/interpreter.md delete mode 100644 documentation/src/crates/interpreter/gas.md delete mode 100644 documentation/src/crates/interpreter/host.md delete mode 100644 documentation/src/crates/interpreter/instruction_result.md delete mode 100644 documentation/src/crates/interpreter/instructions.md delete mode 100644 documentation/src/crates/interpreter/interpreter_action.md delete mode 100644 documentation/src/crates/interpreter/memory.md delete mode 100644 documentation/src/crates/precompile.md delete mode 100644 documentation/src/crates/precompile/blake2.md delete mode 100644 documentation/src/crates/precompile/bn128.md delete mode 100644 documentation/src/crates/precompile/hash.md delete mode 100644 documentation/src/crates/precompile/identity.md delete mode 100644 documentation/src/crates/precompile/modexp.md delete mode 100644 documentation/src/crates/precompile/point_evaluation.md delete mode 100644 documentation/src/crates/precompile/secp256k1.md delete mode 100644 documentation/src/crates/primitives.md delete mode 100644 documentation/src/crates/primitives/bits.md delete mode 100644 documentation/src/crates/primitives/bytecode.md delete mode 100644 documentation/src/crates/primitives/constants.md delete mode 100644 documentation/src/crates/primitives/database.md delete mode 100644 documentation/src/crates/primitives/environment.md delete mode 100644 documentation/src/crates/primitives/kzg.md delete mode 100644 documentation/src/crates/primitives/log.md delete mode 100644 documentation/src/crates/primitives/precompile.md delete mode 100644 documentation/src/crates/primitives/result.md delete mode 100644 documentation/src/crates/primitives/specifications.md delete mode 100644 documentation/src/crates/primitives/state.md delete mode 100644 documentation/src/crates/primitives/utils.md delete mode 100644 documentation/src/crates/revm.md delete mode 100644 documentation/src/crates/revm/builder.md delete mode 100644 documentation/src/crates/revm/evm.md delete mode 100644 documentation/src/crates/revm/handler.md delete mode 100644 documentation/src/crates/revm/inspector.md delete mode 100644 documentation/src/crates/revm/journaled_state.md delete mode 100644 documentation/src/introduction.md diff --git a/.github/workflows/book.yml b/.github/workflows/book.yml index fb41e3ee3b..9d9a198cb0 100644 --- a/.github/workflows/book.yml +++ b/.github/workflows/book.yml @@ -32,7 +32,10 @@ jobs: echo `pwd`/mdbook-template >> $GITHUB_PATH - name: Run tests - run: mdbook test + run: | + cp README.md book/src/README.md + sed -i -e 's|../../README.md|README.md|g' book/src/SUMMARY.md + mdbook test lint: runs-on: ubuntu-latest @@ -78,7 +81,7 @@ jobs: echo `pwd`/mdbook-template >> $GITHUB_PATH - name: Build book - run: mdbook build documentation + run: mdbook build book - name: Build docs run: RUSTDOCFLAGS="--enable-index-page -Zunstable-options" cargo doc --all --no-deps @@ -86,18 +89,18 @@ jobs: - name: Move docs to book folder run: | mkdir -p target/book/docs - mv target/doc documentation/book/docs + mv target/doc book/book/docs - name: Archive artifact shell: sh run: | - chmod -c -R +rX "documentation/book" | + chmod -c -R +rX "book/book" | while read line; do echo "::warning title=Invalid file permissions automatically fixed::$line" done tar \ --dereference --hard-dereference \ - --directory "documentation/book" \ + --directory "book/book" \ -cvf "$RUNNER_TEMP/artifact.tar" \ --exclude=.git \ --exclude=.github \ diff --git a/.gitignore b/.gitignore index 07d5efeddf..f06c5158d6 100644 --- a/.gitignore +++ b/.gitignore @@ -10,7 +10,6 @@ pkg/ bins/revme/temp_folder bins/revme/tests ethereumjs-util.js -book # Generated by the block traces example traces @@ -19,3 +18,8 @@ burntpix/svgs # Rust bug report rustc-ice-* + +# book output of README.md generated by `mdbook serve book` +/book/book +/book/cache.json +/index.html diff --git a/README.md b/README.md index a272f95358..16baa7bce8 100644 --- a/README.md +++ b/README.md @@ -1,157 +1,73 @@ -# revm +### Revm [![CI](https://github.com/bluealloy/revm/actions/workflows/ci.yml/badge.svg)][gh-ci] [![License](https://img.shields.io/badge/License-MIT-orange.svg)][mit-license] [![Chat][tg-badge]][tg-url] +Revm is a highly efficient and stable implementation of the Ethereum Virtual Machine (EVM) written in Rust. + +![banner](https://raw.githubusercontent.com/bluealloy/revm/refs/heads/main/assets/logo/revm-banner.png) + [mit-license]: https://opensource.org/license/mit/ [gh-ci]: https://github.com/bluealloy/revm/actions/workflows/ci.yml [tg-url]: https://t.me/+Ig4WDWOzikA3MzA0 [tg-badge]: https://img.shields.io/badge/chat-telegram-blue -**Rust Ethereum Virtual Machine** - -![](./assets/logo/revm-banner.png) - -Revm is an EVM written in Rust that is focused on **speed** and **simplicity**. -It has a fast and flexible implementation with a simple interface and embedded Host. -It passes all `ethereum/tests` test suites. - -Here is a list of guiding principles that Revm follows. - -* **EVM compatibility and stability** - this goes without saying but it is nice to put it here. In the blockchain industry, stability is the most desired attribute of any system. -* **Speed** - is one of the most important things and most decisions are made to complement this. -* **Simplicity** - simplification of internals so that it can be easily understood and extended, and interface that can be easily used or integrated into other projects. -* **interfacing** - `[no_std]` so that it can be used as wasm lib and integrate with JavaScript and cpp binding if needed. - -# Project - -Structure: - -* crates - * revm -> main EVM library. - * revm-primitives -> Primitive data types. - * revm-interpreter -> Execution loop with instructions - * revm-precompile -> EVM precompiles -* bins: - * revme: cli binary, used for running state test jsons +Known for its robustness, it stands as one of the most popular libraries and critical component of the Ethereum ecosystem. Revm plays a crucial role across various projects, being widely utilized by almost all tooling and block builders. It is integrated into Reth, multiple Layer 2 variants and other clients and serving as a standard for zkVMs. -This project tends to use the newest rust version, so if you're encountering a build error try running `rustup update` first. +Revm offers two primary applications: firstly, it functions as an executor where users can set up block info and process mainnet transactions; secondly, it acts as a framework that facilitates the extension and support of different EVM variants such as revm-optimism. -There were some big efforts on optimization of revm: +### How to use: -* Optimizing interpreter loop: https://github.com/bluealloy/revm/issues/7 -* Introducing Bytecode format (and better bytecode analysis): https://github.com/bluealloy/revm/issues/121 -* Unification of instruction signatures: https://github.com/bluealloy/revm/pull/283 +Here is a straightforward example of using the Execution API: It allows us to create an Ethereum Virtual Machine (EVM) and execute transactions. Additionally, it can be utilized to generate traces with the inspector or more complex example of foundry cheatcodes. -# Building from source +```rust,ignore +let mut evm = Context::mainnet().with_block(block).build_mainnet(); +let out = evm.transact(tx); -```shell -git clone https://github.com/bluealloy/revm.git -cd revm -cargo build --release +// or you can use powerful inspection tool to trace it +let mut evm = evm.with_inspector(tracer); +let out = evm.inspect_with_tx(tx); ``` -**_Note:_** `clang` is required for building revm with `c-kzg` or `secp256k1` feature flags as they depend on `C` libraries. If you don't have it installed, you can install it with `apt install clang`. +The Evm Framework API is somewhat complex to use, but this document provides a detailed explanation. It enables users to extend logic, incorporate various context types, and offers built-in support for inspection. For a practical example, you can refer to the revm-optimism crate. -# Running eth tests +### Users: -go to `cd bins/revme/` +As previously noted, there are several groups of projects that utilize this technology: -Download eth tests from (this will take some time): `git clone https://github.com/ethereum/tests` +* **Major block builders**. +* **Clients**: [Reth](https://github.com/paradigmxyz/reth), [Helios](https://github.com/a16z/helios), [Trin](https://github.com/ethereum/trin),.. +* **Tooling**: [Foundry](https://github.com/foundry-rs/foundry/), [Hardhat](https://github.com/NomicFoundation/hardhat),.. +* **L2s**: [Optimism](https://github.com/bluealloy/revm/tree/main/crates/optimism), [Coinbase](https://www.base.org/), [Scroll](https://github.com/scroll-tech/revm),.. +* **zkVM**: [Risc0](https://github.com/risc0/risc0-ethereum), [Succinct](https://github.com/succinctlabs/sp1-reth),.. -run tests with command: `cargo run --release -- statetest tests/GeneralStateTests/ tests/LegacyTests/Constantinople/GeneralStateTests` +The full list of projects that use Revm is available in the awesome-revm section of the book. -`GeneralStateTests` contains all tests related to EVM. +### How to, dev section -## Running benchmarks - -Benches can be found in [`crates/revm/benches`](./crates/revm/benches). - -Currently, available benches include the following. -- *analysis* -- *snailtracer* -- *transfer* - -To run the `snailtracer` bench, execute the `cargo bench` subcommand below. - -```shell -cargo bench --package revm --profile release -- snailtracer -``` - -Using [flamegraph][flamegraph], you can create a visualization breaking down the runtime of various -sections of the bench execution - a flame graph. Executing the `cargo flamegraph` subcommand requires -installing [flamegraph][flamegraph] by running `cargo install flamegraph`. - -```shell -cargo flamegraph --root --freq 4000 --min-width 0.001 --package revm --bench bench -- snailtracer -``` +Note that book and code docs are still in WIP stage and they are being updated! -This command will produce a flamegraph image output to `flamegraph.svg`. -Flamegraph also requires sudo mode to run (hence the `--root` cli arg) and will prompt you for your password if not in sudo mode already. +Part of the links point to the code documentation or the book. code docs are there to explain usage of particular part of the code where book is to get more of the overview on architecture or how components/projects fit toggether. -[flamegraph]: https://docs.rs/crate/flamegraph/0.1.6 +* How to build and use revm can be found here. (code) +* Architecture overview can be seen here. (book) +* Structure of the project (list of crates) can be seen here. (book) +* How to use Revm Framework can be found here. (book) +* Release procedure and changelogs explanation. (book) +* How to use revme (Revm binary with few commands) can be found here. (code) +* How to run Ethereum test can be found here: (book) +* How to run examples and benchmark with `samply` to check performance. (book) +* If there is more explanations please open PR request for it. -## Running Examples +### Community: +For questions please open an github issue or join public telegram group: [https://t.me/+Ig4WDWOzikA3MzA0](https://t.me/+Ig4WDWOzikA3MzA0) -```shell -# Run database reference example -cargo run -p example-database-ref - -# Run contract deployment example -cargo run -p example-contract-deployment - -# Query Uniswap V2 pool reserves -cargo run -p example-uniswap-get-reserves - -# Execute USDC swap on Uniswap V2 -cargo run -p example-uniswap-v2-usdc-swap - -# Generate block traces -cargo run -p example-block-traces - -# Run database reference example -cargo run -p example-database-ref -``` - -All examples can be found in the `examples/` directory. Each example demonstrates different aspects of revm: -- `block_traces`: Generating execution traces for entire blocks -- `contract_deployment`: Deploying and interacting with smart contracts -- `database_ref`: Using database references for state access -- `uniswap_get_reserves`: Reading state from Uniswap contracts -- `uniswap_v2_usdc_swap`: Executing swaps on Uniswap V2 - -# Used by: - -* [Foundry](https://github.com/foundry-rs/foundry) is a blazing fast, portable and modular toolkit for Ethereum application development written in Rust. -* [Helios](https://github.com/a16z/helios) is a fully trustless, efficient, and portable Ethereum light client written in Rust. -* [Reth](https://github.com/paradigmxyz/reth) Modular, contributor-friendly and blazing-fast implementation of the Ethereum protocol -* [Arbiter](https://github.com/primitivefinance/arbiter) is a framework for stateful Ethereum smart-contract simulation -* [Zeth](https://github.com/risc0/zeth) is an open-source ZK block prover for Ethereum built on the RISC Zero zkVM. -* [VERBS](https://github.com/simtopia/verbs) an open-source Ethereum agent-based modelling and simulation library with a Python API. -* [Hardhat](https://github.com/NomicFoundation/hardhat) is a development environment to compile, deploy, test, and debug your Ethereum software. -* [Trin](https://github.com/ethereum/trin) is Portal Network client. An execution and consensus layer Ethereum light client written in Rust. Portal Network client's provide complete, provable, and distributed execution archival access. -* [Simular](https://github.com/simular-fi/simular/) is a Python smart-contract API with a fast, embedded, Ethereum Virtual Machine. -* [rbuilder](https://github.com/flashbots/rbuilder) is a state of the art Ethereum MEV-Boost block builder written in Rust and designed to work with Reth. -* [Tycho-simulation](https://github.com/propeller-heads/tycho-simulation) is a local simulation toolkit that lets you simulate any DEX pool in a revm environment without worrying about protocol internals. -* ... - -(If you want to add project to the list, ping me or open the PR) - -# Documentation - -The book can be found at github page here: https://bluealloy.github.io/revm/ - -The documentation (alas needs some love) can be found here: https://bluealloy.github.io/revm/docs/ - -To serve the mdbook documentation in a local environment, ensure you have mdbook installed (if not install it with cargo) and then run: - -```shell -mdbook serve documentation -``` +### Licence +Revm is licensed under MIT Licence. -# Contact +Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in these crates by you, shall be licensed as above, without any additional terms or conditions. -There is public telegram group: https://t.me/+Ig4WDWOzikA3MzA0 +### Security -Or if you want to contact me directly, here is my email: dragan0rakita@gmail.com and telegram: https://t.me/draganrakita +For any security questions or findings, please reach out to me directly via email at dragan0rakita@gmail.com or contact me on Keybase under the username [draganrakita](https://keybase.io/draganrakita/). \ No newline at end of file diff --git a/book.toml b/book.toml index 8395e94b05..61682b3c20 100644 --- a/book.toml +++ b/book.toml @@ -1,9 +1,9 @@ [book] -authors = ["Colin Roberts, Waylon Jepsen", "Dragan Rakita"] +authors = ["Dragan Rakita"] language = "en" multilingual = false -src = "documentation/src" -title = "Rust EVM" +src = "book/src" +title = "Revm - Rust Ethereum Virtual Machine" [output.linkcheck] optional = true diff --git a/book/src/SUMMARY.md b/book/src/SUMMARY.md new file mode 100644 index 0000000000..f4f4f89444 --- /dev/null +++ b/book/src/SUMMARY.md @@ -0,0 +1,13 @@ +# Summary + +- [Introduction](./../../README.md) +- [Awesome Revm](./awesome.md) +- [Architecture](./architecture.md) + - [Dependencies](./architecture/dependencies.md) + - [Crates](./architecture/crates.md) +- [Framework](./framework.md) +- [Dev section](./dev.md) +- [Examples](./examples.md) +- [Release procedure](./release_procedure.md) +- [Testing](./testing.md) +- [Contact](./contact.md) \ No newline at end of file diff --git a/book/src/architecture.md b/book/src/architecture.md new file mode 100644 index 0000000000..84e036d77e --- /dev/null +++ b/book/src/architecture.md @@ -0,0 +1,55 @@ +# Architecture + +List of crates can be found in [Crates](./architecture/crates.md) section of the book. + +REVM as any EVM implement a list of [EIP's (Ethereum Improvement Protocol)](https://github.com/ethereum/EIPs) changes over time. Those changes are shipped in the form of hardforks. List of hardforks can be found here [Ethereum Hardforks]() and repository that contains all EIPs can be found here [EIPs](https://eips.ethereum.org/). + +### Main components/traits: + +Revm consist of few traits that implement functionality of the EVM. The main traits are: +* **EvmTrait**: This trait allows as to access main EVM fields and to run interpreter. It defines **Context**, **Precompiles**, **Instructions**. Docs +* **ContextTrait**: is gained from EvmTrait and consist of types needed for execution. It defines environment such as block and transaction, database for runtime fetching of accounts and storage, journal for status changes and revert handling and few more fields. Docs +* **EthHandler**: is a trait that by default implements Ethereum logic, it takes EvmTrait as a input. Entry point is a `run` function. Docs +* **Frame**: is a associate type of EthHandler and contains runtime data of the call and logic of executing the call, default impl is a type is EthFrame. Docs + +Inspection for tracing is extensing above traits with: +* **InspectorEvmTrait** is derived from EvmTrait and allows running Evm in Inspection mode. It contains **Inspector** associate type. Docs +* **EthInspectorHandler** is derived from EthHandler and allows running Evm in Inspection mode. Entry point is `inspect_run` function and it calls a alternative functions for execution loop that includes inspector calls. Docs +* **Inspector** is a a user oriented trait that is used for inspection of the EVM. It is used for tracing. It is part of Evm struct and it is called from EthInspectorHandler and InspectorEvmTrait. Docs + + +### Simplified code + +```rust,ignore +pub trait EvmTrait { + type Context: ContextTrait; + ... + fn execute_interpreter(..); +} + +pub trait EthHandler { + type Evm: EvmTrait; + type Frame: Frame; + ... + fn run(evm); +} +``` + +### flow of execution +Execution flow can be found here (TODO Move to codebase to EthHandler trait): +* It starts with creation of new EVM instance + * Building of the Context + * Building of the EVM. Inspector/Precompiles are created. + * Adding of the Inspector if needed. +* transact/inspect. Both inspection and transaction have same flow where the only difference is that inspection includes calls to the inspector. + * validation of transaction and doing balance gas limit check. + * pre execution loads all warm accounts and deducts the caller. + * Execution : + * Creates first frame with Interpreter or executes precompile. + * run the frame loop: + * Calls Evm to exec interpreter with the frame. Interpreter loops is called here + * Output of Interpreter loop is NextAction that can be a Return of Call. + * If Return, then the frame is popped and the return value is pushed to the parent frame. If it is new call, then a new frame is created and pushed to the call stack. + * If call stack is empty the execution loop is done. + * handles the result of execution.s + * Post execution deals with halt and revert handling redistribution of rewards and reimbursement of unspend gas. \ No newline at end of file diff --git a/book/src/architecture/crates.md b/book/src/architecture/crates.md new file mode 100644 index 0000000000..c6cc10567e --- /dev/null +++ b/book/src/architecture/crates.md @@ -0,0 +1,39 @@ + +Revm project is split in multiple crates, each crate is responsible for different part of the project. The main crates are: + +There is one binary crate `revme`. It is used for running Ethereum state tests json. + +### Library crates +* revm: +* primitives: +* interpreter: +* precompile: +* database: +* database/interface: +* bytecode: +* state: +* specification: +* context: +* context/interface: +* handler: + +### variants +* optimism +* inspector + +### utility +* statetest-types: + +### examples +* block_traces: +* cheatcode_inspector: +* contract_deployment: +* database_components: +* uniswap_get_reserves: +* uniswap_v2_usdc_swap: +* erc20_gas: + + +# Dependency of library crates can be seen here + +TODO Add dependency graph here \ No newline at end of file diff --git a/book/src/architecture/dependencies.md b/book/src/architecture/dependencies.md new file mode 100644 index 0000000000..a47e5fe3e7 --- /dev/null +++ b/book/src/architecture/dependencies.md @@ -0,0 +1,18 @@ +# External core dependencies + +Revm project is no_std compliant, and it uses `alloc` crate for heap allocation. + +Native types are imported from `alloy-primitives` crate, this is where we get Address, Bytes, B256 types where big number U256 is exported from `ruint`. Additionally `hashbrown` crate or `HashMap/HashSet` with different hashing algorithm are imported from it. + +`alloy-eip7702` and `alloy-eip2930` are used in TxEnv as parts of transaction. + +Precompiles require a lot of cryprography and math libs: +- `c-kzg` is a minimal implementation of the Polynomial Commitments API for EIP-4844, written in C. (With rust bindings) +- `modexp` is a big integer modular exponentiation precompile. +- `secp256k1` is an ECDSA public key recovery precompile, based on `secp256k1` curves. `k256` is used as a fallback for no_std environments. +- ... + +`serde` and `serde-json` are behind a feature flag to serialize and deserialize data structures. + +Some utility crates are used throughout the codebase: `auto_impl`, `derive_more` etc. Where in some places few libs are imported for specific use cases like `nnum` or `dawdaw`. + diff --git a/book/src/architecture/overview.md b/book/src/architecture/overview.md new file mode 100644 index 0000000000..1d09dd6c38 --- /dev/null +++ b/book/src/architecture/overview.md @@ -0,0 +1,24 @@ +# Overview + + + + + +# Database Abstractions + +State inherits the `Database` trait and implements fetching of external state and storage, and various functionality on output of the EVM execution. +Most notably, caching changes while execution multiple transactions. + +You can implement the traits `Database`, `DatabaseRef` or `Database + DatabaseCommit` depending on the desired handling of the struct. + +- `Database`: + Has mutable `self` in its functions. + It is useful if you want to modify your cache or update some statistics on `get` calls. + This trait enables `preverify_transaction`, `transact_preverified`, `transact` and `inspect` functions. +- `DatabaseRef`: + Takes a reference on the object. + It is useful if you only have a reference on the state and don't want to update anything on it. + It enables `preverify_transaction`, `transact_preverified_ref`, `transact_ref` and `inspect_ref` functions. +- `Database + DatabaseCommit`: + Allows directly committing changes of a transaction. + It enables `transact_commit` and `inspect_commit` functions. diff --git a/book/src/awesome.md b/book/src/awesome.md new file mode 100644 index 0000000000..d4a34fbb03 --- /dev/null +++ b/book/src/awesome.md @@ -0,0 +1,38 @@ +# Awesome Revm + +A curated list of excellent Revm-related resources. Feel free to contribute to this list! + +#### Repositories +- [**Main Repo:** Revm Repository](https://github.com/bluealloy/revm) - The central code repository for Revm. +- [**Book:** ](https://bluealloy.github.io/revm/) - Comprehensive user documentation for Revm. + +#### Audits +- [**Coomunity driven Audit done by Guido Vranken**](https://rakita.github.io/blog/blog/005-revm-audit/) + +#### Clients +- [**Reth:**](https://github.com/paradigmxyz/reth) A modular, contributor-friendly, and ultra-fast implementation of the Ethereum protocol. +- [**Helios**](https://github.com/a16z/helios) is a trustless, efficient, and portable multichain light client written in Rust. +- [**Trin**](https://github.com/ethereum/trin) is a Rust implementation of a Portal Network client. + +#### EVM Variants +- [**Optimism**](https://github.com/bluealloy/revm/tree/main/crates/optimism) is a ethereum L2 network. +- [**Base**](https://www.base.org/) is an Ethereum Layer 2 (L2) chain that offers a safe, low-cost, developer-friendly way to build on-chain +- [**Scroll**](https://github.com/scroll-tech/revm) is its own Layer 2 network built on Ethereum (more specifically, a “zero-knowledge rollup”). + +#### Tools +- [**Foundry:**](https://github.com/foundry-rs/foundry) A portable and modular toolkit for rapid Ethereum application development in Rust. +- [**Hardhat:**](https://github.com/NomicFoundation/hardhat) A comprehensive development environment for compiling, deploying, testing, and debugging Ethereum software. +- [**Arbiter:**](https://github.com/primitivefinance/arbiter) smart-contract simulation. + +#### Frameworks and Libraries +- [**revm-inspectors:**](https://github.com/paradigmxyz/revm-inspectors) Hooks for EVM execution. +- [**eip3074-instructions:**](https://github.com/paradigmxyz/eip3074-instructions) Implements custom instructions for AUTH and AUTHCALL operations. +- [**Revmc:**](https://github.com/paradigmxyz/revmc) JIT and AOT compiler for the Ethereum Virtual Machine, leveraging Revm. +- [**Risc0-ethereum**](https://github.com/risc0/risc0-ethereum) is a zero-knowledge verifiable general computing platform, with Ethereum integration +- [**Kona**](https://github.com/op-rs/kona) is a suite of portable implementations of the OP Stack rollup state transition, namely the derivation pipeline and the block execution logic. + + +#### Tutorials +- [**Revm is All You Need:**](https://medium.com/@solidquant/revm-is-all-you-need-e01b5b0421e4) Guide on building simulated blockchain environments. +- [**Uniswap Swap Example:**](https://github.com/bluealloy/revm/tree/main/examples/uniswap_get_reserves) Demonstrates a USDC swap on Uniswap V2.evm is available in the [awesome-revm](./awesome.md) section o +- [**revm-by-example:**](https://github.com/Cionn3/revm-by-example) Practical examples using the Rust Ethereum Virtual Machine. \ No newline at end of file diff --git a/book/src/contact.md b/book/src/contact.md new file mode 100644 index 0000000000..9de7ca04cd --- /dev/null +++ b/book/src/contact.md @@ -0,0 +1,17 @@ + +# Contact + +Git repo can be found [https://github.com/bluealloy/revm/](https://github.com/bluealloy/revm/) + +For questions please open github issue or join public telegram group: [https://t.me/+Ig4WDWOzikA3MzA0](https://t.me/+Ig4WDWOzikA3MzA0) + +### Licence + +Licensed under MIT Licence. + +unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in these crates by you, shall be licensed as above, without any additional terms or conditions. + +### Security + +If there is security question/findings please contact me directly on email at`dragan0rakita@gmail.com` or on keybase [@draganrakita](https://keybase.io/draganrakita/). + diff --git a/book/src/dev.md b/book/src/dev.md new file mode 100644 index 0000000000..ec1669dc02 --- /dev/null +++ b/book/src/dev.md @@ -0,0 +1,69 @@ +# Dev Section + +Contains information for developers who want to build and develop revm. + +### Building from source + +```shell +git clone https://github.com/bluealloy/revm.git +cd revm +cargo build --release +``` + +**_Note:_** This project tends to use the newest rust version, so if you're encountering a build error try running rustup update first. + +**_Note:_** `clang` is required for building revm with `c-kzg` or `secp256k1` feature flags as they depend on `C` libraries. If you don't have it installed, you can install it with `apt install clang`. + +### Importing crates + +Main crate is revm, inspection is in saparate crate revm-inspection and revm-database has a few database implementations. + +Current versions of those crates are: +```toml +revm = "20.0.0-alpha.1" +revm-inspection = "0.1.0" +revm-database = "0.1.0" +``` + +Additional tools that can be useful can be found in [Awesome Revm](./awesome.md) section of the book. For example paradigm/revm-inspector crate contains a lot of Inspector used for tracing inside Reth and Foundry. + +### no_std support + +If you are in need of no_std support you would need to use no-default-features flag and disable default features. All crates (expect revme binary) support no_std in some capacity. + +Downside of no_std support is that of right now we don't have a bls12-381 implementation that is no_std compatible. PR that would solve this: + + +### Use case + +Below is a simple usage example of Execution API: where we create an EVM and transact a transaction or when we want to generate traces with the inspector. + +```rust,ignore +let mut evm = Context::mainnet().with_block(block).build_mainnet(); +let out = evm.transact(tx); + +// or you can use powerful inspection tool to trace it +let mut evm = evm.with_inspector(tracer); +let out = evm.inspect_with_tx(tx); +``` + +The usage of the Evm Framework API is a bit more complex, but it is extensively explained here. It allows extending logic, adding different context types, and supporting inspection out of the box. For an example, you can check the revm-optimism crate. + +Examples section of the book lists all examples that are available in the repository. And it is good starting point for understanding how to use revm. + +### Running eth tests + +Eth tests are suite of tests from Ethereum Fondation that are used to test EVM implementations. +Part of these tests are included in revm repository in `tests` folder. + +Download eth tests from (this will take some time): `git clone https://github.com/ethereum/tests` all statetest that can be run by revme can be found in `GeneralStateTests` folder. + +When you have downlodaed the test they can be run via `revme` with command: +`cargo run --release -p revme -- statetest tests/GeneralStateTests/ tests/LegacyTests/Constantinople/GeneralStateTests` + +After running `cargo build --release -p revme` the `revme` binary can be found in `target/release` folder. + + +### CI/CD + +CI/CD runs on GitHub actions and will test no_std/clippy/fmt correctness of the code. It will also run el statetests and benchmarks with codspeed. You can find the configuration in `.github/workflows` folder. \ No newline at end of file diff --git a/book/src/examples.md b/book/src/examples.md new file mode 100644 index 0000000000..4dde916d0d --- /dev/null +++ b/book/src/examples.md @@ -0,0 +1,10 @@ + +# List of examples + +* "examples/block_traces", +* "examples/contract_deployment", +* "examples/database_components", +* "examples/uniswap_get_reserves", +* "examples/uniswap_v2_usdc_swap", +* "examples/erc20_gas", +* "examples/cheatcode_inspector" PENDING \ No newline at end of file diff --git a/book/src/framework.md b/book/src/framework.md new file mode 100644 index 0000000000..f586d249ee --- /dev/null +++ b/book/src/framework.md @@ -0,0 +1,16 @@ +# Revm Framework + +Creating new variant of Revm is done by using a framework that is provided by the project. The framework is a set of traits that can be overridden to create a new logic that is needed. Overriding those traits can add new precompile or omit/change some logic of the EVM. + +The main traits that are used for creating a new variant are: + +Steps to implement a new variant: +1. Include Revm +2. Add main Evm type `MyEvm` and give it a Context, Precompile, Instructions and optionally Inspector. +3. Implement EvmTrait for `MyEvm`. +4. Create a empty `MyEvmHandler` type and implement EthHandler for it. Override any logic that you want. +5. Now you can use `MyEvmHandler` to run your own `MyEvm` instance. Other steps are more for agronomics and easier usage. +6. Create a `MyContextBuilder` trait that will build your context with default types you want to use. +7. Create a `MyEvmBuilder` trait that will build your Evm with default instructions and precompiles. +8. Implement `ExecuteEvm`, `ExecuteCommitEvm` to have same interface as any other variant of EVM. + diff --git a/book/src/release_procedure.md b/book/src/release_procedure.md new file mode 100644 index 0000000000..48af41df25 --- /dev/null +++ b/book/src/release_procedure.md @@ -0,0 +1,5 @@ +# Release procedure + +This document describes the procedure for releasing a new version of the `revm` project. The repository is hosted on github and the published to the crates. Every published crate is part of one tag (currently tag v55) that contains all crates versions. The versions depending on the change can be major, minor or patch, we dont have one version for all packages. + +Link of tag to the particular version of the crate can be found in CHANGELOG file. \ No newline at end of file diff --git a/documentation/src/crates/revm/state.md b/book/src/state.md similarity index 100% rename from documentation/src/crates/revm/state.md rename to book/src/state.md diff --git a/book/src/testing.md b/book/src/testing.md new file mode 100644 index 0000000000..87e4c83198 --- /dev/null +++ b/book/src/testing.md @@ -0,0 +1,11 @@ +# CI/CD + +On every pull request all statetest are run. + +# revme + +Is a binary crate that is used for running Ethereum state tests json and it has few other utilities. + +It can be downloaded from crates as `crates install revme`. + +Test can be found here `tests` or from the [ethereum tests]() repository. \ No newline at end of file diff --git a/documentation/src/SUMMARY.md b/documentation/src/SUMMARY.md deleted file mode 100644 index 1d2900f332..0000000000 --- a/documentation/src/SUMMARY.md +++ /dev/null @@ -1,36 +0,0 @@ -# Summary - -- [Introduction](./introduction.md) -- [Revm](./crates/revm.md) - - [evm](./crates/revm/evm.md) - - [builder](./crates/revm/builder.md) - - [handler](./crates/revm/handler.md) - - [inspector](./crates/revm/inspector.md) - - [state](./crates/revm/state.md) - - [journaled_state](./crates/revm/journaled_state.md) -- [Interpreter](./crates/interpreter.md) - - [gas](./crates/interpreter/gas.md) - - [memory](./crates/interpreter/memory.md) - - [host](./crates/interpreter/host.md) - - [interpreter_action](./crates/interpreter/interpreter_action.md) - - [instruction_result](./crates/interpreter/instruction_result.md) - - [instructions](./crates/interpreter/instructions.md) -- [Primitives](./crates/primitives.md) - - [database](./crates/primitives/database.md) - - [result](./crates/primitives/result.md) - - [environment](./crates/primitives/environment.md) - - [specifications](./crates/primitives/specifications.md) - - [bytecode](./crates/primitives/bytecode.md) - - [constants](./crates/primitives/constants.md) - - [precompile](./crates/primitives/precompile.md) - - [state](./crates/primitives/state.md) - - [utils](./crates/primitives/utils.md) - - [kzg](./crates/primitives/kzg.md) -- [Precompile](./crates/precompile.md) - - [blake2](./crates/precompile/blake2.md) - - [bn128 curve](./crates/precompile/bn128.md) - - [Hash functions](./crates/precompile/hash.md) - - [Identity function](./crates/precompile/identity.md) - - [Modular Exponentiation](./crates/precompile/modexp.md) - - [Secp256k1](./crates/precompile/secp256k1.md) - - [Point Evaluation](./crates/precompile/point_evaluation.md) diff --git a/documentation/src/bins/revm-test.md b/documentation/src/bins/revm-test.md deleted file mode 100644 index 2757b53d14..0000000000 --- a/documentation/src/bins/revm-test.md +++ /dev/null @@ -1 +0,0 @@ -# revm-test diff --git a/documentation/src/bins/revme.md b/documentation/src/bins/revme.md deleted file mode 100644 index 15bca4c3fd..0000000000 --- a/documentation/src/bins/revme.md +++ /dev/null @@ -1 +0,0 @@ -# revme diff --git a/documentation/src/crates/interpreter.md b/documentation/src/crates/interpreter.md deleted file mode 100644 index 0ad39b0b6c..0000000000 --- a/documentation/src/crates/interpreter.md +++ /dev/null @@ -1,27 +0,0 @@ -# Interpreter - -The `interpreter` crate is concerned with the execution of the EVM opcodes and serves as the event loop to step through the opcodes. -The interpreter is concerned with attributes like gas, contracts, memory, stack, and returning execution results. -It is structured as follows: - -### Modules: - -- [gas](./interpreter/gas.md): Handles gas mechanics in the EVM, such as calculating gas costs for operations. -- [host](./interpreter/host.md): Defines the EVM context `Host` trait. -- [interpreter_action](./interpreter/interpreter_action.md): Contains data structures used in the EVM implementation. -- [instruction_result](./interpreter/instruction_result.md): Defines results of instruction execution. -- [instructions](./interpreter/instructions.md): Defines the EVM opcodes (i.e. instructions). - -### External Crates: - -- [alloc](https://doc.rust-lang.org/alloc/): - The `alloc` crate is used to provide the ability to allocate memory on the heap. - It's a part of Rust's standard library that can be used in environments without a full host OS. -- [core](https://doc.rust-lang.org/core/): - The `core` crate is the dependency-free foundation of the Rust standard library. - It includes fundamental types, macros, and traits. - -### Re-exports: -- Several types and functions are re-exported for easier access by users of this library, such as `Gas`, `Host`, `InstructionResult`, `OpCode`, `Interpreter`, `Memory`, `Stack`, and others. - This allows users to import these items directly from the library root instead of from their individual modules. -- `revm_primitives`: This crate is re-exported, providing primitive types or functionality used in the EVM implementation. diff --git a/documentation/src/crates/interpreter/gas.md b/documentation/src/crates/interpreter/gas.md deleted file mode 100644 index cebad5eed2..0000000000 --- a/documentation/src/crates/interpreter/gas.md +++ /dev/null @@ -1,29 +0,0 @@ -# The `gas.rs` Module - -The `gas.rs` module in this Rust EVM implementation manages the concept of "gas" within the Ethereum network. In Ethereum, "gas" signifies the computational effort needed to execute operations, whether a simple transfer of ether or the execution of a smart contract function. Each operation carries a gas cost, and transactions must specify the maximum amount of gas they are willing to consume. - -## Data Structures -- `Gas` Struct - - The `Gas` struct represents the gas state for a particular operation or transaction. The struct is defined as follows: - - ### Fields in `Gas` Struct - - - `limit`: The maximum amount of gas allowed for the operation or transaction. - - `all_used_gas`: The total gas used, inclusive of memory expansion costs. - - `used`: The gas used, excluding memory expansion costs. - - `memory`: The gas used for memory expansion. - - `refunded`: The gas refunded. Certain operations in Ethereum allow for gas refunds, up to half the gas used by a transaction. - -## Methods of the `Gas` Struct - -The `Gas` struct also includes several methods to manage the gas state. Here's a brief summary of their functions: - -- `new`: Creates a new `Gas` instance with a specified gas limit and zero usage and refunds. -- `limit`, `memory`, `refunded`, `spend`, `remaining`: These getters return the current state of the corresponding field. -- `erase_cost`: Decreases the gas usage by a specified amount. -- `record_refund`: Increases the refunded gas by a specified amount. -- `record_cost`: Increases the used gas by a specified amount. It also checks for gas limit overflow. If the new total used gas would exceed the gas limit, it returns `false` and doesn't change the state. -- `record_memory`: This method works similarly to `record_cost`, but specifically for memory expansion gas. It only updates the state if the new memory gas usage is greater than the current usage. -- `gas_refund`: Increases the refunded gas by a specified amount. - diff --git a/documentation/src/crates/interpreter/host.md b/documentation/src/crates/interpreter/host.md deleted file mode 100644 index 90752f3a7d..0000000000 --- a/documentation/src/crates/interpreter/host.md +++ /dev/null @@ -1,24 +0,0 @@ -# The `host.rs` Module - -The `host.rs` module in this Rust EVM implementation defines a crucial trait `Host`. The `Host` trait outlines an interface for the interaction of the EVM interpreter with its environment (or "host"), encompassing essential operations such as account and storage access, creating logs, and invoking transactions. - -The [`Evm`](./../revm/evm.md) struct implements this `Host` trait. - -## Trait Methods - -- `env`: This method provides access to the EVM environment, including information about the current block and transaction. - -- `load_account`: Retrieves information about a given Ethereum account. - -- `block_hash`: Retrieves the block hash for a given block number. - -- `balance`, `code`, `code_hash`, `sload`: These methods retrieve specific information (balance, code, code hash, and specific storage value) for a given Ethereum account. - -- `sstore`: This method sets the value of a specific storage slot in a given Ethereum account. - -- `log`: Creates a log entry with the specified address, topics, and data. Log entries are used by smart contracts to emit events. - -- `selfdestruct`: Marks an Ethereum account to be self-destructed, transferring its funds to a target account. - - -The `Host` trait provides a standard interface that any host environment for the EVM must implement. This abstraction allows the EVM code to interact with the state of the Ethereum network in a generic way, thereby enhancing modularity and interoperability. Different implementations of the `Host` trait can be used to simulate different environments for testing or for connecting to different Ethereum-like networks. \ No newline at end of file diff --git a/documentation/src/crates/interpreter/instruction_result.md b/documentation/src/crates/interpreter/instruction_result.md deleted file mode 100644 index b2b6b4e0c1..0000000000 --- a/documentation/src/crates/interpreter/instruction_result.md +++ /dev/null @@ -1,19 +0,0 @@ -# The `instruction_result.rs` Module - -The `instruction_result.rs` module of this Rust EVM implementation includes the definitions of the `InstructionResult` and `SuccessOrHalt` enum, which represent the possible outcomes of EVM instruction execution, and functions to work with these types. - -- `InstructionResult` Enum - - The `InstructionResult` enum categorizes the different types of results that can arise from executing an EVM instruction. This enumeration uses the `#[repr(u8)]` attribute, meaning its variants have an explicit storage representation of an 8-bit unsigned integer. The different instruction results represent outcomes such as successful continuation, stop, return, self-destruction, reversion, deep call, out of funds, out of gas, and various error conditions. - -- `SuccessOrHalt` Enum - - The `SuccessOrHalt` enum represents the outcome of a transaction execution, distinguishing successful operations, reversion, halting conditions, fatal external errors, and internal continuation. It also provides several methods to check the kind of result and to extract the value of the successful evaluation or halt. - -- `From for SuccessOrHalt` Implementation - - This implementation provides a way to convert an `InstructionResult` into a `SuccessOrHalt`. It maps each instruction result to the corresponding `SuccessOrHalt` variant. - -- Macros for returning instruction results - - The module provides two macros, `return_ok!` and `return_revert!`, which simplify returning some common sets of instruction results. diff --git a/documentation/src/crates/interpreter/instructions.md b/documentation/src/crates/interpreter/instructions.md deleted file mode 100644 index 84b5b8a857..0000000000 --- a/documentation/src/crates/interpreter/instructions.md +++ /dev/null @@ -1,15 +0,0 @@ -# The `instruction.rs` Module in the Rust Ethereum Virtual Machine (EVM) - -The `instruction.rs` module defines interpretation mappings for EVM bytecode. It provides the definition of the `Instruction` struct, as well as the `Opcode` enumeration and the `execute` function, which runs a specific instruction. - -## `Opcode` Enum - -The `Opcode` enum represents the opcodes that are available in the Ethereum Virtual Machine. Each variant corresponds to an operation that can be performed, such as addition, multiplication, subtraction, jumps, and memory operations. - -## `Instruction` Struct - -The `Instruction` struct represents a single instruction in the EVM. It contains the opcode, which is the operation to be performed, and a list of bytes representing the operands for the instruction. - -## `step` Function - -The `step` function interprets an instruction. It uses the opcode to determine what operation to perform and then performs the operation using the operands in the instruction. \ No newline at end of file diff --git a/documentation/src/crates/interpreter/interpreter_action.md b/documentation/src/crates/interpreter/interpreter_action.md deleted file mode 100644 index 2cc7599aea..0000000000 --- a/documentation/src/crates/interpreter/interpreter_action.md +++ /dev/null @@ -1,39 +0,0 @@ -# The `interpreter_action.rs` Module in the Rust Ethereum Virtual Machine (EVM) - -The `interpreter_action.rs` module within this Rust EVM implementation encompasses a collection of data structures used as internal models within the EVM. These models represent various aspects of EVM operations such as call and create inputs, call context, value transfers, and the result of self-destruction operations. - -## Data Structures - -- `CallInputs` Struct - - The `CallInputs` struct is used to encapsulate the inputs to a smart contract call in the EVM. This struct includes the target contract address, the value to be transferred (if any), the input data, the gas limit for the call, the call context, and a boolean indicating if the call is a static call (a read-only operation). - -- `CallScheme` Enum - - The `CallScheme` enum represents the type of call being made to a smart contract. The different types of calls (`CALL`, `CALLCODE`, `DELEGATECALL`, `STATICCALL`) represent different modes of interaction with a smart contract, each with its own semantics concerning the treatment of the message sender, value transfer, and the context in which the called code executes. - -- `CallValue` Enum - - The `CallValue` Enum represents a value transfer between two accounts. - -- `CallOutcome` - - Represents the outcome of a call operation in a virtual machine. This struct encapsulates the result of executing an instruction by an interpreter, including the result itself, gas usage information, and the memory offset where output data is stored. - -- `CreateInputs` Struct - - The `CreateInputs` struct encapsulates the inputs for creating a new smart contract. This includes the address of the creator, the creation scheme, the value to be transferred, the initialization code for the new contract, and the gas limit for the creation operation. - -- `CreateOutcome` Struct - - Represents the outcome of a create operation in an interpreter. This struct holds the result of the operation along with an optional address. It provides methods to determine the next action based on the result of the operation. - -- `EOFCreateInput` Struct - - Inputs for EOF create call. - -- `EOFCreateOutcome` Struct - - Represents the outcome of a create operation in an interpreter. - -In summary, the `interpreter_action.rs` module provides several crucial data structures that facilitate the representation and handling of various EVM operations and their associated data within this Rust EVM implementation. diff --git a/documentation/src/crates/interpreter/memory.md b/documentation/src/crates/interpreter/memory.md deleted file mode 100644 index 6aab06876f..0000000000 --- a/documentation/src/crates/interpreter/memory.md +++ /dev/null @@ -1,35 +0,0 @@ -# EVM Memory - -Is a memory localized to the current Interpreter context. Interpreter context is a call or create frame. It is used by opcodes to store or format data that are more than 32 bytes long, for example calls to format input, return output or for logs data. Revm has a shared memory between all the Interpreters but Interpreter loop only see the part it is allocated to it. - -Extending memory is paid by the gas. It consumes 3 gas per word plus square of the number of words added divided by `512` (`3*N+ N^2/512`). There is no limit on the size of the memory, but it is limited by logarithmic growth of the gas cost. For 30M there is a calculated max memory of 32MB (by [Remco](https://xn--2-umb.com/) in 2022). - -## Opcodes - -Here is a list of all opcodes that are reading or writing to the memory. All read on memory can still change the memory size by extending it with zeroes. Call opcodes are specific as they read input before the call but also write their output after the call (if call is okay and there is an output to write) to the memory. - -These opcodes read from the memory: -* RETURN -* REVERT -* LOG -* KECCAK256 -* CREATE -* CREATE2 -* CALL -* CALLCODE -* DELEGATECALL -* STATICCALL - -These opcodes change the memory: -* EXTCODECOPY -* MLOAD -* MSTORE -* MSTORE8 -* MCOPY -* CODECOPY -* CALLDATACOPY -* RETURNDATACOPY -* CALL -* CALLCODE -* DELEGATECALL -* STATICCALL diff --git a/documentation/src/crates/precompile.md b/documentation/src/crates/precompile.md deleted file mode 100644 index c01c6760a0..0000000000 --- a/documentation/src/crates/precompile.md +++ /dev/null @@ -1,47 +0,0 @@ -# Precompile - -The `precompile` crate contains the implementation of the Ethereum precompile opcodes in the EVM. -Precompiles are a shortcut to execute a function implemented by the EVM itself, rather than an actual contract. -Precompiled contracts are essentially predefined smart contracts on Ethereum, residing at hardcoded addresses and used for computationally heavy operations that are cheaper when implemented this way. -There are 7 precompiles implemented in REVM, and they are: `blake2`, `bn128` curve, `identity`, `secp256k1`, `modexp`, and `sha256` and `ripemd160` hash functions. - -### Modules: - -- [blake2](./precompile/blake2.md): Implements the `BLAKE2` compression function, as specified in [EIP-152](https://eips.ethereum.org/EIPS/eip-152). -- [bn128](./precompile/bn128.md): Implements precompiled contracts for addition, scalar multiplication, and optimal ate pairing check on the `alt_bn128` elliptic curve. -- [hash](./precompile/hash.md): Implements the `SHA256` and `RIPEMD160` hash functions. -- [identity](./precompile/identity.md): Implements the `Identity` precompile, which returns the input data unchanged. -- [point_evaluation](./precompile/point_evaluation.md): Implements the point evaluation precompile for [EIP-4844](https://eips.ethereum.org/EIPS/eip-4844). -- [modexp](./precompile/modexp.md): Implements the big integer modular exponentiation precompile. -- [secp256k1](./precompile/secp256k1.md): Implements the ECDSA public key recovery precompile, based on `secp256k1` curves. - -### Types and Constants: - -- `Address`: A type alias for an array of 20 bytes. This is typically used to represent Ethereum addresses. -- `B256`: A type alias for an array of 32 bytes, typically used to represent 256-bit hashes or integer values in Ethereum. -- `PrecompileOutput`: Represents the output of a precompiled contract execution, including the gas cost, output data, and any logs generated. -- `Log`: Represents an Ethereum log, with an address, a list of topics, and associated data. -- `Precompiles`: A collection of precompiled contracts available in a particular hard fork of Ethereum. -- `Precompile`: Represents a precompiled contract, which can either be a standard Ethereum precompile, or a custom precompile. -- `PrecompileWithAddress`: Associates a precompiled contract with its address. -- `SpecId`: An enumeration representing different hard fork specifications in Ethereum, such as Homestead, Byzantium, Istanbul, Berlin, and Latest. - -### Functions: - -- `calc_linear_cost_u32`: A utility function to calculate the gas cost for certain precompiles based on their input length. -- `u64_to_b160`: A utility function for converting a 64-bit unsigned integer into a 20-byte Ethereum address. - -### External Crates: - -- [alloc](https://doc.rust-lang.org/alloc/): The alloc crate provides types for heap allocation, and is used here for the `Vec` type. -- [core](https://doc.rust-lang.org/core/): The core crate provides fundamental Rust types, macros, and traits, and is used here for `fmt::Result`. - -### Re-exported Crates and Types: - -- `revm_primitives`: This crate is re-exported, indicating it provides some types used by the precompile crate. -- `primitives`: Types from the `primitives` module of `revm_primitives` are re-exported, including `Bytes`, `HashMap`, and all types under `precompile`. The latter includes the `PrecompileError` type, which is aliased to `Error`. - -### Re-exported Functionality: - -- `Precompiles` provides a static method for each Ethereum hard fork specification (e.g., `homestead`, `byzantium`, `istanbul`, `berlin`, `cancun`, and `latest`), each returning a set of precompiles for that specification. -- `Precompiles` also provides methods to retrieve the list of precompile addresses (`addresses`), to check if a given address is a precompile (`contains`), to get the precompile at a given address (`get`), to check if there are no precompiles (`is_empty`), and to get the number of precompiles (`len`). diff --git a/documentation/src/crates/precompile/blake2.md b/documentation/src/crates/precompile/blake2.md deleted file mode 100644 index 43b409cb94..0000000000 --- a/documentation/src/crates/precompile/blake2.md +++ /dev/null @@ -1,47 +0,0 @@ -# blake2 hash - -This module represents a Rust implementation of the `Blake2b` cryptographic hash function, a vital component of Ethereum's broader EIP-152 proposal. The primary purpose of this module is to integrate the `Blake2b` function into Ethereum's precompiled contract mechanism, providing a consistent and efficient way to perform the cryptographic hashing that underpins Ethereum's functionality. - -In [EIP-152](https://eips.ethereum.org/EIPS/eip-152) introduced a new precompiled contract that implements the `BLAKE2` cryptographic hashing algorithm's compression function. The purpose of this is to enhance the interoperability between Ethereum and Zcash, as well as to introduce more versatile cryptographic hash primitives to the Ethereum Virtual Machine (EVM). - -BLAKE2 is not just a powerful cryptographic hash function and SHA3 contender, but it also allows for the efficient validation of the Equihash Proof of Work (PoW) used in Zcash. This could make a Bitcoin Relay-style Simplified Payment Verification (SPV) client feasible on Ethereum, as it enables the verification of Zcash block headers without excessive computational cost. `BLAKE2b`, a common 64-bit `BLAKE2` variant, is highly optimized and performs faster than MD5 on modern processors. - -The rationale behind incorporating `Blake2b` into Ethereum's suite of precompiled contracts is multifaceted: - -- Performance: The `Blake2b` hash function offers excellent performance, particularly when processing large inputs. -- Security: `Blake2b` also provides a high degree of security, making it a suitable choice for cryptographic operations. -- Interoperability: This function is widely used in various parts of the ecosystem, making it a prime candidate for inclusion in Ethereum's precompiled contracts. -- Gas Cost: The gas cost per round (F_ROUND) is specified as 1. This number was decided considering the computational complexity and the necessity to keep the blockchain efficient and prevent spamming. - -## Core Components - -Two primary constants provide the framework for the precompiled contract: - -`F_ROUND: u64`: This is the cost of each round of computation in gas units. Currently set to 1. -`INPUT_LENGTH: usize`: This specifies the required length of the input data, 213 bytes in this case. - -## Precompile Function - run - -The `run` function is the main entry point for the precompiled contract. It consumes an input byte slice and a gas limit, returning a `PrecompileResult`. This function handles input validation, gas cost computation, data manipulation, and the compression algorithm. - -It checks for correct input length and reads the final `block` flag. It then calculates the gas cost based on the number of rounds to be executed. If the gas cost exceeds the provided gas limit, it immediately returns an error. - -Once the validation and gas cost computation are complete, it parses the input into three components: state vector `h`, message `block` vector `m`, and offset counter `t`. - -Following this, it calls the `compress` function from the algo module, passing in the parsed input data and the final `block` flag. - -Finally, it constructs and returns the `PrecompileResult` containing the gas used and the output data. - -## Algorithm Module - algo - -The algo module encapsulates the technical implementation of the `Blake2b` hash function. It includes several key elements: - -Constants: - -- `SIGMA`: This 2D array represents the message word selection permutation used in each round of the algorithm. - -- `IV`: These are the initialization vectors for the `Blake2b` algorithm. - -- The `g` Function: This is the core function within each round of the `Blake2b` algorithm. It manipulates the state vector and mixes in the message data. - -- The `compress` Function: This is the main function that executes the rounds of the `g` function, handles the last `block` flag, and updates the state vector with the output of each round. diff --git a/documentation/src/crates/precompile/bn128.md b/documentation/src/crates/precompile/bn128.md deleted file mode 100644 index 72bfbba1f7..0000000000 --- a/documentation/src/crates/precompile/bn128.md +++ /dev/null @@ -1,13 +0,0 @@ -# bn128 curve - -[EIP-197](https://eips.ethereum.org/EIPS/eip-197) proposed the addition of precompiled contracts for a pairing function on a specific pairing-friendly elliptic curve. This complements [EIP-196](https://eips.ethereum.org/EIPS/eip-196) in enabling zkSNARKs verification within Ethereum smart contracts. zkSNARKs (Zero-Knowledge Succinct Non-Interactive Argument of Knowledge) technology can enhance privacy for Ethereum users due to its Zero-Knowledge property. Moreover, it may offer a scalability solution because of its succinctness and efficient verifiability property. - -Prior to this EIP, Ethereum's smart contract executions were fully transparent, limiting their use in cases involving private information, such as location, identity, or transaction history. While the Ethereum Virtual Machine (EVM) can theoretically use zkSNARKs, their implementation was presently too costly to fit within the block gas limit. [EIP-197](https://eips.ethereum.org/EIPS/eip-197) defines specific parameters for basic primitives that facilitate zkSNARKs. This allows for more efficient implementation, thereby reducing gas costs. - -Notably, setting these parameters doesn't restrict zkSNARKs' use-cases but actually enables the integration of zkSNARK research advancements without requiring further hard forks. Pairing functions, which enable a limited form of multiplicatively homomorphic operations necessary for zkSNARKs, could then be executed within the block gas limit through this precompiled contract. - -The code consists of three modules: `add`, `mul`, and `pair`. The add and `mul` modules implement elliptic curve point addition and scalar multiplication respectively on the bn128 curve, an elliptic curve utilized within Ethereum. Each module defines two versions of the contract, one for the Istanbul and another for the Byzantium Ethereum network upgrades. - -The pair module conducts the pairing check, an operation that enables comparison of two points on the elliptic curve, an essential part of many zero-knowledge proof systems, including zk-SNARKs. Again, two versions for Istanbul and Byzantium are defined. The `run_add`, `run_mul`, and run_pair functions embody the main implementations of the precompiled contracts, with each function accepting an input byte array, executing the appropriate elliptic curve operations, and outputting the results as a byte array. - -The code ensures the allocation of sufficient gas for each operation by stipulating gas costs as constants at the start of each module. It employs the bn library to carry out the actual bn128 operations. As the functions operate with byte arrays, the code features significant byte manipulation and conversion. Consequently, the code presents an implementation of specific elliptic curve operations utilized in Ethereum. diff --git a/documentation/src/crates/precompile/hash.md b/documentation/src/crates/precompile/hash.md deleted file mode 100644 index 2f54cf3740..0000000000 --- a/documentation/src/crates/precompile/hash.md +++ /dev/null @@ -1,7 +0,0 @@ -## SHA256 and RIPEMD160 - -REVM includes precompiled contracts for `SHA256` and `RIPEMD160`, cryptographic hashing functions integral for data integrity and security. The addresses for these precompiled contracts are `0x0000000000000000000000000000000000000002` for `SHA256` and `0x0000000000000000000000000000000000000003` for `RIPEMD160`. - -Each function (`sha256_run` and `ripemd160_run`) accepts two arguments, the input data to be hashed and the gas_limit representing the maximum amount of computational work permissible for the function. They both calculate the gas cost of the operation based on the input data length. If the computed cost surpasses the `gas_limit`, an `Error::OutOfGas` is triggered. - -The `sha256_run` function, corresponding to the `SHA256` precompiled contract, computes the `SHA256` hash of the input data. The `ripemd160_run` function computes the `RIPEMD160` hash of the input and pads it to match Ethereum's 256-bit word size. These precompiled contracts offer a computationally efficient way for Ethereum contracts to perform necessary cryptographic operations. diff --git a/documentation/src/crates/precompile/identity.md b/documentation/src/crates/precompile/identity.md deleted file mode 100644 index 64bd834818..0000000000 --- a/documentation/src/crates/precompile/identity.md +++ /dev/null @@ -1,7 +0,0 @@ -## Identity function - -This precompiled contract performs the identity function. In mathematics, an identity function is a function that always returns the same value as its argument. In this context, the contract takes the input data and returns it as is. This precompiled contract resides at the hardcoded Ethereum address `0x0000000000000000000000000000000000000004`. - -The `identity_run` function takes two arguments: input data, which it returns unaltered, and `gas_limit` which defines the maximum computational work the function is allowed to do. A linear gas cost calculation based on the size of the input data and two constants, `IDENTITY_BASE` (the base cost of the operation) and `IDENTITY_PER_WORD` (the cost per word), is performed. If the calculated gas cost exceeds the `gas_limit`, an `Error::OutOfGas` is returned. - -This identity function can be useful in various scenarios such as forwarding data or acting as a data validation check within a contract. Despite its simplicity, it contributes to the flexibility and broad utility of the Ethereum platform. diff --git a/documentation/src/crates/precompile/modexp.md b/documentation/src/crates/precompile/modexp.md deleted file mode 100644 index ed548e94ea..0000000000 --- a/documentation/src/crates/precompile/modexp.md +++ /dev/null @@ -1,9 +0,0 @@ -# Modular Exponentiation - -REVM also implements two versions of a precompiled contract (Modular Exponential operation), each corresponding to different Ethereum hard forks: Byzantium and Berlin. The contract addresses are `0x0000000000000000000000000000000000000005` for both versions, as they replaced each other in subsequent network upgrades. This operation is used for cryptographic computations and is a crucial part of Ethereum's toolkit. - -The byzantium_run and berlin_run functions each run the modular exponential operation using the `run_inner` function, but each uses a different gas calculation method: `byzantium_gas_calc` for Byzantium and `berlin_gas_calc` for Berlin. The gas calculation method used is chosen based on the Ethereum network's current version. The `run_inner` function is a core function that reads the inputs and performs the modular exponential operation. If the calculated gas cost is higher than the gas limit, an error `Error::OutOfGas` is returned. If all computations are successful, the function returns the result of the operation and the gas cost. - -The calculate_iteration_count function calculates the number of iterations required to compute the operation, based on the length and value of the exponent. The `read_u64_with_overflow` macro reads input data and checks for potential overflows. - -The byzantium_gas_calc function calculates the gas cost for the modular exponential operation as defined in the Byzantium version of the Ethereum protocol. The `berlin_gas_calc` function calculates the gas cost according to the Berlin version, as defined in [EIP-2565](https://eips.ethereum.org/EIPS/eip-2565). These two versions have different formulas to calculate the gas cost of the operation, reflecting the evolution of the Ethereum network. diff --git a/documentation/src/crates/precompile/point_evaluation.md b/documentation/src/crates/precompile/point_evaluation.md deleted file mode 100644 index df982cfe43..0000000000 --- a/documentation/src/crates/precompile/point_evaluation.md +++ /dev/null @@ -1,5 +0,0 @@ -# Point Evaluation Precompile - -This precompile is introduced in [EIP-4844](https://eips.ethereum.org/EIPS/eip-4844) and is used to verify KZG commitments of blobs. The precompile allows for efficient verification of commitments to blob transactions. Blob transactions contain a large amount of data that cannot be accessed by EVM execution, but has a commitment that can be accessed and verified. The EIP is designed to be forward compatible with [Danksharding](https://ethereum.org/en/roadmap/danksharding/) architecture while giving L2s access to cheaper L1 commitments. This precompiled contract resides at the hardcoded Ethereum address `0x000000000000000000000000000000000000000A`. - -A useful resource is the Python reference implementation for the precompile, which can be found [here](https://github.com/ethereum/consensus-specs/blob/86fb82b221474cc89387fa6436806507b3849d88/specs/deneb/polynomial-commitments.md). The implementation in REVM uses [c-kzg-4844](https://github.com/ethereum/c-kzg-4844), via its [foreign function interface](https://en.wikipedia.org/wiki/Foreign_function_interface) bindings, from the Ethereum Foundation. \ No newline at end of file diff --git a/documentation/src/crates/precompile/secp256k1.md b/documentation/src/crates/precompile/secp256k1.md deleted file mode 100644 index 4146448c1e..0000000000 --- a/documentation/src/crates/precompile/secp256k1.md +++ /dev/null @@ -1,9 +0,0 @@ -# Secp256k1 - -This implements Ethereum's precompiled contract `ECRECOVER`, an elliptic curve digital signature algorithm (ECDSA) recovery function that recovers the Ethereum address (public key hash) associated with a given signature. The implementation features two versions, each contingent on whether the secp256k1 cryptographic library is enabled, which depends on the build configuration. - -Both versions define a `secp256k1` module that includes an `ecrecover` function. This function takes a digital signature and a message as input, both represented as byte arrays, and returns the recovered Ethereum address. It performs this operation by using the signature to recover the original public key used for signing, then hashing this public key with `Keccak256`, Ethereum's chosen hash function. The hash is then truncated to match Ethereum's 20-byte address size. - -When `secp256k1` is not enabled, the ecrecover function uses the `k256` library to parse the signature, recover the public key, and perform the hashing. When `secp256k1` is enabled, the function uses the `secp256k1` library for these operations. Although both versions perform the same fundamental operation, they use different cryptographic libraries, which can offer different optimizations and security properties. - -The `ec_recover_run` function is the primary entry point for this precompiled contract. It parses the input to extract the message and signature, checks if enough gas is provided for execution, and calls the appropriate ecrecover function. The result of the recovery operation is returned as a `PrecompileResult`, a type that represents the outcome of a precompiled contract execution in Ethereum. diff --git a/documentation/src/crates/primitives.md b/documentation/src/crates/primitives.md deleted file mode 100644 index 7e91b86cfd..0000000000 --- a/documentation/src/crates/primitives.md +++ /dev/null @@ -1,40 +0,0 @@ -# Primitives - -This crate is a core component of the revm system. -It is designed to provide definitions for a range of types and structures commonly used throughout the application. -It is set up to be compatible with environments that do not include Rust's standard library, as indicated by the `no_std` attribute. - -### Modules: - -- [bytecode](./primitives/bytecode.md): This module provides functionality related to EVM bytecode. -- [constants](./primitives/constants.md): This module contains constant values used throughout the EVM implementation. -- [db](./primitives/database.md): This module contains data structures and functions related to the EVM's database implementation. -- [env](./primitives/environment.md): This module contains types and functions related to the EVM's environment, including block headers, and environment values. -- [precompile](./primitives/precompile.md): This module contains types related to Ethereum's precompiled contracts. -- [result](./primitives/result.md): This module provides types for representing execution results and errors in the EVM. -- [specification](./primitives/specifications.md): This module defines types related to Ethereum specifications (also known as hard forks). -- [state](./primitives/state.md): This module provides types and functions for managing Ethereum state, including accounts and storage. -- [utilities](./primitives/utils.md): This module provides utility functions used in multiple places across the EVM implementation. -- [kzg](./primitives/kzg.md): This module provides types and functions related to KZG commitment, it is employed visibly in the Point Evaluation Precompile. - -### External Crates: - -- `alloc`: The alloc crate provides types for heap allocation. -- `bitvec`: The bitvec crate provides a data structure to handle sequences of bits. -- `bytes`: The bytes crate provides utilities for working with bytes. -- `hex`: The hex crate provides utilities for encoding and decoding hexadecimal. -- `hex_literal`: The hex_literal crate provides a macro for including hexadecimal data directly in the source code. -- `hashbrown`: The hashbrown crate provides high-performance hash map and hash set data structures. -- `ruint`: The ruint crate provides types and functions for big unsigned integer arithmetic. -- `c-kzg`: A minimal implementation of the Polynomial Commitments API for EIP-4844, written in C. (With rust bindings) - -### Re-exported Types: - -- `Address`: A type representing a 160-bit (or 20-byte) array, typically used for Ethereum addresses. -- `B256`: A type representing a 256-bit (or 32-byte) array, typically used for Ethereum hashes or integers. -- `Bytes`: A type representing a sequence of bytes. -- `U256`: A 256-bit unsigned integer type from the `ruint` crate. -- `HashMap` and `HashSet`: High-performance hash map and hash set data structures from the hashbrown crate. - -Re-exported Modules: -All types, constants, and functions from the `bytecode`, `constants`, `env`, `precompile`, `result`, `specification`, `state`, `utilities`, `KzgSettings`, `EnvKzgSettings`, `trusted_setup_points` types and methods were all re-exported, allowing users to import these items directly from the `primitives` crate. diff --git a/documentation/src/crates/primitives/bits.md b/documentation/src/crates/primitives/bits.md deleted file mode 100644 index 1bf623d867..0000000000 --- a/documentation/src/crates/primitives/bits.md +++ /dev/null @@ -1,17 +0,0 @@ -# Bits - -> Note: This module's types have been replaced by [`alloy_primitives`](https://github.com/alloy-rs/core)'s `Address` and `FixedBytes`. - -This module houses the definitions for fixed-size bit arrays, `Address` and `B256`, showcasing its role in managing bits-related operations, to represent 256-bit and 160-bit fixed-size hashes respectively. These are defined using the `construct_fixed_hash!` macro from the `fixed_hash` crate. - -The `AsRef` and `Deref` traits from `derive_more` crate are derived for both of these structures, providing convenient methods for converting these types to and from references of their underlying data. - -The `Arbitrary` trait from the `arbitrary` crate and the `PropTestArbitrary` trait from `proptest_derive` crate are derived conditionally when either testing or the "arbitrary" feature is enabled. - -The code also provides conversions between `B256`, `Address` and various other types such as `u64`, `primitive_types::H256`, `primitive_types::H160`, `primitive_types::U256`, and `ruint::aliases::U256`. The `impl` From blocks specify how to convert from one type to another. - -`impl_fixed_hash_conversions!` macro is used to define conversions between `B256` and `Address` types. - -If the "serde" feature is enabled, the Serialize and Deserialize traits from the serde crate are implemented for `B256` and `Address` using a custom serialization method that outputs/reads these types as hexadecimal strings. This includes a custom serialization/deserialization module for handling hexadecimal data. - -This module (serialize) provides functionality to serialize a slice of bytes to a hexadecimal string, and deserialize a hexadecimal string to a byte vector with size checks. It handles both "0x" prefixed and non-prefixed hexadecimal strings. It also provides functions to convert raw bytes to hexadecimal strings and vice versa, handling potential errors related to non-hexadecimal characters. The module also defines the `ExpectedLen` enum which is used to specify the expected length of the byte vectors during deserialization. diff --git a/documentation/src/crates/primitives/bytecode.md b/documentation/src/crates/primitives/bytecode.md deleted file mode 100644 index 5696488c23..0000000000 --- a/documentation/src/crates/primitives/bytecode.md +++ /dev/null @@ -1,9 +0,0 @@ -# Bytecode - -This module defines structures and methods to manipulate Ethereum bytecode and manage its state. It's built around three main components: `JumpTable`, `BytecodeState`, and `Bytecode`. - -The `JumpTable` structure stores a map of valid `jump` destinations within a given Ethereum bytecode sequence. It is essentially an `Arc` (Atomic Reference Counter) wrapping a `BitVec` (bit vector), which can be accessed and modified using the defined methods, such as `as_slice()`, `from_slice()`, and `is_valid()`. - -The `BytecodeState` is an enumeration, capturing the three possible states of the bytecode: `Raw`, `Checked`, and `Analysed`. In the `Checked` and `Analysed` states, additional data is provided, such as the length of the bytecode and, in the `Analysed` state, a `JumpTable`. - -The `Bytecode` struct holds the actual bytecode, its hash, and its current state (`BytecodeState`). It provides several methods to interact with the bytecode, such as getting the length of the bytecode, checking if it's empty, retrieving its state, and converting the bytecode to a checked state. It also provides methods to create new instances of the `Bytecode` struct in different states. diff --git a/documentation/src/crates/primitives/constants.md b/documentation/src/crates/primitives/constants.md deleted file mode 100644 index 893b067f09..0000000000 --- a/documentation/src/crates/primitives/constants.md +++ /dev/null @@ -1,7 +0,0 @@ -# Constants - -Holds constant values used throughout the system. This module defines important constants that help limit and manage resources in the Ethereum Virtual Machine (EVM). The constants include `STACK_LIMIT` and `CALL_STACK_LIMIT`, which restrict the size of the interpreter stack and the EVM call stack, respectively. Both are set to 1024. - -The module also defines `MAX_CODE_SIZE`, which is set according to [EIP-170](https://eips.ethereum.org/EIPS/eip-170)'s specification. [EIP-170](https://eips.ethereum.org/EIPS/eip-170) imposes a maximum limit on the contract code size to mitigate potential vulnerabilities and inefficiencies in Ethereum. Without this cap, the act of calling a contract can trigger costly operations that scale with the size of the contract's code. These operations include reading the code from disk, preprocessing the code for VM execution, and adding data to the block's proof-of-validity. By implementing `MAX_CODE_SIZE` (set to `0x6000` or ~25kb), the EVM ensures that the cost of these operations remains manageable, even under high gas levels that could be encountered in the future. [EIP-170](https://eips.ethereum.org/EIPS/eip-170)'s implementation thus offers crucial protection against potential DoS attacks and maintains efficiency, especially for future light clients verifying proofs of validity or invalidity. - -Another constant defined here is `MAX_INITCODE_SIZE`, set in accordance with [EIP-3860](https://eips.ethereum.org/EIPS/eip-3860). [EIP-3860](https://eips.ethereum.org/EIPS/eip-3860) extends EIP-170 by introducing a maximum size limit for initialization code (initcode) and enforcing a gas charge for every 32-byte chunk of initcode, to account for the cost of jump destination analysis. Before [EIP-3860](https://eips.ethereum.org/EIPS/eip-3860), initcode analysis during contract creation wasn't metered, nor was there an upper limit for its size, resulting in potential inefficiencies and vulnerabilities. By setting `MAX_INITCODE_SIZE` to 2 \* `MAX_CODE_SIZE` and introducing the said gas charge, [EIP-3860](https://eips.ethereum.org/EIPS/eip-3860) ensures that the cost of initcode analysis scales proportionately with its size. This constant, therefore, facilitates fair charging, simplifies EVM engines by setting explicit limits, and helps to create an extendable cost system for the future. diff --git a/documentation/src/crates/primitives/database.md b/documentation/src/crates/primitives/database.md deleted file mode 100644 index bf7fbbfeee..0000000000 --- a/documentation/src/crates/primitives/database.md +++ /dev/null @@ -1,12 +0,0 @@ -# Database - -Responsible for database operations. This module is where the blockchain's state persistence is managed. -The module defines three primary traits (`Database`, `DatabaseCommit`, and `DatabaseRef`), a structure `RefDBWrapper`, and their associated methods. - -The `Database` trait defines an interface for mutable interaction with the database. It has a generic associated type `Error` to handle different kinds of errors that might occur during these interactions. It provides methods to retrieve basic account information (`basic`), retrieve account code by its hash (`code_by_hash`), retrieve the storage value of an address at a certain index (`storage`), and retrieve the block hash for a certain block number (`block_hash`). - -The `DatabaseCommit` trait defines a single `commit` method for committing changes to the database. The changes are a map between Ethereum-like addresses (type `Address`) and accounts. - -The `DatabaseRef` trait is similar to the `Database` trait but is designed for read-only or immutable interactions. It has the same `Error` associated type and the same set of methods as `Database`, but these methods take `&self` instead of `&mut self`, indicating that they do not mutate the database. - -The `RefDBWrapper` structure is a wrapper around a reference to a `DatabaseRef` type. It implements the `Database` trait, essentially providing a way to treat a `DatabaseRef` as a `Database` by forwarding the `Database` methods to the corresponding `DatabaseRef` methods. diff --git a/documentation/src/crates/primitives/environment.md b/documentation/src/crates/primitives/environment.md deleted file mode 100644 index 8d56024b55..0000000000 --- a/documentation/src/crates/primitives/environment.md +++ /dev/null @@ -1,5 +0,0 @@ -# Environment - -A significant module that manages the execution environment of the EVM. The module contains objects and methods associated with processing transactions and blocks within such a blockchain environment. It defines several structures: `Env`, `BlockEnv`, `TxEnv`, `CfgEnv`, and `CreateScheme`. These structures contain various fields representing the block data, transaction data, environmental configurations, transaction recipient details, and the method of contract creation respectively. - -The `Env` structure, which encapsulates the environment of the EVM, contains methods for calculating effective gas prices and for validating block and transaction data. It also checks transactions against the current state of the associated account, which is necessary to validate the transaction's nonce and the account balance. Various Ethereum Improvement Proposals (EIPs) are also considered in these validations, such as [EIP-1559](https://eips.ethereum.org/EIPS/eip-1559) for the base fee, [EIP-3607](https://eips.ethereum.org/EIPS/eip-3607) for rejecting transactions from senders with deployed code, and [EIP-3298](https://eips.ethereum.org/EIPS/eip-3298) for disabling gas refunds. The code is structured to include optional features and to allow for changes in the EVM specifications. diff --git a/documentation/src/crates/primitives/kzg.md b/documentation/src/crates/primitives/kzg.md deleted file mode 100644 index a9d6468597..0000000000 --- a/documentation/src/crates/primitives/kzg.md +++ /dev/null @@ -1,12 +0,0 @@ -# KZG - -With the introduction of [EIP4844](https://eips.ethereum.org/EIPS/eip-4844), this use of blobs for a more efficient short term storage is employed, the validity of this blob stored in the consensus layer is verified using the `Point Evaluation` pre-compile, a fancy way of verifying that and evaluation at a given point of a committed polynomial is valid, on a much bigger scale, implies that `Data is Available`. - -This module houses; - -1. `KzgSettings`: Stores the setup and parameters needed for computing and verify KZG proofs. - - The `KZG` primitive provides a default `KZGSettings` obtained from [this]( https://ceremony.ethereum.org/) trusted setup ceremony, a provision is also made for using a custom `KZGSettings` if need be, this is available in the `env.cfg`. - - -2. `trusted_setup_points`: This module contains functions and types used for parsing and utilizing the [Trusted Setup](https://ceremony.ethereum.org/) for the `KzgSettings`. diff --git a/documentation/src/crates/primitives/log.md b/documentation/src/crates/primitives/log.md deleted file mode 100644 index 4bfad958df..0000000000 --- a/documentation/src/crates/primitives/log.md +++ /dev/null @@ -1,11 +0,0 @@ -# Log - -> Note: This module's types have been replaced by [`alloy_primitives`](https://github.com/alloy-rs/core)'s `Log` and `LogData`. - -This piece of Rust code defines a structure called Log which represents an Ethereum log entry. These logs are integral parts of the Ethereum network and are typically produced by smart contracts during execution. Each Log has three components: - -- `address`: This field represents the address of the log originator, typically the smart contract that generated the log. The `Address` data type signifies a 160-bit Ethereum address. - -- `topics`: This field is a vector of `B256` type. In Ethereum, logs can have multiple '`topics`'. These are events that can be used to categorize and filter logs. The `B256` type denotes a 256-bit hash, which corresponds to the size of a topic in Ethereum. - -- `data`: This is the actual data of the log entry. The Bytes type is a dynamically-sized byte array, and it can contain any arbitrary data. It contains additional information associated with the event logged by a smart contract. diff --git a/documentation/src/crates/primitives/precompile.md b/documentation/src/crates/primitives/precompile.md deleted file mode 100644 index 965068d4d8..0000000000 --- a/documentation/src/crates/primitives/precompile.md +++ /dev/null @@ -1,9 +0,0 @@ -# precompile - -This module implements precompiled contracts in the EVM, adding a layer of pre-set functionalities. These are documented in more detail in the next section. The module defines the types and the enum that are used to handle precompiled contracts. - -`PrecompileResult`: This is a type alias for a `Result` type. The `Ok` variant of this type contains a tuple (`u64`, `Vec`), where the `u64` integer likely represents gas used by the precompiled contract, and the `Vec` holds the output data. The Err variant contains a PrecompileError. - -`StandardPrecompileFn` and `CustomPrecompileFn`: These are type aliases for function pointers. Both functions take a byte slice and a `u64` (probably the available gas) as arguments and return a `PrecompileResult`. The naming suggests that the former refers to built-in precompiled contracts, while the latter may refer to custom, user-defined contracts. - -`PrecompileError`: This is an enumeration (enum) which describes the different types of errors that could occur while executing a precompiled contract. The listed variants suggest these errors are related to gas consumption, `Blake2` hash function, modular exponentiation ("`Modexp`"), and `Bn128`, which is a specific elliptic curve used in cryptography. diff --git a/documentation/src/crates/primitives/result.md b/documentation/src/crates/primitives/result.md deleted file mode 100644 index 647a35aa48..0000000000 --- a/documentation/src/crates/primitives/result.md +++ /dev/null @@ -1,11 +0,0 @@ -# Result - -At the core of this module is the `ExecutionResult` enum, which describes the possible outcomes of an EVM execution: `Success`, `Revert`, and `Halt`. `Success` represents a successful transaction execution, and it holds important information such as the reason for `success` (an Eval enum), the gas used, the gas refunded, a vector of logs (`Vec`), and the output of the execution. This aligns with the stipulation in [EIP-658](https://eips.ethereum.org/EIPS/eip-658) that introduces a status code in the receipt of a transaction, indicating whether the top-level call was successful or failed. - -`Revert` represents a transaction that was reverted by the `REVERT` opcode without spending all of its gas. It stores the gas used and the output. `Halt` represents a transaction that was reverted for various reasons and consumed all its gas. It stores the reason for halting (a `Halt` enum) and the gas used. - -The `ExecutionResult` enum provides several methods to extract important data from an execution result, such as `is_success()`, `logs()`, `output()`, `into_output()`, `into_logs()`, and `gas_used()`. These methods facilitate accessing key details of a transaction execution. - -The `EVMError` and `InvalidTransaction` enums handle different kinds of errors that can occur in an EVM, including database errors, errors specific to the transaction itself, and errors that occur due to issues with gas, among others. - -The `Output` enum handles different kinds of outputs of an EVM execution, including `Call` and `Create`. This is where the output data from a successful execution or a reverted transaction is stored. diff --git a/documentation/src/crates/primitives/specifications.md b/documentation/src/crates/primitives/specifications.md deleted file mode 100644 index 7b3873fb02..0000000000 --- a/documentation/src/crates/primitives/specifications.md +++ /dev/null @@ -1,15 +0,0 @@ -# Specifications - -Holds data related to Ethereum's technical specifications, serving as a reference point for Ethereum's rules and procedures obtained from the [Ethereum execution specifications](https://github.com/ethereum/execution-specs). The module is primarily used to enumerate and handle Ethereum's network upgrades or "hard forks" within the Ethereum Virtual Machine (EVM). These hard forks are referred to as `SpecId` in the code, representing different phases of Ethereum's development. - -The `SpecId` enum assigns a unique numerical value and a unique string identifier to each Ethereum hard fork. These upgrades range from the earliest ones such as `FRONTIER` and `HOMESTEAD`, through to the most recent ones, including `LONDON`, `MERGE`, `SHANGHAI`, and `LATEST`. - -The code also includes conversion methods such as `try_from_u8()` and `from()`. The former attempts to create a `SpecId` from a given u8 integer, while the latter creates a `SpecId` based on a string representing the name of the hard fork. - -The `enabled()` method in `SpecId` is used to check if one spec is enabled on another, considering the order in which the hard forks were enacted. - -The `Spec` trait is used to abstract the process of checking whether a given spec is enabled. It only has one method, `enabled()`, and a constant `SPEC_ID`. - -The module then defines various `Spec` structs, each representing a different hard fork. These structs implement the `Spec` trait and each struct's `SPEC_ID` corresponds to the correct `SpecId` variant. - -This module provides the necessary framework to handle and interact with the different Ethereum hard forks within the EVM, making it possible to handle transactions and contracts differently depending on which hard fork rules apply. It also simplifies the process of adapting to future hard forks by creating a new `SpecId` and corresponding `Spec` struct. diff --git a/documentation/src/crates/primitives/state.md b/documentation/src/crates/primitives/state.md deleted file mode 100644 index d12a86f001..0000000000 --- a/documentation/src/crates/primitives/state.md +++ /dev/null @@ -1,15 +0,0 @@ -# State - -Manages the EVM's state, including account balances, contract storage, and more. - -This module models an Ethereum account and its state, which includes balance, nonce, code, storage, and status flags. The module also includes methods for interacting with the account's state. - -The `Account` struct includes fields for info (of type `AccountInfo`), storage (a `HashMap` mapping a `U256` value to a `StorageSlot`), and status (of type `AccountStatus`). `AccountInfo` represents the basic information about an Ethereum account, including its balance (`balance`), nonce (`nonce`), code (`code`), and a hash of its code (`code_hash`). - -The `AccountStatus` is a set of bitflags, representing the state of the account. The flags include `Loaded`, `Created`, `SelfDestructed`, `Touched`, and `LoadedAsNotExisting`. The different methods provided within the `Account` struct allow for manipulating these statuses. - -The `StorageSlot` struct represents a storage slot in the Ethereum Virtual Machine. It holds an `original_value` and a `present_value` and includes methods for creating a new slot and checking if the slot's value has been modified. - -Two `HashMap` type aliases are created: `State` and `Storage`. `State` maps from a `Address` address to an `Account` and `Storage` maps from a `U256` key to a `StorageSlot`. - -The module includes a series of methods implemented for `Account` to manipulate and query the account's status. These include methods like `mark_selfdestruct`, `unmark_selfdestruct`, `is_selfdestructed`, `mark_touch`, `unmark_touch`, `is_touched`, `mark_created`, `is_newly_created`, `is_empty`, and `new_not_existing`. diff --git a/documentation/src/crates/primitives/utils.md b/documentation/src/crates/primitives/utils.md deleted file mode 100644 index 5819c091f9..0000000000 --- a/documentation/src/crates/primitives/utils.md +++ /dev/null @@ -1,7 +0,0 @@ -# Utilities - -This Rust module provides utility functions and constants for handling Keccak hashing (used in Ethereum) and creating Ethereum addresses via legacy and `CREATE2` methods. It also includes serialization and deserialization methods for hexadecimal strings representing byte arrays. - -The `KECCAK_EMPTY` constant represents the Keccak-256 hash of an empty input. - -The `keccak256` function takes a byte slice input and returns its Keccak-256 hash as a `B256` value. diff --git a/documentation/src/crates/revm.md b/documentation/src/crates/revm.md deleted file mode 100644 index 2ad609f40a..0000000000 --- a/documentation/src/crates/revm.md +++ /dev/null @@ -1,39 +0,0 @@ -# Rust Ethereum Virtual Machine (revm) - -The `evm` crate is focused on the implementation of Ethereum Virtual Machine (EVM) including call loop and host implementation, database handling, state journaling and powerful logic handlers that can be overwritten. -This crate pulls Primitives, Interpreter and Precompiles together to deliver the rust evm. - -The starting point for reading the documentation is [`Evm`](./revm/evm.md), that is main structure of EVM. -Then, you can read about the [`EvmBuilder`](./revm/builder.md) that is used to create the `Evm` and modify it. -After, you can read about the [`Handler`](./revm/handler.md) that is used to modify the logic of the Evm, and it will tie with how Evm introspection can be done. -Finally, you can read about the [`Inspector`](./revm/inspector.md), a legacy interface for inspecting execution that is now repurposed as a handler register example. - -### Modules: - -- `evm`: This is main module that executes EVM calls. -- `builder`: - This module builds the Evm, sets database, handlers and other parameters. - Here is where we set handlers for specific fork or external state for inspection. -- `db`: - This module includes structures and functions for database interaction. - It is a glue between EVM and database. - It transforms or aggregates the EVM changes. -- `inspector`: - This module introduces the `Inspector` trait and its implementations for observing the EVM execution. - This was the main way to inspect EVM execution before the Builder and Handlers were introduced. - It is still enabled through the Builder. -- `journaled_state`: This module manages the state of the EVM and implements a journaling system to handle changes and reverts. - -### Re-exported Modules: - -- `revm_precompile`: Crate that provides precompiled contracts used in the EVM implementation. -- `revm_interpreter`: Crate that provides execution engine for EVM opcodes. -- `revm_interpreter::primitives`: This module from the `revm_interpreter` crate provides primitive types and other functionality used in the EVM implementation. - -### Re-exported Types: - -- `Database`, `DatabaseCommit`, `InMemoryDB`: These types from the `db` module are re-exported for handling the database operations. -- `EVM`: The `EVM` struct from the `evm` module is re-exported, serving as the main interface to the EVM implementation. -- `EvmContext`: The `EvmContext` struct from the `context` module is re-exported, providing data structures to encapsulate EVM execution data. -- `JournalEntry`, `JournaledState`: These types from the `journaled_state` module are re-exported, providing the journaling system for the EVM state. -- `inspectors`, `Inspector`: The `Inspector` trait and its implementations from the `inspector` module are re-exported for observing the EVM execution. diff --git a/documentation/src/crates/revm/builder.md b/documentation/src/crates/revm/builder.md deleted file mode 100644 index 7737efc99d..0000000000 --- a/documentation/src/crates/revm/builder.md +++ /dev/null @@ -1,171 +0,0 @@ -# Evm Builder - -The builder creates or modifies the EVM and applies different handlers. -It allows setting external context and registering handler custom logic. - -The revm `Evm` consists of `Context` and `Handler`. -`Context` is additionally split between `EvmContext` (contains generic `Database`) and `External` context (generic without restraint). -Read [evm](./evm.md) for more information on the internals. - -The `Builder` ties dependencies between generic `Database`, `External` context and `Spec`. -It allows handler registers to be added that implement logic on those generics. -As they are interconnected, setting `Database` or `ExternalContext` resets handle registers, so builder stages are introduced to mitigate those misuses. - -Simple example of using `EvmBuilder`: - -```rust,ignore - use crate::evm::Evm; - - // Build Evm with default values. - let mut evm = Evm::builder().build(); - let output = evm.transact(); -``` - -## Builder Stages - -There are two builder stages that are used to mitigate potential misuse of the builder: - -- `SetGenericStage`: Initial stage that allows setting the database and external context. -- `HandlerStage`: Allows setting the handler registers but is explicit about setting new generic type as it will void the handler registers. - -Functions from one stage are just renamed functions from other stage, it is made so that the user is more aware of what underlying function does. -For example, in `SettingDbStage` we have `with_db` function while in `HandlerStage` we have `reset_handler_with_db`, both of them set the database but the latter also resets the handler. -There are multiple functions that are common to both stages such as `build`. - -### Builder naming conventions - -In both stages we have: - -- `build` creates the Evm. -- `spec_id` creates new mainnet handler and reapplies all the handler registers. -- `modify_*` functions are used to modify the database, external context or Env. -- `clear_*` functions allows setting default values for Environment. -- `append_handler_register_*` functions are used to push handler registers. - This will transition the builder to the `HandlerStage`. - -In `SetGenericStage` we have: - -- `with_*` are found in `SetGenericStage` and are used to set the generics. - -In `HandlerStage` we have: - -- `reset_handler_with_*` is used if we want to change some of the generic types this will reset the handler registers. - This will transition the builder to the `SetGenericStage`. - -# Creating and modification of Evm - -Evm implements functions that allow using the `EvmBuilder` without even knowing that it exists. -The most obvious one is `Evm::builder()` that creates a new builder with default values. - -Additionally, a function that is very important is `evm.modify()` that allows modifying the Evm. -It returns a builder, allowing users to modify the Evm. - -# Examples - -The following example uses the builder to create an `Evm` with inspector: - -```rust,ignore - use crate::{ - db::EmptyDB, Context, EvmContext, inspector::inspector_handle_register, inspectors::NoOpInspector, Evm, - }; - - // Create the evm. - let evm = Evm::builder() - .with_db(EmptyDB::default()) - .with_external_context(NoOpInspector) - // Register will modify Handler and call NoOpInspector. - .append_handler_register(inspector_handle_register) - // .with_db(..) does not compile as we already locked the builder generics, - // alternative fn is reset_handler_with_db(..) - .build(); - - // Execute the evm. - let output = evm.transact(); - - // Extract evm context. - let Context { - external, - evm: EvmContext { db, .. }, - } = evm.into_context(); -``` - -The next example changes the spec id and environment of an already built evm. - -```rust,ignore - use crate::{Evm,SpecId::BERLIN}; - - // Create default evm. - let evm = Evm::builder().build(); - - // Modify evm spec. - let evm = evm.modify().with_spec_id(BERLIN).build(); - - // Shortcut for above. - let mut evm = evm.modify_spec_id(BERLIN); - - // Execute the evm. - let output1 = evm.transact(); - - // Example of modifying the tx env. - let mut evm = evm.modify().modify_tx_env(|env| env.gas_price = 0.into()).build(); - - // Execute the evm with modified tx env. - let output2 = evm.transact(); -``` - -Example of adding custom precompiles to Evm. - -```rust,ignore -use super::SpecId; -use crate::{ - db::EmptyDB, - inspector::inspector_handle_register, - inspectors::NoOpInspector, - primitives::{Address, Bytes, ContextStatefulPrecompile, ContextPrecompile, PrecompileResult}, - Context, Evm, EvmContext, -}; -use std::sync::Arc; - -struct CustomPrecompile; - -impl ContextStatefulPrecompile, ()> for CustomPrecompile { - fn call( - &self, - _input: &Bytes, - _gas_limit: u64, - _context: &mut EvmContext, - _extcontext: &mut (), - ) -> PrecompileResult { - Ok((10, Bytes::new())) - } -} -fn main() { - let mut evm = Evm::builder() - .with_empty_db() - .with_spec_id(SpecId::HOMESTEAD) - .append_handler_register(|handler| { - let precompiles = handler.pre_execution.load_precompiles(); - handler.pre_execution.load_precompiles = Arc::new(move || { - let mut precompiles = precompiles.clone(); - precompiles.extend([( - Address::ZERO, - ContextPrecompile::ContextStateful(Arc::new(CustomPrecompile)), - )]); - precompiles - }); - }) - .build(); - - evm.transact().unwrap(); -} - -``` - -## Appending handler registers - -Handler registers are simple functions that allow modifying the `Handler` logic by replacing the handler functions. -They are used to add custom logic to the evm execution but they are free to modify the `Handler` in any form they want. -There may be conflicts if handlers that override the same function are added. - -The most common use case for adding new logic to `Handler` is `Inspector` that is used to inspect the execution of the evm. -Example of this can be found in [`Inspector`](./inspector.md) documentation. diff --git a/documentation/src/crates/revm/evm.md b/documentation/src/crates/revm/evm.md deleted file mode 100644 index 264e890d06..0000000000 --- a/documentation/src/crates/revm/evm.md +++ /dev/null @@ -1,56 +0,0 @@ -# EVM - -`Evm` is the primary structure that implements the Ethereum Virtual Machine (EVM), a stack-based virtual machine that executes Ethereum smart contracts. - -## What is inside - -It is consisting of two main parts the `Context` and the `Handler`. `Context` represent the state that is needed for execution and `Handler` contains list of functions that act as a logic. - -`Context` is additionally split between `EvmContext` and `External` context. `EvmContext` is internal and contains `Database`, `Environment`, `JournaledState` and `Precompiles`. And `External` context is fully generic without any trait restrains and its purpose is to allow custom handlers to save state in runtime or allows hooks to be added (For example external contexts can be a Inspector), more on its usage can be seen in [`EvmBuilder`](./builder.md). - -`Evm` implements the [`Host`](./../interpreter/host.md) trait, which defines an interface for the interaction of the EVM Interpreter with its environment (or "host"), encompassing essential operations such as account and storage access, creating logs, and invoking sub calls and selfdestruct. - -Data structures of block and transaction can be found inside `Environment`. And more information on journaled state can be found in [`JournaledState`](../revm/journaled_state.md) documentation. - -## Runtime - -Runtime consists of list of functions from `Handler` that are called in predefined order. -They are grouped by functionality on `Verification`, `PreExecution`, `Execution`, `PostExecution` and `Instruction` functions. -Verification function are related to the pre-verification of set `Environment` data. -Pre-/Post-execution functions deduct and reward caller beneficiary. -And `Execution` functions handle initial call and creates and sub calls. -`Instruction` functions are part of the instruction table that is used inside `Interpreter` to execute opcodes. - -The `Evm` execution runs **two** loops: - - -### Call loop -The first loop is call loop that everything starts with, it creates call frames, handles subcalls, it returns outputs and calls `Interpreter` loop to execute bytecode instructions. -It is handled by `ExecutionHandler`. - -The first loop implements a stack of `Frames`. -It is responsible for handling sub calls and its return outputs. -At the start, `Evm` creates `Frame` containing `Interpreter` and starts the loop. - -The `Interpreter` returns the `InterpreterAction` which can be: -- `Return`: This interpreter finished its run. - `Frame` is popped from the stack and its return value is pushed to the parent `Frame` stack. -- `SubCall`/`SubCreate`: A new `Frame` needs to be created and pushed to the stack. - A new `Frame` is created and pushed to the stack and the loop continues. - When the stack is empty, the loop finishes. - -### Interpreter loop -The second loop is the `Interpreter` loop which is called by the call loop and loops over bytecode opcodes and executes instructions based on the `InstructionTable`. -It is implemented in the [`Interpreter`](../interpreter.md) crate. - -To dive deeper into the `Evm` logic check [`Handler`](./handler.md) documentation. - -# Functionalities - -The function of `Evm` is to start execution, but setting up what it is going to execute is done by `EvmBuilder`. -The main functions of the builder are: -* `preverify` - that only pre-verifies transaction information. -* `transact preverified` - is next step after pre-verification that executes transactions. -* `transact` - it calls both preverifies and executes transactions. -* `builder` and `modify` functions - allow building or modifying the `Evm`, more on this can be found in [`EvmBuilder`](./builder.md) documentation. `builder` is the main way of creating `Evm` and `modify` allows you to modify parts of it without dissolving `Evm`. -* `into_context` - is used when we want to get the `Context` from `Evm`. diff --git a/documentation/src/crates/revm/handler.md b/documentation/src/crates/revm/handler.md deleted file mode 100644 index 43ede26943..0000000000 --- a/documentation/src/crates/revm/handler.md +++ /dev/null @@ -1,120 +0,0 @@ -# Handler - -This is the logic part of the Evm. -It contains the Specification ID, list of functions that do the logic and list of registers that can change behavior of the Handler when it is build. - -Functions can be grouped in five categories and are marked in that way in the code: -* Validation functions: ValidationHandler -* Pre-execution functions: PreExecutionHandler -* Execution functions: ExecutionHandler -* Post-execution functions: PostExecutionHandler -* Instruction table: InstructionTable - -### Handle Registers - -This is a simple function that is used to modify handler functions. -The amazing thing about them is that they can be done over generic external type. -For example, this allows to have a register over trait that allows to add hooks to any type that implements the trait. -That trait can be a `GetInspector` trait, so any implementation is able to register inspector-related functions. -`GetInspector` is implemented on every `Inspector` and it is used inside the `EvmBuilder` to change behavior of the default mainnet Handler. - -Handle registers are set in `EvmBuilder`. -The order of the registers is important as they are called in the order they are registered. -It matters if register overrides the previous handle or just wraps it, overriding handle can disrupt the logic of previous registered handles. - -Registers are very powerful as they allow modification of any part of the Evm and with additional of the `External` context it becomes a powerful combo. -A simple example is to register new pre-compiles for the Evm. - -### ValidationHandler - -Consists of functions that are used to validate transaction and block data. -They are called before the execution of the transaction, to check whether the (`Environment`) data is valid. -They are called in the following order: -* `validate_env`: - Verifies if all data is set in `Environment` and if valid, for example if `gas_limit` is smaller than block `gas_limit`. -* `validate_initial_tx_gas`: - Calculates initial gas needed for the transaction to be executed and checks if it is less than the transaction gas_limit. - Note that this does not touch the `Database` or state. -* `validate_tx_against_state`: - Loads the caller account and checks their information. - Among them the nonce, if there is enough balance to pay for max gas spent and balance transferred. - -### PreExecutionHandler - -Consists of functions that are called before execution. -They are called in the following order: - -* `load`: - Loads access list and beneficiary from `Database`. Cold load is done here. - -* `load_precompiles`: - Retrieves the precompiles for the given spec ID. More info: [precompile](../precompile.md). - -* `apply_eip7702_auth_list` - Applies the EIP-7702 authorization list to the accounts. Return gas refund of already created accounts. - -* `deduct_caller`: - Deducts values from the caller to calculate the maximum amount of gas that can be spent on the transaction. - This loads the caller account from the `Database`. - -### ExecutionHandler - -Consists of functions that handle the execution of the transaction and the stack of the call frames. - -* `call`: - Called on every frame. - It creates a new call frame or returns the frame result (the frame result is only returned when calling `precompile`). - If `FrameReturn` is returned, then the next function that is called is `insert_call_outcome`. - -* `call_return`: - Called after call frame returns from execution. - It is used to calculate the gas that is returned from the frame and create the `FrameResult` that is used to apply the outcome to parent frame in `insert_call_outcome`. - -* `insert_call_outcome`: - Inserts the call outcome to the parent frame. - It is called on every frame that is created except the first one. - For the first frame we use `last_frame_return`. - -* `create`: - Creates new create call frame, create new account and execute bytecode that outputs the code of the new account. - -* `create_return`: - This handler is called after every frame is executed (Expect first). - It will calculate the gas that is returned from the frame and apply output to the parent frame. - -* `insert_create_outcome`: - Inserts the outcome of a call into the virtual machine's state. - -* `last_frame_return`: - This handler is called after last frame is returned. - It is used to calculate the gas that is returned from the first frame and incorporate transaction gas limit (the first frame has limit `gas_limit - initial_gas`). - -### InstructionTable - -This is a list of 256 function pointers that are used to execute instructions. -They have two types, first is simple function that is faster and second is `BoxedInstruction` that has a small performance penalty but allows to capture the data. -Look at the Interpreter documentation for more information. - -### PostExecutionHandler - -Is a list of functions that are called after the execution. They are called in the following order: - -* `refund` - Add EIP-7702 refund for already created accounts and calculates final gas refund that can - be a maximum of 1/5 (1/2 before London hardfork) of spent gas. - -* `reimburse_caller`: - Reimburse the caller with gas that was not spent during the execution of the transaction. - Or balance of gas that needs to be refunded. - -* `reward_beneficiary`: - Reward the beneficiary with the fee that was paid for the transaction. - -* `output`: - Returns the state changes and the result of the execution. - -* `end`: - Called after transaction. End handler will not be called if validation fails. - -* `clear`: - Clears journal state and error and it is always called for the cleanup. \ No newline at end of file diff --git a/documentation/src/crates/revm/inspector.md b/documentation/src/crates/revm/inspector.md deleted file mode 100644 index d9bdfe8b65..0000000000 --- a/documentation/src/crates/revm/inspector.md +++ /dev/null @@ -1,37 +0,0 @@ -# Inspectors - -This module contains various inspectors that can be used to execute and monitor transactions on the Ethereum Virtual Machine (EVM) through the `revm` library. - -## Overview - -There are several built-in inspectors in this module: - -- `NoOpInspector`: A basic inspector that does nothing, which can be used when you don't need to monitor transactions. -- `GasInspector`: Monitors the gas usage of transactions. -- `CustomPrintTracer`: - Traces and prints custom messages during EVM execution. - Available only when the `std` feature is enabled. -- `TracerEip3155`: - This is an inspector that conforms to the [EIP-3155](https://eips.ethereum.org/EIPS/eip-3155) standard for tracing Ethereum transactions. - It's used to generate detailed trace data of transaction execution, which can be useful for debugging, analysis, or for building tools that need to understand the inner workings of Ethereum transactions. - This is only available when both `std` and `serde-json` features are enabled. - -## Inspector trait - -The `Inspector` trait defines methods that are called during various stages of EVM execution. -You can implement this trait to create your own custom inspectors. - -Each of these methods is called at different stages of the execution of a transaction. -They can be used to monitor, debug, or modify the execution of the EVM. - -For example, the `step` method is called on each step of the interpreter, and the `log` method is called when a log is emitted. - -You can implement this trait for a custom database type `DB` that implements the `Database` trait. - -## Usage - -To use an inspector, you need to implement the `Inspector` trait. -For each method, you can decide what you want to do at each point in the EVM execution. -For example, to capture all `SELFDESTRUCT` operations, implement the `selfdestruct` method. - -All methods in the `Inspector` trait are optional to implement; if you do not need specific functionality, you can use the provided default implementations. diff --git a/documentation/src/crates/revm/journaled_state.md b/documentation/src/crates/revm/journaled_state.md deleted file mode 100644 index 91545a8ece..0000000000 --- a/documentation/src/crates/revm/journaled_state.md +++ /dev/null @@ -1,147 +0,0 @@ -# Journaled State - -The `journaled_state` module of the `revm` crate provides a state management implementation for Ethereum-style accounts. It includes support for various actions such as self-destruction of accounts, initial account loading, account state modification, and logging. It also contains several important utility functions such as `is_precompile`. - -This module is built around the `JournaledState` structure, which encapsulates the entire state of the blockchain. `JournaledState` uses an internal state representation (a `HashMap`) that tracks all accounts. Each account is represented by the `Account` structure, which includes fields like balance, nonce, and code hash. For state-changing operations, the module keeps track of all the changes within a "journal" for easy reversion and commitment to the database. This feature is particularly useful for handling reversion of state changes in case of transaction failures or other exceptions. The module interacts with a database through the `Database` trait, which abstracts the operations for fetching and storing data. This design allows for a pluggable backend where different implementations of the `Database` trait can be used to persist the state in various ways (for instance, in-memory or disk-based databases). - -## Data Structures - -- `JournaledState`: - This structure represents the entire state of the blockchain, including accounts, their associated balances, nonces, and code hashes. - It maintains a journal of all state changes that allows for easy reversion and commitment of changes to the database. - -- `Account`: - This structure represents an individual account on the blockchain. - It includes the account's balance, nonce, and code hash. - It also includes a flag indicating if the account is self-destructed, and a map representing the account's storage. - -- `JournalEntry`: - This structure represents an entry in the `JournaledState`'s journal. - Each entry describes an operation that changes the state, such as an account loading, an account destruction, or a storage change. - -## Methods - -- `selfdestruct`: - This method marks an account as self-destructed and transfers its balance to a target account. - If the target account does not exist, it's created. - If the self-destructed account and the target are the same, the balance will be lost. - -- `initial_account_load`: - This method loads an account's basic information from the database without loading the code. - It also loads specified storage slots into memory. - -- `load_account`: - This method loads an account's information into memory and returns whether the account was cold or warm accessed. - -- `load_account_exist`: - This method checks whether an account exists or not. - It returns whether the account was cold or warm accessed and whether it exists. - -- `load_code`: - This method loads an account's code into memory from the database. - -- `sload`: - This method loads a specified storage value of an account. - It returns the value and whether the storage was cold loaded. - -- `sstore`: - This method changes the value of a specified storage slot in an account and returns the original value, the present value, the new value, and whether the storage was cold loaded. - -- `log`: - This method adds a log entry to the journal. - -- `is_precompile`: - This method checks whether an address is a precompiled contract or not. - -# Relevant EIPs - -The JournaledState module's operations are primarily designed to comply with the Ethereum standards defined in several Ethereum Improvement Proposals (EIPs). -More specifically: - -## [EIP-161](https://eips.ethereum.org/EIPS/eip-161): State Trie Clearing - -[EIP-161](https://eips.ethereum.org/EIPS/eip-161) aims to optimize Ethereum's state management by deleting empty accounts. The specification was proposed by Gavin Wood and was activated in the Spurious Dragon hardfork at block number `2,675,000` on the Ethereum mainnet.proposal. The EIP focuses on four main changes: - -- **Account Creation**: - During the creation of an account (whether by transactions or the `CREATE` operation), the nonce of the new account is incremented by one before the execution of the initialization code. - For most networks, the starting value is 1, but this may vary for test networks with non-zero default starting nonces. - -- **`CALL` and `SELFDESTRUCT` charges**: - Prior to [EIP-161](https://eips.ethereum.org/EIPS/eip-161), a gas charge of `25,000` was levied for `CALL` and `SELFDESTRUCT` operations if the destination account did not exist. - With [EIP-161](https://eips.ethereum.org/EIPS/eip-161), this charge is only applied if the operation transfers more than zero value and the destination account is dead (non-existent or empty). - -- **Existence of Empty Accounts**: - An account cannot change its state from non-existent to existent-but-empty. - If an operation resulted in an empty account, the account remains non-existent. - -- **Removal of Empty Accounts**: - At the end of a transaction, any account that was involved in potentially state-changing operations and is now empty will be deleted. - -#### Definitions: -- **empty**: An account is considered "empty" if it has no code, and its nonce and balance are both zero. -- **dead**: An account is considered "dead" if it is non-existent or empty. -- **touched**: An account is considered "touched" when it is involved in any potentially state-changing operation. - -These rules have an impact on how state is managed within the [EIP-161](https://eips.ethereum.org/EIPS/eip-161) context, and this affects how the JournaledState module functions. -For example, operations like `initial_account_load`, and `selfdestruct` all need to take into account whether an account is empty and/or dead. - -## Rationale - -The rationale behind [EIP-161](https://eips.ethereum.org/EIPS/eip-161) is to optimize the Ethereum state management by getting rid of unnecessary data. -Prior to this change, it was possible for the state trie to become bloated with empty accounts. -This bloating resulted in increased storage requirements and slower processing times for Ethereum nodes. - -By removing these empty accounts, the size of the state trie can be reduced, leading to improvements in the performance of Ethereum nodes. -Additionally, the changes regarding the gas costs for `CALL` and `SELFDESTRUCT` operations add a new level of nuance to the Ethereum gas model, further optimizing transaction processing. - -[EIP-161](https://eips.ethereum.org/EIPS/eip-161) has a significant impact on the state management of Ethereum, and thus is highly relevant to the JournaledState module of the revm crate. -The operations defined in this module, such as loading accounts, self-destructing accounts, and changing storage, must all conform to the rules defined in [EIP-161](https://eips.ethereum.org/EIPS/eip-161). - -## [EIP-658](https://eips.ethereum.org/EIPS/eip-658): Embedding transaction status code in receipts - -This EIP is particularly important because it introduced a way to unambiguously determine whether a transaction was successful or not. Before the introduction of [EIP-658](https://eips.ethereum.org/EIPS/eip-658), it was impossible to determine with certainty if a transaction was successful simply based on its gas consumption. This was because with the introduction of the `REVERT` opcode in [EIP-140](https://eips.ethereum.org/EIPS/eip-140), transactions could fail without consuming all gas. - -[EIP-658](https://eips.ethereum.org/EIPS/eip-658) replaced the intermediate state root field in the receipt with a status code that indicates whether the top-level call of the transaction succeeded or failed. The status code is 1 for success and 0 for failure. - -This EIP affects the JournaledState module, as the result of executing transactions and their success or failure status directly influences the state of the blockchain. The execution of state-modifying methods like , `selfdestruct`, `sstore`, and `log` can result in success or failure, and the status needs to be properly reflected in the transaction receipt. - -## Rationale - -The main motivation behind [EIP-658](https://eips.ethereum.org/EIPS/eip-658) was to provide an unambiguous way to determine the success or failure of a transaction. -Before [EIP-658](https://eips.ethereum.org/EIPS/eip-658), users had to rely on checking if a transaction had consumed all gas to guess if it had failed. -However, this was not reliable because of the introduction of the `REVERT` opcode in [EIP-140](https://eips.ethereum.org/EIPS/eip-140). - -Moreover, although full nodes can replay transactions to get their return status, fast nodes can only do this for transactions after their pivot point, and light nodes cannot do it at all. -This means that without [EIP-658](https://eips.ethereum.org/EIPS/eip-658), it is impractical for a non-full node to reliably determine the status of a transaction. - -[EIP-658](https://eips.ethereum.org/EIPS/eip-658) addressed this problem by embedding the status code directly in the transaction receipt, making it easily accessible. This change was minimal and non-disruptive, while it significantly improved the clarity and usability of transaction receipts. - -## [EIP-2929](https://eips.ethereum.org/EIPS/eip-2929): Gas cost increases for state access opcodes - -[EIP-2929](https://eips.ethereum.org/EIPS/eip-2929) proposes an increase in the gas costs for several opcodes when they're used for the first time in a transaction. The EIP was created to mitigate potential DDoS (Distributed Denial of Service) attacks by increasing the cost of potential attack vectors, and to make the stateless witness sizes in Ethereum more manageable. - -[EIP-2929](https://eips.ethereum.org/EIPS/eip-2929) also introduces two sets, `accessed_addresses` and `accessed_storage_keys`, to track the addresses and storage slots that have been accessed within a transaction. This mitigates the additional gas cost for repeated operations on the same address or storage slot within a transaction, as any repeated operation on an already accessed address or storage slot will cost less gas. - -In the context of this EIP, "cold" and "warm" (or "hot") refer to whether an address or storage slot has been accessed before during the execution of a transaction. If an address or storage slot is being accessed for the first time in a transaction, it is referred to as a "cold" access. If it has already been accessed within the same transaction, any subsequent access is referred to as "warm" or "hot". - -- **Parameters**: The EIP defines new parameters such as `COLD_SLOAD_COST` (2100 gas) for a "cold" storage read, `COLD_ACCOUNT_ACCESS_COST` (2600 gas) for a "cold" account access, and `WARM_STORAGE_READ_COST` (100 gas) for a "warm" storage read. - -- **Storage read changes**: For `SLOAD` operation, if the (address, storage_key) pair is not yet in `accessed_storage_keys`, `COLD_SLOAD_COST` gas is charged and the pair is added to `accessed_storage_keys`. If the pair is already in `accessed_storage_keys`, `WARM_STORAGE_READ_COST` gas is charged. - -- **Account access changes**: When an address is the target of certain opcodes (`EXTCODESIZE`, `EXTCODECOPY`, `EXTCODEHASH`, `BALANCE`, `CALL`, `CALLCODE`, `DELEGATECALL`, `STATICCALL`), if the target is not in `accessed_addresses`, `COLD_ACCOUNT_ACCESS_COST` gas is charged, and the address is added to `accessed_addresses`. Otherwise, `WARM_STORAGE_READ_COST` gas is charged. - -- **`SSTORE` changes**: For `SSTORE` operation, if the (address, storage_key) pair is not in `accessed_storage_keys`, an additional `COLD_SLOAD_COST` gas is charged, and the pair is added to `accessed_storage_keys`. - -- **`SELFDESTRUCT` changes**: If the recipient of `SELFDESTRUCT` is not in `accessed_addresses`, an additional `COLD_ACCOUNT_ACCESS_COST` is charged, and the recipient is added to the set. - -This methodology allows Ethereum to maintain an internal record of accessed accounts and storage slots within a transaction, making it possible to charge lower gas fees for repeated operations, thereby reducing the cost for such operations. - -## Rationale - -- **Security**: - Previously, these opcodes were underpriced, making them susceptible to DoS attacks where an attacker sends transactions that access or call a large number of accounts. - By increasing the gas costs, the EIP intends to mitigate these potential security risks. - -- **Improving stateless witness sizes**: - Stateless Ethereum clients don't maintain the complete state of the blockchain, but instead rely on block "witnesses" (a list of all the accounts, storage, and contract code accessed during transaction execution) to validate transactions. - This EIP helps in reducing the size of these witnesses, thereby making stateless Ethereum more viable. diff --git a/documentation/src/introduction.md b/documentation/src/introduction.md deleted file mode 100644 index 272bd488af..0000000000 --- a/documentation/src/introduction.md +++ /dev/null @@ -1,30 +0,0 @@ -# Introduction - -`revm` is an Ethereum Virtual Machine (EVM) written in Rust that is focused on speed and simplicity. This documentation is very much a work in progress and a community effort. If you would like to contribute and improve these docs please make a pr to the [github repo](https://github.com/bluealloy/revm/tree/main). Most importantly, Revm is just the execution environment for ethereum; there is no networking or consensus related work in this repository. - -## Crates - -The project has 4 main crates that are used to build revm. These are: - -- `revm`: The main EVM library. -- `interpreter`: Execution loop with instructions. -- `primitives`: Primitive data types. -- `precompile`: EVM precompiles. - -## Testing with the binaries - -There are two binaries both of which are used for testing. To install them run `cargo install --path bins/`. The binaries are: - -- `revme`: A CLI binary, used for running state test json. Currently it is used to run [ethereum tests](https://github.com/ethereum/tests) to check if revm is compliant. For example if you have the eth tests cloned into a directory called eth tests and the EIP tests in the following directories you can run -```bash -cargo run --profile ethtests -p revme -- \ - statetest \ - ../ethtests/GeneralStateTests/ \ - ../ethtests/LegacyTests/Constantinople/GeneralStateTests/ \ - bins/revme/tests/EIPTests/StateTests/stEIP5656-MCOPY/ \ - bins/revme/tests/EIPTests/StateTests/stEIP1153-transientStorage/ -``` - -- `revm-test`: test binaries with contracts; used mostly to check performance - -If you are interested in contributing, be sure to run the statetests. It is recommended to read about the [ethereum tests](https://ethereum-tests.readthedocs.io/en/latest/).