mirror of
https://github.com/paradigmxyz/reth.git
synced 2026-04-08 03:01:12 -04:00
enhance tx gossip test coverage (#6578)
Co-authored-by: Emilia Hane <emiliaha95@gmail.com>
This commit is contained in:
@@ -916,6 +916,11 @@ impl Peer {
|
||||
Self { kind: PeerKind::Trusted, ..Self::new(addr) }
|
||||
}
|
||||
|
||||
/// Returns the reputation of the peer
|
||||
pub fn reputation(&self) -> i32 {
|
||||
self.reputation
|
||||
}
|
||||
|
||||
fn with_state(addr: SocketAddr, state: PeerConnectionState) -> Self {
|
||||
Self {
|
||||
addr,
|
||||
|
||||
@@ -4,6 +4,7 @@ use crate::{
|
||||
builder::ETH_REQUEST_CHANNEL_CAPACITY,
|
||||
error::NetworkError,
|
||||
eth_requests::EthRequestHandler,
|
||||
peers::PeersHandle,
|
||||
protocol::IntoRlpxSubProtocol,
|
||||
transactions::{TransactionsHandle, TransactionsManager},
|
||||
NetworkConfig, NetworkConfigBuilder, NetworkEvent, NetworkEvents, NetworkHandle,
|
||||
@@ -475,6 +476,10 @@ impl<Pool> PeerHandle<Pool> {
|
||||
self.network.peer_id()
|
||||
}
|
||||
|
||||
pub fn peer_handle(&self) -> &PeersHandle {
|
||||
self.network.peers_handle()
|
||||
}
|
||||
|
||||
pub fn local_addr(&self) -> SocketAddr {
|
||||
self.network.local_addr()
|
||||
}
|
||||
|
||||
@@ -2,9 +2,10 @@
|
||||
|
||||
use rand::thread_rng;
|
||||
use reth_network::test_utils::Testnet;
|
||||
use reth_primitives::U256;
|
||||
use reth_primitives::{TransactionSigned, U256};
|
||||
use reth_provider::test_utils::{ExtendedAccount, MockEthProvider};
|
||||
use reth_transaction_pool::{test_utils::TransactionGenerator, PoolTransaction, TransactionPool};
|
||||
use std::{sync::Arc, time::Duration};
|
||||
#[tokio::test(flavor = "multi_thread")]
|
||||
async fn test_tx_gossip() {
|
||||
reth_tracing::init_test_tracing();
|
||||
@@ -42,3 +43,85 @@ async fn test_tx_gossip() {
|
||||
let received = peer1_tx_listener.recv().await.unwrap();
|
||||
assert_eq!(received, hash);
|
||||
}
|
||||
|
||||
#[tokio::test(flavor = "multi_thread")]
|
||||
async fn test_4844_tx_gossip_penalization() {
|
||||
reth_tracing::init_test_tracing();
|
||||
let provider = MockEthProvider::default();
|
||||
let net = Testnet::create_with(2, provider.clone()).await;
|
||||
|
||||
// install request handlers
|
||||
let net = net.with_eth_pool();
|
||||
|
||||
let handle = net.spawn();
|
||||
|
||||
let peer0 = &handle.peers()[0];
|
||||
let peer1 = &handle.peers()[1];
|
||||
|
||||
// connect all the peers
|
||||
handle.connect_peers().await;
|
||||
|
||||
let mut peer1_tx_listener = peer1.pool().unwrap().pending_transactions_listener();
|
||||
|
||||
let mut gen = TransactionGenerator::new(thread_rng());
|
||||
|
||||
// peer 0 will be penalised for sending txs[0] over gossip
|
||||
let txs = vec![gen.gen_eip4844_pooled(), gen.gen_eip1559_pooled()];
|
||||
|
||||
txs.iter().for_each(|tx| {
|
||||
let sender = tx.sender();
|
||||
provider.add_account(sender, ExtendedAccount::new(0, U256::from(100_000_000)));
|
||||
});
|
||||
|
||||
let signed_txs: Vec<Arc<TransactionSigned>> =
|
||||
txs.iter().map(|tx| Arc::new(tx.transaction().clone().into_signed())).collect();
|
||||
|
||||
let network_handle = peer0.network();
|
||||
|
||||
let peer0_reputation_before =
|
||||
peer1.peer_handle().peer_by_id(peer0.peer_id().clone()).await.unwrap().reputation();
|
||||
|
||||
// sends txs directly to peer1
|
||||
network_handle.send_transactions(peer1.peer_id().clone(), signed_txs);
|
||||
|
||||
let received = peer1_tx_listener.recv().await.unwrap();
|
||||
|
||||
let peer0_reputation_after =
|
||||
peer1.peer_handle().peer_by_id(peer0.peer_id().clone()).await.unwrap().reputation();
|
||||
assert_ne!(peer0_reputation_before, peer0_reputation_after);
|
||||
assert_eq!(received, txs[1].transaction().hash);
|
||||
|
||||
// this will return an [`Empty`] error because blob txs are disallowed to be broadcasted
|
||||
assert!(peer1_tx_listener.try_recv().is_err());
|
||||
}
|
||||
|
||||
#[tokio::test(flavor = "multi_thread")]
|
||||
async fn test_sending_invalid_transactions() {
|
||||
reth_tracing::init_test_tracing();
|
||||
let provider = MockEthProvider::default();
|
||||
let net = Testnet::create_with(2, provider.clone()).await;
|
||||
// install request handlers
|
||||
let net = net.with_eth_pool();
|
||||
|
||||
let handle = net.spawn();
|
||||
|
||||
let peer0 = &handle.peers()[0];
|
||||
let peer1 = &handle.peers()[1];
|
||||
|
||||
// connect all the peers
|
||||
handle.connect_peers().await;
|
||||
|
||||
let mut peer1_tx_listener = peer1.pool().unwrap().pending_transactions_listener();
|
||||
|
||||
let invalid_txs: Vec<Arc<TransactionSigned>> = vec![Arc::new(TransactionSigned::default())];
|
||||
|
||||
let network_handle = peer0.network();
|
||||
|
||||
// sends txs directly to peer1
|
||||
network_handle.send_transactions(peer1.peer_id().clone(), invalid_txs);
|
||||
|
||||
tokio::time::sleep(Duration::from_secs(1)).await;
|
||||
|
||||
// this will return an [`Empty`] error because bad txs are disallowed to be broadcasted
|
||||
assert!(peer1_tx_listener.try_recv().is_err());
|
||||
}
|
||||
|
||||
@@ -2,8 +2,8 @@ use crate::EthPooledTransaction;
|
||||
use rand::Rng;
|
||||
use reth_primitives::{
|
||||
constants::MIN_PROTOCOL_BASE_FEE, sign_message, AccessList, Address, Bytes,
|
||||
FromRecoveredTransaction, Transaction, TransactionKind, TransactionSigned, TxEip1559, TxLegacy,
|
||||
TxValue, B256, MAINNET,
|
||||
FromRecoveredTransaction, Transaction, TransactionKind, TransactionSigned, TxEip1559,
|
||||
TxEip4844, TxLegacy, TxValue, B256, MAINNET,
|
||||
};
|
||||
|
||||
/// A generator for transactions for testing purposes.
|
||||
@@ -91,12 +91,23 @@ impl<R: Rng> TransactionGenerator<R> {
|
||||
self.transaction().into_eip1559()
|
||||
}
|
||||
|
||||
/// Creates a new transaction with a random signer
|
||||
pub fn gen_eip4844(&mut self) -> TransactionSigned {
|
||||
self.transaction().into_eip4844()
|
||||
}
|
||||
|
||||
/// Generates and returns a pooled EIP-1559 transaction with a random signer.
|
||||
pub fn gen_eip1559_pooled(&mut self) -> EthPooledTransaction {
|
||||
EthPooledTransaction::from_recovered_transaction(
|
||||
self.gen_eip1559().into_ecrecovered().unwrap(),
|
||||
)
|
||||
}
|
||||
/// Generates and returns a pooled EIP-4844 transaction with a random signer.
|
||||
pub fn gen_eip4844_pooled(&mut self) -> EthPooledTransaction {
|
||||
EthPooledTransaction::from_recovered_transaction(
|
||||
self.gen_eip4844().into_ecrecovered().unwrap(),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/// A Builder type to configure and create a transaction.
|
||||
@@ -162,6 +173,26 @@ impl TransactionBuilder {
|
||||
self.signer,
|
||||
)
|
||||
}
|
||||
/// Converts the transaction builder into a transaction format using EIP-4844.
|
||||
pub fn into_eip4844(self) -> TransactionSigned {
|
||||
TransactionBuilder::signed(
|
||||
TxEip4844 {
|
||||
chain_id: self.chain_id,
|
||||
nonce: self.nonce,
|
||||
gas_limit: self.gas_limit,
|
||||
max_fee_per_gas: self.max_fee_per_gas,
|
||||
max_priority_fee_per_gas: self.max_priority_fee_per_gas,
|
||||
to: self.to,
|
||||
value: self.value,
|
||||
access_list: self.access_list,
|
||||
input: self.input,
|
||||
blob_versioned_hashes: Default::default(),
|
||||
max_fee_per_blob_gas: Default::default(),
|
||||
}
|
||||
.into(),
|
||||
self.signer,
|
||||
)
|
||||
}
|
||||
|
||||
/// Signs the provided transaction using the specified signer and returns a signed transaction.
|
||||
fn signed(transaction: Transaction, signer: B256) -> TransactionSigned {
|
||||
|
||||
Reference in New Issue
Block a user