Skip to content

Commit 0807a76

Browse files
committed
refactor(chain)!: migrate from CanonicalIter to CanonicalizationTask
- Replace `CanonicalView::new()` constructor with internal `CanonicalView::new()` for use by `CanonicalizationTask` - Remove `TxGraph::try_canonical_view()` and `TxGraph::canonical_view()` methods - Add `TxGraph::canonicalization_task()` method to create canonicalization tasks - Add `LocalChain::canonicalize()` method to process tasks and return `CanonicalView`'s - Update `IndexedTxGraph` to delegate canonicalization to underlying `TxGraph` The new API separates canonicalization logic from I/O operations: - Create canonicalization task: `graph.canonicalization_task(params)` - Execute canonicalization: `chain.canonicalize(task, chain_tip)` BREAKING CHANGE: Remove `CanonicalView::new()` and `TxGraph::canonical_view()` methods in favor of task-based approach
1 parent 11aa903 commit 0807a76

File tree

20 files changed

+364
-408
lines changed

20 files changed

+364
-408
lines changed

crates/bitcoind_rpc/examples/filter_iter.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,8 @@ fn main() -> anyhow::Result<()> {
6969
println!("\ntook: {}s", start.elapsed().as_secs());
7070
println!("Local tip: {}", chain.tip().height());
7171

72-
let canonical_view = graph.canonical_view(&chain, chain.tip().block_id(), Default::default());
72+
let task = graph.canonicalization_task(Default::default());
73+
let canonical_view = chain.canonicalize(task, Some(chain.tip().block_id()));
7374

7475
let unspent: Vec<_> = canonical_view
7576
.filter_unspent_outpoints(graph.index.outpoints().clone())

crates/bitcoind_rpc/tests/test_emitter.rs

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -310,9 +310,12 @@ fn get_balance(
310310
) -> anyhow::Result<Balance> {
311311
let chain_tip = recv_chain.tip().block_id();
312312
let outpoints = recv_graph.index.outpoints().clone();
313-
let balance = recv_graph
314-
.canonical_view(recv_chain, chain_tip, CanonicalizationParams::default())
315-
.balance(outpoints, |_, _| true, 1);
313+
let task = recv_graph
314+
.graph()
315+
.canonicalization_task(CanonicalizationParams::default());
316+
let balance = recv_chain
317+
.canonicalize(task, Some(chain_tip))
318+
.balance(outpoints, |_, _| true, 0);
316319
Ok(balance)
317320
}
318321

@@ -616,8 +619,9 @@ fn test_expect_tx_evicted() -> anyhow::Result<()> {
616619
let _txid_2 = core.send_raw_transaction(&tx1b)?;
617620

618621
// Retrieve the expected unconfirmed txids and spks from the graph.
619-
let exp_spk_txids = graph
620-
.canonical_view(&chain, chain_tip, Default::default())
622+
let task = graph.canonicalization_task(Default::default());
623+
let exp_spk_txids = chain
624+
.canonicalize(task, Some(chain_tip))
621625
.list_expected_spk_txids(&graph.index, ..)
622626
.collect::<Vec<_>>();
623627
assert_eq!(exp_spk_txids, vec![(spk, txid_1)]);
@@ -632,8 +636,11 @@ fn test_expect_tx_evicted() -> anyhow::Result<()> {
632636
// Update graph with evicted tx.
633637
let _ = graph.batch_insert_relevant_evicted_at(mempool_event.evicted);
634638

635-
let canonical_txids = graph
636-
.canonical_view(&chain, chain_tip, CanonicalizationParams::default())
639+
let task = graph
640+
.graph()
641+
.canonicalization_task(CanonicalizationParams::default());
642+
let canonical_txids = chain
643+
.canonicalize(task, Some(chain_tip))
637644
.txs()
638645
.map(|tx| tx.txid)
639646
.collect::<Vec<_>>();

crates/chain/benches/canonicalization.rs

Lines changed: 12 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -95,31 +95,28 @@ fn setup<F: Fn(&mut KeychainTxGraph, &LocalChain)>(f: F) -> (KeychainTxGraph, Lo
9595
}
9696

9797
fn run_list_canonical_txs(tx_graph: &KeychainTxGraph, chain: &LocalChain, exp_txs: usize) {
98-
let view = tx_graph.canonical_view(
99-
chain,
100-
chain.tip().block_id(),
101-
CanonicalizationParams::default(),
102-
);
98+
let task = tx_graph
99+
.graph()
100+
.canonicalization_task(CanonicalizationParams::default());
101+
let view = chain.canonicalize(task, Some(chain.tip().block_id()));
103102
let txs = view.txs();
104103
assert_eq!(txs.count(), exp_txs);
105104
}
106105

107106
fn run_filter_chain_txouts(tx_graph: &KeychainTxGraph, chain: &LocalChain, exp_txos: usize) {
108-
let view = tx_graph.canonical_view(
109-
chain,
110-
chain.tip().block_id(),
111-
CanonicalizationParams::default(),
112-
);
107+
let task = tx_graph
108+
.graph()
109+
.canonicalization_task(CanonicalizationParams::default());
110+
let view = chain.canonicalize(task, Some(chain.tip().block_id()));
113111
let utxos = view.filter_outpoints(tx_graph.index.outpoints().clone());
114112
assert_eq!(utxos.count(), exp_txos);
115113
}
116114

117115
fn run_filter_chain_unspents(tx_graph: &KeychainTxGraph, chain: &LocalChain, exp_utxos: usize) {
118-
let view = tx_graph.canonical_view(
119-
chain,
120-
chain.tip().block_id(),
121-
CanonicalizationParams::default(),
122-
);
116+
let task = tx_graph
117+
.graph()
118+
.canonicalization_task(CanonicalizationParams::default());
119+
let view = chain.canonicalize(task, Some(chain.tip().block_id()));
123120
let utxos = view.filter_unspent_outpoints(tx_graph.index.outpoints().clone());
124121
assert_eq!(utxos.count(), exp_utxos);
125122
}

crates/chain/benches/indexer.rs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -84,8 +84,11 @@ fn do_bench(indexed_tx_graph: &KeychainTxGraph, chain: &LocalChain) {
8484
// Check balance
8585
let chain_tip = chain.tip().block_id();
8686
let op = graph.index.outpoints().clone();
87-
let bal = graph
88-
.canonical_view(chain, chain_tip, CanonicalizationParams::default())
87+
let task = graph
88+
.graph()
89+
.canonicalization_task(CanonicalizationParams::default());
90+
let bal = chain
91+
.canonicalize(task, Some(chain_tip))
8992
.balance(op, |_, _| false, 1);
9093
assert_eq!(bal.total(), AMOUNT * TX_CT as u64);
9194
}

crates/chain/src/canonical_task.rs

Lines changed: 8 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,6 @@ use bitcoin::{Transaction, Txid};
1414
pub struct CanonicalizationRequest<A> {
1515
/// The anchors to check.
1616
pub anchors: Vec<A>,
17-
/// The chain tip to check against.
18-
pub chain_tip: BlockId,
1917
}
2018

2119
/// Response containing the best confirmed anchor, if any.
@@ -30,7 +28,6 @@ type NotCanonicalSet = HashSet<Txid>;
3028
/// Manages the canonicalization process without direct I/O operations.
3129
pub struct CanonicalizationTask<'g, A> {
3230
tx_graph: &'g TxGraph<A>,
33-
chain_tip: BlockId,
3431

3532
unprocessed_assumed_txs: Box<dyn Iterator<Item = (Txid, Arc<Transaction>)> + 'g>,
3633
unprocessed_anchored_txs:
@@ -52,13 +49,7 @@ pub struct CanonicalizationTask<'g, A> {
5249

5350
impl<'g, A: Anchor> CanonicalizationTask<'g, A> {
5451
/// Creates a new canonicalization task.
55-
///
56-
/// Returns the task and an optional initial request.
57-
pub fn new(
58-
tx_graph: &'g TxGraph<A>,
59-
chain_tip: BlockId,
60-
params: CanonicalizationParams,
61-
) -> (Self, Option<CanonicalizationRequest<A>>) {
52+
pub fn new(tx_graph: &'g TxGraph<A>, params: CanonicalizationParams) -> Self {
6253
let anchors = tx_graph.all_anchors();
6354
let unprocessed_assumed_txs = Box::new(
6455
params
@@ -80,7 +71,6 @@ impl<'g, A: Anchor> CanonicalizationTask<'g, A> {
8071

8172
let mut task = Self {
8273
tx_graph,
83-
chain_tip,
8474

8575
unprocessed_assumed_txs,
8676
unprocessed_anchored_txs,
@@ -96,13 +86,10 @@ impl<'g, A: Anchor> CanonicalizationTask<'g, A> {
9686
confirmed_anchors: HashMap::new(),
9787
};
9888

99-
// Process assumed transactions first (they don't need queries)
89+
// process assumed transactions first (they don't need queries)
10090
task.process_assumed_txs();
10191

102-
// Process anchored transactions and get the first request if needed
103-
let initial_request = task.process_anchored_txs();
104-
105-
(task, initial_request)
92+
task
10693
}
10794

10895
/// Returns the next query needed, if any.
@@ -111,7 +98,6 @@ impl<'g, A: Anchor> CanonicalizationTask<'g, A> {
11198
if let Some((_, _, anchors)) = self.pending_anchor_checks.front() {
11299
return Some(CanonicalizationRequest {
113100
anchors: anchors.clone(),
114-
chain_tip: self.chain_tip,
115101
});
116102
}
117103

@@ -152,7 +138,7 @@ impl<'g, A: Anchor> CanonicalizationTask<'g, A> {
152138
}
153139

154140
/// Completes the canonicalization and returns a CanonicalView.
155-
pub fn finish(mut self) -> CanonicalView<A> {
141+
pub fn finish(mut self, chain_tip: BlockId) -> CanonicalView<A> {
156142
// Process remaining transactions (seen and leftover)
157143
self.process_seen_txs();
158144
self.process_leftover_txs();
@@ -232,7 +218,7 @@ impl<'g, A: Anchor> CanonicalizationTask<'g, A> {
232218
}
233219
}
234220

235-
CanonicalView::from_parts(self.chain_tip, view_order, view_txs, view_spends)
221+
CanonicalView::new(chain_tip, view_order, view_txs, view_spends)
236222
}
237223

238224
fn is_canonicalized(&self, txid: Txid) -> bool {
@@ -426,23 +412,10 @@ mod tests {
426412
};
427413
let _ = tx_graph.insert_anchor(txid, anchor);
428414

429-
// Create canonicalization task
415+
// Create canonicalization task and canonicalize using the chain
430416
let params = CanonicalizationParams::default();
431-
let (mut task, initial_request) = CanonicalizationTask::new(&tx_graph, chain_tip, params);
432-
433-
// Process requests
434-
if let Some(request) = initial_request {
435-
let response = chain.handle_canonicalization_request(&request).unwrap();
436-
task.resolve_query(response);
437-
}
438-
439-
while let Some(request) = task.next_query() {
440-
let response = chain.handle_canonicalization_request(&request).unwrap();
441-
task.resolve_query(response);
442-
}
443-
444-
// Get canonical view
445-
let canonical_view = task.finish();
417+
let task = CanonicalizationTask::new(&tx_graph, params);
418+
let canonical_view = chain.canonicalize(task, Some(chain_tip));
446419

447420
// Should have one canonical transaction
448421
assert_eq!(canonical_view.txs().len(), 1);

0 commit comments

Comments
 (0)