Skip to content

Commit 56fc161

Browse files
authored
Merge branch 'main' into next
2 parents 52c8265 + 75ad078 commit 56fc161

File tree

3 files changed

+50
-2
lines changed

3 files changed

+50
-2
lines changed

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,10 @@
22

33
## v0.15.0 (TBD)
44

5+
## v0.14.1 (2025-04-02)
6+
7+
- Fixed batch building issue with unauthenticated notes consumed in the same batch as they were created ([#1875](https://github.com/0xMiden/node/issues/1875)).
8+
59
## v0.14.0 (2025-04-01)
610

711
### Enhancements

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

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use std::collections::HashMap;
1+
use std::collections::{HashMap, HashSet};
22
use std::sync::Arc;
33

44
use miden_protocol::Word;
@@ -29,7 +29,14 @@ impl GraphNode for SelectedBatch {
2929
}
3030

3131
fn unauthenticated_notes(&self) -> Box<dyn Iterator<Item = Word> + '_> {
32-
Box::new(self.transactions().iter().flat_map(|tx| tx.unauthenticated_note_commitments()))
32+
// Filter notes that are produced within this batch.
33+
let output_notes: HashSet<Word> = self.output_notes().collect();
34+
Box::new(
35+
self.transactions()
36+
.iter()
37+
.flat_map(|tx| tx.unauthenticated_note_commitments())
38+
.filter(move |note| !output_notes.contains(note)),
39+
)
3340
}
3441

3542
fn account_updates(

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

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -406,3 +406,40 @@ fn pass_through_txs_with_note_dependencies() {
406406

407407
assert_eq!(uut, reference);
408408
}
409+
410+
/// Tests that a batch containing transactions with intra-batch unauthenticated note dependencies
411+
/// can be appended to the batch graph.
412+
#[test]
413+
fn intra_batch_unauthenticated_note() {
414+
let (mut uut, _) = Mempool::for_tests();
415+
416+
let tx_final = MockProvenTxBuilder::with_account_index(0).build();
417+
let account_update = tx_final.account_update();
418+
419+
let tx_pass_through = MockProvenTxBuilder::with_account(
420+
account_update.account_id(),
421+
account_update.initial_state_commitment(),
422+
account_update.initial_state_commitment(),
423+
);
424+
425+
// Transaction A creates note.
426+
let tx_a = tx_pass_through
427+
.clone()
428+
.nullifiers_range(0..2)
429+
.private_notes_created_range(3..4)
430+
.build();
431+
let tx_a = Arc::new(AuthenticatedTransaction::from_inner(tx_a));
432+
433+
// Transaction B consumes the note (unauthenticated).
434+
let tx_b = tx_pass_through.unauthenticated_notes_range(3..4).build();
435+
let tx_b = Arc::new(AuthenticatedTransaction::from_inner(tx_b));
436+
437+
// Add both transactions before selecting a batch so they end up in the same batch.
438+
uut.add_transaction(tx_a.clone()).unwrap();
439+
uut.add_transaction(tx_b.clone()).unwrap();
440+
441+
let batch = uut.select_batch().unwrap();
442+
443+
assert!(batch.transactions().contains(&tx_a));
444+
assert!(batch.transactions().contains(&tx_b));
445+
}

0 commit comments

Comments
 (0)