Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4,247 changes: 824 additions & 3,423 deletions Cargo.lock

Large diffs are not rendered by default.

13 changes: 0 additions & 13 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,19 +11,6 @@ homepage = "https://github.com/rainlanguage/rainlang"
alloy = { version = "1.0.9", features = ["sol-types", "json", "json-abi"] }
anyhow = "1.0.70"
clap = { version = "4.2.5", features = ["cargo", "derive"] }
foundry-evm = { git = "https://github.com/foundry-rs/foundry", rev = "ed86c645f037f1cc4e5c1583f074a7b2142c4f66" }
foundry-evm-core = { git = "https://github.com/foundry-rs/foundry", rev = "ed86c645f037f1cc4e5c1583f074a7b2142c4f66" }
foundry-fork-db = "0.15.0"
foundry-block-explorers = "0.18.0"
revm = { version = "24.0.1", default-features = false, features = [
"std",
"serde",
"memory_limit",
"optional_eip3607",
"optional_block_gas_limit",
"optional_no_base_fee",
"arbitrary",
] }
serde = "1.0.160"
serde_bytes = "0.11.9"
serde_json = "1.0.112"
Expand Down
5 changes: 4 additions & 1 deletion crates/cli/src/commands/eval.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,10 @@ use anyhow::anyhow;
use clap::Args;
use rainlang_bindings::IInterpreterStoreV3::FullyQualifiedNamespace;
use rainlang_eval::trace::RainEvalResult;
use rainlang_eval::{eval::ForkEvalArgs, fork::Forker};
use rainlang_eval::{
eval::{ForkEvalArgs, ForkEvalExt},
fork::Forker,
};
use std::path::PathBuf;

/// CLI arguments for evaluating a Rainlang expression.
Expand Down
2 changes: 1 addition & 1 deletion crates/cli/src/commands/parse.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use alloy::primitives::Address;
use anyhow::Result;
use anyhow::anyhow;
use clap::Args;
use rainlang_eval::eval::ForkParseArgs;
use rainlang_eval::eval::{ForkEvalExt, ForkParseArgs};
use rainlang_eval::fork::Forker;
use std::path::PathBuf;

Expand Down
12 changes: 4 additions & 8 deletions crates/eval/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,18 +13,14 @@ serde = { workspace = true }
eyre = { workspace = true }
rain-error-decoding = { workspace = true }

# The forking executor (multi-fork, calls, tracing, replay) now lives in the
# published rain-forker crate instead of the unpublishable foundry-evm git dep.
# Native-only: forking against a live RPC has no meaning on wasm.
[target.'cfg(not(target_family = "wasm"))'.dependencies]
foundry-evm = { workspace = true }
revm = { workspace = true }
rain-forker = "0.1"

[target.'cfg(target_family = "wasm")'.dependencies]
wasm-bindgen-utils.workspace = true
revm = { version = "25.0.0", default-features = false, features = [
"kzg-rs",
"portable",
"std",
"tracer",
] }

[dev-dependencies]
tracing = { workspace = true }
Expand Down
59 changes: 5 additions & 54 deletions crates/eval/src/error.rs
Original file line number Diff line number Diff line change
@@ -1,54 +1,5 @@
use alloy::primitives::ruint::FromUintError;
#[cfg(not(target_family = "wasm"))]
use foundry_evm::{backend::DatabaseError, executors::RawCallResult};
use rain_error_decoding::{AbiDecodeFailedErrors, AbiDecodedErrorType};
use thiserror::Error;

