mirror of
https://github.com/pezkuwichain/revive-differential-tests.git
synced 2026-06-13 11:41:03 +00:00
Cleanup implementation
This commit is contained in:
@@ -22,10 +22,8 @@ use indexmap::IndexMap;
|
|||||||
use revive_dt_compiler::{Compiler, SolidityCompiler};
|
use revive_dt_compiler::{Compiler, SolidityCompiler};
|
||||||
use revive_dt_config::Arguments;
|
use revive_dt_config::Arguments;
|
||||||
use revive_dt_format::case::CaseIdx;
|
use revive_dt_format::case::CaseIdx;
|
||||||
use revive_dt_format::input::{Calldata, Expected, ExpectedOutput, Method, default_caller};
|
use revive_dt_format::input::{Calldata, Expected, ExpectedOutput, Method};
|
||||||
use revive_dt_format::metadata::{
|
use revive_dt_format::metadata::{ContractInstance, ContractPathAndIdentifier};
|
||||||
AddressReplacementMap, ContractInstance, ContractPathAndIdentifier,
|
|
||||||
};
|
|
||||||
use revive_dt_format::{input::Input, metadata::Metadata, mode::SolcMode};
|
use revive_dt_format::{input::Input, metadata::Metadata, mode::SolcMode};
|
||||||
use revive_dt_node_interaction::EthereumNode;
|
use revive_dt_node_interaction::EthereumNode;
|
||||||
use revive_dt_report::reporter::{CompilationTask, Report, Span};
|
use revive_dt_report::reporter::{CompilationTask, Report, Span};
|
||||||
@@ -147,17 +145,11 @@ where
|
|||||||
case_idx: CaseIdx,
|
case_idx: CaseIdx,
|
||||||
input: &Input,
|
input: &Input,
|
||||||
node: &T::Blockchain,
|
node: &T::Blockchain,
|
||||||
address_replacement: &AddressReplacementMap,
|
|
||||||
) -> anyhow::Result<(TransactionReceipt, GethTrace, DiffMode)> {
|
) -> anyhow::Result<(TransactionReceipt, GethTrace, DiffMode)> {
|
||||||
let deployment_receipts =
|
let deployment_receipts =
|
||||||
self.handle_contract_deployment(metadata, case_idx, input, node, address_replacement)?;
|
self.handle_contract_deployment(metadata, case_idx, input, node)?;
|
||||||
let execution_receipt = self.handle_input_execution(
|
let execution_receipt =
|
||||||
case_idx,
|
self.handle_input_execution(case_idx, input, deployment_receipts, node)?;
|
||||||
input,
|
|
||||||
deployment_receipts,
|
|
||||||
node,
|
|
||||||
address_replacement,
|
|
||||||
)?;
|
|
||||||
self.handle_input_expectations(case_idx, input, &execution_receipt, node)?;
|
self.handle_input_expectations(case_idx, input, &execution_receipt, node)?;
|
||||||
self.handle_input_diff(case_idx, execution_receipt, node)
|
self.handle_input_diff(case_idx, execution_receipt, node)
|
||||||
}
|
}
|
||||||
@@ -169,7 +161,6 @@ where
|
|||||||
case_idx: CaseIdx,
|
case_idx: CaseIdx,
|
||||||
input: &Input,
|
input: &Input,
|
||||||
node: &T::Blockchain,
|
node: &T::Blockchain,
|
||||||
address_replacement: &AddressReplacementMap,
|
|
||||||
) -> anyhow::Result<HashMap<ContractInstance, TransactionReceipt>> {
|
) -> anyhow::Result<HashMap<ContractInstance, TransactionReceipt>> {
|
||||||
let span = tracing::debug_span!(
|
let span = tracing::debug_span!(
|
||||||
"Handling contract deployment",
|
"Handling contract deployment",
|
||||||
@@ -261,16 +252,7 @@ where
|
|||||||
TransactionBuilder::<Ethereum>::with_deploy_code(tx, code)
|
TransactionBuilder::<Ethereum>::with_deploy_code(tx, code)
|
||||||
};
|
};
|
||||||
|
|
||||||
let receipt = match node.execute_transaction(
|
let receipt = match node.execute_transaction(tx) {
|
||||||
tx,
|
|
||||||
Some(
|
|
||||||
address_replacement
|
|
||||||
.as_ref()
|
|
||||||
.values()
|
|
||||||
.map(|(sk, _)| sk)
|
|
||||||
.map(Clone::clone),
|
|
||||||
),
|
|
||||||
) {
|
|
||||||
Ok(receipt) => receipt,
|
Ok(receipt) => receipt,
|
||||||
Err(error) => {
|
Err(error) => {
|
||||||
tracing::error!(
|
tracing::error!(
|
||||||
@@ -334,7 +316,6 @@ where
|
|||||||
input: &Input,
|
input: &Input,
|
||||||
mut deployment_receipts: HashMap<ContractInstance, TransactionReceipt>,
|
mut deployment_receipts: HashMap<ContractInstance, TransactionReceipt>,
|
||||||
node: &T::Blockchain,
|
node: &T::Blockchain,
|
||||||
address_replacement: &AddressReplacementMap,
|
|
||||||
) -> anyhow::Result<TransactionReceipt> {
|
) -> anyhow::Result<TransactionReceipt> {
|
||||||
match input.method {
|
match input.method {
|
||||||
// This input was already executed when `handle_input` was called. We just need to
|
// This input was already executed when `handle_input` was called. We just need to
|
||||||
@@ -358,16 +339,7 @@ where
|
|||||||
|
|
||||||
tracing::trace!("Executing transaction for input: {input:?}");
|
tracing::trace!("Executing transaction for input: {input:?}");
|
||||||
|
|
||||||
match node.execute_transaction(
|
match node.execute_transaction(tx) {
|
||||||
tx,
|
|
||||||
Some(
|
|
||||||
address_replacement
|
|
||||||
.as_ref()
|
|
||||||
.values()
|
|
||||||
.map(|(sk, _)| sk)
|
|
||||||
.map(Clone::clone),
|
|
||||||
),
|
|
||||||
) {
|
|
||||||
Ok(receipt) => Ok(receipt),
|
Ok(receipt) => Ok(receipt),
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
tracing::error!(
|
tracing::error!(
|
||||||
@@ -599,7 +571,7 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub struct Driver<'a, Leader: Platform, Follower: Platform> {
|
pub struct Driver<'a, Leader: Platform, Follower: Platform> {
|
||||||
metadata: &'a mut Metadata,
|
metadata: &'a Metadata,
|
||||||
config: &'a Arguments,
|
config: &'a Arguments,
|
||||||
leader_node: &'a Leader::Blockchain,
|
leader_node: &'a Leader::Blockchain,
|
||||||
follower_node: &'a Follower::Blockchain,
|
follower_node: &'a Follower::Blockchain,
|
||||||
@@ -611,7 +583,7 @@ where
|
|||||||
F: Platform,
|
F: Platform,
|
||||||
{
|
{
|
||||||
pub fn new(
|
pub fn new(
|
||||||
metadata: &'a mut Metadata,
|
metadata: &'a Metadata,
|
||||||
config: &'a Arguments,
|
config: &'a Arguments,
|
||||||
leader_node: &'a L::Blockchain,
|
leader_node: &'a L::Blockchain,
|
||||||
follower_node: &'a F::Blockchain,
|
follower_node: &'a F::Blockchain,
|
||||||
@@ -722,44 +694,6 @@ where
|
|||||||
|
|
||||||
// For cases if one of the inputs fail then we move on to the next case and we do NOT
|
// For cases if one of the inputs fail then we move on to the next case and we do NOT
|
||||||
// bail out of the whole thing.
|
// bail out of the whole thing.
|
||||||
let replacement_maps = self
|
|
||||||
.metadata
|
|
||||||
.cases
|
|
||||||
.iter_mut()
|
|
||||||
.enumerate()
|
|
||||||
.map(|(case_id, case)| (CaseIdx::new(case_id), case))
|
|
||||||
.fold(HashMap::new(), |mut map, (case_idx, case)| {
|
|
||||||
let mut replacement_map = AddressReplacementMap::default();
|
|
||||||
case.inputs
|
|
||||||
.iter()
|
|
||||||
.filter_map(|input| {
|
|
||||||
if input.caller == default_caller() {
|
|
||||||
None
|
|
||||||
} else {
|
|
||||||
Some(input.caller)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.for_each(|caller| {
|
|
||||||
replacement_map.get(caller);
|
|
||||||
});
|
|
||||||
if let Err(error) = case.handle_address_replacement(&mut replacement_map) {
|
|
||||||
tracing::error!(
|
|
||||||
target = ?Target::Leader,
|
|
||||||
?error,
|
|
||||||
"Case address replacement failed"
|
|
||||||
);
|
|
||||||
execution_result.add_failed_case(
|
|
||||||
Target::Leader,
|
|
||||||
mode.clone(),
|
|
||||||
case.name.as_deref().unwrap_or("no case name").to_owned(),
|
|
||||||
case_idx,
|
|
||||||
0,
|
|
||||||
anyhow::Error::msg(format!("{error}")),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
map.insert(case_idx, replacement_map);
|
|
||||||
map
|
|
||||||
});
|
|
||||||
|
|
||||||
'case_loop: for (case_idx, case) in self.metadata.cases.iter().enumerate() {
|
'case_loop: for (case_idx, case) in self.metadata.cases.iter().enumerate() {
|
||||||
let tracing_span = tracing::info_span!(
|
let tracing_span = tracing::info_span!(
|
||||||
@@ -770,7 +704,6 @@ where
|
|||||||
let _guard = tracing_span.enter();
|
let _guard = tracing_span.enter();
|
||||||
|
|
||||||
let case_idx = CaseIdx::new_from(case_idx);
|
let case_idx = CaseIdx::new_from(case_idx);
|
||||||
let replacement_map = replacement_maps.get(&case_idx).cloned().unwrap_or_default();
|
|
||||||
|
|
||||||
// For inputs if one of the inputs fail we move on to the next case (we do not move
|
// For inputs if one of the inputs fail we move on to the next case (we do not move
|
||||||
// on to the next input as it doesn't make sense. It depends on the previous one).
|
// on to the next input as it doesn't make sense. It depends on the previous one).
|
||||||
@@ -782,13 +715,8 @@ where
|
|||||||
tracing::info_span!("Executing input", contract_name = ?input.instance)
|
tracing::info_span!("Executing input", contract_name = ?input.instance)
|
||||||
.in_scope(|| {
|
.in_scope(|| {
|
||||||
let (leader_receipt, _, leader_diff) = match leader_state
|
let (leader_receipt, _, leader_diff) = match leader_state
|
||||||
.handle_input(
|
.handle_input(self.metadata, case_idx, &input, self.leader_node)
|
||||||
self.metadata,
|
{
|
||||||
case_idx,
|
|
||||||
&input,
|
|
||||||
self.leader_node,
|
|
||||||
&replacement_map,
|
|
||||||
) {
|
|
||||||
Ok(result) => result,
|
Ok(result) => result,
|
||||||
Err(error) => {
|
Err(error) => {
|
||||||
tracing::error!(
|
tracing::error!(
|
||||||
@@ -817,7 +745,6 @@ where
|
|||||||
case_idx,
|
case_idx,
|
||||||
&input,
|
&input,
|
||||||
self.follower_node,
|
self.follower_node,
|
||||||
&replacement_map,
|
|
||||||
) {
|
) {
|
||||||
Ok(result) => result,
|
Ok(result) => result,
|
||||||
Err(error) => {
|
Err(error) => {
|
||||||
|
|||||||
+77
-11
@@ -1,5 +1,13 @@
|
|||||||
use std::{collections::HashMap, sync::LazyLock};
|
use std::{
|
||||||
|
collections::{HashMap, HashSet},
|
||||||
|
sync::LazyLock,
|
||||||
|
};
|
||||||
|
|
||||||
|
use alloy::{
|
||||||
|
network::TxSigner,
|
||||||
|
primitives::FixedBytes,
|
||||||
|
signers::{Signature, local::PrivateKeySigner},
|
||||||
|
};
|
||||||
use clap::Parser;
|
use clap::Parser;
|
||||||
use rayon::{ThreadPoolBuilder, prelude::*};
|
use rayon::{ThreadPoolBuilder, prelude::*};
|
||||||
|
|
||||||
@@ -8,7 +16,11 @@ use revive_dt_core::{
|
|||||||
Geth, Kitchensink, Platform,
|
Geth, Kitchensink, Platform,
|
||||||
driver::{Driver, State},
|
driver::{Driver, State},
|
||||||
};
|
};
|
||||||
use revive_dt_format::{corpus::Corpus, metadata::MetadataFile};
|
use revive_dt_format::{
|
||||||
|
corpus::Corpus,
|
||||||
|
input::default_caller,
|
||||||
|
metadata::{AddressReplacementMap, MetadataFile},
|
||||||
|
};
|
||||||
use revive_dt_node::pool::NodePool;
|
use revive_dt_node::pool::NodePool;
|
||||||
use revive_dt_report::reporter::{Report, Span};
|
use revive_dt_report::reporter::{Report, Span};
|
||||||
use temp_dir::TempDir;
|
use temp_dir::TempDir;
|
||||||
@@ -20,12 +32,48 @@ static TEMP_DIR: LazyLock<TempDir> = LazyLock::new(|| TempDir::new().unwrap());
|
|||||||
fn main() -> anyhow::Result<()> {
|
fn main() -> anyhow::Result<()> {
|
||||||
let args = init_cli()?;
|
let args = init_cli()?;
|
||||||
|
|
||||||
for (corpus, mut tests) in collect_corpora(&args)? {
|
let mut corpora = collect_corpora(&args)?;
|
||||||
|
let mut replacement_private_keys = HashSet::<FixedBytes<32>>::new();
|
||||||
|
for case in corpora
|
||||||
|
.values_mut()
|
||||||
|
.flat_map(|metadata| metadata.iter_mut())
|
||||||
|
.flat_map(|metadata| metadata.content.cases.iter_mut())
|
||||||
|
{
|
||||||
|
let mut replacement_map = AddressReplacementMap::new();
|
||||||
|
for address in case.inputs.iter().filter_map(|input| {
|
||||||
|
if input.caller != default_caller() {
|
||||||
|
Some(input.caller)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}) {
|
||||||
|
replacement_map.get(address);
|
||||||
|
}
|
||||||
|
case.handle_address_replacement(&mut replacement_map)?;
|
||||||
|
replacement_private_keys.extend(
|
||||||
|
replacement_map
|
||||||
|
.into_inner()
|
||||||
|
.into_values()
|
||||||
|
.map(|(sk, _)| sk)
|
||||||
|
.map(|sk| sk.to_bytes()),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (corpus, tests) in collect_corpora(&args)? {
|
||||||
let span = Span::new(corpus, args.clone())?;
|
let span = Span::new(corpus, args.clone())?;
|
||||||
|
|
||||||
match &args.compile_only {
|
match &args.compile_only {
|
||||||
Some(platform) => compile_corpus(&args, &tests, platform, span),
|
Some(platform) => compile_corpus(&args, &tests, platform, span),
|
||||||
None => execute_corpus(&args, &mut tests, span)?,
|
None => execute_corpus(
|
||||||
|
&args,
|
||||||
|
&tests,
|
||||||
|
replacement_private_keys
|
||||||
|
.clone()
|
||||||
|
.into_iter()
|
||||||
|
.map(|bytes| PrivateKeySigner::from_bytes(&bytes).expect("Can't fail"))
|
||||||
|
.collect::<Vec<_>>(),
|
||||||
|
span,
|
||||||
|
)?,
|
||||||
}
|
}
|
||||||
|
|
||||||
Report::save()?;
|
Report::save()?;
|
||||||
@@ -83,17 +131,26 @@ fn collect_corpora(args: &Arguments) -> anyhow::Result<HashMap<Corpus, Vec<Metad
|
|||||||
Ok(corpora)
|
Ok(corpora)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn run_driver<L, F>(args: &Arguments, tests: &mut [MetadataFile], span: Span) -> anyhow::Result<()>
|
fn run_driver<L, F>(
|
||||||
|
args: &Arguments,
|
||||||
|
tests: &[MetadataFile],
|
||||||
|
additional_signers: impl IntoIterator<Item: TxSigner<Signature> + Send + Sync + 'static>
|
||||||
|
+ Clone
|
||||||
|
+ Send
|
||||||
|
+ Sync
|
||||||
|
+ 'static,
|
||||||
|
span: Span,
|
||||||
|
) -> anyhow::Result<()>
|
||||||
where
|
where
|
||||||
L: Platform,
|
L: Platform,
|
||||||
F: Platform,
|
F: Platform,
|
||||||
L::Blockchain: revive_dt_node::Node + Send + Sync + 'static,
|
L::Blockchain: revive_dt_node::Node + Send + Sync + 'static,
|
||||||
F::Blockchain: revive_dt_node::Node + Send + Sync + 'static,
|
F::Blockchain: revive_dt_node::Node + Send + Sync + 'static,
|
||||||
{
|
{
|
||||||
let leader_nodes = NodePool::<L::Blockchain>::new(args)?;
|
let leader_nodes = NodePool::<L::Blockchain>::new(args, additional_signers.clone())?;
|
||||||
let follower_nodes = NodePool::<F::Blockchain>::new(args)?;
|
let follower_nodes = NodePool::<F::Blockchain>::new(args, additional_signers)?;
|
||||||
|
|
||||||
tests.par_iter_mut().for_each(
|
tests.par_iter().for_each(
|
||||||
|MetadataFile {
|
|MetadataFile {
|
||||||
content: metadata,
|
content: metadata,
|
||||||
path: metadata_file_path,
|
path: metadata_file_path,
|
||||||
@@ -141,13 +198,22 @@ where
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn execute_corpus(args: &Arguments, tests: &mut [MetadataFile], span: Span) -> anyhow::Result<()> {
|
fn execute_corpus(
|
||||||
|
args: &Arguments,
|
||||||
|
tests: &[MetadataFile],
|
||||||
|
additional_signers: impl IntoIterator<Item: TxSigner<Signature> + Send + Sync + 'static>
|
||||||
|
+ Clone
|
||||||
|
+ Send
|
||||||
|
+ Sync
|
||||||
|
+ 'static,
|
||||||
|
span: Span,
|
||||||
|
) -> anyhow::Result<()> {
|
||||||
match (&args.leader, &args.follower) {
|
match (&args.leader, &args.follower) {
|
||||||
(TestingPlatform::Geth, TestingPlatform::Kitchensink) => {
|
(TestingPlatform::Geth, TestingPlatform::Kitchensink) => {
|
||||||
run_driver::<Geth, Kitchensink>(args, tests, span)?
|
run_driver::<Geth, Kitchensink>(args, tests, additional_signers, span)?
|
||||||
}
|
}
|
||||||
(TestingPlatform::Geth, TestingPlatform::Geth) => {
|
(TestingPlatform::Geth, TestingPlatform::Geth) => {
|
||||||
run_driver::<Geth, Geth>(args, tests, span)?
|
run_driver::<Geth, Geth>(args, tests, additional_signers, span)?
|
||||||
}
|
}
|
||||||
_ => unimplemented!(),
|
_ => unimplemented!(),
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -448,8 +448,8 @@ pub fn resolve_argument(
|
|||||||
mod tests {
|
mod tests {
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
use alloy::{json_abi::JsonAbi, network::TxSigner};
|
use alloy::json_abi::JsonAbi;
|
||||||
use alloy_primitives::{Signature, address};
|
use alloy_primitives::address;
|
||||||
use alloy_sol_types::SolValue;
|
use alloy_sol_types::SolValue;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
|
||||||
@@ -459,7 +459,6 @@ mod tests {
|
|||||||
fn execute_transaction(
|
fn execute_transaction(
|
||||||
&self,
|
&self,
|
||||||
_: TransactionRequest,
|
_: TransactionRequest,
|
||||||
_: Option<impl IntoIterator<Item: TxSigner<Signature> + Send + Sync + 'static>>,
|
|
||||||
) -> anyhow::Result<alloy::rpc::types::TransactionReceipt> {
|
) -> anyhow::Result<alloy::rpc::types::TransactionReceipt> {
|
||||||
unimplemented!()
|
unimplemented!()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,8 +7,8 @@ use std::{
|
|||||||
str::FromStr,
|
str::FromStr,
|
||||||
};
|
};
|
||||||
|
|
||||||
use alloy::{network::TxSigner, signers::local::PrivateKeySigner};
|
use alloy::signers::local::PrivateKeySigner;
|
||||||
use alloy_primitives::{Address, Signature};
|
use alloy_primitives::Address;
|
||||||
use revive_dt_node_interaction::EthereumNode;
|
use revive_dt_node_interaction::EthereumNode;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
@@ -389,7 +389,6 @@ impl EthereumNode for UnimplementedEthereumNode {
|
|||||||
fn execute_transaction(
|
fn execute_transaction(
|
||||||
&self,
|
&self,
|
||||||
_: alloy::rpc::types::TransactionRequest,
|
_: alloy::rpc::types::TransactionRequest,
|
||||||
_: Option<impl IntoIterator<Item: TxSigner<Signature> + Send + Sync + 'static>>,
|
|
||||||
) -> anyhow::Result<alloy::rpc::types::TransactionReceipt> {
|
) -> anyhow::Result<alloy::rpc::types::TransactionReceipt> {
|
||||||
anyhow::bail!("Unimplemented")
|
anyhow::bail!("Unimplemented")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,11 +1,9 @@
|
|||||||
//! This crate implements all node interactions.
|
//! This crate implements all node interactions.
|
||||||
|
|
||||||
use alloy::eips::BlockNumberOrTag;
|
use alloy::eips::BlockNumberOrTag;
|
||||||
use alloy::network::TxSigner;
|
|
||||||
use alloy::primitives::{Address, BlockHash, BlockNumber, BlockTimestamp, ChainId, U256};
|
use alloy::primitives::{Address, BlockHash, BlockNumber, BlockTimestamp, ChainId, U256};
|
||||||
use alloy::rpc::types::trace::geth::{DiffMode, GethDebugTracingOptions, GethTrace};
|
use alloy::rpc::types::trace::geth::{DiffMode, GethDebugTracingOptions, GethTrace};
|
||||||
use alloy::rpc::types::{TransactionReceipt, TransactionRequest};
|
use alloy::rpc::types::{TransactionReceipt, TransactionRequest};
|
||||||
use alloy::signers::Signature;
|
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
|
|
||||||
mod blocking_executor;
|
mod blocking_executor;
|
||||||
@@ -14,13 +12,7 @@ pub use blocking_executor::*;
|
|||||||
/// An interface for all interactions with Ethereum compatible nodes.
|
/// An interface for all interactions with Ethereum compatible nodes.
|
||||||
pub trait EthereumNode {
|
pub trait EthereumNode {
|
||||||
/// Execute the [TransactionRequest] and return a [TransactionReceipt].
|
/// Execute the [TransactionRequest] and return a [TransactionReceipt].
|
||||||
fn execute_transaction(
|
fn execute_transaction(&self, transaction: TransactionRequest) -> Result<TransactionReceipt>;
|
||||||
&self,
|
|
||||||
transaction: TransactionRequest,
|
|
||||||
additional_signers: Option<
|
|
||||||
impl IntoIterator<Item: TxSigner<Signature> + Send + Sync + 'static>,
|
|
||||||
>,
|
|
||||||
) -> Result<TransactionReceipt>;
|
|
||||||
|
|
||||||
/// Trace the transaction in the [TransactionReceipt] and return a [GethTrace].
|
/// Trace the transaction in the [TransactionReceipt] and return a [GethTrace].
|
||||||
fn trace_transaction(
|
fn trace_transaction(
|
||||||
|
|||||||
+29
-36
@@ -22,7 +22,7 @@ use alloy::{
|
|||||||
TransactionReceipt, TransactionRequest,
|
TransactionReceipt, TransactionRequest,
|
||||||
trace::geth::{DiffMode, GethDebugTracingOptions, PreStateConfig, PreStateFrame},
|
trace::geth::{DiffMode, GethDebugTracingOptions, PreStateConfig, PreStateFrame},
|
||||||
},
|
},
|
||||||
signers::{Signature, local::PrivateKeySigner},
|
signers::Signature,
|
||||||
};
|
};
|
||||||
use revive_dt_config::Arguments;
|
use revive_dt_config::Arguments;
|
||||||
use revive_dt_node_interaction::{BlockingExecutor, EthereumNode};
|
use revive_dt_node_interaction::{BlockingExecutor, EthereumNode};
|
||||||
@@ -196,19 +196,13 @@ impl Instance {
|
|||||||
|
|
||||||
fn provider(
|
fn provider(
|
||||||
&self,
|
&self,
|
||||||
additional_signers: Option<
|
|
||||||
impl IntoIterator<Item: TxSigner<Signature> + Send + Sync + 'static>,
|
|
||||||
>,
|
|
||||||
) -> impl Future<
|
) -> impl Future<
|
||||||
Output = anyhow::Result<
|
Output = anyhow::Result<
|
||||||
FillProvider<impl TxFiller<Ethereum>, impl Provider<Ethereum>, Ethereum>,
|
FillProvider<impl TxFiller<Ethereum>, impl Provider<Ethereum>, Ethereum>,
|
||||||
>,
|
>,
|
||||||
> + 'static {
|
> + 'static {
|
||||||
let connection_string = self.connection_string();
|
let connection_string = self.connection_string();
|
||||||
let mut wallet = self.wallet.clone();
|
let wallet = self.wallet.clone();
|
||||||
for signer in additional_signers.into_iter().flatten() {
|
|
||||||
wallet.register_signer(signer);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Note: We would like all providers to make use of the same nonce manager so that we have
|
// Note: We would like all providers to make use of the same nonce manager so that we have
|
||||||
// monotonically increasing nonces that are cached. The cached nonce manager uses Arc's in
|
// monotonically increasing nonces that are cached. The cached nonce manager uses Arc's in
|
||||||
@@ -228,16 +222,6 @@ impl Instance {
|
|||||||
.map_err(Into::into)
|
.map_err(Into::into)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn provider_no_additional_signers(
|
|
||||||
&self,
|
|
||||||
) -> impl Future<
|
|
||||||
Output = anyhow::Result<
|
|
||||||
FillProvider<impl TxFiller<Ethereum>, impl Provider<Ethereum>, Ethereum>,
|
|
||||||
>,
|
|
||||||
> + 'static {
|
|
||||||
self.provider(None::<Vec<PrivateKeySigner>>)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl EthereumNode for Instance {
|
impl EthereumNode for Instance {
|
||||||
@@ -245,11 +229,8 @@ impl EthereumNode for Instance {
|
|||||||
fn execute_transaction(
|
fn execute_transaction(
|
||||||
&self,
|
&self,
|
||||||
transaction: TransactionRequest,
|
transaction: TransactionRequest,
|
||||||
additional_signers: Option<
|
|
||||||
impl IntoIterator<Item: TxSigner<Signature> + Send + Sync + 'static>,
|
|
||||||
>,
|
|
||||||
) -> anyhow::Result<alloy::rpc::types::TransactionReceipt> {
|
) -> anyhow::Result<alloy::rpc::types::TransactionReceipt> {
|
||||||
let provider = self.provider(additional_signers);
|
let provider = self.provider();
|
||||||
BlockingExecutor::execute(async move {
|
BlockingExecutor::execute(async move {
|
||||||
let outer_span = tracing::debug_span!("Submitting transaction", ?transaction);
|
let outer_span = tracing::debug_span!("Submitting transaction", ?transaction);
|
||||||
let _outer_guard = outer_span.enter();
|
let _outer_guard = outer_span.enter();
|
||||||
@@ -336,7 +317,7 @@ impl EthereumNode for Instance {
|
|||||||
trace_options: GethDebugTracingOptions,
|
trace_options: GethDebugTracingOptions,
|
||||||
) -> anyhow::Result<alloy::rpc::types::trace::geth::GethTrace> {
|
) -> anyhow::Result<alloy::rpc::types::trace::geth::GethTrace> {
|
||||||
let tx_hash = transaction.transaction_hash;
|
let tx_hash = transaction.transaction_hash;
|
||||||
let provider = self.provider_no_additional_signers();
|
let provider = self.provider();
|
||||||
BlockingExecutor::execute(async move {
|
BlockingExecutor::execute(async move {
|
||||||
Ok(provider
|
Ok(provider
|
||||||
.await?
|
.await?
|
||||||
@@ -363,7 +344,7 @@ impl EthereumNode for Instance {
|
|||||||
|
|
||||||
#[tracing::instrument(skip_all, fields(geth_node_id = self.id))]
|
#[tracing::instrument(skip_all, fields(geth_node_id = self.id))]
|
||||||
fn chain_id(&self) -> anyhow::Result<alloy::primitives::ChainId> {
|
fn chain_id(&self) -> anyhow::Result<alloy::primitives::ChainId> {
|
||||||
let provider = self.provider_no_additional_signers();
|
let provider = self.provider();
|
||||||
BlockingExecutor::execute(async move {
|
BlockingExecutor::execute(async move {
|
||||||
provider.await?.get_chain_id().await.map_err(Into::into)
|
provider.await?.get_chain_id().await.map_err(Into::into)
|
||||||
})?
|
})?
|
||||||
@@ -371,7 +352,7 @@ impl EthereumNode for Instance {
|
|||||||
|
|
||||||
#[tracing::instrument(skip_all, fields(geth_node_id = self.id))]
|
#[tracing::instrument(skip_all, fields(geth_node_id = self.id))]
|
||||||
fn block_gas_limit(&self, number: BlockNumberOrTag) -> anyhow::Result<u128> {
|
fn block_gas_limit(&self, number: BlockNumberOrTag) -> anyhow::Result<u128> {
|
||||||
let provider = self.provider_no_additional_signers();
|
let provider = self.provider();
|
||||||
BlockingExecutor::execute(async move {
|
BlockingExecutor::execute(async move {
|
||||||
provider
|
provider
|
||||||
.await?
|
.await?
|
||||||
@@ -384,7 +365,7 @@ impl EthereumNode for Instance {
|
|||||||
|
|
||||||
#[tracing::instrument(skip_all, fields(geth_node_id = self.id))]
|
#[tracing::instrument(skip_all, fields(geth_node_id = self.id))]
|
||||||
fn block_coinbase(&self, number: BlockNumberOrTag) -> anyhow::Result<Address> {
|
fn block_coinbase(&self, number: BlockNumberOrTag) -> anyhow::Result<Address> {
|
||||||
let provider = self.provider_no_additional_signers();
|
let provider = self.provider();
|
||||||
BlockingExecutor::execute(async move {
|
BlockingExecutor::execute(async move {
|
||||||
provider
|
provider
|
||||||
.await?
|
.await?
|
||||||
@@ -397,7 +378,7 @@ impl EthereumNode for Instance {
|
|||||||
|
|
||||||
#[tracing::instrument(skip_all, fields(geth_node_id = self.id))]
|
#[tracing::instrument(skip_all, fields(geth_node_id = self.id))]
|
||||||
fn block_difficulty(&self, number: BlockNumberOrTag) -> anyhow::Result<U256> {
|
fn block_difficulty(&self, number: BlockNumberOrTag) -> anyhow::Result<U256> {
|
||||||
let provider = self.provider_no_additional_signers();
|
let provider = self.provider();
|
||||||
BlockingExecutor::execute(async move {
|
BlockingExecutor::execute(async move {
|
||||||
provider
|
provider
|
||||||
.await?
|
.await?
|
||||||
@@ -410,7 +391,7 @@ impl EthereumNode for Instance {
|
|||||||
|
|
||||||
#[tracing::instrument(skip_all, fields(geth_node_id = self.id))]
|
#[tracing::instrument(skip_all, fields(geth_node_id = self.id))]
|
||||||
fn block_hash(&self, number: BlockNumberOrTag) -> anyhow::Result<BlockHash> {
|
fn block_hash(&self, number: BlockNumberOrTag) -> anyhow::Result<BlockHash> {
|
||||||
let provider = self.provider_no_additional_signers();
|
let provider = self.provider();
|
||||||
BlockingExecutor::execute(async move {
|
BlockingExecutor::execute(async move {
|
||||||
provider
|
provider
|
||||||
.await?
|
.await?
|
||||||
@@ -423,7 +404,7 @@ impl EthereumNode for Instance {
|
|||||||
|
|
||||||
#[tracing::instrument(skip_all, fields(geth_node_id = self.id))]
|
#[tracing::instrument(skip_all, fields(geth_node_id = self.id))]
|
||||||
fn block_timestamp(&self, number: BlockNumberOrTag) -> anyhow::Result<BlockTimestamp> {
|
fn block_timestamp(&self, number: BlockNumberOrTag) -> anyhow::Result<BlockTimestamp> {
|
||||||
let provider = self.provider_no_additional_signers();
|
let provider = self.provider();
|
||||||
BlockingExecutor::execute(async move {
|
BlockingExecutor::execute(async move {
|
||||||
provider
|
provider
|
||||||
.await?
|
.await?
|
||||||
@@ -436,7 +417,7 @@ impl EthereumNode for Instance {
|
|||||||
|
|
||||||
#[tracing::instrument(skip_all, fields(geth_node_id = self.id))]
|
#[tracing::instrument(skip_all, fields(geth_node_id = self.id))]
|
||||||
fn last_block_number(&self) -> anyhow::Result<BlockNumber> {
|
fn last_block_number(&self) -> anyhow::Result<BlockNumber> {
|
||||||
let provider = self.provider_no_additional_signers();
|
let provider = self.provider();
|
||||||
BlockingExecutor::execute(async move {
|
BlockingExecutor::execute(async move {
|
||||||
provider.await?.get_block_number().await.map_err(Into::into)
|
provider.await?.get_block_number().await.map_err(Into::into)
|
||||||
})?
|
})?
|
||||||
@@ -444,11 +425,19 @@ impl EthereumNode for Instance {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Node for Instance {
|
impl Node for Instance {
|
||||||
fn new(config: &Arguments) -> Self {
|
fn new(
|
||||||
|
config: &Arguments,
|
||||||
|
additional_signers: impl IntoIterator<Item: TxSigner<Signature> + Send + Sync + 'static>,
|
||||||
|
) -> Self {
|
||||||
let geth_directory = config.directory().join(Self::BASE_DIRECTORY);
|
let geth_directory = config.directory().join(Self::BASE_DIRECTORY);
|
||||||
let id = NODE_COUNT.fetch_add(1, Ordering::SeqCst);
|
let id = NODE_COUNT.fetch_add(1, Ordering::SeqCst);
|
||||||
let base_directory = geth_directory.join(id.to_string());
|
let base_directory = geth_directory.join(id.to_string());
|
||||||
|
|
||||||
|
let mut wallet = config.wallet();
|
||||||
|
for signer in additional_signers {
|
||||||
|
wallet.register_signer(signer);
|
||||||
|
}
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
connection_string: base_directory.join(Self::IPC_FILE).display().to_string(),
|
connection_string: base_directory.join(Self::IPC_FILE).display().to_string(),
|
||||||
data_directory: base_directory.join(Self::DATA_DIRECTORY),
|
data_directory: base_directory.join(Self::DATA_DIRECTORY),
|
||||||
@@ -459,7 +448,7 @@ impl Node for Instance {
|
|||||||
handle: None,
|
handle: None,
|
||||||
network_id: config.network_id,
|
network_id: config.network_id,
|
||||||
start_timeout: config.geth_start_timeout,
|
start_timeout: config.geth_start_timeout,
|
||||||
wallet: config.wallet(),
|
wallet,
|
||||||
// We know that we only need to be storing 2 files so we can specify that when creating
|
// We know that we only need to be storing 2 files so we can specify that when creating
|
||||||
// the vector. It's the stdout and stderr of the geth node.
|
// the vector. It's the stdout and stderr of the geth node.
|
||||||
logs_file_to_flush: Vec::with_capacity(2),
|
logs_file_to_flush: Vec::with_capacity(2),
|
||||||
@@ -524,6 +513,8 @@ impl Drop for Instance {
|
|||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use revive_dt_config::Arguments;
|
use revive_dt_config::Arguments;
|
||||||
|
|
||||||
|
use alloy::signers::local::PrivateKeySigner;
|
||||||
use temp_dir::TempDir;
|
use temp_dir::TempDir;
|
||||||
|
|
||||||
use crate::{GENESIS_JSON, Node};
|
use crate::{GENESIS_JSON, Node};
|
||||||
@@ -540,7 +531,7 @@ mod tests {
|
|||||||
|
|
||||||
fn new_node() -> (Instance, TempDir) {
|
fn new_node() -> (Instance, TempDir) {
|
||||||
let (args, temp_dir) = test_config();
|
let (args, temp_dir) = test_config();
|
||||||
let mut node = Instance::new(&args);
|
let mut node = Instance::new(&args, Vec::<PrivateKeySigner>::with_capacity(0));
|
||||||
node.init(GENESIS_JSON.to_owned())
|
node.init(GENESIS_JSON.to_owned())
|
||||||
.expect("Failed to initialize the node")
|
.expect("Failed to initialize the node")
|
||||||
.spawn_process()
|
.spawn_process()
|
||||||
@@ -550,21 +541,23 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn init_works() {
|
fn init_works() {
|
||||||
Instance::new(&test_config().0)
|
Instance::new(&test_config().0, Vec::<PrivateKeySigner>::with_capacity(0))
|
||||||
.init(GENESIS_JSON.to_string())
|
.init(GENESIS_JSON.to_string())
|
||||||
.unwrap();
|
.unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn spawn_works() {
|
fn spawn_works() {
|
||||||
Instance::new(&test_config().0)
|
Instance::new(&test_config().0, Vec::<PrivateKeySigner>::with_capacity(0))
|
||||||
.spawn(GENESIS_JSON.to_string())
|
.spawn(GENESIS_JSON.to_string())
|
||||||
.unwrap();
|
.unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn version_works() {
|
fn version_works() {
|
||||||
let version = Instance::new(&test_config().0).version().unwrap();
|
let version = Instance::new(&test_config().0, Vec::<PrivateKeySigner>::with_capacity(0))
|
||||||
|
.version()
|
||||||
|
.unwrap();
|
||||||
assert!(
|
assert!(
|
||||||
version.starts_with("geth version"),
|
version.starts_with("geth version"),
|
||||||
"expected version string, got: '{version}'"
|
"expected version string, got: '{version}'"
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ use alloy::{
|
|||||||
eth::{Block, Header, Transaction},
|
eth::{Block, Header, Transaction},
|
||||||
trace::geth::{DiffMode, GethDebugTracingOptions, PreStateConfig, PreStateFrame},
|
trace::geth::{DiffMode, GethDebugTracingOptions, PreStateConfig, PreStateFrame},
|
||||||
},
|
},
|
||||||
signers::{Signature, local::PrivateKeySigner},
|
signers::Signature,
|
||||||
};
|
};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use serde_json::{Value as JsonValue, json};
|
use serde_json::{Value as JsonValue, json};
|
||||||
@@ -336,9 +336,6 @@ impl KitchensinkNode {
|
|||||||
|
|
||||||
fn provider(
|
fn provider(
|
||||||
&self,
|
&self,
|
||||||
additional_signers: Option<
|
|
||||||
impl IntoIterator<Item: TxSigner<Signature> + Send + Sync + 'static>,
|
|
||||||
>,
|
|
||||||
) -> impl Future<
|
) -> impl Future<
|
||||||
Output = anyhow::Result<
|
Output = anyhow::Result<
|
||||||
FillProvider<
|
FillProvider<
|
||||||
@@ -349,10 +346,7 @@ impl KitchensinkNode {
|
|||||||
>,
|
>,
|
||||||
> + 'static {
|
> + 'static {
|
||||||
let connection_string = self.connection_string();
|
let connection_string = self.connection_string();
|
||||||
let mut wallet = self.wallet.clone();
|
let wallet = self.wallet.clone();
|
||||||
for signer in additional_signers.into_iter().flatten() {
|
|
||||||
wallet.register_signer(signer);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Note: We would like all providers to make use of the same nonce manager so that we have
|
// Note: We would like all providers to make use of the same nonce manager so that we have
|
||||||
// monotonically increasing nonces that are cached. The cached nonce manager uses Arc's in
|
// monotonically increasing nonces that are cached. The cached nonce manager uses Arc's in
|
||||||
@@ -377,20 +371,6 @@ impl KitchensinkNode {
|
|||||||
.map_err(Into::into)
|
.map_err(Into::into)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn provider_no_additional_signers(
|
|
||||||
&self,
|
|
||||||
) -> impl Future<
|
|
||||||
Output = anyhow::Result<
|
|
||||||
FillProvider<
|
|
||||||
impl TxFiller<KitchenSinkNetwork>,
|
|
||||||
impl Provider<KitchenSinkNetwork>,
|
|
||||||
KitchenSinkNetwork,
|
|
||||||
>,
|
|
||||||
>,
|
|
||||||
> + 'static {
|
|
||||||
self.provider(None::<Vec<PrivateKeySigner>>)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl EthereumNode for KitchensinkNode {
|
impl EthereumNode for KitchensinkNode {
|
||||||
@@ -398,12 +378,9 @@ impl EthereumNode for KitchensinkNode {
|
|||||||
fn execute_transaction(
|
fn execute_transaction(
|
||||||
&self,
|
&self,
|
||||||
transaction: alloy::rpc::types::TransactionRequest,
|
transaction: alloy::rpc::types::TransactionRequest,
|
||||||
additional_signers: Option<
|
|
||||||
impl IntoIterator<Item: TxSigner<Signature> + Send + Sync + 'static>,
|
|
||||||
>,
|
|
||||||
) -> anyhow::Result<TransactionReceipt> {
|
) -> anyhow::Result<TransactionReceipt> {
|
||||||
tracing::debug!(?transaction, "Submitting transaction");
|
tracing::debug!(?transaction, "Submitting transaction");
|
||||||
let provider = self.provider(additional_signers);
|
let provider = self.provider();
|
||||||
let receipt = BlockingExecutor::execute(async move {
|
let receipt = BlockingExecutor::execute(async move {
|
||||||
Ok(provider
|
Ok(provider
|
||||||
.await?
|
.await?
|
||||||
@@ -423,7 +400,7 @@ impl EthereumNode for KitchensinkNode {
|
|||||||
trace_options: GethDebugTracingOptions,
|
trace_options: GethDebugTracingOptions,
|
||||||
) -> anyhow::Result<alloy::rpc::types::trace::geth::GethTrace> {
|
) -> anyhow::Result<alloy::rpc::types::trace::geth::GethTrace> {
|
||||||
let tx_hash = transaction.transaction_hash;
|
let tx_hash = transaction.transaction_hash;
|
||||||
let provider = self.provider_no_additional_signers();
|
let provider = self.provider();
|
||||||
BlockingExecutor::execute(async move {
|
BlockingExecutor::execute(async move {
|
||||||
Ok(provider
|
Ok(provider
|
||||||
.await?
|
.await?
|
||||||
@@ -450,7 +427,7 @@ impl EthereumNode for KitchensinkNode {
|
|||||||
|
|
||||||
#[tracing::instrument(skip_all, fields(geth_node_id = self.id))]
|
#[tracing::instrument(skip_all, fields(geth_node_id = self.id))]
|
||||||
fn chain_id(&self) -> anyhow::Result<alloy::primitives::ChainId> {
|
fn chain_id(&self) -> anyhow::Result<alloy::primitives::ChainId> {
|
||||||
let provider = self.provider_no_additional_signers();
|
let provider = self.provider();
|
||||||
BlockingExecutor::execute(async move {
|
BlockingExecutor::execute(async move {
|
||||||
provider.await?.get_chain_id().await.map_err(Into::into)
|
provider.await?.get_chain_id().await.map_err(Into::into)
|
||||||
})?
|
})?
|
||||||
@@ -458,7 +435,7 @@ impl EthereumNode for KitchensinkNode {
|
|||||||
|
|
||||||
#[tracing::instrument(skip_all, fields(geth_node_id = self.id))]
|
#[tracing::instrument(skip_all, fields(geth_node_id = self.id))]
|
||||||
fn block_gas_limit(&self, number: BlockNumberOrTag) -> anyhow::Result<u128> {
|
fn block_gas_limit(&self, number: BlockNumberOrTag) -> anyhow::Result<u128> {
|
||||||
let provider = self.provider_no_additional_signers();
|
let provider = self.provider();
|
||||||
BlockingExecutor::execute(async move {
|
BlockingExecutor::execute(async move {
|
||||||
provider
|
provider
|
||||||
.await?
|
.await?
|
||||||
@@ -471,7 +448,7 @@ impl EthereumNode for KitchensinkNode {
|
|||||||
|
|
||||||
#[tracing::instrument(skip_all, fields(geth_node_id = self.id))]
|
#[tracing::instrument(skip_all, fields(geth_node_id = self.id))]
|
||||||
fn block_coinbase(&self, number: BlockNumberOrTag) -> anyhow::Result<Address> {
|
fn block_coinbase(&self, number: BlockNumberOrTag) -> anyhow::Result<Address> {
|
||||||
let provider = self.provider_no_additional_signers();
|
let provider = self.provider();
|
||||||
BlockingExecutor::execute(async move {
|
BlockingExecutor::execute(async move {
|
||||||
provider
|
provider
|
||||||
.await?
|
.await?
|
||||||
@@ -484,7 +461,7 @@ impl EthereumNode for KitchensinkNode {
|
|||||||
|
|
||||||
#[tracing::instrument(skip_all, fields(geth_node_id = self.id))]
|
#[tracing::instrument(skip_all, fields(geth_node_id = self.id))]
|
||||||
fn block_difficulty(&self, number: BlockNumberOrTag) -> anyhow::Result<U256> {
|
fn block_difficulty(&self, number: BlockNumberOrTag) -> anyhow::Result<U256> {
|
||||||
let provider = self.provider_no_additional_signers();
|
let provider = self.provider();
|
||||||
BlockingExecutor::execute(async move {
|
BlockingExecutor::execute(async move {
|
||||||
provider
|
provider
|
||||||
.await?
|
.await?
|
||||||
@@ -497,7 +474,7 @@ impl EthereumNode for KitchensinkNode {
|
|||||||
|
|
||||||
#[tracing::instrument(skip_all, fields(geth_node_id = self.id))]
|
#[tracing::instrument(skip_all, fields(geth_node_id = self.id))]
|
||||||
fn block_hash(&self, number: BlockNumberOrTag) -> anyhow::Result<BlockHash> {
|
fn block_hash(&self, number: BlockNumberOrTag) -> anyhow::Result<BlockHash> {
|
||||||
let provider = self.provider_no_additional_signers();
|
let provider = self.provider();
|
||||||
BlockingExecutor::execute(async move {
|
BlockingExecutor::execute(async move {
|
||||||
provider
|
provider
|
||||||
.await?
|
.await?
|
||||||
@@ -510,7 +487,7 @@ impl EthereumNode for KitchensinkNode {
|
|||||||
|
|
||||||
#[tracing::instrument(skip_all, fields(geth_node_id = self.id))]
|
#[tracing::instrument(skip_all, fields(geth_node_id = self.id))]
|
||||||
fn block_timestamp(&self, number: BlockNumberOrTag) -> anyhow::Result<BlockTimestamp> {
|
fn block_timestamp(&self, number: BlockNumberOrTag) -> anyhow::Result<BlockTimestamp> {
|
||||||
let provider = self.provider_no_additional_signers();
|
let provider = self.provider();
|
||||||
BlockingExecutor::execute(async move {
|
BlockingExecutor::execute(async move {
|
||||||
provider
|
provider
|
||||||
.await?
|
.await?
|
||||||
@@ -523,7 +500,7 @@ impl EthereumNode for KitchensinkNode {
|
|||||||
|
|
||||||
#[tracing::instrument(skip_all, fields(geth_node_id = self.id))]
|
#[tracing::instrument(skip_all, fields(geth_node_id = self.id))]
|
||||||
fn last_block_number(&self) -> anyhow::Result<BlockNumber> {
|
fn last_block_number(&self) -> anyhow::Result<BlockNumber> {
|
||||||
let provider = self.provider_no_additional_signers();
|
let provider = self.provider();
|
||||||
BlockingExecutor::execute(async move {
|
BlockingExecutor::execute(async move {
|
||||||
provider.await?.get_block_number().await.map_err(Into::into)
|
provider.await?.get_block_number().await.map_err(Into::into)
|
||||||
})?
|
})?
|
||||||
@@ -531,18 +508,26 @@ impl EthereumNode for KitchensinkNode {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Node for KitchensinkNode {
|
impl Node for KitchensinkNode {
|
||||||
fn new(config: &Arguments) -> Self {
|
fn new(
|
||||||
|
config: &Arguments,
|
||||||
|
additional_signers: impl IntoIterator<Item: TxSigner<Signature> + Send + Sync + 'static>,
|
||||||
|
) -> Self {
|
||||||
let kitchensink_directory = config.directory().join(Self::BASE_DIRECTORY);
|
let kitchensink_directory = config.directory().join(Self::BASE_DIRECTORY);
|
||||||
let id = NODE_COUNT.fetch_add(1, Ordering::SeqCst);
|
let id = NODE_COUNT.fetch_add(1, Ordering::SeqCst);
|
||||||
let base_directory = kitchensink_directory.join(id.to_string());
|
let base_directory = kitchensink_directory.join(id.to_string());
|
||||||
let logs_directory = base_directory.join(Self::LOGS_DIRECTORY);
|
let logs_directory = base_directory.join(Self::LOGS_DIRECTORY);
|
||||||
|
|
||||||
|
let mut wallet = config.wallet();
|
||||||
|
for signer in additional_signers {
|
||||||
|
wallet.register_signer(signer);
|
||||||
|
}
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
id,
|
id,
|
||||||
substrate_binary: config.kitchensink.clone(),
|
substrate_binary: config.kitchensink.clone(),
|
||||||
eth_proxy_binary: config.eth_proxy.clone(),
|
eth_proxy_binary: config.eth_proxy.clone(),
|
||||||
rpc_url: String::new(),
|
rpc_url: String::new(),
|
||||||
wallet: config.wallet(),
|
wallet,
|
||||||
base_directory,
|
base_directory,
|
||||||
logs_directory,
|
logs_directory,
|
||||||
process_substrate: None,
|
process_substrate: None,
|
||||||
@@ -1041,7 +1026,7 @@ impl BlockHeader for KitchenSinkHeader {
|
|||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use alloy::rpc::types::TransactionRequest;
|
use alloy::{rpc::types::TransactionRequest, signers::local::PrivateKeySigner};
|
||||||
use revive_dt_config::Arguments;
|
use revive_dt_config::Arguments;
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
use std::sync::{LazyLock, Mutex};
|
use std::sync::{LazyLock, Mutex};
|
||||||
@@ -1084,7 +1069,7 @@ mod tests {
|
|||||||
let _guard = NODE_START_MUTEX.lock().unwrap();
|
let _guard = NODE_START_MUTEX.lock().unwrap();
|
||||||
|
|
||||||
let (args, temp_dir) = test_config();
|
let (args, temp_dir) = test_config();
|
||||||
let mut node = KitchensinkNode::new(&args);
|
let mut node = KitchensinkNode::new(&args, Vec::<PrivateKeySigner>::with_capacity(0));
|
||||||
node.init(GENESIS_JSON)
|
node.init(GENESIS_JSON)
|
||||||
.expect("Failed to initialize the node")
|
.expect("Failed to initialize the node")
|
||||||
.spawn_process()
|
.spawn_process()
|
||||||
@@ -1106,10 +1091,7 @@ mod tests {
|
|||||||
// Arrange
|
// Arrange
|
||||||
let (node, args, _temp_dir) = new_node();
|
let (node, args, _temp_dir) = new_node();
|
||||||
|
|
||||||
let provider = node
|
let provider = node.provider().await.expect("Failed to create provider");
|
||||||
.provider_no_additional_signers()
|
|
||||||
.await
|
|
||||||
.expect("Failed to create provider");
|
|
||||||
|
|
||||||
let account_address = args.wallet().default_signer().address();
|
let account_address = args.wallet().default_signer().address();
|
||||||
let transaction = TransactionRequest::default()
|
let transaction = TransactionRequest::default()
|
||||||
@@ -1142,7 +1124,8 @@ mod tests {
|
|||||||
}
|
}
|
||||||
"#;
|
"#;
|
||||||
|
|
||||||
let mut dummy_node = KitchensinkNode::new(&test_config().0);
|
let mut dummy_node =
|
||||||
|
KitchensinkNode::new(&test_config().0, Vec::<PrivateKeySigner>::with_capacity(0));
|
||||||
|
|
||||||
// Call `init()`
|
// Call `init()`
|
||||||
dummy_node.init(genesis_content).expect("init failed");
|
dummy_node.init(genesis_content).expect("init failed");
|
||||||
@@ -1186,7 +1169,8 @@ mod tests {
|
|||||||
}
|
}
|
||||||
"#;
|
"#;
|
||||||
|
|
||||||
let node = KitchensinkNode::new(&test_config().0);
|
let node =
|
||||||
|
KitchensinkNode::new(&test_config().0, Vec::<PrivateKeySigner>::with_capacity(0));
|
||||||
|
|
||||||
let result = node
|
let result = node
|
||||||
.extract_balance_from_genesis_file(genesis_json)
|
.extract_balance_from_genesis_file(genesis_json)
|
||||||
@@ -1259,7 +1243,7 @@ mod tests {
|
|||||||
fn spawn_works() {
|
fn spawn_works() {
|
||||||
let (config, _temp_dir) = test_config();
|
let (config, _temp_dir) = test_config();
|
||||||
|
|
||||||
let mut node = KitchensinkNode::new(&config);
|
let mut node = KitchensinkNode::new(&config, Vec::<PrivateKeySigner>::with_capacity(0));
|
||||||
node.spawn(GENESIS_JSON.to_string()).unwrap();
|
node.spawn(GENESIS_JSON.to_string()).unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1267,7 +1251,7 @@ mod tests {
|
|||||||
fn version_works() {
|
fn version_works() {
|
||||||
let (config, _temp_dir) = test_config();
|
let (config, _temp_dir) = test_config();
|
||||||
|
|
||||||
let node = KitchensinkNode::new(&config);
|
let node = KitchensinkNode::new(&config, Vec::<PrivateKeySigner>::with_capacity(0));
|
||||||
let version = node.version().unwrap();
|
let version = node.version().unwrap();
|
||||||
|
|
||||||
assert!(
|
assert!(
|
||||||
@@ -1280,7 +1264,7 @@ mod tests {
|
|||||||
fn eth_rpc_version_works() {
|
fn eth_rpc_version_works() {
|
||||||
let (config, _temp_dir) = test_config();
|
let (config, _temp_dir) = test_config();
|
||||||
|
|
||||||
let node = KitchensinkNode::new(&config);
|
let node = KitchensinkNode::new(&config, Vec::<PrivateKeySigner>::with_capacity(0));
|
||||||
let version = node.eth_rpc_version().unwrap();
|
let version = node.eth_rpc_version().unwrap();
|
||||||
|
|
||||||
assert!(
|
assert!(
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
//! This crate implements the testing nodes.
|
//! This crate implements the testing nodes.
|
||||||
|
|
||||||
|
use alloy::{network::TxSigner, signers::Signature};
|
||||||
use revive_dt_config::Arguments;
|
use revive_dt_config::Arguments;
|
||||||
use revive_dt_node_interaction::EthereumNode;
|
use revive_dt_node_interaction::EthereumNode;
|
||||||
|
|
||||||
@@ -14,7 +15,10 @@ pub const GENESIS_JSON: &str = include_str!("../../../genesis.json");
|
|||||||
/// An abstract interface for testing nodes.
|
/// An abstract interface for testing nodes.
|
||||||
pub trait Node: EthereumNode {
|
pub trait Node: EthereumNode {
|
||||||
/// Create a new uninitialized instance.
|
/// Create a new uninitialized instance.
|
||||||
fn new(config: &Arguments) -> Self;
|
fn new(
|
||||||
|
config: &Arguments,
|
||||||
|
additional_signers: impl IntoIterator<Item: TxSigner<Signature> + Send + Sync + 'static>,
|
||||||
|
) -> Self;
|
||||||
|
|
||||||
/// Spawns a node configured according to the genesis json.
|
/// Spawns a node configured according to the genesis json.
|
||||||
///
|
///
|
||||||
|
|||||||
+19
-4
@@ -6,6 +6,7 @@ use std::{
|
|||||||
thread,
|
thread,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
use alloy::{network::TxSigner, signers::Signature};
|
||||||
use anyhow::Context;
|
use anyhow::Context;
|
||||||
use revive_dt_config::Arguments;
|
use revive_dt_config::Arguments;
|
||||||
|
|
||||||
@@ -23,7 +24,14 @@ where
|
|||||||
T: Node + Send + 'static,
|
T: Node + Send + 'static,
|
||||||
{
|
{
|
||||||
/// Create a new Pool. This will start as many nodes as there are workers in `config`.
|
/// Create a new Pool. This will start as many nodes as there are workers in `config`.
|
||||||
pub fn new(config: &Arguments) -> anyhow::Result<Self> {
|
pub fn new(
|
||||||
|
config: &Arguments,
|
||||||
|
additional_signers: impl IntoIterator<Item: TxSigner<Signature> + Send + Sync + 'static>
|
||||||
|
+ Clone
|
||||||
|
+ Send
|
||||||
|
+ Sync
|
||||||
|
+ 'static,
|
||||||
|
) -> anyhow::Result<Self> {
|
||||||
let nodes = config.workers;
|
let nodes = config.workers;
|
||||||
let genesis = read_to_string(&config.genesis_file).context(format!(
|
let genesis = read_to_string(&config.genesis_file).context(format!(
|
||||||
"can not read genesis file: {}",
|
"can not read genesis file: {}",
|
||||||
@@ -34,7 +42,10 @@ where
|
|||||||
for _ in 0..nodes {
|
for _ in 0..nodes {
|
||||||
let config = config.clone();
|
let config = config.clone();
|
||||||
let genesis = genesis.clone();
|
let genesis = genesis.clone();
|
||||||
handles.push(thread::spawn(move || spawn_node::<T>(&config, genesis)));
|
let additional_signers = additional_signers.clone();
|
||||||
|
handles.push(thread::spawn(move || {
|
||||||
|
spawn_node::<T>(&config, additional_signers, genesis)
|
||||||
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut nodes = Vec::with_capacity(nodes);
|
let mut nodes = Vec::with_capacity(nodes);
|
||||||
@@ -60,8 +71,12 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn spawn_node<T: Node + Send>(args: &Arguments, genesis: String) -> anyhow::Result<T> {
|
fn spawn_node<T: Node + Send>(
|
||||||
let mut node = T::new(args);
|
args: &Arguments,
|
||||||
|
additional_signers: impl IntoIterator<Item: TxSigner<Signature> + Send + Sync + 'static>,
|
||||||
|
genesis: String,
|
||||||
|
) -> anyhow::Result<T> {
|
||||||
|
let mut node = T::new(args, additional_signers);
|
||||||
tracing::info!("starting node: {}", node.connection_string());
|
tracing::info!("starting node: {}", node.connection_string());
|
||||||
node.spawn(genesis)?;
|
node.spawn(genesis)?;
|
||||||
Ok(node)
|
Ok(node)
|
||||||
|
|||||||
Reference in New Issue
Block a user