Skip to content

Commit c34e0c1

Browse files
AurelienFTxgreenx
andauthored
Add excluded_contract filter to extract of transaction from TxPool (#2956)
## Linked Issues/PRs Close #2949 ## Description This is an unoptimized version that will be changed with the rest of the already inefficient version of selection when we will do #2950. ## Checklist - [x] Breaking changes are clearly marked as such in the PR description and changelog - [x] New behavior is reflected in tests - [x] [The specification](https://github.com/FuelLabs/fuel-specs/) matches the implemented behavior (link update PR if changes are needed) ### Before requesting review - [x] I have reviewed the code myself - [x] I have created follow-up issues caused by this PR and linked them here --------- Co-authored-by: Green Baneling <[email protected]>
1 parent 53a54dc commit c34e0c1

File tree

8 files changed

+130
-2
lines changed

8 files changed

+130
-2
lines changed

.changes/added/2956.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Add excluded_contract filter to extract of transaction from TxPool.

crates/fuel-core/src/service/adapters/executor.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,10 @@ use fuel_core_types::{
2121
relayer::Event,
2222
},
2323
};
24-
use std::sync::Arc;
24+
use std::{
25+
collections::HashSet,
26+
sync::Arc,
27+
};
2528
use tokio::sync::mpsc::error::TrySendError;
2629

2730
use super::PreconfirmationSender;
@@ -39,6 +42,7 @@ impl fuel_core_executor::ports::TransactionsSource for TransactionsSource {
3942
max_gas: gas_limit,
4043
maximum_txs: transactions_limit,
4144
maximum_block_size: block_transaction_size_limit,
45+
excluded_contracts: HashSet::default(),
4246
})
4347
.unwrap_or_default()
4448
.into_iter()

crates/services/txpool_v2/src/selection_algorithms/mod.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
use std::collections::HashSet;
2+
3+
use fuel_core_types::fuel_tx::ContractId;
4+
15
use crate::storage::{
26
RemovedTransactions,
37
StorageData,
@@ -15,6 +19,8 @@ pub struct Constraints {
1519
pub maximum_txs: u16,
1620
/// Maximum size of the block.
1721
pub maximum_block_size: u32,
22+
/// List of excluded contracts.
23+
pub excluded_contracts: HashSet<ContractId>,
1824
}
1925

2026
/// The selection algorithm is responsible for selecting the best transactions to include in a block.

crates/services/txpool_v2/src/selection_algorithms/ratio_tip_gas.rs

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -173,7 +173,9 @@ where
173173
let mut transactions_to_remove = Vec::new();
174174
let mut transactions_to_promote = Vec::new();
175175

176-
for (key, storage_id) in &self.executable_transactions_sorted_tip_gas_ratio {
176+
'outer: for (key, storage_id) in
177+
&self.executable_transactions_sorted_tip_gas_ratio
178+
{
177179
if nb_left == 0 || gas_left == 0 || space_left == 0 {
178180
break;
179181
}
@@ -190,6 +192,17 @@ where
190192
continue
191193
};
192194

195+
for input in stored_transaction.transaction.inputs() {
196+
if let fuel_core_types::fuel_tx::Input::Contract(contract) = input {
197+
if constraints
198+
.excluded_contracts
199+
.contains(&contract.contract_id)
200+
{
201+
continue 'outer;
202+
}
203+
}
204+
}
205+
193206
let less_price = stored_transaction.transaction.max_gas_price()
194207
< constraints.minimal_gas_price;
195208

crates/services/txpool_v2/src/tests/stability_test.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -186,6 +186,7 @@ fn stability_test_with_seed(seed: u64, limits: Limits, config: Config) {
186186
maximum_txs: u16::MAX,
187187
maximum_block_size: u32::MAX,
188188
minimal_gas_price: 0,
189+
excluded_contracts: Default::default(),
189190
});
190191

191192
if result.is_empty() {

crates/services/txpool_v2/src/tests/tests_pool.rs

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
use std::collections::HashSet;
2+
13
use crate::{
24
config::{
35
Config,
@@ -643,6 +645,7 @@ fn get_sorted_out_tx1_2_3() {
643645
max_gas: u64::MAX,
644646
maximum_txs: u16::MAX,
645647
maximum_block_size: u32::MAX,
648+
excluded_contracts: Default::default(),
646649
});
647650

648651
// Then
@@ -700,6 +703,7 @@ fn get_sorted_out_tx_same_tips() {
700703
max_gas: u64::MAX,
701704
maximum_txs: u16::MAX,
702705
maximum_block_size: u32::MAX,
706+
excluded_contracts: Default::default(),
703707
});
704708

705709
// Then
@@ -757,6 +761,7 @@ fn get_sorted_out_zero_tip() {
757761
max_gas: u64::MAX,
758762
maximum_txs: u16::MAX,
759763
maximum_block_size: u32::MAX,
764+
excluded_contracts: Default::default(),
760765
});
761766

762767
// Then
@@ -814,6 +819,7 @@ fn get_sorted_out_tx_profitable_ratios() {
814819
max_gas: u64::MAX,
815820
maximum_txs: u16::MAX,
816821
maximum_block_size: u32::MAX,
822+
excluded_contracts: Default::default(),
817823
});
818824

819825
// Then
@@ -853,6 +859,7 @@ fn get_sorted_out_tx_by_creation_instant() {
853859
max_gas: u64::MAX,
854860
maximum_txs: u16::MAX,
855861
maximum_block_size: u32::MAX,
862+
excluded_contracts: Default::default(),
856863
});
857864

