Skip to content

Commit ccecfa5

Browse files
Update tests to match reversion strategy
1 parent a6239aa commit ccecfa5

3 files changed

Lines changed: 95 additions & 18 deletions

File tree

crates/block-producer/src/mempool/graph/dag.rs

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -279,6 +279,8 @@ where
279279

280280
#[cfg(test)]
281281
mod tests {
282+
use std::collections::HashSet;
283+
282284
use miden_protocol::block::BlockNumber;
283285

284286
use super::*;
@@ -314,4 +316,35 @@ mod tests {
314316
graph.selection_candidates().keys().map(|id| **id).collect();
315317
assert_eq!(candidates_after_parent, vec![2]);
316318
}
319+
320+
#[test]
321+
fn expired_and_unselected_returns_only_expired_unselected_nodes() {
322+
let mut graph = Graph::<TestNode>::default();
323+
324+
graph
325+
.append(
326+
TestNode::new(1).with_output_notes([1]).with_expires_at(BlockNumber::from(5u32)),
327+
)
328+
.unwrap();
329+
graph
330+
.append(
331+
TestNode::new(2).with_output_notes([2]).with_expires_at(BlockNumber::from(6u32)),
332+
)
333+
.unwrap();
334+
graph
335+
.append(
336+
TestNode::new(3)
337+
.with_output_notes([3])
338+
.with_expires_at(BlockNumber::from(10u32)),
339+
)
340+
.unwrap();
341+
342+
graph.select_candidate(1);
343+
344+
let expired = graph.expired_and_unselected(BlockNumber::from(6u32));
345+
let mut expected = HashSet::new();
346+
expected.insert(2u32);
347+
348+
assert_eq!(expired, expected);
349+
}
317350
}

crates/block-producer/src/mempool/mod.rs