/// Errors that can occur when calling a forked EVM.
#[derive(Debug, Error)]
pub enum ForkCallError {
#[error("Executor error: {0}")]
ExecutorError(String),
#[cfg(not(target_family = "wasm"))]
#[error("Call failed: {:#?}", .0)]
Failed(Box<RawCallResult>),
#[error("Typed error: {0}")]
TypedError(String),
#[error(transparent)]
AbiDecodeFailed(#[from] AbiDecodeFailedErrors),
#[error(transparent)]
AbiDecodedError(#[from] AbiDecodedErrorType),
#[error("Failed to deserialize serialized expression: {0}")]
DeserializeFailed(String),
#[error(transparent)]
U64FromUint256(#[from] FromUintError<u64>),
#[error(transparent)]
Eyre(#[from] eyre::Report),
#[error("Replay transaction error: {:#?}", .0)]
ReplayTransactionError(#[from] ReplayTransactionError),
}

/// Errors specific to replaying a historical transaction.
#[derive(Debug, Error)]
pub enum ReplayTransactionError {
#[error("Transaction not found for hash {0} and fork url {1}")]
TransactionNotFound(String, String),
#[error("No active fork found")]
NoActiveFork,
#[cfg(not(target_family = "wasm"))]
#[error("Database error for hash {0} and fork url {1}: {2}")]
DatabaseError(String, String, DatabaseError),
#[error("No block number found in transaction for hash {0} and fork url {1}")]
NoBlockNumberFound(String, String),
#[error("No from address found in transaction for hash {0} and fork url {1}")]
NoFromAddressFound(String, String),
#[error("Cannot replay genesis block (block 0) transaction for hash {0} and fork url {1}")]
GenesisBlockReplay(String, String),
}

#[cfg(not(target_family = "wasm"))]
impl From<RawCallResult> for ForkCallError {
fn from(value: RawCallResult) -> Self {
Self::Failed(Box::new(value))
}
}
//! Re-export of the forking error types, which now live in `rain-forker`.
//!
//! Kept as `rain_interpreter_eval::error` for backwards compatibility with
//! downstream consumers.
pub use rain_forker::error::{ForkCallError, ReplayTransactionError};
36 changes: 24 additions & 12 deletions crates/eval/src/eval.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,12 +52,26 @@ impl From<ForkEvalArgs> for ForkParseArgs {
}
}

impl Forker {
/// Parses Rainlang string and returns the parsed result.
///
/// Discovers the deployer address from Rainlang, then calls
/// `parse2` on it.
pub async fn fork_parse(
/// Rain-specific parse/eval helpers on top of the generic [`Forker`].
///
/// Defined as an extension trait because `Forker` now lives in the external
/// `rain-forker` crate, so inherent methods can't be added to it here.
pub trait ForkEvalExt {
/// Parses a Rainlang string against the deployer discovered from `rainlang`.
fn fork_parse(
&self,
args: ForkParseArgs,
) -> impl std::future::Future<Output = Result<ForkTypedReturn<parse2Call>, ForkCallError>>;

/// Evaluates a Rainlang string against the interpreter discovered from `rainlang`.
fn fork_eval(
&self,
args: ForkEvalArgs,
) -> impl std::future::Future<Output = Result<ForkTypedReturn<eval4Call>, ForkCallError>>;
}

impl ForkEvalExt for Forker {
async fn fork_parse(
&self,
args: ForkParseArgs,
) -> Result<ForkTypedReturn<parse2Call>, ForkCallError> {
Expand Down Expand Up @@ -92,7 +106,7 @@ impl Forker {
///
/// Discovers all component addresses from Rainlang, parses the
/// Rainlang string via the deployer, then evaluates via the interpreter.
pub async fn fork_eval(
async fn fork_eval(
&self,
args: ForkEvalArgs,
) -> Result<ForkTypedReturn<eval4Call>, ForkCallError> {
Expand Down Expand Up @@ -171,7 +185,7 @@ mod tests {
use crate::fork::NewForkedEvm;
use alloy::primitives::FixedBytes;
use rainlang_test_fixtures::LocalEvm;
use std::{ops::Deref, sync::Arc};
use std::sync::Arc;

#[tokio::test(flavor = "multi_thread", worker_threads = 1)]
async fn test_fork_parse() {
Expand Down Expand Up @@ -229,10 +243,8 @@ mod tests {
let mut expected_stack_trace = vec![0u8, 0u8, 0u8, 0u8];
expected_stack_trace.append(&mut <FixedBytes<32>>::left_padding_from(&[3u8]).to_vec());

let sparsed_trace_arena = res.raw.traces.unwrap();
let source_index_zero_trace = sparsed_trace_arena.deref().clone().into_nodes()[1]
.to_owned()
.trace;
let trace_arena = res.raw.traces.unwrap();
let source_index_zero_trace = trace_arena.into_nodes()[1].to_owned().trace;
assert_eq!(source_index_zero_trace.data.to_vec(), expected_stack_trace);

// asserting the known trace address
Expand Down
Loading
Loading