858865
// Then
@@ -1292,6 +1299,7 @@ fn verify_and_insert__when_dependent_tx_is_extracted_new_tx_still_accepted() {
12921299
max_gas: u64::MAX,
12931300
maximum_txs: u16::MAX,
12941301
maximum_block_size: u32::MAX,
1302+
excluded_contracts: Default::default(),
12951303
});
12961304
assert_eq!(txs.len(), 1);
12971305
assert_eq!(pool_dependency_tx.id(), txs[0].id());
@@ -1405,3 +1413,74 @@ fn insert__tx_upgrade_with_invalid_wasm() {
14051413
));
14061414
universe.assert_pool_integrity(&[]);
14071415
}
1416+
1417+
#[test]
1418+
fn extract__tx_with_excluded_contract() {
1419+
let mut universe = TestPoolUniverse::default().config(Config {
1420+
utxo_validation: false,
1421+
..Default::default()
1422+
});
1423+
universe.build_pool();
1424+
1425+
// Given
1426+
let (create_tx_1, excluded_contract) =
1427+
universe.build_create_contract_transaction(vec![1, 2, 3]);
1428+
let (create_tx_2, authorized_contract) =
1429+
universe.build_create_contract_transaction(vec![4, 5, 6]);
1430+
let tx1 = universe.build_script_transaction(
1431+
Some(vec![Input::contract(
1432+
Default::default(),
1433+
Default::default(),
1434+
Default::default(),
1435+
Default::default(),
1436+
excluded_contract,
1437+
)]),
1438+
Some(vec![Output::contract(
1439+
0,
1440+
Default::default(),
1441+
Default::default(),
1442+
)]),
1443+
0,
1444+
);
1445+
let tx2 = universe.build_script_transaction(
1446+
Some(vec![Input::contract(
1447+
Default::default(),
1448+
Default::default(),
1449+
Default::default(),
1450+
Default::default(),
1451+
authorized_contract,
1452+
)]),
1453+
Some(vec![Output::contract(
1454+
0,
1455+
Default::default(),
1456+
Default::default(),
1457+
)]),
1458+
0,
1459+
);
1460+
let mut excluded_contracts = HashSet::default();
1461+
excluded_contracts.insert(excluded_contract);
1462+
1463+
let tx2_id = tx2.id(&ChainId::default());
1464+
1465+
universe.verify_and_insert(create_tx_1).unwrap();
1466+
universe.verify_and_insert(create_tx_2).unwrap();
1467+
let tx1 = universe.verify_and_insert(tx1).unwrap();
1468+
universe.verify_and_insert(tx2).unwrap();
1469+
1470+
// When
1471+
let txs = universe
1472+
.get_pool()
1473+
.write()
1474+
.extract_transactions_for_block(Constraints {
1475+
minimal_gas_price: 0,
1476+
max_gas: u64::MAX,
1477+
maximum_txs: u16::MAX,
1478+
maximum_block_size: u32::MAX,
1479+
excluded_contracts,
1480+
});
1481+
1482+
// Then
1483+
assert_eq!(txs.len(), 3, "Should have 1 txs");
1484+
assert_eq!(txs[2].id(), tx2_id, "First should be tx2");
1485+
universe.assert_pool_integrity(&[tx1]);
1486+
}

crates/services/txpool_v2/src/tests/tests_service.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -494,6 +494,7 @@ async fn insert__tx_depends_one_extracted_and_one_pool_tx() {
494494
max_gas: u64::MAX,
495495
maximum_txs: u16::MAX,
496496
maximum_block_size: u32::MAX,
497+
excluded_contracts: Default::default(),
497498
})
498499
.unwrap();
499500

@@ -508,6 +509,7 @@ async fn insert__tx_depends_one_extracted_and_one_pool_tx() {
508509
max_gas: u64::MAX,
509510
maximum_txs: u16::MAX,
510511
maximum_block_size: u32::MAX,
512+
excluded_contracts: Default::default(),
511513
})
512514
.unwrap();
513515

@@ -547,6 +549,7 @@ async fn pending_pool__returns_error_for_transaction_that_spends_already_spent_u
547549
max_gas: u64::MAX,
548550
maximum_txs: u16::MAX,
549551
maximum_block_size: u32::MAX,
552+
excluded_contracts: Default::default(),
550553
})
551554
.unwrap();
552555

@@ -594,6 +597,7 @@ async fn pending_pool__returns_error_after_timeout_for_transaction_that_spends_u
594597
max_gas: u64::MAX,
595598
maximum_txs: u16::MAX,
596599
maximum_block_size: u32::MAX,
600+
excluded_contracts: Default::default(),
597601
})
598602
.unwrap();
599603

crates/services/txpool_v2/src/tests/universe.rs

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -260,6 +260,26 @@ impl TestPoolUniverse {
260260
tx_builder.finalize().into()
261261
}
262262

263+
pub fn build_create_contract_transaction(
264+
&mut self,
265+
code: Vec<u8>,
266+
) -> (Transaction, ContractId) {
267+
let (_, gas_coin) = self.setup_coin();
268+
let contract: Contract = code.clone().into();
269+
let id = contract.id(&Default::default(), &contract.root(), &Default::default());
270+
let mut tx_builder = TransactionBuilder::create(
271+
code.into(),
272+
Default::default(),
273+
Default::default(),
274+
);
275+
tx_builder.add_input(gas_coin);
276+
tx_builder.add_output(Output::ContractCreated {
277+
contract_id: id,
278+
state_root: Default::default(),
279+
});
280+
(tx_builder.finalize().into(), id)
281+
}
282+
263283
pub fn build_mint_transaction(&mut self) -> Transaction {
264284
let tx_builder = TransactionBuilder::mint(
265285
0u32.into(),

0 commit comments

Comments
 (0)