initialize geth via the standard json

Signed-off-by: xermicus <bigcyrill@hotmail.com>
This commit is contained in:
xermicus
2025-03-23 00:05:53 +01:00
parent f9a0542d49
commit 6cd4519d89
15 changed files with 228 additions and 64 deletions
Generated
+15 -6
View File
@@ -1441,7 +1441,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "33d852cb9b869c2a9b3df2f71a3074817f01e1844f839a144f5fcef059a4eb5d"
dependencies = [
"libc",
"windows-sys 0.52.0",
"windows-sys 0.59.0",
]
[[package]]
@@ -2862,16 +2862,23 @@ dependencies = [
"serde_json",
]
[[package]]
name = "revive-dt-config"
version = "0.1.0"
dependencies = [
"clap",
]
[[package]]
name = "revive-dt-core"
version = "0.1.0"
dependencies = [
"anyhow",
"clap",
"env_logger",
"log",
"rayon",
"revive-dt-compiler",
"revive-dt-config",
"revive-dt-format",
"revive-solc-json-interface",
"semver 1.0.26",
@@ -2897,6 +2904,9 @@ version = "0.1.0"
dependencies = [
"alloy",
"anyhow",
"revive-dt-config",
"revive-dt-node-interaction",
"serde_json",
]
[[package]]
@@ -2908,7 +2918,6 @@ dependencies = [
"hex",
"log",
"once_cell",
"revive-dt-node",
"serde_json",
"tokio",
]
@@ -3051,7 +3060,7 @@ dependencies = [
"errno",
"libc",
"linux-raw-sys",
"windows-sys 0.52.0",
"windows-sys 0.59.0",
]
[[package]]
@@ -3392,7 +3401,7 @@ dependencies = [
"cfg-if",
"libc",
"psm",
"windows-sys 0.52.0",
"windows-sys 0.59.0",
]
[[package]]
@@ -3526,7 +3535,7 @@ dependencies = [
"getrandom 0.3.2",
"once_cell",
"rustix",
"windows-sys 0.52.0",
"windows-sys 0.59.0",
]
[[package]]
+6 -5
View File
@@ -14,6 +14,7 @@ rust-version = "1.85.0"
[workspace.dependencies]
revive-dt-compiler = { version = "0.1.0", path = "crates/compiler" }
revive-dt-config = { version = "0.1.0", path = "crates/config" }
revive-dt-core = { version = "0.1.0", path = "crates/core" }
revive-dt-format = { version = "0.1.0", path = "crates/format" }
revive-dt-node = { version = "0.1.0", path = "crates/node" }
@@ -43,13 +44,13 @@ revive-differential = { git = "https://github.com/paritytech/revive", rev = "497
version = "0.12.6"
default-features = false
features = [
"providers",
"rpc-types",
"json-abi",
"reqwest",
"std",
"genesis",
"provider-debug-api"
"providers",
"provider-debug-api",
"reqwest",
"rpc-types",
"std",
]
[profile.bench]
+12
View File
@@ -0,0 +1,12 @@
[package]
name = "revive-dt-config"
description = "global configuration for the revive differential tester"
version.workspace = true
authors.workspace = true
license.workspace = true
edition.workspace = true
repository.workspace = true
rust-version.workspace = true
[dependencies]
clap = { workspace = true }
+39
View File
@@ -0,0 +1,39 @@
//! The global configuration used accross all revive differential testing crates.
use std::{path::PathBuf, sync::OnceLock};
use clap::Parser;
static ARGUMENTS: OnceLock<Arguments> = OnceLock::new();
/// Get the command line arguments.
pub fn get_args() -> &'static Arguments {
ARGUMENTS.get_or_init(Arguments::parse)
}
#[derive(Debug, Parser, Clone)]
#[command(
name = "revive compiler differential tester utility",
arg_required_else_help = true
)]
pub struct Arguments {
/// The path to the `resolc` executable to be tested.
///
/// By default it uses the `resolc` binary found in `$PATH`.
#[arg(long = "resolc", short, default_value = "resolc")]
pub resolc: PathBuf,
/// A list of test corpus JSON files to be tested.
#[arg(long = "corpus", short)]
pub corpus: Vec<PathBuf>,
/// A place to store temporary artifacts during test execution.
#[arg(long = "workdir", short)]
pub working_directory: PathBuf,
/// The path to the `geth` executable.
///
/// By default it uses `geth` binary found in `$PATH`.
#[arg(short, long = "geth", default_value = "geth")]
pub geth: PathBuf,
}
+1 -1
View File
@@ -16,9 +16,9 @@ path = "src/main.rs"
revive-dt-compiler = { workspace = true }
revive-dt-format = { workspace = true }
revive-solc-json-interface = { workspace = true }
revive-dt-config = { workspace = true }
anyhow = { workspace = true }
clap = { workspace = true }
log = { workspace = true }
env_logger = { workspace = true }
rayon = { workspace = true }
-17
View File
@@ -1,17 +0,0 @@
use std::path::PathBuf;
use clap::Parser;
#[derive(Debug, Parser)]
#[command(name = "The PolkaVM Solidity compiler", arg_required_else_help = true)]
pub struct Arguments {
/// The path where the `resolc` executable to be tested is found at.
///
/// By default it uses the `resolc` found in `$PATH`
#[arg(long = "resolc")]
pub resolc: Option<PathBuf>,
/// A list of test corpus JSON files to be tested.
#[arg(long = "corpus")]
pub corpus: Vec<PathBuf>,
}
-1
View File
@@ -3,5 +3,4 @@
//! This crate defines the testing configuration and
//! provides a helper utilty to execute tests.
pub mod arguments;
pub mod driver;
+4 -6
View File
@@ -1,17 +1,15 @@
use std::collections::BTreeSet;
use clap::Parser;
use rayon::prelude::*;
use revive_dt_core::{arguments::Arguments, driver::compiler::build_evm};
use revive_dt_config::*;
use revive_dt_core::driver::compiler::build_evm;
use revive_dt_format::corpus::Corpus;
fn main() -> anyhow::Result<()> {
env_logger::init();
let args = Arguments::try_parse()?;
for path in args.corpus.iter().collect::<BTreeSet<_>>() {
for path in get_args().corpus.iter().collect::<BTreeSet<_>>() {
log::trace!("attempting corpus {path:?}");
let corpus = Corpus::try_from_path(path)?;
log::info!("found corpus: {corpus:?}");
-2
View File
@@ -16,5 +16,3 @@ log = { workspace = true }
once_cell = { workspace = true }
serde_json = { workspace = true }
tokio = { workspace = true }
revive-dt-node = { workspace = true }
+2 -3
View File
@@ -2,15 +2,14 @@
use alloy::rpc::types::trace::geth::GethTrace;
use alloy::rpc::types::{TransactionReceipt, TransactionRequest};
use revive_dt_node::Node;
use tokio_runtime::TO_TOKIO;
mod tokio_runtime;
pub mod trace;
pub mod transaction;
/// An interface for all node interactions.
pub trait NodeInteraction: Node {
/// An interface for all interactions with Ethereum compatible nodes.
pub trait EthereumNode {
/// Execute the [TransactionRequest] and return a [TransactionReceipt].
fn execute_transaction(
&self,
+3 -4
View File
@@ -5,7 +5,6 @@ use alloy::providers::ProviderBuilder;
use alloy::providers::ext::DebugApi;
use alloy::rpc::types::TransactionReceipt;
use alloy::rpc::types::trace::geth::{GethDebugTracingOptions, GethTrace};
use revive_dt_node::Node;
use tokio::sync::mpsc;
use crate::TO_TOKIO;
@@ -37,10 +36,10 @@ impl AsyncNodeInteraction for Trace {
/// Trace the transaction in [TransactionReceipt] against the `node`,
/// using the provided [GethDebugTracingOptions].
pub fn trace_transaction<T: Node>(
pub fn trace_transaction(
transaction_receipt: TransactionReceipt,
options: GethDebugTracingOptions,
node: &T,
connection_string: String,
) -> anyhow::Result<GethTrace> {
let trace_sender = TO_TOKIO.lock().unwrap().trace_sender.clone();
let (geth_trace_sender, mut geth_trace_receiver) = mpsc::channel(1);
@@ -49,7 +48,7 @@ pub fn trace_transaction<T: Node>(
transaction_hash: transaction_receipt.transaction_hash,
options,
geth_trace_sender,
connection_string: node.connection_string(),
connection_string,
})?;
geth_trace_receiver
+3 -4
View File
@@ -2,7 +2,6 @@
use alloy::providers::{Provider, ProviderBuilder};
use alloy::rpc::types::{TransactionReceipt, TransactionRequest};
use revive_dt_node::Node;
use tokio::sync::mpsc;
use crate::TO_TOKIO;
@@ -34,9 +33,9 @@ impl AsyncNodeInteraction for Transaction {
}
/// Execute the [TransactionRequest] against the `node`.
pub fn execute_transaction<T: Node>(
pub fn execute_transaction(
transaction_request: TransactionRequest,
node: &T,
connection_string: String,
) -> anyhow::Result<TransactionReceipt> {
let request_sender = TO_TOKIO.lock().unwrap().transaction_sender.clone();
let (receipt_sender, mut receipt_receiver) = mpsc::channel(1);
@@ -44,7 +43,7 @@ pub fn execute_transaction<T: Node>(
request_sender.blocking_send(Transaction {
transaction_request,
receipt_sender,
connection_string: node.connection_string(),
connection_string,
})?;
receipt_receiver
+4
View File
@@ -11,3 +11,7 @@ rust-version.workspace = true
[dependencies]
anyhow = { workspace = true }
alloy = { workspace = true }
serde_json = { workspace = true }
revive-dt-node-interaction = { workspace = true }
revive-dt-config = { workspace = true }
+125
View File
@@ -0,0 +1,125 @@
//! The go-ethereum node implementation.
use std::{
fs::{File, create_dir, exists},
path::PathBuf,
process::{Command, Stdio},
sync::atomic::{AtomicU32, Ordering},
};
use alloy::{
genesis::Genesis,
rpc::types::trace::geth::{DiffMode, PreStateFrame},
};
use revive_dt_config::get_args;
use revive_dt_node_interaction::{
EthereumNode, trace::trace_transaction, transaction::execute_transaction,
};
use crate::Node;
static NODE_COUNT: AtomicU32 = AtomicU32::new(0);
#[derive(Debug)]
pub struct Instance {
connection_string: String,
directory: PathBuf,
geth: PathBuf,
id: u32,
}
impl Instance {
pub fn new() -> anyhow::Result<Self> {
let args = get_args();
let geth_directory = args.working_directory.join("geth");
if !exists(&geth_directory)? {
create_dir(&geth_directory)?;
}
let id = NODE_COUNT.fetch_add(1, Ordering::SeqCst);
let directory = geth_directory.join(id.to_string());
let connection_string = directory.join("geth.ipc").display().to_string();
Ok(Self {
connection_string,
directory,
geth: args.geth.clone(),
id,
})
}
}
impl Instance {
/// Call `init` on the node to configure it's genesis.
fn init(&mut self, genesis: Genesis) -> anyhow::Result<()> {
let genesis_path = self.directory.join("genesis.json");
let mut file = File::create(&genesis_path)?;
serde_json::to_writer_pretty(&mut file, &genesis)?;
if !Command::new(&self.geth)
.arg("--datadir")
.arg(self.directory.join("data"))
.stderr(Stdio::null())
.stdout(Stdio::null())
.spawn()?
.wait()?
.success()
{
anyhow::bail!("failed to initialize geth node {:?}", &self);
}
Ok(())
}
}
impl EthereumNode for Instance {
fn execute_transaction(
&self,
transaction_request: alloy::rpc::types::TransactionRequest,
) -> anyhow::Result<alloy::rpc::types::TransactionReceipt> {
execute_transaction(transaction_request, self.connection_string())
}
fn trace_transaction(
&self,
transaction_receipt: alloy::rpc::types::TransactionReceipt,
) -> anyhow::Result<alloy::rpc::types::trace::geth::GethTrace> {
trace_transaction(
transaction_receipt,
Default::default(),
self.connection_string(),
)
}
}
impl Node for Instance {
fn connection_string(&self) -> String {
self.connection_string.clone()
}
fn shutdown(self) -> anyhow::Result<()> {
Ok(())
}
fn spawn(&mut self, genesis: Genesis) -> anyhow::Result<&mut Self> {
self.init(genesis)?;
Ok(self)
}
fn state_diff(
&self,
transaction: alloy::rpc::types::TransactionReceipt,
) -> anyhow::Result<DiffMode> {
match self
.trace_transaction(transaction)?
.try_into_pre_state_frame()?
{
PreStateFrame::Diff(diff) => Ok(diff),
_ => anyhow::bail!("expected a diff mode trace"),
}
}
}
+14 -15
View File
@@ -1,29 +1,28 @@
//! An abstract interface for testing nodes.
//! This crate implements the testing nodes.
use alloy::{
genesis::Genesis,
rpc::types::{TransactionReceipt, TransactionRequest, trace::parity::StateDiff},
rpc::types::{TransactionReceipt, trace::geth::DiffMode},
};
use revive_dt_node_interaction::EthereumNode;
pub trait Node {
/// Configures the node with the given genesis configuration.
fn with_genesis(&mut self, genesis: &Genesis) -> anyhow::Result<&mut Self>;
pub mod geth;
/// Spawns the node, blocking until it's ready to accept transactions.
fn spawn(&mut self) -> anyhow::Result<&mut Self>;
/// An abstract interface for testing nodes.
pub trait Node: EthereumNode {
/// Spawns a node configured according to the [Genesis].
///
/// Blocking until it's ready to accept transactions.
fn spawn(&mut self, genesis: Genesis) -> anyhow::Result<&mut Self>;
/// Prune the node, blocking until it's completely stopped.
/// Prune the node instance and related data.
///
/// Blocking until it's completely stopped.
fn shutdown(self) -> anyhow::Result<()>;
/// Returns the nodes connection string.
fn connection_string(&self) -> String;
/// Execute the [TransactionRequest], blocking until the transaction is mined.
fn execute_transaction(
&self,
transaction: &TransactionRequest,
) -> anyhow::Result<TransactionReceipt>;
/// Returns the state diff of the transaction hash in the [TransactionReceipt].
fn state_diff(&self, transaction: &TransactionReceipt) -> anyhow::Result<StateDiff>;
fn state_diff(&self, transaction: TransactionReceipt) -> anyhow::Result<DiffMode>;
}