Lines changed: 17 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -266,14 +266,19 @@ impl Mempool {
266266
#[instrument(target = COMPONENT, name = "mempool.rollback_batch", skip_all)]
267267
pub fn rollback_batch(&mut self, batch: BatchId) {
268268
let reverted_batches = self.batches.revert_batch_and_descendants(batch);
269-
let mut txs = Vec::new();
270-
for reverted in reverted_batches {
271-
self.transactions.requeue_transactions(&reverted);
272-
txs.extend(reverted.transactions().iter().map(|tx| tx.id()));
269+
for reverted in &reverted_batches {
270+
self.transactions.requeue_transactions(reverted);
273271
}
274272

275-
let reverted_txs = self.transactions.increment_failure_count(txs.into_iter());
276-
self.subscription.txs_reverted(reverted_txs);
273+
// Find rolled back batch to mark the txs as failed.
274+
//
275+
// Note that its possible it doesn't exist, since this batch could have already been
276+
// reverted as part of a separate rollback.
277+
if let Some(batch) = reverted_batches.iter().find(|reverted| reverted.id() == batch) {
278+
let failed_txs = batch.transactions().iter().map(|tx| tx.id());
279+
let reverted_txs = self.transactions.increment_failure_count(failed_txs);
280+
self.subscription.txs_reverted(reverted_txs);
281+
}
277282

278283
self.inject_telemetry();
279284
}
@@ -378,18 +383,18 @@ impl Mempool {
378383
// Revert the batches, and requeue the transactions for batch selection.
379384
//
380385
// Transactions which have failed excessively are also reverted.
381-
let (_, batches) = self.pending_block.take().expect("we just checked it is some");
382-
let mut txs = Vec::new();
383-
for batch in batches {
386+
let (_, block) = self.pending_block.take().expect("we just checked it is some");
387+
for batch in &block {
384388
let reverted = self.batches.revert_batch_and_descendants(batch.id());
385389

386390
for batch in reverted {
387391
self.transactions.requeue_transactions(&batch);
388-
txs.extend(batch.transactions().iter().map(|tx| tx.id()));
389392
}
390393
}
391-
392-
let reverted_txs = self.transactions.increment_failure_count(txs.into_iter());
394+
let failed_txs = block
395+
.iter()
396+
.flat_map(|batch| batch.transactions().as_slice().iter().map(TransactionHeader::id));
397+
let reverted_txs = self.transactions.increment_failure_count(failed_txs);
393398

394399
self.subscription.txs_reverted(reverted_txs);
395400
self.inject_telemetry();

crates/block-producer/src/mempool/tests.rs

Lines changed: 45 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ use std::sync::Arc;
22

33
use miden_protocol::Word;
44
use miden_protocol::block::{BlockHeader, BlockNumber};
5+
use miden_protocol::transaction::TransactionHeader;
56
use pretty_assertions::assert_eq;
67
use serial_test::serial;
78

@@ -114,6 +115,9 @@ fn failed_batch_transactions_are_requeued() {
114115
reference.select_batch().unwrap();
115116
reference.add_transaction(txs[1].clone()).unwrap();
116117
reference.add_transaction(txs[2].clone()).unwrap();
118+
reference
119+
.transactions
120+
.increment_failure_count(failed_batch.txs().iter().map(|tx| tx.id()));
117121

118122
assert_eq!(uut, reference);
119123
}
@@ -185,11 +189,9 @@ fn cannot_have_multiple_inflight_blocks() {
185189
// BLOCK FAILED TESTS
186190
// ================================================================================================
187191

188-
/// A failed block should have all of its transactions reverted.
189192
#[test]
190-
fn block_failure_reverts_its_transactions() {
191-
// We will revert everything so the reference should be the empty mempool.
192-
let (mut uut, reference) = Mempool::for_tests();
193+
fn block_failure_increments_tx_failures() {
194+
let (mut uut, mut reference) = Mempool::for_tests();
193195

194196
let reverted_txs = MockProvenTxBuilder::sequential();
195197

@@ -200,20 +202,51 @@ fn block_failure_reverts_its_transactions() {
200202
])));
201203

202204
// Block 1 will contain just the first batch.
203-
let (number, _batches) = uut.select_block();
205+
let (number, block) = uut.select_block();
204206

205207
// Create another dependent batch.
206208
uut.add_transaction(reverted_txs[1].clone()).unwrap();
207209
uut.select_batch();
208210
// Create another dependent transaction.
209211
uut.add_transaction(reverted_txs[2].clone()).unwrap();
210212

211-
// Fail the block which should result in everything reverting.
212213
uut.rollback_block(number);
213214

215+
// Reference should contain all transactions, no batches, with tx failure from just that block.
216+
reference.add_transaction(reverted_txs[0].clone()).unwrap();
217+
reference.add_transaction(reverted_txs[1].clone()).unwrap();
218+
reference.add_transaction(reverted_txs[2].clone()).unwrap();
219+
220+
reference.transactions.increment_failure_count(
221+
block
222+
.iter()
223+
.flat_map(|batch| batch.transactions().as_slice().iter().map(TransactionHeader::id)),
224+
);
225+
214226
assert_eq!(uut, reference);
215227
}
216228

229+
#[test]
230+
fn transactions_exceeding_failure_limit_are_removed() {
231+
let (mut uut, _) = Mempool::for_tests();
232+
233+
let failing_tx = MockProvenTxBuilder::with_account_index(0).build();
234+
let failing_tx = Arc::new(AuthenticatedTransaction::from_inner(failing_tx));
235+
let tx_id = failing_tx.id();
236+
237+
uut.add_transaction(failing_tx).unwrap();
238+
239+
for _ in 0..3 {
240+
let reverted = uut.transactions.increment_failure_count(std::iter::once(tx_id));
241+
assert!(reverted.is_empty());
242+
assert_eq!(uut.unbatched_transactions_count(), 1);
243+
}
244+
245+
let reverted = uut.transactions.increment_failure_count(std::iter::once(tx_id));
246+
assert!(reverted.contains(&tx_id));
247+
assert_eq!(uut.unbatched_transactions_count(), 0);
248+
}
249+
217250
/// We've decided that transactions from a rolled back batch should be requeued.
218251
///
219252
/// This test checks this at a basic level by ensuring that rolling back a batch is the same as
@@ -244,6 +277,9 @@ fn transactions_from_reverted_batches_are_requeued() {
244277
reference.add_transaction(tx_set_a[1].clone()).unwrap();
245278
reference.add_transaction(tx_set_b[2].clone()).unwrap();
246279
reference.add_transaction(tx_set_a[2].clone()).unwrap();
280+
reference
281+
.transactions
282+
.increment_failure_count([tx_set_a[1].id(), tx_set_b[1].id()].into_iter());
247283

248284
assert_eq!(uut, reference);
249285
}
@@ -339,6 +375,9 @@ fn pass_through_txs_with_note_dependencies() {
339375
uut.rollback_batch(batch_a.id());
340376
reference.add_transaction(tx_pass_through_a).unwrap();
341377
reference.add_transaction(tx_pass_through_b).unwrap();
378+
reference
379+
.transactions
380+
.increment_failure_count(batch_a.txs().iter().map(|tx| tx.id()));
342381

343382
assert_eq!(uut, reference);
344383
}

0 commit comments

Comments
 (0)