mirror of
https://github.com/pezkuwichain/revive-differential-tests.git
synced 2026-07-22 12:05:44 +00:00
Make the ethereum node trait object compatible
This commit is contained in:
@@ -8,7 +8,7 @@ use alloy::consensus::EMPTY_ROOT_HASH;
|
|||||||
use alloy::hex;
|
use alloy::hex;
|
||||||
use alloy::json_abi::JsonAbi;
|
use alloy::json_abi::JsonAbi;
|
||||||
use alloy::network::{Ethereum, TransactionBuilder};
|
use alloy::network::{Ethereum, TransactionBuilder};
|
||||||
use alloy::primitives::U256;
|
use alloy::primitives::{TxHash, U256};
|
||||||
use alloy::rpc::types::TransactionReceipt;
|
use alloy::rpc::types::TransactionReceipt;
|
||||||
use alloy::rpc::types::trace::geth::{
|
use alloy::rpc::types::trace::geth::{
|
||||||
CallFrame, GethDebugBuiltInTracerType, GethDebugTracerConfig, GethDebugTracerType,
|
CallFrame, GethDebugBuiltInTracerType, GethDebugTracerConfig, GethDebugTracerType,
|
||||||
@@ -124,14 +124,14 @@ where
|
|||||||
.await
|
.await
|
||||||
.context("Failed during transaction execution phase of input handling")?;
|
.context("Failed during transaction execution phase of input handling")?;
|
||||||
let tracing_result = self
|
let tracing_result = self
|
||||||
.handle_input_call_frame_tracing(&execution_receipt, node)
|
.handle_input_call_frame_tracing(execution_receipt.transaction_hash, node)
|
||||||
.await
|
.await
|
||||||
.context("Failed during callframe tracing phase of input handling")?;
|
.context("Failed during callframe tracing phase of input handling")?;
|
||||||
self.handle_input_variable_assignment(input, &tracing_result)
|
self.handle_input_variable_assignment(input, &tracing_result)
|
||||||
.context("Failed to assign variables from callframe output")?;
|
.context("Failed to assign variables from callframe output")?;
|
||||||
let (_, (geth_trace, diff_mode)) = try_join!(
|
let (_, (geth_trace, diff_mode)) = try_join!(
|
||||||
self.handle_input_expectations(input, &execution_receipt, node, &tracing_result),
|
self.handle_input_expectations(input, &execution_receipt, node, &tracing_result),
|
||||||
self.handle_input_diff(&execution_receipt, node)
|
self.handle_input_diff(execution_receipt.transaction_hash, node)
|
||||||
)
|
)
|
||||||
.context("Failed while evaluating expectations and diffs in parallel")?;
|
.context("Failed while evaluating expectations and diffs in parallel")?;
|
||||||
Ok((execution_receipt, geth_trace, diff_mode))
|
Ok((execution_receipt, geth_trace, diff_mode))
|
||||||
@@ -250,11 +250,11 @@ where
|
|||||||
#[instrument(level = "info", skip_all)]
|
#[instrument(level = "info", skip_all)]
|
||||||
async fn handle_input_call_frame_tracing(
|
async fn handle_input_call_frame_tracing(
|
||||||
&self,
|
&self,
|
||||||
execution_receipt: &TransactionReceipt,
|
tx_hash: TxHash,
|
||||||
node: &T::Blockchain,
|
node: &T::Blockchain,
|
||||||
) -> anyhow::Result<CallFrame> {
|
) -> anyhow::Result<CallFrame> {
|
||||||
node.trace_transaction(
|
node.trace_transaction(
|
||||||
execution_receipt,
|
tx_hash,
|
||||||
GethDebugTracingOptions {
|
GethDebugTracingOptions {
|
||||||
tracer: Some(GethDebugTracerType::BuiltInTracer(
|
tracer: Some(GethDebugTracerType::BuiltInTracer(
|
||||||
GethDebugBuiltInTracerType::CallTracer,
|
GethDebugBuiltInTracerType::CallTracer,
|
||||||
@@ -507,7 +507,7 @@ where
|
|||||||
#[instrument(level = "info", skip_all)]
|
#[instrument(level = "info", skip_all)]
|
||||||
async fn handle_input_diff(
|
async fn handle_input_diff(
|
||||||
&self,
|
&self,
|
||||||
execution_receipt: &TransactionReceipt,
|
tx_hash: TxHash,
|
||||||
node: &T::Blockchain,
|
node: &T::Blockchain,
|
||||||
) -> anyhow::Result<(GethTrace, DiffMode)> {
|
) -> anyhow::Result<(GethTrace, DiffMode)> {
|
||||||
let trace_options = GethDebugTracingOptions::prestate_tracer(PreStateConfig {
|
let trace_options = GethDebugTracingOptions::prestate_tracer(PreStateConfig {
|
||||||
@@ -517,11 +517,11 @@ where
|
|||||||
});
|
});
|
||||||
|
|
||||||
let trace = node
|
let trace = node
|
||||||
.trace_transaction(execution_receipt, trace_options)
|
.trace_transaction(tx_hash, trace_options)
|
||||||
.await
|
.await
|
||||||
.context("Failed to obtain geth prestate tracer output")?;
|
.context("Failed to obtain geth prestate tracer output")?;
|
||||||
let diff = node
|
let diff = node
|
||||||
.state_diff(execution_receipt)
|
.state_diff(tx_hash)
|
||||||
.await
|
.await
|
||||||
.context("Failed to obtain state diff for transaction")?;
|
.context("Failed to obtain state diff for transaction")?;
|
||||||
|
|
||||||
|
|||||||
@@ -53,5 +53,5 @@ pub trait DynPlatform {
|
|||||||
|
|
||||||
/// Creates a new node for the platform by spawning a new thread, creating the node object,
|
/// Creates a new node for the platform by spawning a new thread, creating the node object,
|
||||||
/// initializing it, spawning it, and waiting for it to start up.
|
/// initializing it, spawning it, and waiting for it to start up.
|
||||||
fn new_node(&self) -> Box<dyn PlatformNode>;
|
fn new_node(&self) -> Box<dyn EthereumNode>;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,39 +1,42 @@
|
|||||||
//! This crate implements all node interactions.
|
//! This crate implements all node interactions.
|
||||||
|
|
||||||
use alloy::primitives::{Address, StorageKey, U256};
|
use std::pin::Pin;
|
||||||
|
|
||||||
|
use alloy::primitives::{Address, StorageKey, TxHash, U256};
|
||||||
use alloy::rpc::types::trace::geth::{DiffMode, GethDebugTracingOptions, GethTrace};
|
use alloy::rpc::types::trace::geth::{DiffMode, GethDebugTracingOptions, GethTrace};
|
||||||
use alloy::rpc::types::{EIP1186AccountProofResponse, TransactionReceipt, TransactionRequest};
|
use alloy::rpc::types::{EIP1186AccountProofResponse, TransactionReceipt, TransactionRequest};
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use revive_dt_format::traits::ResolverApi;
|
use revive_dt_format::traits::ResolverApi;
|
||||||
|
|
||||||
/// An interface for all interactions with Ethereum compatible nodes.
|
/// An interface for all interactions with Ethereum compatible nodes.
|
||||||
|
#[allow(clippy::type_complexity)]
|
||||||
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,
|
&self,
|
||||||
transaction: TransactionRequest,
|
transaction: TransactionRequest,
|
||||||
) -> impl Future<Output = Result<TransactionReceipt>>;
|
) -> Pin<Box<dyn Future<Output = 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(
|
||||||
&self,
|
&self,
|
||||||
receipt: &TransactionReceipt,
|
tx_hash: TxHash,
|
||||||
trace_options: GethDebugTracingOptions,
|
trace_options: GethDebugTracingOptions,
|
||||||
) -> impl Future<Output = Result<GethTrace>>;
|
) -> Pin<Box<dyn Future<Output = Result<GethTrace>> + '_>>;
|
||||||
|
|
||||||
/// Returns the state diff of the transaction hash in the [TransactionReceipt].
|
/// Returns the state diff of the transaction hash in the [TransactionReceipt].
|
||||||
fn state_diff(&self, receipt: &TransactionReceipt) -> impl Future<Output = Result<DiffMode>>;
|
fn state_diff(&self, tx_hash: TxHash) -> Pin<Box<dyn Future<Output = Result<DiffMode>> + '_>>;
|
||||||
|
|
||||||
/// Returns the balance of the provided [`Address`] back.
|
/// Returns the balance of the provided [`Address`] back.
|
||||||
fn balance_of(&self, address: Address) -> impl Future<Output = Result<U256>>;
|
fn balance_of(&self, address: Address) -> Pin<Box<dyn Future<Output = Result<U256>> + '_>>;
|
||||||
|
|
||||||
/// Returns the latest storage proof of the provided [`Address`]
|
/// Returns the latest storage proof of the provided [`Address`]
|
||||||
fn latest_state_proof(
|
fn latest_state_proof(
|
||||||
&self,
|
&self,
|
||||||
address: Address,
|
address: Address,
|
||||||
keys: Vec<StorageKey>,
|
keys: Vec<StorageKey>,
|
||||||
) -> impl Future<Output = Result<EIP1186AccountProofResponse>>;
|
) -> Pin<Box<dyn Future<Output = Result<EIP1186AccountProofResponse>> + '_>>;
|
||||||
|
|
||||||
/// Returns the resolver that is to use with this ethereum node.
|
/// Returns the resolver that is to use with this ethereum node.
|
||||||
fn resolver(&self) -> impl Future<Output = Result<Box<dyn ResolverApi + '_>>>;
|
fn resolver(&self) -> Pin<Box<dyn Future<Output = Result<Box<dyn ResolverApi + '_>>> + '_>>;
|
||||||
}
|
}
|
||||||
|
|||||||
+139
-119
@@ -25,7 +25,7 @@ use alloy::{
|
|||||||
fillers::{CachedNonceManager, ChainIdFiller, FillProvider, NonceFiller, TxFiller},
|
fillers::{CachedNonceManager, ChainIdFiller, FillProvider, NonceFiller, TxFiller},
|
||||||
},
|
},
|
||||||
rpc::types::{
|
rpc::types::{
|
||||||
EIP1186AccountProofResponse, TransactionReceipt, TransactionRequest,
|
EIP1186AccountProofResponse, TransactionRequest,
|
||||||
trace::geth::{DiffMode, GethDebugTracingOptions, PreStateConfig, PreStateFrame},
|
trace::geth::{DiffMode, GethDebugTracingOptions, PreStateConfig, PreStateFrame},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
@@ -296,152 +296,172 @@ impl EthereumNode for GethNode {
|
|||||||
fields(geth_node_id = self.id, connection_string = self.connection_string),
|
fields(geth_node_id = self.id, connection_string = self.connection_string),
|
||||||
err,
|
err,
|
||||||
)]
|
)]
|
||||||
async fn execute_transaction(
|
fn execute_transaction(
|
||||||
&self,
|
&self,
|
||||||
transaction: TransactionRequest,
|
transaction: TransactionRequest,
|
||||||
) -> anyhow::Result<alloy::rpc::types::TransactionReceipt> {
|
) -> Pin<Box<dyn Future<Output = anyhow::Result<alloy::rpc::types::TransactionReceipt>> + '_>>
|
||||||
let provider = self
|
{
|
||||||
.provider()
|
Box::pin(async move {
|
||||||
.await
|
let provider = self
|
||||||
.context("Failed to create provider for transaction submission")?;
|
.provider()
|
||||||
|
.await
|
||||||
|
.context("Failed to create provider for transaction submission")?;
|
||||||
|
|
||||||
let pending_transaction = provider
|
let pending_transaction = provider
|
||||||
.send_transaction(transaction)
|
.send_transaction(transaction)
|
||||||
.await
|
.await
|
||||||
.inspect_err(
|
.inspect_err(
|
||||||
|err| tracing::error!(%err, "Encountered an error when submitting the transaction"),
|
|err| tracing::error!(%err, "Encountered an error when submitting the transaction"),
|
||||||
)
|
)
|
||||||
.context("Failed to submit transaction to geth node")?;
|
.context("Failed to submit transaction to geth node")?;
|
||||||
let transaction_hash = *pending_transaction.tx_hash();
|
let transaction_hash = *pending_transaction.tx_hash();
|
||||||
|
|
||||||
// The following is a fix for the "transaction indexing is in progress" error that we used
|
// 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
|
// 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,
|
// 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
|
// 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
|
// 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
|
// 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
|
// 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
|
// _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
|
// 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
|
// 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.
|
// indexing is in progress" error or if the receipt is None.
|
||||||
//
|
//
|
||||||
// Getting the transaction indexed and taking a receipt can take a long time especially when
|
// Getting the transaction indexed and taking a receipt can take a long time especially when
|
||||||
// a lot of transactions are being submitted to the node. Thus, while initially we only
|
// a lot of transactions are being submitted to the node. Thus, while initially we only
|
||||||
// allowed for 60 seconds of waiting with a 1 second delay in polling, we need to allow for
|
// allowed for 60 seconds of waiting with a 1 second delay in polling, we need to allow for
|
||||||
// a larger wait time. Therefore, in here we allow for 5 minutes of waiting with exponential
|
// a larger wait time. Therefore, in here we allow for 5 minutes of waiting with exponential
|
||||||
// backoff each time we attempt to get the receipt and find that it's not available.
|
// backoff each time we attempt to get the receipt and find that it's not available.
|
||||||
let provider = Arc::new(provider);
|
let provider = Arc::new(provider);
|
||||||
poll(
|
poll(
|
||||||
Self::RECEIPT_POLLING_DURATION,
|
Self::RECEIPT_POLLING_DURATION,
|
||||||
PollingWaitBehavior::Constant(Duration::from_millis(200)),
|
PollingWaitBehavior::Constant(Duration::from_millis(200)),
|
||||||
move || {
|
move || {
|
||||||
let provider = provider.clone();
|
let provider = provider.clone();
|
||||||
async move {
|
async move {
|
||||||
match provider.get_transaction_receipt(transaction_hash).await {
|
match provider.get_transaction_receipt(transaction_hash).await {
|
||||||
Ok(Some(receipt)) => Ok(ControlFlow::Break(receipt)),
|
Ok(Some(receipt)) => Ok(ControlFlow::Break(receipt)),
|
||||||
Ok(None) => Ok(ControlFlow::Continue(())),
|
Ok(None) => Ok(ControlFlow::Continue(())),
|
||||||
Err(error) => {
|
Err(error) => {
|
||||||
let error_string = error.to_string();
|
let error_string = error.to_string();
|
||||||
match error_string.contains(Self::TRANSACTION_INDEXING_ERROR) {
|
match error_string.contains(Self::TRANSACTION_INDEXING_ERROR) {
|
||||||
true => Ok(ControlFlow::Continue(())),
|
true => Ok(ControlFlow::Continue(())),
|
||||||
false => Err(error.into()),
|
false => Err(error.into()),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
},
|
)
|
||||||
)
|
.instrument(tracing::info_span!(
|
||||||
.instrument(tracing::info_span!(
|
"Awaiting transaction receipt",
|
||||||
"Awaiting transaction receipt",
|
?transaction_hash
|
||||||
?transaction_hash
|
))
|
||||||
))
|
.await
|
||||||
.await
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
#[instrument(level = "info", skip_all, fields(geth_node_id = self.id))]
|
#[instrument(level = "info", skip_all, fields(geth_node_id = self.id))]
|
||||||
async fn trace_transaction(
|
fn trace_transaction(
|
||||||
&self,
|
&self,
|
||||||
transaction: &TransactionReceipt,
|
tx_hash: TxHash,
|
||||||
trace_options: GethDebugTracingOptions,
|
trace_options: GethDebugTracingOptions,
|
||||||
) -> anyhow::Result<alloy::rpc::types::trace::geth::GethTrace> {
|
) -> Pin<Box<dyn Future<Output = anyhow::Result<alloy::rpc::types::trace::geth::GethTrace>> + '_>>
|
||||||
let provider = Arc::new(
|
{
|
||||||
|
Box::pin(async move {
|
||||||
|
let provider = Arc::new(
|
||||||
|
self.provider()
|
||||||
|
.await
|
||||||
|
.context("Failed to create provider for tracing")?,
|
||||||
|
);
|
||||||
|
poll(
|
||||||
|
Self::TRACE_POLLING_DURATION,
|
||||||
|
PollingWaitBehavior::Constant(Duration::from_millis(200)),
|
||||||
|
move || {
|
||||||
|
let provider = provider.clone();
|
||||||
|
let trace_options = trace_options.clone();
|
||||||
|
async move {
|
||||||
|
match provider
|
||||||
|
.debug_trace_transaction(tx_hash, trace_options)
|
||||||
|
.await
|
||||||
|
{
|
||||||
|
Ok(trace) => Ok(ControlFlow::Break(trace)),
|
||||||
|
Err(error) => {
|
||||||
|
let error_string = error.to_string();
|
||||||
|
match error_string.contains(Self::TRANSACTION_TRACING_ERROR) {
|
||||||
|
true => Ok(ControlFlow::Continue(())),
|
||||||
|
false => Err(error.into()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
)
|
||||||
|
.await
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
#[instrument(level = "info", skip_all, fields(geth_node_id = self.id))]
|
||||||
|
fn state_diff(
|
||||||
|
&self,
|
||||||
|
tx_hash: TxHash,
|
||||||
|
) -> Pin<Box<dyn Future<Output = anyhow::Result<DiffMode>> + '_>> {
|
||||||
|
Box::pin(async move {
|
||||||
|
let trace_options = GethDebugTracingOptions::prestate_tracer(PreStateConfig {
|
||||||
|
diff_mode: Some(true),
|
||||||
|
disable_code: None,
|
||||||
|
disable_storage: None,
|
||||||
|
});
|
||||||
|
match self
|
||||||
|
.trace_transaction(tx_hash, trace_options)
|
||||||
|
.await
|
||||||
|
.context("Failed to trace transaction for prestate diff")?
|
||||||
|
.try_into_pre_state_frame()
|
||||||
|
.context("Failed to convert trace into pre-state frame")?
|
||||||
|
{
|
||||||
|
PreStateFrame::Diff(diff) => Ok(diff),
|
||||||
|
_ => anyhow::bail!("expected a diff mode trace"),
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
#[instrument(level = "info", skip_all, fields(geth_node_id = self.id))]
|
||||||
|
fn balance_of(
|
||||||
|
&self,
|
||||||
|
address: Address,
|
||||||
|
) -> Pin<Box<dyn Future<Output = anyhow::Result<U256>> + '_>> {
|
||||||
|
Box::pin(async move {
|
||||||
self.provider()
|
self.provider()
|
||||||
.await
|
.await
|
||||||
.context("Failed to create provider for tracing")?,
|
.context("Failed to get the Geth provider")?
|
||||||
);
|
.get_balance(address)
|
||||||
poll(
|
.await
|
||||||
Self::TRACE_POLLING_DURATION,
|
.map_err(Into::into)
|
||||||
PollingWaitBehavior::Constant(Duration::from_millis(200)),
|
})
|
||||||
move || {
|
|
||||||
let provider = provider.clone();
|
|
||||||
let trace_options = trace_options.clone();
|
|
||||||
async move {
|
|
||||||
match provider
|
|
||||||
.debug_trace_transaction(transaction.transaction_hash, trace_options)
|
|
||||||
.await
|
|
||||||
{
|
|
||||||
Ok(trace) => Ok(ControlFlow::Break(trace)),
|
|
||||||
Err(error) => {
|
|
||||||
let error_string = error.to_string();
|
|
||||||
match error_string.contains(Self::TRANSACTION_TRACING_ERROR) {
|
|
||||||
true => Ok(ControlFlow::Continue(())),
|
|
||||||
false => Err(error.into()),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
)
|
|
||||||
.await
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[instrument(level = "info", skip_all, fields(geth_node_id = self.id))]
|
#[instrument(level = "info", skip_all, fields(geth_node_id = self.id))]
|
||||||
async fn state_diff(&self, transaction: &TransactionReceipt) -> anyhow::Result<DiffMode> {
|
fn latest_state_proof(
|
||||||
let trace_options = GethDebugTracingOptions::prestate_tracer(PreStateConfig {
|
|
||||||
diff_mode: Some(true),
|
|
||||||
disable_code: None,
|
|
||||||
disable_storage: None,
|
|
||||||
});
|
|
||||||
match self
|
|
||||||
.trace_transaction(transaction, trace_options)
|
|
||||||
.await
|
|
||||||
.context("Failed to trace transaction for prestate diff")?
|
|
||||||
.try_into_pre_state_frame()
|
|
||||||
.context("Failed to convert trace into pre-state frame")?
|
|
||||||
{
|
|
||||||
PreStateFrame::Diff(diff) => Ok(diff),
|
|
||||||
_ => anyhow::bail!("expected a diff mode trace"),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[instrument(level = "info", skip_all, fields(geth_node_id = self.id))]
|
|
||||||
async fn balance_of(&self, address: Address) -> anyhow::Result<U256> {
|
|
||||||
self.provider()
|
|
||||||
.await
|
|
||||||
.context("Failed to get the Geth provider")?
|
|
||||||
.get_balance(address)
|
|
||||||
.await
|
|
||||||
.map_err(Into::into)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[instrument(level = "info", skip_all, fields(geth_node_id = self.id))]
|
|
||||||
async fn latest_state_proof(
|
|
||||||
&self,
|
&self,
|
||||||
address: Address,
|
address: Address,
|
||||||
keys: Vec<StorageKey>,
|
keys: Vec<StorageKey>,
|
||||||
) -> anyhow::Result<EIP1186AccountProofResponse> {
|
) -> Pin<Box<dyn Future<Output = anyhow::Result<EIP1186AccountProofResponse>> + '_>> {
|
||||||
self.provider()
|
Box::pin(async move {
|
||||||
.await
|
self.provider()
|
||||||
.context("Failed to get the Geth provider")?
|
.await
|
||||||
.get_proof(address, keys)
|
.context("Failed to get the Geth provider")?
|
||||||
.latest()
|
.get_proof(address, keys)
|
||||||
.await
|
.latest()
|
||||||
.map_err(Into::into)
|
.await
|
||||||
|
.map_err(Into::into)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
#[instrument(level = "info", skip_all, fields(geth_node_id = self.id))]
|
// #[instrument(level = "info", skip_all, fields(geth_node_id = self.id))]
|
||||||
fn resolver(&self) -> impl Future<Output = anyhow::Result<Box<dyn ResolverApi + '_>>> {
|
fn resolver(
|
||||||
|
&self,
|
||||||
|
) -> Pin<Box<dyn Future<Output = anyhow::Result<Box<dyn ResolverApi + '_>>> + '_>> {
|
||||||
Box::pin(async move {
|
Box::pin(async move {
|
||||||
let id = self.id;
|
let id = self.id;
|
||||||
let provider = self.provider().await?;
|
let provider = self.provider().await?;
|
||||||
|
|||||||
@@ -412,77 +412,95 @@ impl KitchensinkNode {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl EthereumNode for KitchensinkNode {
|
impl EthereumNode for KitchensinkNode {
|
||||||
async fn execute_transaction(
|
fn execute_transaction(
|
||||||
&self,
|
&self,
|
||||||
transaction: alloy::rpc::types::TransactionRequest,
|
transaction: alloy::rpc::types::TransactionRequest,
|
||||||
) -> anyhow::Result<TransactionReceipt> {
|
) -> Pin<Box<dyn Future<Output = anyhow::Result<TransactionReceipt>> + '_>> {
|
||||||
let receipt = self
|
Box::pin(async move {
|
||||||
.provider()
|
let receipt = self
|
||||||
.await
|
.provider()
|
||||||
.context("Failed to create provider for transaction submission")?
|
.await
|
||||||
.send_transaction(transaction)
|
.context("Failed to create provider for transaction submission")?
|
||||||
.await
|
.send_transaction(transaction)
|
||||||
.context("Failed to submit transaction to kitchensink proxy")?
|
.await
|
||||||
.get_receipt()
|
.context("Failed to submit transaction to kitchensink proxy")?
|
||||||
.await
|
.get_receipt()
|
||||||
.context("Failed to fetch transaction receipt from kitchensink proxy")?;
|
.await
|
||||||
Ok(receipt)
|
.context("Failed to fetch transaction receipt from kitchensink proxy")?;
|
||||||
|
Ok(receipt)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn trace_transaction(
|
fn trace_transaction(
|
||||||
&self,
|
&self,
|
||||||
transaction: &TransactionReceipt,
|
tx_hash: TxHash,
|
||||||
trace_options: GethDebugTracingOptions,
|
trace_options: GethDebugTracingOptions,
|
||||||
) -> anyhow::Result<alloy::rpc::types::trace::geth::GethTrace> {
|
) -> Pin<Box<dyn Future<Output = anyhow::Result<alloy::rpc::types::trace::geth::GethTrace>> + '_>>
|
||||||
let tx_hash = transaction.transaction_hash;
|
{
|
||||||
self.provider()
|
Box::pin(async move {
|
||||||
.await
|
self.provider()
|
||||||
.context("Failed to create provider for debug tracing")?
|
.await
|
||||||
.debug_trace_transaction(tx_hash, trace_options)
|
.context("Failed to create provider for debug tracing")?
|
||||||
.await
|
.debug_trace_transaction(tx_hash, trace_options)
|
||||||
.context("Failed to obtain debug trace from kitchensink proxy")
|
.await
|
||||||
|
.context("Failed to obtain debug trace from kitchensink proxy")
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn state_diff(&self, transaction: &TransactionReceipt) -> anyhow::Result<DiffMode> {
|
fn state_diff(
|
||||||
let trace_options = GethDebugTracingOptions::prestate_tracer(PreStateConfig {
|
&self,
|
||||||
diff_mode: Some(true),
|
tx_hash: TxHash,
|
||||||
disable_code: None,
|
) -> Pin<Box<dyn Future<Output = anyhow::Result<DiffMode>> + '_>> {
|
||||||
disable_storage: None,
|
Box::pin(async move {
|
||||||
});
|
let trace_options = GethDebugTracingOptions::prestate_tracer(PreStateConfig {
|
||||||
match self
|
diff_mode: Some(true),
|
||||||
.trace_transaction(transaction, trace_options)
|
disable_code: None,
|
||||||
.await?
|
disable_storage: None,
|
||||||
.try_into_pre_state_frame()?
|
});
|
||||||
{
|
match self
|
||||||
PreStateFrame::Diff(diff) => Ok(diff),
|
.trace_transaction(tx_hash, trace_options)
|
||||||
_ => anyhow::bail!("expected a diff mode trace"),
|
.await?
|
||||||
}
|
.try_into_pre_state_frame()?
|
||||||
|
{
|
||||||
|
PreStateFrame::Diff(diff) => Ok(diff),
|
||||||
|
_ => anyhow::bail!("expected a diff mode trace"),
|
||||||
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn balance_of(&self, address: Address) -> anyhow::Result<U256> {
|
fn balance_of(
|
||||||
self.provider()
|
&self,
|
||||||
.await
|
address: Address,
|
||||||
.context("Failed to get the Kitchensink provider")?
|
) -> Pin<Box<dyn Future<Output = anyhow::Result<U256>> + '_>> {
|
||||||
.get_balance(address)
|
Box::pin(async move {
|
||||||
.await
|
self.provider()
|
||||||
.map_err(Into::into)
|
.await
|
||||||
|
.context("Failed to get the Kitchensink provider")?
|
||||||
|
.get_balance(address)
|
||||||
|
.await
|
||||||
|
.map_err(Into::into)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn latest_state_proof(
|
fn latest_state_proof(
|
||||||
&self,
|
&self,
|
||||||
address: Address,
|
address: Address,
|
||||||
keys: Vec<StorageKey>,
|
keys: Vec<StorageKey>,
|
||||||
) -> anyhow::Result<EIP1186AccountProofResponse> {
|
) -> Pin<Box<dyn Future<Output = anyhow::Result<EIP1186AccountProofResponse>> + '_>> {
|
||||||
self.provider()
|
Box::pin(async move {
|
||||||
.await
|
self.provider()
|
||||||
.context("Failed to get the Kitchensink provider")?
|
.await
|
||||||
.get_proof(address, keys)
|
.context("Failed to get the Kitchensink provider")?
|
||||||
.latest()
|
.get_proof(address, keys)
|
||||||
.await
|
.latest()
|
||||||
.map_err(Into::into)
|
.await
|
||||||
|
.map_err(Into::into)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn resolver(&self) -> impl Future<Output = anyhow::Result<Box<dyn ResolverApi + '_>>> {
|
fn resolver(
|
||||||
|
&self,
|
||||||
|
) -> Pin<Box<dyn Future<Output = anyhow::Result<Box<dyn ResolverApi + '_>>> + '_>> {
|
||||||
Box::pin(async move {
|
Box::pin(async move {
|
||||||
let id = self.id;
|
let id = self.id;
|
||||||
let provider = self.provider().await?;
|
let provider = self.provider().await?;
|
||||||
|
|||||||
Reference in New Issue
Block a user