Compare commits

...

3 Commits

Author SHA1 Message Date
Omar Abdulla ec4ec43a5c Remove unneeded dependency 2025-07-14 18:58:07 +03:00
Omar Abdulla cec67056ae Remove code that was accidentally committed. 2025-07-14 18:50:26 +03:00
Omar 5eb3a0e1b5 Fix for "transaction indexing is in progress" (#32)
* Retry getting transaction receipt

* Small fix to logging consistency

* Introduce a custom kitchensink network

* Fix formtting and clippy
2025-07-14 09:32:57 +00:00
7 changed files with 98 additions and 17 deletions
+4
View File
@@ -3,3 +3,7 @@
.DS_Store .DS_Store
node_modules node_modules
/*.json /*.json
# We do not want to commit any log files that we produce from running the code locally so this is
# added to the .gitignore file.
*.log
Generated
+7 -6
View File
@@ -67,9 +67,9 @@ checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923"
[[package]] [[package]]
name = "alloy" name = "alloy"
version = "1.0.9" version = "1.0.20"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0093d23bf026b580c1f66ed3a053d8209c104a446c5264d3ad99587f6edef24e" checksum = "ae58d888221eecf621595e2096836ce7cfc37be06bfa39d7f64aa6a3ea4c9e5b"
dependencies = [ dependencies = [
"alloy-consensus", "alloy-consensus",
"alloy-contract", "alloy-contract",
@@ -162,9 +162,9 @@ dependencies = [
[[package]] [[package]]
name = "alloy-core" name = "alloy-core"
version = "1.1.2" version = "1.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a3c5a28f166629752f2e7246b813cdea3243cca59aab2d4264b1fd68392c10eb" checksum = "ad31216895d27d307369daa1393f5850b50bbbd372478a9fa951c095c210627e"
dependencies = [ dependencies = [
"alloy-dyn-abi", "alloy-dyn-abi",
"alloy-json-abi", "alloy-json-abi",
@@ -175,9 +175,9 @@ dependencies = [
[[package]] [[package]]
name = "alloy-dyn-abi" name = "alloy-dyn-abi"
version = "1.1.2" version = "1.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "18cc14d832bc3331ca22a1c7819de1ede99f58f61a7d123952af7dde8de124a6" checksum = "7b95b3deca680efc7e9cba781f1a1db352fa1ea50e6384a514944dcf4419e652"
dependencies = [ dependencies = [
"alloy-json-abi", "alloy-json-abi",
"alloy-primitives", "alloy-primitives",
@@ -4002,6 +4002,7 @@ dependencies = [
"sp-core", "sp-core",
"sp-runtime", "sp-runtime",
"temp-dir", "temp-dir",
"tokio",
"tracing", "tracing",
] ]
+3
View File
@@ -68,6 +68,9 @@ features = [
"rpc-types", "rpc-types",
"signer-local", "signer-local",
"std", "std",
"network",
"serde",
"rpc-types-eth",
] ]
[profile.bench] [profile.bench]
+1 -1
View File
@@ -1,4 +1,4 @@
//! The global configuration used accross all revive differential testing crates. //! The global configuration used across all revive differential testing crates.
use std::{ use std::{
fmt::Display, fmt::Display,
+1
View File
@@ -12,6 +12,7 @@ rust-version.workspace = true
anyhow = { workspace = true } anyhow = { workspace = true }
alloy = { workspace = true } alloy = { workspace = true }
tracing = { workspace = true } tracing = { workspace = true }
tokio = { workspace = true }
revive-dt-node-interaction = { workspace = true } revive-dt-node-interaction = { workspace = true }
revive-dt-config = { workspace = true } revive-dt-config = { workspace = true }
+77 -8
View File
@@ -159,17 +159,85 @@ impl EthereumNode for Instance {
let connection_string = self.connection_string(); let connection_string = self.connection_string();
let wallet = self.wallet.clone(); let wallet = self.wallet.clone();
tracing::debug!("Submitting transaction: {transaction:#?}");
execute_transaction(Box::pin(async move { execute_transaction(Box::pin(async move {
Ok(ProviderBuilder::new() let outer_span = tracing::debug_span!("Submitting transaction", ?transaction,);
let _outer_guard = outer_span.enter();
let provider = ProviderBuilder::new()
.wallet(wallet) .wallet(wallet)
.connect(&connection_string) .connect(&connection_string)
.await? .await?;
.send_transaction(transaction)
.await? let pending_transaction = provider.send_transaction(transaction).await?;
.get_receipt() let transaction_hash = pending_transaction.tx_hash();
.await?)
let span = tracing::info_span!("Awaiting transaction receipt", ?transaction_hash);
let _guard = span.enter();
// The following is a fix for the "transaction indexing is in progress" error that we
// used to get. You can find more information on this in the following GH issue in geth
// https://github.com/ethereum/go-ethereum/issues/28877. To summarize what's going on,
// before we can get the receipt of the transaction it needs to have been indexed by the
// node's indexer. Just because the transaction has been confirmed it doesn't mean that
// it has been indexed. When we call alloy's `get_receipt` it checks if the transaction
// was confirmed. If it has been, then it will call `eth_getTransactionReceipt` method
// which _might_ return the above error if the tx has not yet been indexed yet. So, we
// need to implement a retry mechanism for the receipt to keep retrying to get it until
// it eventually works, but we only do that if the error we get back is the "transaction
// indexing is in progress" error or if the receipt is None.
//
// At the moment we do not allow for the 60 seconds to be modified and we take it as
// being an implementation detail that's invisible to anything outside of this module.
//
// We allow a total of 60 retries for getting the receipt with one second between each
// retry and the next which means that we allow for a total of 60 seconds of waiting
// before we consider that we're unable to get the transaction receipt.
let mut retries = 0;
loop {
match provider.get_transaction_receipt(*transaction_hash).await {
Ok(Some(receipt)) => {
tracing::info!("Obtained the transaction receipt");
break Ok(receipt);
}
Ok(None) => {
if retries == 60 {
tracing::error!(
"Polled for transaction receipt for 60 seconds but failed to get it"
);
break Err(anyhow::anyhow!("Failed to get the transaction receipt"));
} else {
tracing::trace!(
retries,
"Sleeping for 1 second and trying to get the receipt again"
);
retries += 1;
tokio::time::sleep(std::time::Duration::from_secs(1)).await;
continue;
}
}
Err(error) => {
let error_string = error.to_string();
if error_string.contains("transaction indexing is in progress") {
if retries == 60 {
tracing::error!(
"Polled for transaction receipt for 60 seconds but failed to get it"
);
break Err(error.into());
} else {
tracing::trace!(
retries,
"Sleeping for 1 second and trying to get the receipt again"
);
retries += 1;
tokio::time::sleep(std::time::Duration::from_secs(1)).await;
continue;
}
} else {
break Err(error.into());
}
}
}
}
})) }))
} }
@@ -270,6 +338,7 @@ impl Node for Instance {
impl Drop for Instance { impl Drop for Instance {
fn drop(&mut self) { fn drop(&mut self) {
tracing::info!(id = self.id, "Dropping node");
if let Some(child) = self.handle.as_mut() { if let Some(child) = self.handle.as_mut() {
let _ = child.kill(); let _ = child.kill();
} }
+5 -2
View File
@@ -254,7 +254,8 @@ impl EthereumNode for KitchensinkNode {
tracing::debug!("Submitting transaction: {transaction:#?}"); tracing::debug!("Submitting transaction: {transaction:#?}");
execute_transaction(Box::pin(async move { tracing::info!("Submitting tx to kitchensink");
let receipt = execute_transaction(Box::pin(async move {
Ok(ProviderBuilder::new() Ok(ProviderBuilder::new()
.wallet(wallet) .wallet(wallet)
.connect(&url) .connect(&url)
@@ -263,7 +264,9 @@ impl EthereumNode for KitchensinkNode {
.await? .await?
.get_receipt() .get_receipt()
.await?) .await?)
})) }));
tracing::info!(?receipt, "Submitted tx to kitchensink");
receipt
} }
fn trace_transaction( fn trace_transaction(