Skip to content

Commit

Permalink
feat(crate): no-std support (#60)
Browse files Browse the repository at this point in the history
* feat(crate): no-std support

This adds a std feature (enabled by default), and adds support for a no-std environment. The most notable changes are:

- `OnceLock` has been replaced for `OnceCell` on `BlockOutput`. We lose thread safety by doing this, but the EVM, and trevm by extension, has been designed to work on a single-thread context, so this is OK for now (and easily encapsulable with message passing if concurrency was indeed needed e.g for a fuzzer).
- The 3155 tracer test util was std-gated. This is OK, as the 3155 tracer requires std anywhere.

* chore: misc fixes and missing alloc/core imports

* chore(errors): manually implement errors instead of using thiserror

* feat: no-default features check on trevm

* chore: remove comments

* feat: implement ERror for JournalDecodeError

* chore: rebase

* fixes
  • Loading branch information
Evalir authored Oct 22, 2024
1 parent 28cb36d commit 67d3f6e
Show file tree
Hide file tree
Showing 16 changed files with 172 additions and 56 deletions.
18 changes: 17 additions & 1 deletion .github/workflows/rust-ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,20 @@ env:

jobs:
rust-base:
uses: init4tech/actions/.github/workflows/rust-base.yml@main
uses: init4tech/actions/.github/workflows/rust-base.yml@main

test-no-features:
name: Test Suite (no default features)
runs-on:
group: init4-runners
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Install Rust toolchain
uses: dtolnay/rust-toolchain@stable
- uses: Swatinem/rust-cache@v2
- name: Run tests
env:
CARGO_NET_GIT_FETCH_WITH_CLI: true
run: |
cargo test --no-default-features
5 changes: 3 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,6 @@ revm = { version = "16.0.0", default-features = false, features = ["std"] }

zenith-types = "0.10"

thiserror = "1.0"

# TODO: remove this later
# https://github.com/serde-rs/serde/issues/2844
serde = { version = "=1.0.210"}
Expand All @@ -64,13 +62,16 @@ eyre = "0.6"

[features]
default = [
"std",
"revm/std",
"revm/c-kzg",
"revm/blst",
"revm/portable",
"revm/secp256k1",
]

std = ["revm/std", "alloy/std", "alloy-rlp/std", "alloy-primitives/std", "alloy-sol-types/std"]

test-utils = ["revm/test-utils", "revm/std", "revm/serde-json", "revm/alloydb"]


Expand Down
66 changes: 49 additions & 17 deletions src/driver/alloy.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use crate::{
trevm_bail, trevm_ensure, unwrap_or_trevm_err, Block, BundleDriver, DriveBundleResult,
};
use alloc::vec::Vec;
use alloy::{
consensus::{Transaction, TxEip4844Variant, TxEnvelope},
eips::{eip2718::Decodable2718, BlockNumberOrTag},
Expand All @@ -11,51 +12,82 @@ use alloy::{
};
use alloy_primitives::{bytes::Buf, keccak256, Address, Bytes, TxKind, U256};
use revm::primitives::{EVMError, ExecutionResult, MAX_BLOB_GAS_PER_BLOCK};
use thiserror::Error;

/// Possible errors that can occur while driving a bundle.
#[derive(Error)]
pub enum BundleError<Db: revm::Database> {
/// The block number of the bundle does not match the block number of the revm block configuration.
#[error("revm block number must match the bundle block number")]
BlockNumberMismatch,
/// The timestamp of the bundle is out of range.
#[error("timestamp out of range")]
TimestampOutOfRange,
/// The bundle was reverted (or halted).
#[error("bundle reverted")]
BundleReverted,
/// The bundle has no transactions
#[error("bundle has no transactions")]
BundleEmpty,
/// Too many blob transactions
#[error("max blob gas limit exceeded")]
Eip4844BlobGasExceeded,
/// An unsupported transaction type was encountered.
#[error("unsupported transaction type")]
UnsupportedTransactionType,
/// An error occurred while decoding a transaction contained in the bundle.
#[error("transaction decoding error")]
TransactionDecodingError(#[from] alloy::eips::eip2718::Eip2718Error),
/// An error ocurred while recovering the sender of a transaction
#[error("transaction sender recovery error")]
TransactionSenderRecoveryError(#[from] alloy_primitives::SignatureError),
TransactionDecodingError(alloy::eips::eip2718::Eip2718Error),
/// An error occurred while recovering the sender of a transaction.
TransactionSenderRecoveryError(alloy_primitives::SignatureError),
/// An error occurred while running the EVM.
#[error("internal EVM Error")]
EVMError {
/// The error that occurred while running the EVM.
inner: EVMError<Db::Error>,
},
}

impl<Db: revm::Database> core::fmt::Display for BundleError<Db> {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
match self {
Self::BlockNumberMismatch => {
write!(f, "revm block number must match the bundle block number")
}
Self::TimestampOutOfRange => write!(f, "timestamp out of range"),
Self::BundleReverted => write!(f, "bundle reverted"),
Self::BundleEmpty => write!(f, "bundle has no transactions"),
Self::Eip4844BlobGasExceeded => write!(f, "max blob gas limit exceeded"),
Self::UnsupportedTransactionType => write!(f, "unsupported transaction type"),
Self::TransactionDecodingError(_) => write!(f, "transaction decoding error"),
Self::TransactionSenderRecoveryError(_) => {
write!(f, "transaction sender recovery error")
}
Self::EVMError { inner: _ } => write!(f, "internal EVM Error"),
}
}
}

impl<Db: revm::Database> From<alloy::eips::eip2718::Eip2718Error> for BundleError<Db> {
fn from(err: alloy::eips::eip2718::Eip2718Error) -> Self {
Self::TransactionDecodingError(err)
}
}

impl<Db: revm::Database> From<alloy_primitives::SignatureError> for BundleError<Db> {
fn from(err: alloy_primitives::SignatureError) -> Self {
Self::TransactionSenderRecoveryError(err)
}
}

impl<Db: revm::Database> From<EVMError<Db::Error>> for BundleError<Db> {
fn from(inner: EVMError<Db::Error>) -> Self {
Self::EVMError { inner }
}
}

impl<Db: revm::Database> std::fmt::Debug for BundleError<Db> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
impl<Db: revm::Database> core::error::Error for BundleError<Db> {
fn source(&self) -> Option<&(dyn core::error::Error + 'static)> {
match self {
Self::TransactionDecodingError(err) => Some(err),
Self::TransactionSenderRecoveryError(err) => Some(err),
_ => None,
}
}
}

impl<Db: revm::Database> core::fmt::Debug for BundleError<Db> {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
match self {
Self::TimestampOutOfRange => write!(f, "TimestampOutOfRange"),
Self::BlockNumberMismatch => write!(f, "BlockNumberMismatch"),
Expand Down Expand Up @@ -94,7 +126,7 @@ where
/// Clear the driver, resetting the response. This resets the driver,
/// allowing for resimulation of the same bundle.
pub fn clear(&mut self) -> R {
std::mem::take(&mut self.response)
core::mem::take(&mut self.response)
}
}

Expand Down
2 changes: 1 addition & 1 deletion src/driver/block.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ pub trait BlockDriver<Ext> {
type Block: Block;

/// An error type for this driver.
type Error<Db: Database>: std::error::Error + From<EVMError<Db::Error>>;
type Error<Db: Database>: core::error::Error + From<EVMError<Db::Error>>;

/// Get a reference to the block filler for this driver.
fn block(&self) -> &Self::Block;
Expand Down
2 changes: 1 addition & 1 deletion src/driver/bundle.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ pub type DriveBundleResult<'a, Ext, Db, T> =
/// entire lifecycle of a bundle, simulating the entire list of transactions.
pub trait BundleDriver<Ext> {
/// An error type for this driver.
type Error<Db: Database>: std::error::Error + From<EVMError<Db::Error>>;
type Error<Db: Database>: core::error::Error + From<EVMError<Db::Error>>;

/// Run the transactions contained in the bundle.
fn run_bundle<'a, Db: Database + DatabaseCommit>(
Expand Down
2 changes: 1 addition & 1 deletion src/driver/chain.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ pub trait ChainDriver<Ext> {
type BlockDriver: BlockDriver<Ext>;

/// An error type for this driver.
type Error<Db: Database>: std::error::Error
type Error<Db: Database>: core::error::Error
+ From<EVMError<Db::Error>>
+ From<<Self::BlockDriver as BlockDriver<Ext>>::Error<Db>>;

Expand Down
17 changes: 9 additions & 8 deletions src/evm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@ use crate::{
EvmNeedsCfg, EvmNeedsTx, EvmReady, EvmTransacted, HasBlock, HasCfg, HasTx, NeedsCfg, NeedsTx,
TransactedState, Tx,
};
use alloc::{boxed::Box, fmt};
use alloy_primitives::{Address, Bytes, U256};
use core::convert::Infallible;
use revm::{
db::{states::bundle_state::BundleRetention, BundleState, State},
primitives::{
Expand All @@ -13,7 +15,6 @@ use revm::{
},
Database, DatabaseCommit, DatabaseRef, Evm,
};
use std::{convert::Infallible, fmt};

/// Trevm provides a type-safe interface to the EVM, using the typestate pattern.
///
Expand Down Expand Up @@ -459,7 +460,7 @@ impl<'a, Ext, Db: Database + DatabaseCommit> EvmNeedsCfg<'a, Ext, Db> {
pub fn fill_cfg<T: Cfg>(mut self, filler: &T) -> EvmNeedsBlock<'a, Ext, Db> {
filler.fill_cfg(&mut self.inner);
// SAFETY: Same size and repr. Only phantomdata type changes
unsafe { std::mem::transmute(self) }
unsafe { core::mem::transmute(self) }
}
}

Expand Down Expand Up @@ -567,7 +568,7 @@ impl<'a, Ext, Db: Database + DatabaseCommit, TrevmState: HasCfg> Trevm<'a, Ext,
settings: revm::primitives::EnvKzgSettings,
) -> revm::primitives::EnvKzgSettings {
let cfg = self.inner.cfg_mut();
std::mem::replace(&mut cfg.kzg_settings, settings)
core::mem::replace(&mut cfg.kzg_settings, settings)
}

/// Set a limit beyond which a callframe's memory cannot be resized.
Expand All @@ -582,7 +583,7 @@ impl<'a, Ext, Db: Database + DatabaseCommit, TrevmState: HasCfg> Trevm<'a, Ext,
#[cfg(feature = "memory_limit")]
pub fn set_memory_limit(&mut self, new_limit: u64) -> u64 {
let cfg = self.inner.cfg_mut();
std::mem::replace(&mut cfg.memory_limit, new_limit)
core::mem::replace(&mut cfg.memory_limit, new_limit)
}

/// Disable balance checks. If the sender does not have enough balance to
Expand Down Expand Up @@ -833,7 +834,7 @@ impl<'a, Ext, Db: Database + DatabaseCommit> EvmNeedsBlock<'a, Ext, Db> {
pub fn fill_block<B: Block>(mut self, filler: &B) -> EvmNeedsTx<'a, Ext, Db> {
filler.fill_block(self.inner_mut_unchecked());
// SAFETY: Same size and repr. Only phantomdata type changes
unsafe { std::mem::transmute(self) }
unsafe { core::mem::transmute(self) }
}
}

Expand Down Expand Up @@ -905,7 +906,7 @@ impl<'a, Ext, Db: Database + DatabaseCommit> EvmNeedsTx<'a, Ext, Db> {
/// Close the current block, returning the EVM ready for the next block.
pub fn close_block(self) -> EvmNeedsBlock<'a, Ext, Db> {
// SAFETY: Same size and repr. Only phantomdata type changes
unsafe { std::mem::transmute(self) }
unsafe { core::mem::transmute(self) }
}

/// Drive a bundle to completion, apply some post-bundle logic, and return the
Expand All @@ -926,7 +927,7 @@ impl<'a, Ext, Db: Database + DatabaseCommit> EvmNeedsTx<'a, Ext, Db> {
pub fn fill_tx<T: Tx>(mut self, filler: &T) -> EvmReady<'a, Ext, Db> {
filler.fill_tx(&mut self.inner);
// SAFETY: Same size and repr. Only phantomdata type changes
unsafe { std::mem::transmute(self) }
unsafe { core::mem::transmute(self) }
}

/// Execute a transaction. Shortcut for `fill_tx(tx).run_tx()`.
Expand Down Expand Up @@ -992,7 +993,7 @@ impl<'a, Ext, Db: Database + DatabaseCommit> EvmReady<'a, Ext, Db> {
// logic in a block driver

// SAFETY: Same size and repr. Only phantomdata type changes
unsafe { std::mem::transmute(self) }
unsafe { core::mem::transmute(self) }
}

/// Execute the loaded transaction. This is a wrapper around
Expand Down
4 changes: 1 addition & 3 deletions src/ext.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
use std::collections::HashMap;

use alloy_primitives::{Address, B256, U256};
use revm::{
primitives::{Account, AccountInfo, Bytecode, EvmState, EvmStorageSlot},
primitives::{Account, AccountInfo, Bytecode, EvmState, EvmStorageSlot, HashMap},
Database, DatabaseCommit,
};

Expand Down
1 change: 1 addition & 0 deletions src/fill/zenith.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use crate::Tx;
use alloc::vec;
use alloy_primitives::{Address, U256};
use alloy_sol_types::SolCall;
use revm::primitives::{TransactTo, TxEnv};
Expand Down
Loading

0 comments on commit 67d3f6e

Please sign in to comment.