mirror of
https://github.com/pezkuwichain/revive-differential-tests.git
synced 2026-06-14 06:21:09 +00:00
Update the account pre-funding handling
This commit is contained in:
@@ -650,7 +650,7 @@ pub struct WalletConfiguration {
|
|||||||
/// its wallet signers. With a value of N, private keys (0, N] will be added to the signer set
|
/// its wallet signers. With a value of N, private keys (0, N] will be added to the signer set
|
||||||
/// of the node.
|
/// of the node.
|
||||||
#[clap(long = "wallet.additional-keys", default_value_t = 100_000)]
|
#[clap(long = "wallet.additional-keys", default_value_t = 100_000)]
|
||||||
additional_keys: usize,
|
pub additional_keys: usize,
|
||||||
|
|
||||||
/// The wallet object that will be used.
|
/// The wallet object that will be used.
|
||||||
#[clap(skip)]
|
#[clap(skip)]
|
||||||
@@ -779,7 +779,6 @@ impl AsRef<Path> for WorkingDirectoryConfiguration {
|
|||||||
impl Default for WorkingDirectoryConfiguration {
|
impl Default for WorkingDirectoryConfiguration {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
TempDir::new()
|
TempDir::new()
|
||||||
.map(|tempdir| dbg!(tempdir.dont_delete_on_drop()))
|
|
||||||
.map(Arc::new)
|
.map(Arc::new)
|
||||||
.map(Self::TemporaryDirectory)
|
.map(Self::TemporaryDirectory)
|
||||||
.expect("Failed to create the temporary directory")
|
.expect("Failed to create the temporary directory")
|
||||||
|
|||||||
@@ -9,7 +9,7 @@
|
|||||||
//! that the tool has.
|
//! that the tool has.
|
||||||
|
|
||||||
use std::{
|
use std::{
|
||||||
collections::BTreeMap,
|
collections::{BTreeMap, HashSet},
|
||||||
fs::{File, create_dir_all},
|
fs::{File, create_dir_all},
|
||||||
io::Read,
|
io::Read,
|
||||||
ops::ControlFlow,
|
ops::ControlFlow,
|
||||||
@@ -24,7 +24,7 @@ use std::{
|
|||||||
};
|
};
|
||||||
|
|
||||||
use alloy::{
|
use alloy::{
|
||||||
eips::BlockNumberOrTag,
|
eips::{BlockId, BlockNumberOrTag},
|
||||||
genesis::{Genesis, GenesisAccount},
|
genesis::{Genesis, GenesisAccount},
|
||||||
network::{Ethereum, EthereumWallet, NetworkWallet},
|
network::{Ethereum, EthereumWallet, NetworkWallet},
|
||||||
primitives::{
|
primitives::{
|
||||||
@@ -39,10 +39,8 @@ use alloy::{
|
|||||||
EIP1186AccountProofResponse, TransactionRequest,
|
EIP1186AccountProofResponse, TransactionRequest,
|
||||||
trace::geth::{DiffMode, GethDebugTracingOptions, PreStateConfig, PreStateFrame},
|
trace::geth::{DiffMode, GethDebugTracingOptions, PreStateConfig, PreStateFrame},
|
||||||
},
|
},
|
||||||
signers::local::PrivateKeySigner,
|
|
||||||
};
|
};
|
||||||
use anyhow::Context as _;
|
use anyhow::Context as _;
|
||||||
use futures::future;
|
|
||||||
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;
|
||||||
@@ -94,7 +92,7 @@ pub struct LighthouseGethNode {
|
|||||||
process: Option<Process>,
|
process: Option<Process>,
|
||||||
|
|
||||||
/* Prefunded Account Information */
|
/* Prefunded Account Information */
|
||||||
prefunded_account_private_key: PrivateKeySigner,
|
prefunded_account_address: Address,
|
||||||
|
|
||||||
/* Provider Related Fields */
|
/* Provider Related Fields */
|
||||||
wallet: Arc<EthereumWallet>,
|
wallet: Arc<EthereumWallet>,
|
||||||
@@ -166,7 +164,7 @@ impl LighthouseGethNode {
|
|||||||
process: None,
|
process: None,
|
||||||
|
|
||||||
/* Prefunded Account Information */
|
/* Prefunded Account Information */
|
||||||
prefunded_account_private_key: PrivateKeySigner::random(),
|
prefunded_account_address: wallet.default_signer().address(),
|
||||||
|
|
||||||
/* Provider Related Fields */
|
/* Provider Related Fields */
|
||||||
wallet: wallet.clone(),
|
wallet: wallet.clone(),
|
||||||
@@ -236,7 +234,7 @@ impl LighthouseGethNode {
|
|||||||
num_validator_keys_per_node: 64,
|
num_validator_keys_per_node: 64,
|
||||||
genesis_delay: 10,
|
genesis_delay: 10,
|
||||||
prefunded_accounts: {
|
prefunded_accounts: {
|
||||||
let map = std::iter::once(self.prefunded_account_private_key.address())
|
let map = std::iter::once(self.prefunded_account_address)
|
||||||
.map(|address| (address, GenesisAccount::default().with_balance(U256::MAX)))
|
.map(|address| (address, GenesisAccount::default().with_balance(U256::MAX)))
|
||||||
.collect::<BTreeMap<_, _>>();
|
.collect::<BTreeMap<_, _>>();
|
||||||
serde_json::to_string(&map).unwrap()
|
serde_json::to_string(&map).unwrap()
|
||||||
@@ -330,6 +328,12 @@ impl LighthouseGethNode {
|
|||||||
Ok(self)
|
Ok(self)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[instrument(
|
||||||
|
level = "info",
|
||||||
|
skip_all,
|
||||||
|
fields(lighthouse_node_id = self.id, connection_string = self.connection_string),
|
||||||
|
err(Debug),
|
||||||
|
)]
|
||||||
async fn provider(
|
async fn provider(
|
||||||
&self,
|
&self,
|
||||||
) -> anyhow::Result<FillProvider<impl TxFiller<Ethereum>, impl Provider<Ethereum>, Ethereum>>
|
) -> anyhow::Result<FillProvider<impl TxFiller<Ethereum>, impl Provider<Ethereum>, Ethereum>>
|
||||||
@@ -350,21 +354,130 @@ impl LighthouseGethNode {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Funds all of the accounts in the Ethereum wallet from the initially funded account.
|
/// Funds all of the accounts in the Ethereum wallet from the initially funded account.
|
||||||
|
#[instrument(
|
||||||
|
level = "info",
|
||||||
|
skip_all,
|
||||||
|
fields(lighthouse_node_id = self.id, connection_string = self.connection_string),
|
||||||
|
err(Debug),
|
||||||
|
)]
|
||||||
async fn fund_all_accounts(&self) -> anyhow::Result<()> {
|
async fn fund_all_accounts(&self) -> anyhow::Result<()> {
|
||||||
let tasks = NetworkWallet::<Ethereum>::signer_addresses(self.wallet.as_ref())
|
let mut providers =
|
||||||
.enumerate()
|
futures::future::try_join_all((0..100).map(|_| self.provider()).collect::<Vec<_>>())
|
||||||
.map(|(nonce, address)| async move {
|
.await
|
||||||
let transaction = TransactionRequest::default()
|
.context("Failed to create the providers")?
|
||||||
.from(self.prefunded_account_private_key.address())
|
.into_iter()
|
||||||
.to(address)
|
.map(Arc::new)
|
||||||
.nonce(nonce as _)
|
.collect::<Vec<_>>();
|
||||||
.value(INITIAL_BALANCE.try_into().unwrap());
|
|
||||||
self.execute_transaction(transaction).await
|
let mut tx_hashes = futures::future::try_join_all(
|
||||||
})
|
NetworkWallet::<Ethereum>::signer_addresses(self.wallet.as_ref())
|
||||||
.collect::<Vec<_>>();
|
.enumerate()
|
||||||
future::try_join_all(tasks).await?;
|
.map(|(nonce, address)| {
|
||||||
|
let provider = providers[nonce % 100].clone();
|
||||||
|
async move {
|
||||||
|
let transaction = TransactionRequest::default()
|
||||||
|
.from(self.prefunded_account_address)
|
||||||
|
.to(address)
|
||||||
|
.nonce(nonce as _)
|
||||||
|
.value(INITIAL_BALANCE.try_into().unwrap());
|
||||||
|
provider
|
||||||
|
.send_transaction(transaction)
|
||||||
|
.await
|
||||||
|
.map(|tx| *tx.tx_hash())
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.collect::<Vec<_>>(),
|
||||||
|
)
|
||||||
|
.await
|
||||||
|
.context("Failed to submit all transactions")?
|
||||||
|
.into_iter()
|
||||||
|
.collect::<HashSet<_>>();
|
||||||
|
|
||||||
|
let provider = providers.pop().unwrap();
|
||||||
|
let mut block_number = 0 as BlockNumber;
|
||||||
|
while !tx_hashes.is_empty() {
|
||||||
|
let Ok(Some(block)) = provider
|
||||||
|
.get_block(BlockId::Number(BlockNumberOrTag::Number(block_number)))
|
||||||
|
.await
|
||||||
|
else {
|
||||||
|
continue;
|
||||||
|
};
|
||||||
|
|
||||||
|
for hash in block.transactions.into_hashes().as_hashes().unwrap() {
|
||||||
|
tx_hashes.remove(hash);
|
||||||
|
}
|
||||||
|
|
||||||
|
block_number += 1
|
||||||
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn internal_execute_transaction<'a>(
|
||||||
|
transaction: TransactionRequest,
|
||||||
|
provider: Arc<
|
||||||
|
FillProvider<impl TxFiller<Ethereum> + 'a, impl Provider<Ethereum> + 'a, Ethereum>,
|
||||||
|
>,
|
||||||
|
) -> Pin<Box<dyn Future<Output = anyhow::Result<alloy::rpc::types::TransactionReceipt>> + 'a>>
|
||||||
|
{
|
||||||
|
Box::pin(async move {
|
||||||
|
let pending_transaction = provider
|
||||||
|
.send_transaction(transaction)
|
||||||
|
.await
|
||||||
|
.inspect_err(|err| {
|
||||||
|
tracing::error!(
|
||||||
|
%err,
|
||||||
|
"Encountered an error when submitting the transaction"
|
||||||
|
)
|
||||||
|
})
|
||||||
|
.context("Failed to submit transaction to geth node")?;
|
||||||
|
let transaction_hash = *pending_transaction.tx_hash();
|
||||||
|
|
||||||
|
// 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.
|
||||||
|
//
|
||||||
|
// 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 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 backoff each time we attempt to get the receipt and find that it's
|
||||||
|
// not available.
|
||||||
|
poll(
|
||||||
|
Self::RECEIPT_POLLING_DURATION,
|
||||||
|
PollingWaitBehavior::Constant(Duration::from_millis(500)),
|
||||||
|
move || {
|
||||||
|
let provider = provider.clone();
|
||||||
|
async move {
|
||||||
|
match provider.get_transaction_receipt(transaction_hash).await {
|
||||||
|
Ok(Some(receipt)) => Ok(ControlFlow::Break(receipt)),
|
||||||
|
Ok(None) => Ok(ControlFlow::Continue(())),
|
||||||
|
Err(error) => {
|
||||||
|
let error_string = error.to_string();
|
||||||
|
match error_string.contains(Self::TRANSACTION_INDEXING_ERROR) {
|
||||||
|
true => Ok(ControlFlow::Continue(())),
|
||||||
|
false => Err(error.into()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
)
|
||||||
|
.instrument(tracing::info_span!(
|
||||||
|
"Awaiting transaction receipt",
|
||||||
|
?transaction_hash
|
||||||
|
))
|
||||||
|
.await
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl EthereumNode for LighthouseGethNode {
|
impl EthereumNode for LighthouseGethNode {
|
||||||
@@ -395,64 +508,9 @@ impl EthereumNode for LighthouseGethNode {
|
|||||||
let provider = self
|
let provider = self
|
||||||
.provider()
|
.provider()
|
||||||
.await
|
.await
|
||||||
|
.map(Arc::new)
|
||||||
.context("Failed to create provider for transaction submission")?;
|
.context("Failed to create provider for transaction submission")?;
|
||||||
|
Self::internal_execute_transaction(transaction, provider).await
|
||||||
let pending_transaction = provider
|
|
||||||
.send_transaction(transaction)
|
|
||||||
.await
|
|
||||||
.inspect_err(|err| {
|
|
||||||
tracing::error!(
|
|
||||||
%err,
|
|
||||||
"Encountered an error when submitting the transaction"
|
|
||||||
)
|
|
||||||
})
|
|
||||||
.context("Failed to submit transaction to geth node")?;
|
|
||||||
let transaction_hash = *pending_transaction.tx_hash();
|
|
||||||
|
|
||||||
// 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.
|
|
||||||
//
|
|
||||||
// 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 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 backoff each time we attempt to get the receipt and find that it's
|
|
||||||
// not available.
|
|
||||||
let provider = Arc::new(provider);
|
|
||||||
poll(
|
|
||||||
Self::RECEIPT_POLLING_DURATION,
|
|
||||||
PollingWaitBehavior::Constant(Duration::from_millis(500)),
|
|
||||||
move || {
|
|
||||||
let provider = provider.clone();
|
|
||||||
async move {
|
|
||||||
match provider.get_transaction_receipt(transaction_hash).await {
|
|
||||||
Ok(Some(receipt)) => Ok(ControlFlow::Break(receipt)),
|
|
||||||
Ok(None) => Ok(ControlFlow::Continue(())),
|
|
||||||
Err(error) => {
|
|
||||||
let error_string = error.to_string();
|
|
||||||
match error_string.contains(Self::TRANSACTION_INDEXING_ERROR) {
|
|
||||||
true => Ok(ControlFlow::Continue(())),
|
|
||||||
false => Err(error.into()),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
)
|
|
||||||
.instrument(tracing::info_span!(
|
|
||||||
"Awaiting transaction receipt",
|
|
||||||
?transaction_hash
|
|
||||||
))
|
|
||||||
.await
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -876,7 +934,9 @@ mod tests {
|
|||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
fn test_config() -> TestExecutionContext {
|
fn test_config() -> TestExecutionContext {
|
||||||
TestExecutionContext::default()
|
let mut config = TestExecutionContext::default();
|
||||||
|
config.wallet_configuration.additional_keys = 100;
|
||||||
|
config
|
||||||
}
|
}
|
||||||
|
|
||||||
fn new_node() -> (TestExecutionContext, LighthouseGethNode) {
|
fn new_node() -> (TestExecutionContext, LighthouseGethNode) {
|
||||||
@@ -911,6 +971,7 @@ mod tests {
|
|||||||
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();
|
||||||
|
node.fund_all_accounts().await.expect("Failed");
|
||||||
|
|
||||||
let account_address = context
|
let account_address = context
|
||||||
.wallet_configuration
|
.wallet_configuration
|
||||||
|
|||||||
+1
-1
@@ -91,7 +91,7 @@ echo ""
|
|||||||
# Run the tool
|
# Run the tool
|
||||||
RUST_LOG="info" cargo run --release -- execute-tests \
|
RUST_LOG="info" cargo run --release -- execute-tests \
|
||||||
--platform geth-evm-solc \
|
--platform geth-evm-solc \
|
||||||
--platform revive-dev-node-polkavm-resolc \
|
--platform lighthouse-geth-evm-solc \
|
||||||
--corpus "$CORPUS_FILE" \
|
--corpus "$CORPUS_FILE" \
|
||||||
--working-directory "$WORKDIR" \
|
--working-directory "$WORKDIR" \
|
||||||
--concurrency.number-of-nodes 5 \
|
--concurrency.number-of-nodes 5 \
|
||||||
|
|||||||
Reference in New Issue
Block a user