Compare commits

..

2 Commits

Author SHA1 Message Date
Omar Abdulla 983ee7f355 Merge remote-tracking branch 'origin/main' into refactor/update-compiler-semaphore 2025-10-06 01:27:35 +03:00
Omar Abdulla bd983a0919 Update compiler semaphore 2025-10-06 01:26:39 +03:00
22 changed files with 361 additions and 4047 deletions
-62
View File
@@ -15,7 +15,6 @@ concurrency:
env: env:
CARGO_TERM_COLOR: always CARGO_TERM_COLOR: always
POLKADOT_VERSION: polkadot-stable2506-2
jobs: jobs:
cache-polkadot: cache-polkadot:
@@ -66,37 +65,6 @@ jobs:
run: | run: |
cd polkadot-sdk cd polkadot-sdk
cargo install --path substrate/frame/revive/rpc --bin eth-rpc cargo install --path substrate/frame/revive/rpc --bin eth-rpc
- name: Cache downloaded Polkadot binaries
id: cache-polkadot
uses: actions/cache@v3
with:
path: |
~/polkadot-cache/polkadot
~/polkadot-cache/polkadot-execute-worker
~/polkadot-cache/polkadot-prepare-worker
~/polkadot-cache/polkadot-parachain
key: polkadot-downloaded-${{ matrix.os }}-${{ env.POLKADOT_VERSION }}
- name: Download Polkadot binaries on macOS
if: matrix.os == 'macos-14' && steps.cache-polkadot.outputs.cache-hit != 'true'
run: |
mkdir -p ~/polkadot-cache
curl -sL https://github.com/paritytech/polkadot-sdk/releases/download/${{ env.POLKADOT_VERSION }}/polkadot-aarch64-apple-darwin -o ~/polkadot-cache/polkadot
curl -sL https://github.com/paritytech/polkadot-sdk/releases/download/${{ env.POLKADOT_VERSION }}/polkadot-execute-worker-aarch64-apple-darwin -o ~/polkadot-cache/polkadot-execute-worker
curl -sL https://github.com/paritytech/polkadot-sdk/releases/download/${{ env.POLKADOT_VERSION }}/polkadot-prepare-worker-aarch64-apple-darwin -o ~/polkadot-cache/polkadot-prepare-worker
curl -sL https://github.com/paritytech/polkadot-sdk/releases/download/${{ env.POLKADOT_VERSION }}/polkadot-parachain-aarch64-apple-darwin -o ~/polkadot-cache/polkadot-parachain
chmod +x ~/polkadot-cache/*
- name: Download Polkadot binaries on Ubuntu
if: matrix.os == 'ubuntu-24.04' && steps.cache-polkadot.outputs.cache-hit != 'true'
run: |
mkdir -p ~/polkadot-cache
curl -sL https://github.com/paritytech/polkadot-sdk/releases/download/${{ env.POLKADOT_VERSION }}/polkadot -o ~/polkadot-cache/polkadot
curl -sL https://github.com/paritytech/polkadot-sdk/releases/download/${{ env.POLKADOT_VERSION }}/polkadot-execute-worker -o ~/polkadot-cache/polkadot-execute-worker
curl -sL https://github.com/paritytech/polkadot-sdk/releases/download/${{ env.POLKADOT_VERSION }}/polkadot-prepare-worker -o ~/polkadot-cache/polkadot-prepare-worker
curl -sL https://github.com/paritytech/polkadot-sdk/releases/download/${{ env.POLKADOT_VERSION }}/polkadot-parachain -o ~/polkadot-cache/polkadot-parachain
chmod +x ~/polkadot-cache/*
ci: ci:
name: CI on ${{ matrix.os }} name: CI on ${{ matrix.os }}
@@ -118,24 +86,6 @@ jobs:
~/.cargo/bin/eth-rpc ~/.cargo/bin/eth-rpc
key: polkadot-binaries-${{ matrix.os }}-${{ hashFiles('polkadot-sdk/.git') }} key: polkadot-binaries-${{ matrix.os }}-${{ hashFiles('polkadot-sdk/.git') }}
- name: Restore downloaded Polkadot binaries from cache
uses: actions/cache@v3
with:
path: |
~/polkadot-cache/polkadot
~/polkadot-cache/polkadot-execute-worker
~/polkadot-cache/polkadot-prepare-worker
~/polkadot-cache/polkadot-parachain
key: polkadot-downloaded-${{ matrix.os }}-${{ env.POLKADOT_VERSION }}
- name: Install Polkadot binaries
run: |
sudo cp ~/polkadot-cache/polkadot /usr/local/bin/
sudo cp ~/polkadot-cache/polkadot-execute-worker /usr/local/bin/
sudo cp ~/polkadot-cache/polkadot-prepare-worker /usr/local/bin/
sudo cp ~/polkadot-cache/polkadot-parachain /usr/local/bin/
sudo chmod +x /usr/local/bin/polkadot*
- name: Setup Rust toolchain - name: Setup Rust toolchain
uses: actions-rust-lang/setup-rust-toolchain@v1 uses: actions-rust-lang/setup-rust-toolchain@v1
with: with:
@@ -220,18 +170,6 @@ jobs:
- name: Check resolc version - name: Check resolc version
run: resolc --version run: resolc --version
- name: Check polkadot version
run: polkadot --version
- name: Check polkadot-parachain version
run: polkadot-parachain --version
- name: Check polkadot-execute-worker version
run: polkadot-execute-worker --version
- name: Check polkadot-prepare-worker version
run: polkadot-prepare-worker --version
- name: Test Formatting - name: Test Formatting
run: make format run: make format
Generated
+57 -2137
View File
File diff suppressed because it is too large Load Diff
-4
View File
@@ -22,9 +22,7 @@ revive-dt-node-pool = { version = "0.1.0", path = "crates/node-pool" }
revive-dt-report = { version = "0.1.0", path = "crates/report" } revive-dt-report = { version = "0.1.0", path = "crates/report" }
revive-dt-solc-binaries = { version = "0.1.0", path = "crates/solc-binaries" } revive-dt-solc-binaries = { version = "0.1.0", path = "crates/solc-binaries" }
ansi_term = "0.12.1"
anyhow = "1.0" anyhow = "1.0"
async-stream = { version = "0.3.6" }
bson = { version = "2.15.0" } bson = { version = "2.15.0" }
cacache = { version = "13.1.0" } cacache = { version = "13.1.0" }
clap = { version = "4", features = ["derive"] } clap = { version = "4", features = ["derive"] }
@@ -75,8 +73,6 @@ revive-solc-json-interface = { git = "https://github.com/paritytech/revive", rev
revive-common = { git = "https://github.com/paritytech/revive", rev = "3389865af7c3ff6f29a586d82157e8bc573c1a8e" } revive-common = { git = "https://github.com/paritytech/revive", rev = "3389865af7c3ff6f29a586d82157e8bc573c1a8e" }
revive-differential = { git = "https://github.com/paritytech/revive", rev = "3389865af7c3ff6f29a586d82157e8bc573c1a8e" } revive-differential = { git = "https://github.com/paritytech/revive", rev = "3389865af7c3ff6f29a586d82157e8bc573c1a8e" }
zombienet-sdk = { git = "https://github.com/paritytech/zombienet-sdk.git", rev = "891f6554354ce466abd496366dbf8b4f82141241" }
[workspace.dependencies.alloy] [workspace.dependencies.alloy]
version = "1.0.37" version = "1.0.37"
default-features = false default-features = false
-6
View File
@@ -39,10 +39,6 @@ pub enum PlatformIdentifier {
ReviveDevNodePolkavmResolc, ReviveDevNodePolkavmResolc,
/// The revive dev node with the REVM backend with the solc compiler. /// The revive dev node with the REVM backend with the solc compiler.
ReviveDevNodeRevmSolc, ReviveDevNodeRevmSolc,
/// A zombienet based Substrate/Polkadot node with the PolkaVM backend with the resolc compiler.
ZombienetPolkavmResolc,
/// A zombienet based Substrate/Polkadot node with the REVM backend with the solc compiler.
ZombienetRevmSolc,
} }
/// An enum of the platform identifiers of all of the platforms supported by this framework. /// An enum of the platform identifiers of all of the platforms supported by this framework.
@@ -99,8 +95,6 @@ pub enum NodeIdentifier {
Kitchensink, Kitchensink,
/// The revive dev node implementation. /// The revive dev node implementation.
ReviveDevNode, ReviveDevNode,
/// A zombienet spawned nodes
Zombienet,
} }
/// An enum representing the identifiers of the supported VMs. /// An enum representing the identifiers of the supported VMs.
@@ -7,10 +7,7 @@ pragma solidity >=0.6.9;
import "./callable.sol"; import "./callable.sol";
contract Main { contract Main {
function main( function main(uint[1] calldata p1, Callable callable) public returns(uint) {
uint[1] calldata p1,
Callable callable
) public pure returns (uint) {
return callable.f(p1); return callable.f(p1);
} }
} }
+8 -102
View File
@@ -107,16 +107,6 @@ impl AsRef<KurtosisConfiguration> for Context {
} }
} }
impl AsRef<PolkadotParachainConfiguration> for Context {
fn as_ref(&self) -> &PolkadotParachainConfiguration {
match self {
Self::Test(context) => context.as_ref().as_ref(),
Self::Benchmark(context) => context.as_ref().as_ref(),
Self::ExportJsonSchema => unreachable!(),
}
}
}
impl AsRef<KitchensinkConfiguration> for Context { impl AsRef<KitchensinkConfiguration> for Context {
fn as_ref(&self) -> &KitchensinkConfiguration { fn as_ref(&self) -> &KitchensinkConfiguration {
match self { match self {
@@ -202,18 +192,6 @@ impl AsRef<ReportConfiguration> for Context {
#[derive(Clone, Debug, Parser, Serialize)] #[derive(Clone, Debug, Parser, Serialize)]
pub struct TestExecutionContext { pub struct TestExecutionContext {
/// The set of platforms that the differential tests should run on.
#[arg(
short = 'p',
long = "platform",
default_values = ["geth-evm-solc", "revive-dev-node-polkavm-resolc"]
)]
pub platforms: Vec<PlatformIdentifier>,
/// The output format to use for the tool's output.
#[arg(short, long, default_value_t = OutputFormat::CargoTestLike)]
pub output_format: OutputFormat,
/// The working directory that the program will use for all of the temporary artifacts needed at /// The working directory that the program will use for all of the temporary artifacts needed at
/// runtime. /// runtime.
/// ///
@@ -227,6 +205,14 @@ pub struct TestExecutionContext {
)] )]
pub working_directory: WorkingDirectoryConfiguration, pub working_directory: WorkingDirectoryConfiguration,
/// The set of platforms that the differential tests should run on.
#[arg(
short = 'p',
long = "platform",
default_values = ["geth-evm-solc", "revive-dev-node-polkavm-resolc"]
)]
pub platforms: Vec<PlatformIdentifier>,
/// Configuration parameters for the corpus files to use. /// Configuration parameters for the corpus files to use.
#[clap(flatten, next_help_heading = "Corpus Configuration")] #[clap(flatten, next_help_heading = "Corpus Configuration")]
pub corpus_configuration: CorpusConfiguration, pub corpus_configuration: CorpusConfiguration,
@@ -239,10 +225,6 @@ pub struct TestExecutionContext {
#[clap(flatten, next_help_heading = "Resolc Configuration")] #[clap(flatten, next_help_heading = "Resolc Configuration")]
pub resolc_configuration: ResolcConfiguration, pub resolc_configuration: ResolcConfiguration,
/// Configuration parameters for the Polkadot Parachain.
#[clap(flatten, next_help_heading = "Polkadot Parachain Configuration")]
pub polkadot_parachain_configuration: PolkadotParachainConfiguration,
/// Configuration parameters for the geth node. /// Configuration parameters for the geth node.
#[clap(flatten, next_help_heading = "Geth Configuration")] #[clap(flatten, next_help_heading = "Geth Configuration")]
pub geth_configuration: GethConfiguration, pub geth_configuration: GethConfiguration,
@@ -336,10 +318,6 @@ pub struct BenchmarkingContext {
#[clap(flatten, next_help_heading = "Kitchensink Configuration")] #[clap(flatten, next_help_heading = "Kitchensink Configuration")]
pub kitchensink_configuration: KitchensinkConfiguration, pub kitchensink_configuration: KitchensinkConfiguration,
/// Configuration parameters for the Polkadot Parachain.
#[clap(flatten, next_help_heading = "Polkadot Parachain Configuration")]
pub polkadot_parachain_configuration: PolkadotParachainConfiguration,
/// Configuration parameters for the Revive Dev Node. /// Configuration parameters for the Revive Dev Node.
#[clap(flatten, next_help_heading = "Revive Dev Node Configuration")] #[clap(flatten, next_help_heading = "Revive Dev Node Configuration")]
pub revive_dev_node_configuration: ReviveDevNodeConfiguration, pub revive_dev_node_configuration: ReviveDevNodeConfiguration,
@@ -401,12 +379,6 @@ impl AsRef<GethConfiguration> for TestExecutionContext {
} }
} }
impl AsRef<PolkadotParachainConfiguration> for TestExecutionContext {
fn as_ref(&self) -> &PolkadotParachainConfiguration {
&self.polkadot_parachain_configuration
}
}
impl AsRef<KurtosisConfiguration> for TestExecutionContext { impl AsRef<KurtosisConfiguration> for TestExecutionContext {
fn as_ref(&self) -> &KurtosisConfiguration { fn as_ref(&self) -> &KurtosisConfiguration {
&self.lighthouse_configuration &self.lighthouse_configuration
@@ -503,12 +475,6 @@ impl AsRef<KurtosisConfiguration> for BenchmarkingContext {
} }
} }
impl AsRef<PolkadotParachainConfiguration> for BenchmarkingContext {
fn as_ref(&self) -> &PolkadotParachainConfiguration {
&self.polkadot_parachain_configuration
}
}
impl AsRef<KitchensinkConfiguration> for BenchmarkingContext { impl AsRef<KitchensinkConfiguration> for BenchmarkingContext {
fn as_ref(&self) -> &KitchensinkConfiguration { fn as_ref(&self) -> &KitchensinkConfiguration {
&self.kitchensink_configuration &self.kitchensink_configuration
@@ -579,30 +545,6 @@ pub struct ResolcConfiguration {
pub path: PathBuf, pub path: PathBuf,
} }
/// A set of configuration parameters for Polkadot Parachain.
#[derive(Clone, Debug, Parser, Serialize)]
pub struct PolkadotParachainConfiguration {
/// Specifies the path of the polkadot-parachain node to be used by the tool.
///
/// If this is not specified, then the tool assumes that it should use the polkadot-parachain binary
/// that's provided in the user's $PATH.
#[clap(
id = "polkadot-parachain.path",
long = "polkadot-parachain.path",
default_value = "polkadot-parachain"
)]
pub path: PathBuf,
/// The amount of time to wait upon startup before considering that the node timed out.
#[clap(
id = "polkadot-parachain.start-timeout-ms",
long = "polkadot-parachain.start-timeout-ms",
default_value = "5000",
value_parser = parse_duration
)]
pub start_timeout_ms: Duration,
}
/// A set of configuration parameters for Geth. /// A set of configuration parameters for Geth.
#[derive(Clone, Debug, Parser, Serialize)] #[derive(Clone, Debug, Parser, Serialize)]
pub struct GethConfiguration { pub struct GethConfiguration {
@@ -684,14 +626,6 @@ pub struct ReviveDevNodeConfiguration {
value_parser = parse_duration value_parser = parse_duration
)] )]
pub start_timeout_ms: Duration, pub start_timeout_ms: Duration,
/// The consensus to use for the spawned revive-dev-node.
#[clap(
id = "revive-dev-node.consensus",
long = "revive-dev-node.consensus",
default_value = "instant-seal"
)]
pub consensus: String,
} }
/// A set of configuration parameters for the ETH RPC. /// A set of configuration parameters for the ETH RPC.
@@ -959,32 +893,4 @@ pub enum TestingPlatform {
Geth, Geth,
/// The kitchensink runtime provides the PolkaVM (PVM) based node implementation. /// The kitchensink runtime provides the PolkaVM (PVM) based node implementation.
Kitchensink, Kitchensink,
/// A polkadot/Substrate based network
Zombienet,
}
/// The output format to use for the test execution output.
#[derive(
Clone,
Copy,
Debug,
PartialEq,
Eq,
PartialOrd,
Ord,
Hash,
Serialize,
ValueEnum,
EnumString,
Display,
AsRefStr,
IntoStaticStr,
)]
#[strum(serialize_all = "kebab-case")]
pub enum OutputFormat {
/// The legacy format that was used in the past for the output.
Legacy,
/// An output format that looks heavily resembles the output from `cargo test`.
CargoTestLike,
} }
-1
View File
@@ -21,7 +21,6 @@ revive-dt-node = { workspace = true }
revive-dt-node-interaction = { workspace = true } revive-dt-node-interaction = { workspace = true }
revive-dt-report = { workspace = true } revive-dt-report = { workspace = true }
ansi_term = { workspace = true }
alloy = { workspace = true } alloy = { workspace = true }
anyhow = { workspace = true } anyhow = { workspace = true }
bson = { workspace = true } bson = { workspace = true }
@@ -22,7 +22,6 @@ use alloy::{
}, },
}; };
use anyhow::{Context as _, Result, bail}; use anyhow::{Context as _, Result, bail};
use futures::TryFutureExt;
use indexmap::IndexMap; use indexmap::IndexMap;
use revive_dt_common::{ use revive_dt_common::{
futures::{PollingWaitBehavior, poll}, futures::{PollingWaitBehavior, poll},
@@ -36,7 +35,7 @@ use revive_dt_format::{
}, },
traits::{ResolutionContext, ResolverApi}, traits::{ResolutionContext, ResolverApi},
}; };
use tokio::sync::{Mutex, OnceCell, mpsc::UnboundedSender}; use tokio::sync::{Mutex, mpsc::UnboundedSender};
use tracing::{Instrument, Span, debug, error, field::display, info, info_span, instrument}; use tracing::{Instrument, Span, debug, error, field::display, info, info_span, instrument};
use crate::{ use crate::{
@@ -124,7 +123,13 @@ where
&self.platform_information.reporter, &self.platform_information.reporter,
) )
.await .await
.inspect_err(|err| error!(?err, "Pre-linking compilation failed")) .inspect_err(|err| {
error!(
?err,
platform_identifier = %self.platform_information.platform.platform_identifier(),
"Pre-linking compilation failed"
)
})
.context("Failed to produce the pre-linking compiled contracts")?; .context("Failed to produce the pre-linking compiled contracts")?;
let mut deployed_libraries = None::<HashMap<_, _>>; let mut deployed_libraries = None::<HashMap<_, _>>;
@@ -132,7 +137,13 @@ where
.test_definition .test_definition
.metadata .metadata
.contract_sources() .contract_sources()
.inspect_err(|err| error!(?err, "Failed to retrieve contract sources from metadata")) .inspect_err(|err| {
error!(
?err,
platform_identifier = %self.platform_information.platform.platform_identifier(),
"Failed to retrieve contract sources from metadata"
)
})
.context("Failed to get the contract instances from the metadata file")?; .context("Failed to get the contract instances from the metadata file")?;
for library_instance in self for library_instance in self
.test_definition .test_definition
@@ -180,19 +191,20 @@ where
TransactionRequest::default().from(deployer_address), TransactionRequest::default().from(deployer_address),
code, code,
); );
let receipt = self let receipt = self.execute_transaction(tx).await.inspect_err(|err| {
.execute_transaction(tx) error!(
.and_then(|(_, receipt_fut)| receipt_fut) ?err,
.await %library_instance,
.inspect_err(|err| { platform_identifier = %self.platform_information.platform.platform_identifier(),
error!( "Failed to deploy the library"
?err, )
%library_instance, })?;
"Failed to deploy the library"
)
})?;
debug!(?library_instance, "Deployed library"); debug!(
?library_instance,
platform_identifier = %self.platform_information.platform.platform_identifier(),
"Deployed library"
);
let library_address = receipt let library_address = receipt
.contract_address .contract_address
@@ -215,7 +227,13 @@ where
&self.platform_information.reporter, &self.platform_information.reporter,
) )
.await .await
.inspect_err(|err| error!(?err, "Post-linking compilation failed")) .inspect_err(|err| {
error!(
?err,
platform_identifier = %self.platform_information.platform.platform_identifier(),
"Post-linking compilation failed"
)
})
.context("Failed to compile the post-link contracts")?; .context("Failed to compile the post-link contracts")?;
self.execution_state = ExecutionState::new( self.execution_state = ExecutionState::new(
@@ -251,6 +269,7 @@ where
skip_all, skip_all,
fields( fields(
driver_id = self.driver_id, driver_id = self.driver_id,
platform_identifier = %self.platform_information.platform.platform_identifier(),
%step_path, %step_path,
), ),
err(Debug), err(Debug),
@@ -286,11 +305,15 @@ where
.handle_function_call_contract_deployment(step) .handle_function_call_contract_deployment(step)
.await .await
.context("Failed to deploy contracts for the function call step")?; .context("Failed to deploy contracts for the function call step")?;
let transaction_hash = self let execution_receipt = self
.handle_function_call_execution(step, deployment_receipts) .handle_function_call_execution(step, deployment_receipts)
.await .await
.context("Failed to handle the function call execution")?; .context("Failed to handle the function call execution")?;
self.handle_function_call_variable_assignment(step, transaction_hash) let tracing_result = self
.handle_function_call_call_frame_tracing(execution_receipt.transaction_hash)
.await
.context("Failed to handle the function call call frame tracing")?;
self.handle_function_call_variable_assignment(step, &tracing_result)
.await .await
.context("Failed to handle function call variable assignment")?; .context("Failed to handle function call variable assignment")?;
Ok(1) Ok(1)
@@ -344,19 +367,18 @@ where
&mut self, &mut self,
step: &FunctionCallStep, step: &FunctionCallStep,
mut deployment_receipts: HashMap<ContractInstance, TransactionReceipt>, mut deployment_receipts: HashMap<ContractInstance, TransactionReceipt>,
) -> Result<TxHash> { ) -> Result<TransactionReceipt> {
match step.method { match step.method {
// This step was already executed when `handle_step` was called. We just need to // This step was already executed when `handle_step` was called. We just need to
// lookup the transaction receipt in this case and continue on. // lookup the transaction receipt in this case and continue on.
Method::Deployer => deployment_receipts Method::Deployer => deployment_receipts
.remove(&step.instance) .remove(&step.instance)
.context("Failed to find deployment receipt for constructor call") .context("Failed to find deployment receipt for constructor call"),
.map(|receipt| receipt.transaction_hash),
Method::Fallback | Method::FunctionName(_) => { Method::Fallback | Method::FunctionName(_) => {
let tx = step let tx = step
.as_transaction(self.resolver.as_ref(), self.default_resolution_context()) .as_transaction(self.resolver.as_ref(), self.default_resolution_context())
.await?; .await?;
Ok(self.execute_transaction(tx).await?.0) self.execute_transaction(tx).await
} }
} }
} }
@@ -395,19 +417,15 @@ where
async fn handle_function_call_variable_assignment( async fn handle_function_call_variable_assignment(
&mut self, &mut self,
step: &FunctionCallStep, step: &FunctionCallStep,
tx_hash: TxHash, tracing_result: &CallFrame,
) -> Result<()> { ) -> Result<()> {
let Some(ref assignments) = step.variable_assignments else { let Some(ref assignments) = step.variable_assignments else {
return Ok(()); return Ok(());
}; };
// Handling the return data variable assignments. // Handling the return data variable assignments.
let callframe = OnceCell::new();
for (variable_name, output_word) in assignments.return_data.iter().zip( for (variable_name, output_word) in assignments.return_data.iter().zip(
callframe tracing_result
.get_or_try_init(|| self.handle_function_call_call_frame_tracing(tx_hash))
.await
.context("Failed to get the callframe trace for transaction")?
.output .output
.as_ref() .as_ref()
.unwrap_or_default() .unwrap_or_default()
@@ -529,6 +547,7 @@ where
skip_all, skip_all,
fields( fields(
driver_id = self.driver_id, driver_id = self.driver_id,
platform_identifier = %self.platform_information.platform.platform_identifier(),
%contract_instance, %contract_instance,
%deployer %deployer
), ),
@@ -571,6 +590,7 @@ where
skip_all, skip_all,
fields( fields(
driver_id = self.driver_id, driver_id = self.driver_id,
platform_identifier = %self.platform_information.platform.platform_identifier(),
%contract_instance, %contract_instance,
%deployer %deployer
), ),
@@ -640,11 +660,7 @@ where
TransactionBuilder::<Ethereum>::with_deploy_code(tx, code) TransactionBuilder::<Ethereum>::with_deploy_code(tx, code)
}; };
let receipt = match self let receipt = match self.execute_transaction(tx).await {
.execute_transaction(tx)
.and_then(|(_, receipt_fut)| receipt_fut)
.await
{
Ok(receipt) => receipt, Ok(receipt) => receipt,
Err(error) => { Err(error) => {
tracing::error!(?error, "Contract deployment transaction failed."); tracing::error!(?error, "Contract deployment transaction failed.");
@@ -718,7 +734,7 @@ where
async fn execute_transaction( async fn execute_transaction(
&self, &self,
transaction: TransactionRequest, transaction: TransactionRequest,
) -> anyhow::Result<(TxHash, impl Future<Output = Result<TransactionReceipt>>)> { ) -> anyhow::Result<TransactionReceipt> {
let node = self.platform_information.node; let node = self.platform_information.node;
let transaction_hash = node let transaction_hash = node
.submit_transaction(transaction) .submit_transaction(transaction)
@@ -731,28 +747,24 @@ where
.send(WatcherEvent::SubmittedTransaction { transaction_hash }) .send(WatcherEvent::SubmittedTransaction { transaction_hash })
.context("Failed to send the transaction hash to the watcher")?; .context("Failed to send the transaction hash to the watcher")?;
Ok((transaction_hash, async move { info!("Starting to poll for transaction receipt");
info!("Starting to poll for transaction receipt"); poll(
poll( Duration::from_secs(30 * 60),
Duration::from_secs(30 * 60), PollingWaitBehavior::Constant(Duration::from_secs(1)),
PollingWaitBehavior::Constant(Duration::from_secs(1)), || {
|| { async move {
async move { match node.get_receipt(transaction_hash).await {
match node.get_receipt(transaction_hash).await { Ok(receipt) => {
Ok(receipt) => { info!("Polling succeeded, receipt found");
info!("Polling succeeded, receipt found"); Ok(ControlFlow::Break(receipt))
Ok(ControlFlow::Break(receipt))
}
Err(_) => Ok(ControlFlow::Continue(())),
} }
Err(_) => Ok(ControlFlow::Continue(())),
} }
.instrument(info_span!("Polling for receipt")) }
}, .instrument(info_span!("Polling for receipt"))
) },
.instrument(info_span!("Polling for receipt", %transaction_hash)) )
.await .await
.inspect(|_| info!("Found the transaction receipt"))
}))
} }
// endregion:Transaction Execution // endregion:Transaction Execution
} }
@@ -8,7 +8,7 @@ use revive_dt_common::types::PrivateKeyAllocator;
use revive_dt_core::Platform; use revive_dt_core::Platform;
use revive_dt_format::steps::{Step, StepIdx, StepPath}; use revive_dt_format::steps::{Step, StepIdx, StepPath};
use tokio::sync::Mutex; use tokio::sync::Mutex;
use tracing::{Instrument, error, info, info_span, instrument, warn}; use tracing::{error, info, info_span, instrument, warn};
use revive_dt_config::{BenchmarkingContext, Context}; use revive_dt_config::{BenchmarkingContext, Context};
use revive_dt_report::Reporter; use revive_dt_report::Reporter;
@@ -159,15 +159,12 @@ pub async fn handle_differential_benchmarks(
futures::future::try_join( futures::future::try_join(
watcher.run(), watcher.run(),
driver driver.execute_all().inspect(|_| {
.execute_all() info!("All transactions submitted - driver completed execution");
.instrument(info_span!("Executing Benchmarks", %platform_identifier)) watcher_tx
.inspect(|_| { .send(WatcherEvent::AllTransactionsSubmitted)
info!("All transactions submitted - driver completed execution"); .unwrap()
watcher_tx }),
.send(WatcherEvent::AllTransactionsSubmitted)
.unwrap()
}),
) )
.await .await
.context("Failed to run the driver and executor") .context("Failed to run the driver and executor")
@@ -104,10 +104,6 @@ impl Watcher {
async move { async move {
let mut mined_blocks_information = Vec::new(); let mut mined_blocks_information = Vec::new();
// region:TEMPORARY
eprintln!("Watcher information for {}", self.platform_identifier);
eprintln!("block_number,block_timestamp,mined_gas,block_gas_limit,tx_count");
// endregion:TEMPORARY
while let Some(block) = blocks_information_stream.next().await { while let Some(block) = blocks_information_stream.next().await {
// If the block number is equal to or less than the last block before the // If the block number is equal to or less than the last block before the
// repetition then we ignore it and continue on to the next block. // repetition then we ignore it and continue on to the next block.
@@ -122,9 +118,8 @@ impl Watcher {
} }
info!( info!(
block_number = block.block_number,
block_tx_count = block.transaction_hashes.len(),
remaining_transactions = watch_for_transaction_hashes.read().await.len(), remaining_transactions = watch_for_transaction_hashes.read().await.len(),
block_tx_count = block.transaction_hashes.len(),
"Observed a block" "Observed a block"
); );
@@ -136,20 +131,6 @@ impl Watcher {
watch_for_transaction_hashes.remove(tx_hash); watch_for_transaction_hashes.remove(tx_hash);
} }
// region:TEMPORARY
// TODO: The following core is TEMPORARY and will be removed once we have proper
// reporting in place and then it can be removed. This serves as as way of doing
// some very simple reporting for the time being.
eprintln!(
"\"{}\",\"{}\",\"{}\",\"{}\",\"{}\"",
block.block_number,
block.block_timestamp,
block.mined_gas,
block.block_gas_limit,
block.transaction_hashes.len()
);
// endregion:TEMPORARY
mined_blocks_information.push(block); mined_blocks_information.push(block);
} }
@@ -158,10 +139,41 @@ impl Watcher {
} }
}; };
let (_, _) = let (_, mined_blocks_information) =
futures::future::join(watcher_event_watching_task, block_information_watching_task) futures::future::join(watcher_event_watching_task, block_information_watching_task)
.await; .await;
// region:TEMPORARY
{
// TODO: The following core is TEMPORARY and will be removed once we have proper
// reporting in place and then it can be removed. This serves as as way of doing some
// very simple reporting for the time being.
use std::io::Write;
let mut stderr = std::io::stderr().lock();
writeln!(
stderr,
"Watcher information for {}",
self.platform_identifier
)?;
writeln!(
stderr,
"block_number,block_timestamp,mined_gas,block_gas_limit,tx_count"
)?;
for block in mined_blocks_information {
writeln!(
stderr,
"{},{},{},{},{}",
block.block_number,
block.block_timestamp,
block.mined_gas,
block.block_gas_limit,
block.transaction_hashes.len()
)?
}
}
// endregion:TEMPORARY
Ok(()) Ok(())
} }
} }
+25 -9
View File
@@ -31,7 +31,7 @@ use revive_dt_format::{
traits::ResolutionContext, traits::ResolutionContext,
}; };
use tokio::sync::Mutex; use tokio::sync::Mutex;
use tracing::{error, info, instrument}; use tracing::{debug, error, info, instrument};
use crate::{ use crate::{
differential_tests::ExecutionState, differential_tests::ExecutionState,
@@ -109,6 +109,7 @@ impl<'a> Driver<'a, StepsIterator> {
// endregion:Constructors // endregion:Constructors
// region:Execution // region:Execution
#[instrument(level = "info", skip_all)]
pub async fn execute_all(mut self) -> Result<usize> { pub async fn execute_all(mut self) -> Result<usize> {
let platform_drivers = std::mem::take(&mut self.platform_drivers); let platform_drivers = std::mem::take(&mut self.platform_drivers);
let results = futures::future::try_join_all( let results = futures::future::try_join_all(
@@ -217,6 +218,8 @@ where
.flatten() .flatten()
.flat_map(|(_, map)| map.values()) .flat_map(|(_, map)| map.values())
{ {
debug!(%library_instance, "Deploying Library Instance");
let ContractPathAndIdent { let ContractPathAndIdent {
contract_source_path: library_source_path, contract_source_path: library_source_path,
contract_ident: library_ident, contract_ident: library_ident,
@@ -265,6 +268,12 @@ where
) )
})?; })?;
debug!(
?library_instance,
platform_identifier = %platform_information.platform.platform_identifier(),
"Deployed library"
);
let library_address = receipt let library_address = receipt
.contract_address .contract_address
.expect("Failed to deploy the library"); .expect("Failed to deploy the library");
@@ -303,6 +312,7 @@ where
// endregion:Constructors & Initialization // endregion:Constructors & Initialization
// region:Step Handling // region:Step Handling
#[instrument(level = "info", skip_all)]
pub async fn execute_all(mut self) -> Result<usize> { pub async fn execute_all(mut self) -> Result<usize> {
while let Some(result) = self.execute_next_step().await { while let Some(result) = self.execute_next_step().await {
result? result?
@@ -310,6 +320,14 @@ where
Ok(self.steps_executed) Ok(self.steps_executed)
} }
#[instrument(
level = "info",
skip_all,
fields(
platform_identifier = %self.platform_information.platform.platform_identifier(),
node_id = self.platform_information.node.id(),
),
)]
pub async fn execute_next_step(&mut self) -> Option<Result<()>> { pub async fn execute_next_step(&mut self) -> Option<Result<()>> {
let (step_path, step) = self.steps_iterator.next()?; let (step_path, step) = self.steps_iterator.next()?;
info!(%step_path, "Executing Step"); info!(%step_path, "Executing Step");
@@ -326,7 +344,6 @@ where
skip_all, skip_all,
fields( fields(
platform_identifier = %self.platform_information.platform.platform_identifier(), platform_identifier = %self.platform_information.platform.platform_identifier(),
node_id = self.platform_information.node.id(),
%step_path, %step_path,
), ),
err(Debug), err(Debug),
@@ -385,7 +402,6 @@ where
Ok(1) Ok(1)
} }
#[instrument(level = "debug", skip_all)]
async fn handle_function_call_contract_deployment( async fn handle_function_call_contract_deployment(
&mut self, &mut self,
step: &FunctionCallStep, step: &FunctionCallStep,
@@ -431,7 +447,6 @@ where
Ok(receipts) Ok(receipts)
} }
#[instrument(level = "debug", skip_all)]
async fn handle_function_call_execution( async fn handle_function_call_execution(
&mut self, &mut self,
step: &FunctionCallStep, step: &FunctionCallStep,
@@ -455,12 +470,14 @@ where
} }
}; };
self.platform_information.node.execute_transaction(tx).await match self.platform_information.node.execute_transaction(tx).await {
Ok(receipt) => Ok(receipt),
Err(err) => Err(err),
}
} }
} }
} }
#[instrument(level = "debug", skip_all)]
async fn handle_function_call_call_frame_tracing( async fn handle_function_call_call_frame_tracing(
&mut self, &mut self,
tx_hash: TxHash, tx_hash: TxHash,
@@ -492,7 +509,6 @@ where
}) })
} }
#[instrument(level = "debug", skip_all)]
async fn handle_function_call_variable_assignment( async fn handle_function_call_variable_assignment(
&mut self, &mut self,
step: &FunctionCallStep, step: &FunctionCallStep,
@@ -525,7 +541,6 @@ where
Ok(()) Ok(())
} }
#[instrument(level = "debug", skip_all)]
async fn handle_function_call_assertions( async fn handle_function_call_assertions(
&mut self, &mut self,
step: &FunctionCallStep, step: &FunctionCallStep,
@@ -568,7 +583,6 @@ where
.await .await
} }
#[instrument(level = "debug", skip_all)]
async fn handle_function_call_assertion_item( async fn handle_function_call_assertion_item(
&self, &self,
receipt: &TransactionReceipt, receipt: &TransactionReceipt,
@@ -851,6 +865,7 @@ where
level = "info", level = "info",
skip_all, skip_all,
fields( fields(
platform_identifier = %self.platform_information.platform.platform_identifier(),
%contract_instance, %contract_instance,
%deployer %deployer
), ),
@@ -892,6 +907,7 @@ where
level = "info", level = "info",
skip_all, skip_all,
fields( fields(
platform_identifier = %self.platform_information.platform.platform_identifier(),
%contract_instance, %contract_instance,
%deployer %deployer
), ),
+90 -192
View File
@@ -1,21 +1,20 @@
//! The main entry point into differential testing. //! The main entry point into differential testing.
use std::{ use std::{
collections::{BTreeMap, BTreeSet}, collections::BTreeMap,
io::{BufWriter, Write, stderr}, io::{BufWriter, Write, stderr},
sync::Arc, sync::Arc,
time::{Duration, Instant}, time::Instant,
}; };
use ansi_term::{ANSIStrings, Color};
use anyhow::Context as _; use anyhow::Context as _;
use futures::{FutureExt, StreamExt}; use futures::{FutureExt, StreamExt};
use revive_dt_common::types::PrivateKeyAllocator; use revive_dt_common::types::PrivateKeyAllocator;
use revive_dt_core::Platform; use revive_dt_core::Platform;
use tokio::sync::{Mutex, RwLock, Semaphore}; use tokio::sync::Mutex;
use tracing::{Instrument, error, info, info_span, instrument}; use tracing::{Instrument, error, info, info_span, instrument};
use revive_dt_config::{Context, OutputFormat, TestExecutionContext}; use revive_dt_config::{Context, TestExecutionContext};
use revive_dt_report::{Reporter, ReporterEvent, TestCaseStatus}; use revive_dt_report::{Reporter, ReporterEvent, TestCaseStatus};
use crate::{ use crate::{
@@ -102,40 +101,20 @@ pub async fn handle_differential_tests(
))); )));
// Creating the driver and executing all of the steps. // Creating the driver and executing all of the steps.
let semaphore = context let driver_task = futures::future::join_all(test_definitions.iter().map(|test_definition| {
.concurrency_configuration let private_key_allocator = private_key_allocator.clone();
.concurrency_limit() let cached_compiler = cached_compiler.clone();
.map(Semaphore::new) let mode = test_definition.mode.clone();
.map(Arc::new); let span = info_span!(
let running_task_list = Arc::new(RwLock::new(BTreeSet::<usize>::new())); "Executing Test Case",
let driver_task = futures::future::join_all(test_definitions.iter().enumerate().map( metadata_file_path = %test_definition.metadata_file_path.display(),
|(test_id, test_definition)| { case_idx = %test_definition.case_idx,
let running_task_list = running_task_list.clone(); mode = %mode
let semaphore = semaphore.clone(); );
async move {
let private_key_allocator = private_key_allocator.clone(); let driver =
let cached_compiler = cached_compiler.clone(); match Driver::new_root(test_definition, private_key_allocator, &cached_compiler)
let mode = test_definition.mode.clone(); .await
let span = info_span!(
"Executing Test Case",
test_id,
metadata_file_path = %test_definition.metadata_file_path.display(),
case_idx = %test_definition.case_idx,
mode = %mode,
);
async move {
let permit = match semaphore.as_ref() {
Some(semaphore) => Some(semaphore.acquire().await.expect("Can't fail")),
None => None,
};
running_task_list.write().await.insert(test_id);
let driver = match Driver::new_root(
test_definition,
private_key_allocator,
&cached_compiler,
)
.await
{ {
Ok(driver) => driver, Ok(driver) => driver,
Err(error) => { Err(error) => {
@@ -144,52 +123,35 @@ pub async fn handle_differential_tests(
.report_test_failed_event(format!("{error:#}")) .report_test_failed_event(format!("{error:#}"))
.expect("Can't fail"); .expect("Can't fail");
error!("Test Case Failed"); error!("Test Case Failed");
drop(permit);
running_task_list.write().await.remove(&test_id);
return; return;
} }
}; };
info!("Created the driver for the test case"); info!("Created the driver for the test case");
match driver.execute_all().await { match driver.execute_all().await {
Ok(steps_executed) => test_definition Ok(steps_executed) => test_definition
.reporter
.report_test_succeeded_event(steps_executed)
.expect("Can't fail"),
Err(error) => {
test_definition
.reporter .reporter
.report_test_succeeded_event(steps_executed) .report_test_failed_event(format!("{error:#}"))
.expect("Can't fail"), .expect("Can't fail");
Err(error) => { error!("Test Case Failed");
test_definition }
.reporter };
.report_test_failed_event(format!("{error:#}")) info!("Finished the execution of the test case")
.expect("Can't fail"); }
error!("Test Case Failed"); .instrument(span)
} }))
};
info!("Finished the execution of the test case");
drop(permit);
running_task_list.write().await.remove(&test_id);
}
.instrument(span)
},
))
.inspect(|_| { .inspect(|_| {
info!("Finished executing all test cases"); info!("Finished executing all test cases");
reporter_clone reporter_clone
.report_completion_event() .report_completion_event()
.expect("Can't fail") .expect("Can't fail")
}); });
let cli_reporting_task = start_cli_reporting_task(context.output_format, reporter); let cli_reporting_task = start_cli_reporting_task(reporter);
tokio::task::spawn(async move {
loop {
let remaining_tasks = running_task_list.read().await;
info!(
count = remaining_tasks.len(),
?remaining_tasks,
"Remaining Tests"
);
tokio::time::sleep(Duration::from_secs(10)).await
}
});
futures::future::join(driver_task, cli_reporting_task).await; futures::future::join(driver_task, cli_reporting_task).await;
@@ -197,15 +159,21 @@ pub async fn handle_differential_tests(
} }
#[allow(irrefutable_let_patterns, clippy::uninlined_format_args)] #[allow(irrefutable_let_patterns, clippy::uninlined_format_args)]
async fn start_cli_reporting_task(output_format: OutputFormat, reporter: Reporter) { async fn start_cli_reporting_task(reporter: Reporter) {
let mut aggregator_events_rx = reporter.subscribe().await.expect("Can't fail"); let mut aggregator_events_rx = reporter.subscribe().await.expect("Can't fail");
drop(reporter); drop(reporter);
let start = Instant::now(); let start = Instant::now();
let mut global_success_count = 0; const GREEN: &str = "\x1B[32m";
let mut global_failure_count = 0; const RED: &str = "\x1B[31m";
let mut global_ignore_count = 0; const GREY: &str = "\x1B[90m";
const COLOR_RESET: &str = "\x1B[0m";
const BOLD: &str = "\x1B[1m";
const BOLD_RESET: &str = "\x1B[22m";
let mut number_of_successes = 0;
let mut number_of_failures = 0;
let mut buf = BufWriter::new(stderr()); let mut buf = BufWriter::new(stderr());
while let Ok(event) = aggregator_events_rx.recv().await { while let Ok(event) = aggregator_events_rx.recv().await {
@@ -218,125 +186,55 @@ async fn start_cli_reporting_task(output_format: OutputFormat, reporter: Reporte
continue; continue;
}; };
match output_format { let _ = writeln!(buf, "{} - {}", mode, metadata_file_path.display());
OutputFormat::Legacy => { for (case_idx, case_status) in case_status.into_iter() {
let _ = writeln!(buf, "{} - {}", mode, metadata_file_path.display()); let _ = write!(buf, "\tCase Index {case_idx:>3}: ");
for (case_idx, case_status) in case_status.into_iter() { let _ = match case_status {
let _ = write!(buf, "\tCase Index {case_idx:>3}: "); TestCaseStatus::Succeeded { steps_executed } => {
let _ = match case_status { number_of_successes += 1;
TestCaseStatus::Succeeded { steps_executed } => { writeln!(
global_success_count += 1; buf,
writeln!( "{}{}Case Succeeded{} - Steps Executed: {}{}",
buf, GREEN, BOLD, BOLD_RESET, steps_executed, COLOR_RESET
"{}", )
ANSIStrings(&[
Color::Green.bold().paint("Case Succeeded"),
Color::Green
.paint(format!(" - Steps Executed: {steps_executed}")),
])
)
}
TestCaseStatus::Failed { reason } => {
global_failure_count += 1;
writeln!(
buf,
"{}",
ANSIStrings(&[
Color::Red.bold().paint("Case Failed"),
Color::Red.paint(format!(" - Reason: {}", reason.trim())),
])
)
}
TestCaseStatus::Ignored { reason, .. } => {
global_ignore_count += 1;
writeln!(
buf,
"{}",
ANSIStrings(&[
Color::Yellow.bold().paint("Case Ignored"),
Color::Yellow.paint(format!(" - Reason: {}", reason.trim())),
])
)
}
};
} }
let _ = writeln!(buf); TestCaseStatus::Failed { reason } => {
} number_of_failures += 1;
OutputFormat::CargoTestLike => { writeln!(
writeln!( buf,
buf, "{}{}Case Failed{} - Reason: {}{}",
"\t{} {} - {}\n", RED,
Color::Green.paint("Running"), BOLD,
metadata_file_path.display(), BOLD_RESET,
mode reason.trim(),
) COLOR_RESET,
.unwrap(); )
let mut success_count = 0;
let mut failure_count = 0;
let mut ignored_count = 0;
writeln!(buf, "running {} tests", case_status.len()).unwrap();
for (case_idx, case_result) in case_status.iter() {
let status = match case_result {
TestCaseStatus::Succeeded { .. } => {
success_count += 1;
global_success_count += 1;
Color::Green.paint("ok")
}
TestCaseStatus::Failed { reason } => {
failure_count += 1;
global_failure_count += 1;
Color::Red.paint(format!("FAILED, {reason}"))
}
TestCaseStatus::Ignored { reason, .. } => {
ignored_count += 1;
global_ignore_count += 1;
Color::Yellow.paint(format!("ignored, {reason:?}"))
}
};
writeln!(buf, "test case_idx_{} ... {}", case_idx, status).unwrap();
} }
writeln!(buf).unwrap(); TestCaseStatus::Ignored { reason, .. } => writeln!(
let status = if failure_count > 0 {
Color::Red.paint("FAILED")
} else {
Color::Green.paint("ok")
};
writeln!(
buf, buf,
"test result: {}. {} passed; {} failed; {} ignored", "{}{}Case Ignored{} - Reason: {}{}",
status, success_count, failure_count, ignored_count, GREY,
) BOLD,
.unwrap(); BOLD_RESET,
writeln!(buf).unwrap() reason.trim(),
} COLOR_RESET,
),
};
} }
let _ = writeln!(buf);
} }
// Summary at the end. // Summary at the end.
match output_format { let _ = writeln!(
OutputFormat::Legacy => { buf,
writeln!( "{} cases: {}{}{} cases succeeded, {}{}{} cases failed in {} seconds",
buf, number_of_successes + number_of_failures,
"{} cases: {} cases succeeded, {} cases failed in {} seconds", GREEN,
global_success_count + global_failure_count + global_ignore_count, number_of_successes,
Color::Green.paint(global_success_count.to_string()), COLOR_RESET,
Color::Red.paint(global_failure_count.to_string()), RED,
start.elapsed().as_secs() number_of_failures,
) COLOR_RESET,
.unwrap(); start.elapsed().as_secs()
} );
OutputFormat::CargoTestLike => {
writeln!(
buf,
"run finished. {} passed; {} failed; {} ignored; finished in {}s",
global_success_count,
global_failure_count,
global_ignore_count,
start.elapsed().as_secs()
)
.unwrap();
}
}
} }
+7 -119
View File
@@ -16,7 +16,7 @@ use revive_dt_config::*;
use revive_dt_node::{ use revive_dt_node::{
Node, node_implementations::geth::GethNode, Node, node_implementations::geth::GethNode,
node_implementations::lighthouse_geth::LighthouseGethNode, node_implementations::lighthouse_geth::LighthouseGethNode,
node_implementations::substrate::SubstrateNode, node_implementations::zombienet::ZombienetNode, node_implementations::substrate::SubstrateNode,
}; };
use revive_dt_node_interaction::EthereumNode; use revive_dt_node_interaction::EthereumNode;
use tracing::info; use tracing::info;
@@ -184,7 +184,6 @@ impl Platform for KitchensinkPolkavmResolcPlatform {
let node = SubstrateNode::new( let node = SubstrateNode::new(
kitchensink_path, kitchensink_path,
SubstrateNode::KITCHENSINK_EXPORT_CHAINSPEC_COMMAND, SubstrateNode::KITCHENSINK_EXPORT_CHAINSPEC_COMMAND,
None,
context, context,
); );
let node = spawn_node(node, genesis)?; let node = spawn_node(node, genesis)?;
@@ -237,7 +236,6 @@ impl Platform for KitchensinkRevmSolcPlatform {
let node = SubstrateNode::new( let node = SubstrateNode::new(
kitchensink_path, kitchensink_path,
SubstrateNode::KITCHENSINK_EXPORT_CHAINSPEC_COMMAND, SubstrateNode::KITCHENSINK_EXPORT_CHAINSPEC_COMMAND,
None,
context, context,
); );
let node = spawn_node(node, genesis)?; let node = spawn_node(node, genesis)?;
@@ -282,17 +280,14 @@ impl Platform for ReviveDevNodePolkavmResolcPlatform {
context: Context, context: Context,
) -> anyhow::Result<JoinHandle<anyhow::Result<Box<dyn EthereumNode + Send + Sync>>>> { ) -> anyhow::Result<JoinHandle<anyhow::Result<Box<dyn EthereumNode + Send + Sync>>>> {
let genesis_configuration = AsRef::<GenesisConfiguration>::as_ref(&context); let genesis_configuration = AsRef::<GenesisConfiguration>::as_ref(&context);
let revive_dev_node_configuration = AsRef::<ReviveDevNodeConfiguration>::as_ref(&context); let revive_dev_node_path = AsRef::<ReviveDevNodeConfiguration>::as_ref(&context)
.path
let revive_dev_node_path = revive_dev_node_configuration.path.clone(); .clone();
let revive_dev_node_consensus = revive_dev_node_configuration.consensus.clone();
let genesis = genesis_configuration.genesis()?.clone(); let genesis = genesis_configuration.genesis()?.clone();
Ok(thread::spawn(move || { Ok(thread::spawn(move || {
let node = SubstrateNode::new( let node = SubstrateNode::new(
revive_dev_node_path, revive_dev_node_path,
SubstrateNode::REVIVE_DEV_NODE_EXPORT_CHAINSPEC_COMMAND, SubstrateNode::REVIVE_DEV_NODE_EXPORT_CHAINSPEC_COMMAND,
Some(revive_dev_node_consensus),
context, context,
); );
let node = spawn_node(node, genesis)?; let node = spawn_node(node, genesis)?;
@@ -337,17 +332,14 @@ impl Platform for ReviveDevNodeRevmSolcPlatform {
context: Context, context: Context,
) -> anyhow::Result<JoinHandle<anyhow::Result<Box<dyn EthereumNode + Send + Sync>>>> { ) -> anyhow::Result<JoinHandle<anyhow::Result<Box<dyn EthereumNode + Send + Sync>>>> {
let genesis_configuration = AsRef::<GenesisConfiguration>::as_ref(&context); let genesis_configuration = AsRef::<GenesisConfiguration>::as_ref(&context);
let revive_dev_node_configuration = AsRef::<ReviveDevNodeConfiguration>::as_ref(&context); let revive_dev_node_path = AsRef::<ReviveDevNodeConfiguration>::as_ref(&context)
.path
let revive_dev_node_path = revive_dev_node_configuration.path.clone(); .clone();
let revive_dev_node_consensus = revive_dev_node_configuration.consensus.clone();
let genesis = genesis_configuration.genesis()?.clone(); let genesis = genesis_configuration.genesis()?.clone();
Ok(thread::spawn(move || { Ok(thread::spawn(move || {
let node = SubstrateNode::new( let node = SubstrateNode::new(
revive_dev_node_path, revive_dev_node_path,
SubstrateNode::REVIVE_DEV_NODE_EXPORT_CHAINSPEC_COMMAND, SubstrateNode::REVIVE_DEV_NODE_EXPORT_CHAINSPEC_COMMAND,
Some(revive_dev_node_consensus),
context, context,
); );
let node = spawn_node(node, genesis)?; let node = spawn_node(node, genesis)?;
@@ -367,102 +359,6 @@ impl Platform for ReviveDevNodeRevmSolcPlatform {
} }
} }
#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Default, Hash)]
pub struct ZombienetPolkavmResolcPlatform;
impl Platform for ZombienetPolkavmResolcPlatform {
fn platform_identifier(&self) -> PlatformIdentifier {
PlatformIdentifier::ZombienetPolkavmResolc
}
fn node_identifier(&self) -> NodeIdentifier {
NodeIdentifier::Zombienet
}
fn vm_identifier(&self) -> VmIdentifier {
VmIdentifier::PolkaVM
}
fn compiler_identifier(&self) -> CompilerIdentifier {
CompilerIdentifier::Resolc
}
fn new_node(
&self,
context: Context,
) -> anyhow::Result<JoinHandle<anyhow::Result<Box<dyn EthereumNode + Send + Sync>>>> {
let genesis_configuration = AsRef::<GenesisConfiguration>::as_ref(&context);
let polkadot_parachain_path = AsRef::<PolkadotParachainConfiguration>::as_ref(&context)
.path
.clone();
let genesis = genesis_configuration.genesis()?.clone();
Ok(thread::spawn(move || {
let node = ZombienetNode::new(polkadot_parachain_path, context);
let node = spawn_node(node, genesis)?;
Ok(Box::new(node) as Box<_>)
}))
}
fn new_compiler(
&self,
context: Context,
version: Option<VersionOrRequirement>,
) -> Pin<Box<dyn Future<Output = anyhow::Result<Box<dyn SolidityCompiler>>>>> {
Box::pin(async move {
let compiler = Resolc::new(context, version).await;
compiler.map(|compiler| Box::new(compiler) as Box<dyn SolidityCompiler>)
})
}
}
#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Default, Hash)]
pub struct ZombienetRevmSolcPlatform;
impl Platform for ZombienetRevmSolcPlatform {
fn platform_identifier(&self) -> PlatformIdentifier {
PlatformIdentifier::ZombienetRevmSolc
}
fn node_identifier(&self) -> NodeIdentifier {
NodeIdentifier::Zombienet
}
fn vm_identifier(&self) -> VmIdentifier {
VmIdentifier::Evm
}
fn compiler_identifier(&self) -> CompilerIdentifier {
CompilerIdentifier::Solc
}
fn new_node(
&self,
context: Context,
) -> anyhow::Result<JoinHandle<anyhow::Result<Box<dyn EthereumNode + Send + Sync>>>> {
let genesis_configuration = AsRef::<GenesisConfiguration>::as_ref(&context);
let polkadot_parachain_path = AsRef::<PolkadotParachainConfiguration>::as_ref(&context)
.path
.clone();
let genesis = genesis_configuration.genesis()?.clone();
Ok(thread::spawn(move || {
let node = ZombienetNode::new(polkadot_parachain_path, context);
let node = spawn_node(node, genesis)?;
Ok(Box::new(node) as Box<_>)
}))
}
fn new_compiler(
&self,
context: Context,
version: Option<VersionOrRequirement>,
) -> Pin<Box<dyn Future<Output = anyhow::Result<Box<dyn SolidityCompiler>>>>> {
Box::pin(async move {
let compiler = Solc::new(context, version).await;
compiler.map(|compiler| Box::new(compiler) as Box<dyn SolidityCompiler>)
})
}
}
impl From<PlatformIdentifier> for Box<dyn Platform> { impl From<PlatformIdentifier> for Box<dyn Platform> {
fn from(value: PlatformIdentifier) -> Self { fn from(value: PlatformIdentifier) -> Self {
match value { match value {
@@ -482,10 +378,6 @@ impl From<PlatformIdentifier> for Box<dyn Platform> {
PlatformIdentifier::ReviveDevNodeRevmSolc => { PlatformIdentifier::ReviveDevNodeRevmSolc => {
Box::new(ReviveDevNodeRevmSolcPlatform) as Box<_> Box::new(ReviveDevNodeRevmSolcPlatform) as Box<_>
} }
PlatformIdentifier::ZombienetPolkavmResolc => {
Box::new(ZombienetPolkavmResolcPlatform) as Box<_>
}
PlatformIdentifier::ZombienetRevmSolc => Box::new(ZombienetRevmSolcPlatform) as Box<_>,
} }
} }
} }
@@ -509,10 +401,6 @@ impl From<PlatformIdentifier> for &dyn Platform {
PlatformIdentifier::ReviveDevNodeRevmSolc => { PlatformIdentifier::ReviveDevNodeRevmSolc => {
&ReviveDevNodeRevmSolcPlatform as &dyn Platform &ReviveDevNodeRevmSolcPlatform as &dyn Platform
} }
PlatformIdentifier::ZombienetPolkavmResolc => {
&ZombienetPolkavmResolcPlatform as &dyn Platform
}
PlatformIdentifier::ZombienetRevmSolc => &ZombienetRevmSolcPlatform as &dyn Platform,
} }
} }
} }
-2
View File
@@ -11,7 +11,6 @@ rust-version.workspace = true
[dependencies] [dependencies]
anyhow = { workspace = true } anyhow = { workspace = true }
alloy = { workspace = true } alloy = { workspace = true }
async-stream = { workspace = true }
futures = { workspace = true } futures = { workspace = true }
tracing = { workspace = true } tracing = { workspace = true }
tower = { workspace = true } tower = { workspace = true }
@@ -30,7 +29,6 @@ serde_yaml_ng = { workspace = true }
sp-core = { workspace = true } sp-core = { workspace = true }
sp-runtime = { workspace = true } sp-runtime = { workspace = true }
zombienet-sdk = { workspace = true }
[dev-dependencies] [dev-dependencies]
temp-dir = { workspace = true } temp-dir = { workspace = true }
@@ -17,7 +17,7 @@ use std::{
pin::Pin, pin::Pin,
process::{Command, Stdio}, process::{Command, Stdio},
sync::{ sync::{
Arc, Arc, LazyLock,
atomic::{AtomicU32, Ordering}, atomic::{AtomicU32, Ordering},
}, },
time::{Duration, SystemTime, UNIX_EPOCH}, time::{Duration, SystemTime, UNIX_EPOCH},
@@ -47,7 +47,7 @@ use futures::{Stream, StreamExt};
use revive_common::EVMVersion; use revive_common::EVMVersion;
use serde::{Deserialize, Deserializer, Serialize, Serializer}; use serde::{Deserialize, Deserializer, Serialize, Serializer};
use serde_with::serde_as; use serde_with::serde_as;
use tokio::sync::OnceCell; use tokio::sync::{OnceCell, Semaphore};
use tracing::{Instrument, info, instrument}; use tracing::{Instrument, info, instrument};
use revive_dt_common::{ use revive_dt_common::{
@@ -105,6 +105,7 @@ pub struct LighthouseGethNode {
persistent_http_provider: OnceCell<ConcreteProvider<Ethereum, Arc<EthereumWallet>>>, persistent_http_provider: OnceCell<ConcreteProvider<Ethereum, Arc<EthereumWallet>>>,
persistent_ws_provider: OnceCell<ConcreteProvider<Ethereum, Arc<EthereumWallet>>>, persistent_ws_provider: OnceCell<ConcreteProvider<Ethereum, Arc<EthereumWallet>>>,
http_provider_requests_semaphore: LazyLock<Semaphore>,
} }
impl LighthouseGethNode { impl LighthouseGethNode {
@@ -175,6 +176,7 @@ impl LighthouseGethNode {
nonce_manager: Default::default(), nonce_manager: Default::default(),
persistent_http_provider: OnceCell::const_new(), persistent_http_provider: OnceCell::const_new(),
persistent_ws_provider: OnceCell::const_new(), persistent_ws_provider: OnceCell::const_new(),
http_provider_requests_semaphore: LazyLock::new(|| Semaphore::const_new(500)),
} }
} }
@@ -564,6 +566,8 @@ impl EthereumNode for LighthouseGethNode {
transaction: TransactionRequest, transaction: TransactionRequest,
) -> Pin<Box<dyn Future<Output = anyhow::Result<TxHash>> + '_>> { ) -> Pin<Box<dyn Future<Output = anyhow::Result<TxHash>> + '_>> {
Box::pin(async move { Box::pin(async move {
let _permit = self.http_provider_requests_semaphore.acquire().await;
let provider = self let provider = self
.http_provider() .http_provider()
.await .await
@@ -1131,7 +1135,6 @@ mod tests {
} }
#[tokio::test] #[tokio::test]
#[ignore = "Ignored since they take a long time to run"]
async fn node_mines_simple_transfer_transaction_and_returns_receipt() { async fn node_mines_simple_transfer_transaction_and_returns_receipt() {
// Arrange // Arrange
let (context, node) = new_node(); let (context, node) = new_node();
@@ -1,4 +1,3 @@
pub mod geth; pub mod geth;
pub mod lighthouse_geth; pub mod lighthouse_geth;
pub mod substrate; pub mod substrate;
pub mod zombienet;
@@ -36,8 +36,7 @@ use alloy::{
}, },
}; };
use anyhow::Context as _; use anyhow::Context as _;
use async_stream::stream; use futures::{Stream, StreamExt};
use futures::Stream;
use revive_common::EVMVersion; use revive_common::EVMVersion;
use revive_dt_common::fs::clear_directory; use revive_dt_common::fs::clear_directory;
use revive_dt_format::traits::ResolverApi; use revive_dt_format::traits::ResolverApi;
@@ -55,10 +54,7 @@ use crate::{
Node, Node,
constants::{CHAIN_ID, INITIAL_BALANCE}, constants::{CHAIN_ID, INITIAL_BALANCE},
helpers::{Process, ProcessReadinessWaitBehavior}, helpers::{Process, ProcessReadinessWaitBehavior},
provider_utils::{ provider_utils::{ConcreteProvider, FallbackGasFiller, construct_concurrency_limited_provider},
ConcreteProvider, FallbackGasFiller, construct_concurrency_limited_provider,
execute_transaction,
},
}; };
static NODE_COUNT: AtomicU32 = AtomicU32::new(0); static NODE_COUNT: AtomicU32 = AtomicU32::new(0);
@@ -81,11 +77,10 @@ pub struct SubstrateNode {
wallet: Arc<EthereumWallet>, wallet: Arc<EthereumWallet>,
nonce_manager: CachedNonceManager, nonce_manager: CachedNonceManager,
provider: OnceCell<ConcreteProvider<ReviveNetwork, Arc<EthereumWallet>>>, provider: OnceCell<ConcreteProvider<ReviveNetwork, Arc<EthereumWallet>>>,
consensus: Option<String>,
} }
impl SubstrateNode { impl SubstrateNode {
const BASE_DIRECTORY: &str = "substrate"; const BASE_DIRECTORY: &str = "Substrate";
const LOGS_DIRECTORY: &str = "logs"; const LOGS_DIRECTORY: &str = "logs";
const DATA_DIRECTORY: &str = "chains"; const DATA_DIRECTORY: &str = "chains";
@@ -104,7 +99,6 @@ impl SubstrateNode {
pub fn new( pub fn new(
node_path: PathBuf, node_path: PathBuf,
export_chainspec_command: &str, export_chainspec_command: &str,
consensus: Option<String>,
context: impl AsRef<WorkingDirectoryConfiguration> context: impl AsRef<WorkingDirectoryConfiguration>
+ AsRef<EthRpcConfiguration> + AsRef<EthRpcConfiguration>
+ AsRef<WalletConfiguration>, + AsRef<WalletConfiguration>,
@@ -134,7 +128,6 @@ impl SubstrateNode {
wallet: wallet.clone(), wallet: wallet.clone(),
nonce_manager: Default::default(), nonce_manager: Default::default(),
provider: Default::default(), provider: Default::default(),
consensus,
} }
} }
@@ -232,7 +225,7 @@ impl SubstrateNode {
self.logs_directory.as_path(), self.logs_directory.as_path(),
self.node_binary.as_path(), self.node_binary.as_path(),
|command, stdout_file, stderr_file| { |command, stdout_file, stderr_file| {
let cmd = command command
.arg("--dev") .arg("--dev")
.arg("--chain") .arg("--chain")
.arg(chainspec_path) .arg(chainspec_path)
@@ -249,16 +242,9 @@ impl SubstrateNode {
.arg("all") .arg("all")
.arg("--rpc-max-connections") .arg("--rpc-max-connections")
.arg(u32::MAX.to_string()) .arg(u32::MAX.to_string())
.arg("--pool-limit")
.arg(u32::MAX.to_string())
.arg("--pool-kbytes")
.arg(u32::MAX.to_string())
.env("RUST_LOG", Self::SUBSTRATE_LOG_ENV) .env("RUST_LOG", Self::SUBSTRATE_LOG_ENV)
.stdout(stdout_file) .stdout(stdout_file)
.stderr(stderr_file); .stderr(stderr_file);
if let Some(consensus) = self.consensus.as_ref() {
cmd.arg("--consensus").arg(consensus.clone());
}
}, },
ProcessReadinessWaitBehavior::TimeBoundedWaitFunction { ProcessReadinessWaitBehavior::TimeBoundedWaitFunction {
max_wait_duration: Duration::from_secs(30), max_wait_duration: Duration::from_secs(30),
@@ -360,7 +346,7 @@ impl SubstrateNode {
.get_or_try_init(|| async move { .get_or_try_init(|| async move {
construct_concurrency_limited_provider::<ReviveNetwork, _>( construct_concurrency_limited_provider::<ReviveNetwork, _>(
self.rpc_url.as_str(), self.rpc_url.as_str(),
FallbackGasFiller::new(u64::MAX, 5_000_000_000, 1_000_000_000), FallbackGasFiller::new(250_000_000, 5_000_000_000, 1_000_000_000),
ChainIdFiller::new(Some(CHAIN_ID)), ChainIdFiller::new(Some(CHAIN_ID)),
NonceFiller::new(self.nonce_manager.clone()), NonceFiller::new(self.nonce_manager.clone()),
self.wallet.clone(), self.wallet.clone(),
@@ -422,12 +408,23 @@ impl EthereumNode for SubstrateNode {
&self, &self,
transaction: TransactionRequest, transaction: TransactionRequest,
) -> Pin<Box<dyn Future<Output = anyhow::Result<TransactionReceipt>> + '_>> { ) -> Pin<Box<dyn Future<Output = anyhow::Result<TransactionReceipt>> + '_>> {
static SEMAPHORE: std::sync::LazyLock<tokio::sync::Semaphore> =
std::sync::LazyLock::new(|| tokio::sync::Semaphore::new(500));
Box::pin(async move { Box::pin(async move {
let provider = self let _permit = SEMAPHORE.acquire().await?;
let receipt = self
.provider() .provider()
.await .await
.context("Failed to create the provider")?; .context("Failed to create provider for transaction submission")?
execute_transaction(provider, transaction).await .send_transaction(transaction)
.await
.context("Failed to submit transaction to substrate proxy")?
.get_receipt()
.await
.context("Failed to fetch transaction receipt from substrate proxy")?;
Ok(receipt)
}) })
} }
@@ -519,46 +516,37 @@ impl EthereumNode for SubstrateNode {
+ '_, + '_,
>, >,
> { > {
fn create_stream(
provider: ConcreteProvider<ReviveNetwork, Arc<EthereumWallet>>,
) -> impl Stream<Item = MinedBlockInformation> {
stream! {
let mut block_number = provider.get_block_number().await.expect("Failed to get the block number");
loop {
tokio::time::sleep(Duration::from_secs(1)).await;
let Ok(Some(block)) = provider.get_block_by_number(BlockNumberOrTag::Number(block_number)).await
else {
continue;
};
block_number += 1;
yield MinedBlockInformation {
block_number: block.number(),
block_timestamp: block.header.timestamp,
mined_gas: block.header.gas_used as _,
block_gas_limit: block.header.gas_limit,
transaction_hashes: block
.transactions
.into_hashes()
.as_hashes()
.expect("Must be hashes")
.to_vec(),
};
};
}
}
Box::pin(async move { Box::pin(async move {
let provider = self let provider = self
.provider() .provider()
.await .await
.context("Failed to create the provider for a block subscription")?; .context("Failed to create the provider for block subscription")?;
let mut block_subscription = provider
.watch_full_blocks()
.await
.context("Failed to create the blocks stream")?;
block_subscription.set_channel_size(0xFFFF);
block_subscription.set_poll_interval(Duration::from_secs(1));
let block_stream = block_subscription.into_stream();
let stream = Box::pin(create_stream(provider)) let mined_block_information_stream = block_stream.filter_map(|block| async {
as Pin<Box<dyn Stream<Item = MinedBlockInformation>>>; let block = block.ok()?;
Some(MinedBlockInformation {
block_number: block.number(),
block_timestamp: block.header.timestamp,
mined_gas: block.header.gas_used as _,
block_gas_limit: block.header.gas_limit,
transaction_hashes: block
.transactions
.into_hashes()
.as_hashes()
.expect("Must be hashes")
.to_vec(),
})
});
Ok(stream) Ok(Box::pin(mined_block_information_stream)
as Pin<Box<dyn Stream<Item = MinedBlockInformation>>>)
}) })
} }
} }
@@ -1190,7 +1178,6 @@ mod tests {
let mut node = SubstrateNode::new( let mut node = SubstrateNode::new(
context.kitchensink_configuration.path.clone(), context.kitchensink_configuration.path.clone(),
SubstrateNode::KITCHENSINK_EXPORT_CHAINSPEC_COMMAND, SubstrateNode::KITCHENSINK_EXPORT_CHAINSPEC_COMMAND,
None,
&context, &context,
); );
node.init(context.genesis_configuration.genesis().unwrap().clone()) node.init(context.genesis_configuration.genesis().unwrap().clone())
@@ -1256,7 +1243,6 @@ mod tests {
let mut dummy_node = SubstrateNode::new( let mut dummy_node = SubstrateNode::new(
context.kitchensink_configuration.path.clone(), context.kitchensink_configuration.path.clone(),
SubstrateNode::KITCHENSINK_EXPORT_CHAINSPEC_COMMAND, SubstrateNode::KITCHENSINK_EXPORT_CHAINSPEC_COMMAND,
None,
&context, &context,
); );
@@ -1309,7 +1295,6 @@ mod tests {
let node = SubstrateNode::new( let node = SubstrateNode::new(
context.kitchensink_configuration.path.clone(), context.kitchensink_configuration.path.clone(),
SubstrateNode::KITCHENSINK_EXPORT_CHAINSPEC_COMMAND, SubstrateNode::KITCHENSINK_EXPORT_CHAINSPEC_COMMAND,
None,
&context, &context,
); );
File diff suppressed because it is too large Load Diff
@@ -7,10 +7,6 @@ use alloy::{
transports::TransportResult, transports::TransportResult,
}; };
// Percentage padding applied to estimated gas (e.g. 120 = 20% padding)
const GAS_ESTIMATE_PADDING_NUMERATOR: u64 = 120;
const GAS_ESTIMATE_PADDING_DENOMINATOR: u64 = 100;
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
pub struct FallbackGasFiller { pub struct FallbackGasFiller {
inner: GasFiller, inner: GasFiller,
@@ -60,6 +56,8 @@ where
provider: &P, provider: &P,
tx: &<N as Network>::TransactionRequest, tx: &<N as Network>::TransactionRequest,
) -> TransportResult<Self::Fillable> { ) -> TransportResult<Self::Fillable> {
// Try to fetch GasFillers “fillable” (gas_price, base_fee, estimate_gas, …)
// If it errors (i.e. tx would revert under eth_estimateGas), swallow it.
match self.inner.prepare(provider, tx).await { match self.inner.prepare(provider, tx).await {
Ok(fill) => Ok(Some(fill)), Ok(fill) => Ok(Some(fill)),
Err(_) => Ok(None), Err(_) => Ok(None),
@@ -72,17 +70,8 @@ where
mut tx: alloy::providers::SendableTx<N>, mut tx: alloy::providers::SendableTx<N>,
) -> TransportResult<SendableTx<N>> { ) -> TransportResult<SendableTx<N>> {
if let Some(fill) = fillable { if let Some(fill) = fillable {
let mut tx = self.inner.fill(fill, tx).await?; // our inner GasFiller succeeded — use it
if let Some(builder) = tx.as_mut_builder() { self.inner.fill(fill, tx).await
if let Some(estimated) = builder.gas_limit() {
let padded = estimated
.checked_mul(GAS_ESTIMATE_PADDING_NUMERATOR)
.and_then(|v| v.checked_div(GAS_ESTIMATE_PADDING_DENOMINATOR))
.unwrap_or(u64::MAX);
builder.set_gas_limit(padded);
}
}
Ok(tx)
} else { } else {
if let Some(builder) = tx.as_mut_builder() { if let Some(builder) = tx.as_mut_builder() {
builder.set_gas_limit(self.default_gas_limit); builder.set_gas_limit(self.default_gas_limit);
+2 -2
View File
@@ -1,7 +1,7 @@
mod concurrency_limiter; mod concurrency_limiter;
mod fallback_gas_filler; mod fallback_gas_provider;
mod provider; mod provider;
pub use concurrency_limiter::*; pub use concurrency_limiter::*;
pub use fallback_gas_filler::*; pub use fallback_gas_provider::*;
pub use provider::*; pub use provider::*;
+4 -73
View File
@@ -1,16 +1,14 @@
use std::{ops::ControlFlow, sync::LazyLock, time::Duration}; use std::sync::LazyLock;
use alloy::{ use alloy::{
network::{Ethereum, Network, NetworkWallet, TransactionBuilder4844}, network::{Network, NetworkWallet, TransactionBuilder4844},
providers::{ providers::{
Identity, PendingTransactionBuilder, Provider, ProviderBuilder, RootProvider, Identity, ProviderBuilder, RootProvider,
fillers::{ChainIdFiller, FillProvider, JoinFill, NonceFiller, TxFiller, WalletFiller}, fillers::{ChainIdFiller, FillProvider, JoinFill, NonceFiller, TxFiller, WalletFiller},
}, },
rpc::client::ClientBuilder, rpc::client::ClientBuilder,
}; };
use anyhow::{Context, Result}; use anyhow::{Context, Result};
use revive_dt_common::futures::{PollingWaitBehavior, poll};
use tracing::{Instrument, debug, info, info_span};
use crate::provider_utils::{ConcurrencyLimiterLayer, FallbackGasFiller}; use crate::provider_utils::{ConcurrencyLimiterLayer, FallbackGasFiller};
@@ -44,7 +42,7 @@ where
// requests at any point of time and no more than that. This is done in an effort to stabilize // requests at any point of time and no more than that. This is done in an effort to stabilize
// the framework from some of the interment issues that we've been seeing related to RPC calls. // the framework from some of the interment issues that we've been seeing related to RPC calls.
static GLOBAL_CONCURRENCY_LIMITER_LAYER: LazyLock<ConcurrencyLimiterLayer> = static GLOBAL_CONCURRENCY_LIMITER_LAYER: LazyLock<ConcurrencyLimiterLayer> =
LazyLock::new(|| ConcurrencyLimiterLayer::new(500)); LazyLock::new(|| ConcurrencyLimiterLayer::new(10));
let client = ClientBuilder::default() let client = ClientBuilder::default()
.layer(GLOBAL_CONCURRENCY_LIMITER_LAYER.clone()) .layer(GLOBAL_CONCURRENCY_LIMITER_LAYER.clone())
@@ -63,70 +61,3 @@ where
Ok(provider) Ok(provider)
} }
pub async fn execute_transaction<N, W>(
provider: ConcreteProvider<N, W>,
transaction: N::TransactionRequest,
) -> Result<N::ReceiptResponse>
where
N: Network<
TransactionRequest: TransactionBuilder4844,
TxEnvelope = <Ethereum as Network>::TxEnvelope,
>,
W: NetworkWallet<N>,
Identity: TxFiller<N>,
FallbackGasFiller: TxFiller<N>,
ChainIdFiller: TxFiller<N>,
NonceFiller: TxFiller<N>,
WalletFiller<W>: TxFiller<N>,
{
let sendable_transaction = provider
.fill(transaction)
.await
.context("Failed to fill transaction")?;
let transaction_envelope = sendable_transaction
.try_into_envelope()
.context("Failed to convert transaction into an envelope")?;
let tx_hash = *transaction_envelope.tx_hash();
let mut pending_transaction = match provider.send_tx_envelope(transaction_envelope).await {
Ok(pending_transaction) => pending_transaction,
Err(error) => {
let error_string = error.to_string();
if error_string.contains("Transaction Already Imported") {
PendingTransactionBuilder::<N>::new(provider.root().clone(), tx_hash)
} else {
return Err(error).context(format!("Failed to submit transaction {tx_hash}"));
}
}
};
debug!(%tx_hash, "Submitted Transaction");
pending_transaction.set_timeout(Some(Duration::from_secs(120)));
let tx_hash = pending_transaction.watch().await.context(format!(
"Transaction inclusion watching timeout for {tx_hash}"
))?;
poll(
Duration::from_secs(60),
PollingWaitBehavior::Constant(Duration::from_secs(3)),
|| {
let provider = provider.clone();
async move {
match provider.get_transaction_receipt(tx_hash).await {
Ok(Some(receipt)) => {
info!("Found the transaction receipt");
Ok(ControlFlow::Break(receipt))
}
_ => Ok(ControlFlow::Continue(())),
}
}
},
)
.instrument(info_span!("Polling for receipt", %tx_hash))
.await
.context(format!("Polling for receipt failed for {tx_hash}"))
}
+6 -4
View File
@@ -76,6 +76,8 @@ cat > "$CORPUS_FILE" << EOF
{ {
"name": "MatterLabs Solidity Simple, Complex, and Semantic Tests", "name": "MatterLabs Solidity Simple, Complex, and Semantic Tests",
"paths": [ "paths": [
"$(realpath "$TEST_REPO_DIR/fixtures/solidity/translated_semantic_tests")",
"$(realpath "$TEST_REPO_DIR/fixtures/solidity/complex")",
"$(realpath "$TEST_REPO_DIR/fixtures/solidity/simple")" "$(realpath "$TEST_REPO_DIR/fixtures/solidity/simple")"
] ]
} }
@@ -94,15 +96,15 @@ echo ""
cargo build --release; cargo build --release;
RUST_LOG="info,alloy_pubsub::service=error" ./target/release/retester test \ RUST_LOG="info,alloy_pubsub::service=error" ./target/release/retester test \
--platform geth-evm-solc \ --platform geth-evm-solc \
--platform revive-dev-node-revm-solc \
--corpus "$CORPUS_FILE" \ --corpus "$CORPUS_FILE" \
--working-directory "$WORKDIR" \ --working-directory "$WORKDIR" \
--concurrency.number-of-nodes 10 \ --concurrency.number-of-nodes 5 \
--concurrency.number-of-threads 5 \
--concurrency.ignore-concurrency-limit \
--wallet.additional-keys 100000 \ --wallet.additional-keys 100000 \
--kitchensink.path "$SUBSTRATE_NODE_BIN" \ --kitchensink.path "$SUBSTRATE_NODE_BIN" \
--revive-dev-node.path "$REVIVE_DEV_NODE_BIN" \ --revive-dev-node.path "$REVIVE_DEV_NODE_BIN" \
--eth-rpc.path "$ETH_RPC_BIN" \ --eth-rpc.path "$ETH_RPC_BIN" \
> logs.log > logs.log \
2> output.log
echo -e "${GREEN}=== Test run completed! ===${NC}" echo -e "${GREEN}=== Test run completed! ===${NC}"