From 56a94ca3ff0e0aec8c48c4f178486d1826d7dfa7 Mon Sep 17 00:00:00 2001 From: Andrea Cerone Date: Wed, 25 Sep 2024 13:27:15 +0100 Subject: [PATCH] Executor: test Tx_count limit with incorrect tx source (#2242) ## Linked Issues/PRs Closes https://github.com/FuelLabs/fuel-core/issues/2225 ## Description As per discussion, we should check that the current Executor logic is resilient against transactions source that ignore the limit on MAX_TX_COUNT. ## Checklist - [ ] New behavior is reflected in tests ### Before requesting review - [ ] I have reviewed the code myself --------- Co-authored-by: Green Baneling --- crates/fuel-core/src/executor.rs | 75 ++++++++++++++++++++++++++++++++ 1 file changed, 75 insertions(+) diff --git a/crates/fuel-core/src/executor.rs b/crates/fuel-core/src/executor.rs index 97dda0275df..7300127a33a 100644 --- a/crates/fuel-core/src/executor.rs +++ b/crates/fuel-core/src/executor.rs @@ -3,6 +3,9 @@ #[allow(non_snake_case)] #[cfg(test)] mod tests { + + use std::sync::Mutex; + use crate as fuel_core; use fuel_core::database::Database; use fuel_core_executor::{ @@ -13,6 +16,7 @@ mod tests { ports::{ MaybeCheckedTransaction, RelayerPort, + TransactionsSource, }, refs::ContractRef, }; @@ -183,6 +187,32 @@ mod tests { } } + /// Bad transaction source: ignores the limit of `u16::MAX -1` transactions + /// that should be returned by [`TransactionsSource::next()`]. + /// It is used only for testing purposes + pub struct BadTransactionsSource { + transactions: Mutex>, + } + + impl BadTransactionsSource { + pub fn new(transactions: Vec) -> Self { + Self { + transactions: Mutex::new( + transactions + .into_iter() + .map(MaybeCheckedTransaction::Transaction) + .collect(), + ), + } + } + } + + impl TransactionsSource for BadTransactionsSource { + fn next(&self, _: u64, _: u16, _: u32) -> Vec { + std::mem::take(&mut *self.transactions.lock().unwrap()) + } + } + fn add_consensus_parameters( mut database: Database, consensus_parameters: &ConsensusParameters, @@ -3022,6 +3052,51 @@ mod tests { ); } + #[test] + fn block_producer_never_includes_more_than_max_tx_count_transactions_with_bad_tx_source( + ) { + let block_height = 1u32; + let block_da_height = 2u64; + + let mut consensus_parameters = ConsensusParameters::default(); + + // Given + let transactions_in_tx_source = (MAX_TX_COUNT as usize) + 10; + consensus_parameters.set_block_gas_limit(u64::MAX); + let config = Config { + consensus_parameters, + ..Default::default() + }; + + let block = test_block( + block_height.into(), + block_da_height.into(), + transactions_in_tx_source, + ); + let partial_fuel_block: PartialFuelBlock = block.into(); + let components = Components { + header_to_produce: partial_fuel_block.header, + transactions_source: BadTransactionsSource::new( + partial_fuel_block.transactions, + ), + coinbase_recipient: Default::default(), + gas_price: 0, + }; + + // When + let producer = create_executor(Database::default(), config); + let (result, _) = producer + .produce_without_commit_with_source(components) + .unwrap() + .into(); + + // Then + assert_eq!( + result.block.transactions().len(), + (MAX_TX_COUNT as usize + 1) + ); + } + #[cfg(feature = "relayer")] mod relayer { use super::*;