From b40c17c0af095659c39e49b90a0d29dbe4b052cb Mon Sep 17 00:00:00 2001 From: pgherveou Date: Wed, 8 Oct 2025 09:52:13 +0200 Subject: [PATCH] fixes --- crates/ml-test-runner/src/cached_compiler.rs | 2 - crates/ml-test-runner/src/main.rs | 4 +- crates/node/src/node_implementations/geth.rs | 66 ++++++++++++++++++- .../src/node_implementations/substrate.rs | 7 +- 4 files changed, 70 insertions(+), 9 deletions(-) delete mode 100644 crates/ml-test-runner/src/cached_compiler.rs diff --git a/crates/ml-test-runner/src/cached_compiler.rs b/crates/ml-test-runner/src/cached_compiler.rs deleted file mode 100644 index 949b495..0000000 --- a/crates/ml-test-runner/src/cached_compiler.rs +++ /dev/null @@ -1,2 +0,0 @@ -// Re-export the cached compiler from core to avoid code duplication -pub use revive_dt_core::CachedCompiler; diff --git a/crates/ml-test-runner/src/main.rs b/crates/ml-test-runner/src/main.rs index 262e4c2..7ba359e 100644 --- a/crates/ml-test-runner/src/main.rs +++ b/crates/ml-test-runner/src/main.rs @@ -312,9 +312,9 @@ async fn execute_test_file( info!("Using existing node"); let existing_node: Box = match args.platform { TestingPlatform::Geth => - Box::new(revive_dt_node::node_implementations::geth::GethNode::new_existing(&args.private_key)?), + Box::new(revive_dt_node::node_implementations::geth::GethNode::new_existing(&args.private_key).await?), TestingPlatform::Kitchensink | TestingPlatform::Zombienet => Box::new( - revive_dt_node::node_implementations::substrate::SubstrateNode::new_existing(&args.private_key)?, + revive_dt_node::node_implementations::substrate::SubstrateNode::new_existing(&args.private_key).await?, ), }; Box::leak(existing_node) diff --git a/crates/node/src/node_implementations/geth.rs b/crates/node/src/node_implementations/geth.rs index d809d08..a70f7b9 100644 --- a/crates/node/src/node_implementations/geth.rs +++ b/crates/node/src/node_implementations/geth.rs @@ -130,7 +130,7 @@ impl GethNode { } } - pub fn new_existing(private_key: &str) -> anyhow::Result { + pub async fn new_existing(private_key: &str) -> anyhow::Result { use alloy::{primitives::FixedBytes, signers::local::PrivateKeySigner}; let key_str = private_key.trim().strip_prefix("0x").unwrap_or(private_key.trim()); @@ -147,9 +147,10 @@ impl GethNode { let signer = PrivateKeySigner::from_bytes(&FixedBytes(bytes)) .map_err(|e| anyhow::anyhow!("Failed to create signer from private key: {}", e))?; + let address = signer.address(); let wallet = Arc::new(EthereumWallet::new(signer)); - Ok(Self { + let node = Self { connection_string: "http://localhost:8545".to_string(), base_directory: PathBuf::new(), data_directory: PathBuf::new(), @@ -162,7 +163,66 @@ impl GethNode { wallet, nonce_manager: Default::default(), provider: Default::default(), - }) + }; + + // Check balance and fund if needed + node.ensure_funded(address).await?; + + Ok(node) + } + + async fn ensure_funded(&self, address: Address) -> anyhow::Result<()> { + use alloy::{ + primitives::utils::{format_ether, parse_ether}, + providers::{Provider, ProviderBuilder}, + }; + + // Create a simple HTTP provider without wallet for balance check + let simple_provider = + ProviderBuilder::new().connect_http(self.connection_string.parse()?); + + // Check current balance + let balance = simple_provider.get_balance(address).await?; + let min_balance = parse_ether("1000")?; // 1000 ETH + + if balance >= min_balance { + tracing::info!( + "Wallet {} already has sufficient balance: {} ETH", + address, + format_ether(balance) + ); + return Ok(()); + } + + tracing::info!( + "Funding wallet {} (current: {} ETH, target: 1000 ETH)", + address, + format_ether(balance) + ); + + // Need to fund the account - get the node's managed account + let accounts = simple_provider.get_accounts().await?; + if accounts.is_empty() { + anyhow::bail!("No managed accounts available on the node to fund wallet"); + } + + let from_account = accounts[0]; + + // Send funding transaction from managed account (unsigned, node will sign) + let funding_amount = min_balance - balance; + let tx = + TransactionRequest::default().from(from_account).to(address).value(funding_amount); + + simple_provider + .send_transaction(tx) + .await? + .get_receipt() + .await + .context("Failed to get receipt for funding transaction")?; + + tracing::info!("Successfully funded wallet {}", address); + + Ok(()) } /// Create the node directory and call `geth init` to configure the genesis. diff --git a/crates/node/src/node_implementations/substrate.rs b/crates/node/src/node_implementations/substrate.rs index e08c5f1..ee7a5d8 100644 --- a/crates/node/src/node_implementations/substrate.rs +++ b/crates/node/src/node_implementations/substrate.rs @@ -132,7 +132,7 @@ impl SubstrateNode { } } - pub fn new_existing(private_key: &str) -> anyhow::Result { + pub async fn new_existing(private_key: &str) -> anyhow::Result { use alloy::{primitives::FixedBytes, signers::local::PrivateKeySigner}; let key_str = private_key.trim().strip_prefix("0x").unwrap_or(private_key.trim()); @@ -140,7 +140,10 @@ impl SubstrateNode { .map_err(|e| anyhow::anyhow!("Failed to decode private key hex: {}", e))?; if key_bytes.len() != 32 { - anyhow::bail!("Private key must be 32 bytes (64 hex characters), got {}", key_bytes.len()); + anyhow::bail!( + "Private key must be 32 bytes (64 hex characters), got {}", + key_bytes.len() + ); } let mut bytes = [0u8; 32];