From 34b8879b1588eaeccd21c05bfe3949085fbdf478 Mon Sep 17 00:00:00 2001 From: Cyrill Leutwiler Date: Tue, 25 Mar 2025 17:54:40 +0100 Subject: [PATCH] deploy tx Signed-off-by: Cyrill Leutwiler --- crates/config/src/lib.rs | 4 +++ crates/core/src/driver/mod.rs | 37 ++++++++++++++------ crates/core/src/main.rs | 20 ++++++++--- crates/format/src/input.rs | 57 +++++++++++++++++++++++++++++-- crates/node/src/lib.rs | 1 + crates/node/src/pool.rs | 38 +++++++++++++++++++++ crates/solc-binaries/src/cache.rs | 2 +- 7 files changed, 141 insertions(+), 18 deletions(-) create mode 100644 crates/node/src/pool.rs diff --git a/crates/config/src/lib.rs b/crates/config/src/lib.rs index a073281..1a5878e 100644 --- a/crates/config/src/lib.rs +++ b/crates/config/src/lib.rs @@ -81,6 +81,10 @@ pub struct Arguments { /// Only compile against this testing platform (doesn't execute the tests). #[arg(long = "compile-only")] pub compile_only: bool, + + /// Determines the amount of tests that are executed in parallel. + #[arg(long = "workers", default_value = "12")] + pub workers: usize, } impl Arguments { diff --git a/crates/core/src/driver/mod.rs b/crates/core/src/driver/mod.rs index 4344378..7a2cf4a 100644 --- a/crates/core/src/driver/mod.rs +++ b/crates/core/src/driver/mod.rs @@ -1,14 +1,17 @@ //! The test driver handles the compilation and execution of the test cases. -use alloy::primitives::{Address, map::HashMap}; +use alloy::{ + primitives::{Address, map::HashMap}, + rpc::types::trace::geth::GethTrace, +}; use revive_dt_compiler::{Compiler, CompilerInput, SolidityCompiler}; use revive_dt_config::Arguments; use revive_dt_format::{ - case::Case, + input::Input, metadata::Metadata, mode::{Mode, SolcMode}, }; -use revive_dt_node::Node; +use revive_dt_node_interaction::EthereumNode; use revive_dt_solc_binaries::download_solc; use revive_solc_json_interface::SolcStandardJsonOutput; @@ -23,7 +26,6 @@ pub struct State<'a, T: Platform> { config: &'a Arguments, contracts: Contracts, deployed_contracts: HashMap, - node: T::Blockchain, } impl<'a, T> State<'a, T> @@ -35,7 +37,6 @@ where config, contracts: Default::default(), deployed_contracts: Default::default(), - node: ::new(config), } } @@ -61,10 +62,18 @@ where Ok(()) } - pub fn execute_case(&mut self, case: &Case) -> anyhow::Result<()> { - for input in &case.inputs {} - - Ok(()) + pub fn execute_input( + &mut self, + input: &Input, + node: &T::Blockchain, + ) -> anyhow::Result { + let receipt = node.execute_transaction(input.legacy_transaction( + self.config.network_id, + 0, + &self.deployed_contracts, + )?)?; + dbg!(&receipt); + Ok(node.trace_transaction(receipt)?) } } @@ -89,7 +98,11 @@ where } } - pub fn execute(&mut self) -> anyhow::Result<()> { + pub fn execute( + &mut self, + leader: L::Blockchain, + follower: F::Blockchain, + ) -> anyhow::Result<()> { for mode in self.modes() { self.leader.build_contracts(&mode, self.metadata)?; self.follower.build_contracts(&mode, self.metadata)?; @@ -99,7 +112,9 @@ where } for case in &self.metadata.cases { - self.leader.execute_case(case)?; + for input in &case.inputs { + let expected = self.leader.execute_input(input, &leader)?; + } } *self = Self::new(self.metadata, self.config); diff --git a/crates/core/src/main.rs b/crates/core/src/main.rs index ed05737..c6217a1 100644 --- a/crates/core/src/main.rs +++ b/crates/core/src/main.rs @@ -1,11 +1,12 @@ use std::collections::BTreeSet; use clap::Parser; -use rayon::prelude::*; +use rayon::{ThreadPoolBuilder, prelude::*}; use revive_dt_config::*; use revive_dt_core::{Geth, Kitchensink, driver::Driver}; use revive_dt_format::corpus::Corpus; +use revive_dt_node::{Node, geth}; use temp_dir::TempDir; fn main() -> anyhow::Result<()> { @@ -19,23 +20,34 @@ fn main() -> anyhow::Result<()> { args.temp_dir = TempDir::new()?.into() } + ThreadPoolBuilder::new() + .num_threads(args.workers) + .build_global() + .unwrap(); + for path in args.corpus.iter().collect::>() { log::trace!("attempting corpus {path:?}"); let corpus = Corpus::try_from_path(path)?; log::info!("found corpus: {corpus:?}"); let tests = corpus.enumerate_tests(); - log::info!("found {} tests", tests.len()); + log::info!("corpus '{}' contains {} tests", &corpus.name, tests.len()); tests.par_iter().for_each(|metadata| { + let (leader, follower) = match (&args.leader, &args.follower) { + (TestingPlatform::Geth, TestingPlatform::Kitchensink) => { + (geth::Instance::new(&args), geth::Instance::new(&args)) + } + _ => unimplemented!(), + }; let mut driver = match (&args.leader, &args.follower) { (TestingPlatform::Geth, TestingPlatform::Kitchensink) => { - Driver::::new(metadata, &args) + Driver::::new(metadata, &args) } _ => unimplemented!(), }; - match driver.execute() { + match Driver::::new(metadata, &args).execute(leader, follower) { Ok(build) => { log::info!( "metadata {} success", diff --git a/crates/format/src/input.rs b/crates/format/src/input.rs index 63f0abb..543ae2e 100644 --- a/crates/format/src/input.rs +++ b/crates/format/src/input.rs @@ -1,4 +1,9 @@ -use alloy::json_abi::Function; +use std::collections::HashMap; + +use alloy::{ + json_abi::Function, network::TransactionBuilder, primitives::Address, + rpc::types::TransactionRequest, +}; use semver::VersionReq; use serde::{Deserialize, de::Deserializer}; use serde_json::Value; @@ -26,11 +31,17 @@ where #[derive(Clone, Debug, Default, Deserialize, Eq, PartialEq)] pub struct Input { - pub instance: Option, + #[serde(default = "default_caller")] + pub caller: Address, + pub comment: Option, + #[serde(default = "default_instance")] + pub instance: String, #[serde(deserialize_with = "deserialize_method")] pub method: Method, pub calldata: Option, pub expected: Option, + pub value: Option, + pub storage: Option>, } #[derive(Clone, Debug, Deserialize, Eq, PartialEq)] @@ -98,3 +109,45 @@ where } }) } + +impl Input { + fn instance_to_address( + &self, + instance: &str, + deployed_contracts: &HashMap, + ) -> anyhow::Result
{ + deployed_contracts + .get(instance) + .copied() + .ok_or_else(|| anyhow::anyhow!("instance {instance} not deployed")) + } + + /// Parse this input into a legacy transaction. + pub fn legacy_transaction( + &self, + chain_id: u64, + nonce: u64, + deployed_contracts: &HashMap, + ) -> anyhow::Result { + let to = match self.method { + Method::Deployer => Address::ZERO, + _ => self.instance_to_address(&self.instance, deployed_contracts)?, + }; + + Ok(TransactionRequest::default() + .with_from(self.caller.clone()) + .with_to(to) + .with_nonce(nonce) + .with_chain_id(chain_id) + .with_gas_price(20_000_000_000) + .with_gas_limit(20_000_000_000)) + } +} + +fn default_instance() -> String { + "Test".to_string() +} + +fn default_caller() -> Address { + "90F8bf6A479f320ead074411a4B0e7944Ea8c9C1".parse().unwrap() +} diff --git a/crates/node/src/lib.rs b/crates/node/src/lib.rs index 3b3cd39..6a7c704 100644 --- a/crates/node/src/lib.rs +++ b/crates/node/src/lib.rs @@ -5,6 +5,7 @@ use revive_dt_config::Arguments; use revive_dt_node_interaction::EthereumNode; pub mod geth; +pub mod pool; /// The default genesis configuration. pub const GENESIS_JSON: &str = include_str!("../../../genesis.json"); diff --git a/crates/node/src/pool.rs b/crates/node/src/pool.rs new file mode 100644 index 0000000..bc6501a --- /dev/null +++ b/crates/node/src/pool.rs @@ -0,0 +1,38 @@ +use std::sync::{ + LazyLock, Mutex, + mpsc::{Receiver, Sender}, +}; + +pub trait NodePool { + fn access() -> &'static LazyLock>>; +} + +use revive_dt_config::Arguments; + +use crate::Node; + +//static POOL: LazyLock>> = LazyLock::new(Default::default); + +pub struct Handle { + node: T, + notifier: Sender<()>, +} + +pub struct Pool { + request: Receiver<()>, + nodes: usize, + handles: Vec, +} + +impl Pool +where + T: Node, +{ + pub fn spawn() {} +} + +// spawner: loops on a queue + +pub fn get_handle>(config: &Arguments) -> Receiver { + todo!() +} diff --git a/crates/solc-binaries/src/cache.rs b/crates/solc-binaries/src/cache.rs index ee664e9..e54cb82 100644 --- a/crates/solc-binaries/src/cache.rs +++ b/crates/solc-binaries/src/cache.rs @@ -39,7 +39,7 @@ fn download_to_file(path: &Path, downloader: &GHDownloader) -> anyhow::Result<() log::info!("caching file: {}", path.display()); let Ok(file) = File::create_new(path) else { - log::warn!("cache file already exists: {}", path.display()); + log::debug!("cache file already exists: {}", path.display()); return Ok(()); };