From: Leonardo Lima Date: Tue, 19 May 2026 18:56:26 +0000 (-0300) Subject: chore(workspace): use new `LocalChain::canonical_view` API X-Git-Url: http://internal-gitweb-vhost/blockdata/script/encode/-script/-progress/PersistenceException.ErrorHandler.html?a=commitdiff_plain;h=bb83da8260fb167fa548f31c12710153095e9064;p=bdk chore(workspace): use new `LocalChain::canonical_view` API Updates the codebase to use the new convenience `LocalChain::canonical_view` method in order to generate the `CanonicalView`. Internally the convenience method follows the `sans-IO` approach, separating the canonicalization algorithm from i/o operations, and it's used as follows: 1. Create a new `CanonicalizationTask` with a `TxGraph`, by calling: `graph.canonicalization_task(params)` 2. Execute the canonicalization process with a chain oracle (e.g `LocalChain`, which implements `ChainOracle` trait), by calling: `chain.canonicalize(task, chain_tip)` --- diff --git a/crates/bitcoind_rpc/examples/filter_iter.rs b/crates/bitcoind_rpc/examples/filter_iter.rs index e79bde67..a346a2db 100644 --- a/crates/bitcoind_rpc/examples/filter_iter.rs +++ b/crates/bitcoind_rpc/examples/filter_iter.rs @@ -69,7 +69,8 @@ fn main() -> anyhow::Result<()> { println!("\ntook: {}s", start.elapsed().as_secs()); println!("Local tip: {}", chain.tip().height()); - let canonical_view = graph.canonical_view(&chain, chain.tip().block_id(), Default::default()); + let canonical_view = + chain.canonical_view(graph.graph(), chain.tip().block_id(), Default::default()); let unspent: Vec<_> = canonical_view .filter_unspent_outpoints(graph.index.outpoints().clone()) diff --git a/crates/bitcoind_rpc/tests/test_emitter.rs b/crates/bitcoind_rpc/tests/test_emitter.rs index b75d474c..2aeede62 100644 --- a/crates/bitcoind_rpc/tests/test_emitter.rs +++ b/crates/bitcoind_rpc/tests/test_emitter.rs @@ -5,7 +5,7 @@ use bdk_chain::{ bitcoin::{Address, Amount, Txid}, local_chain::{CheckPoint, LocalChain}, spk_txout::SpkTxOutIndex, - Balance, BlockId, CanonicalizationParams, IndexedTxGraph, Merge, + Balance, BlockId, IndexedTxGraph, Merge, }; use bdk_testenv::{ anyhow, @@ -318,11 +318,14 @@ fn get_balance( recv_chain: &LocalChain, recv_graph: &IndexedTxGraph>, ) -> anyhow::Result { - let chain_tip = recv_chain.tip().block_id(); let outpoints = recv_graph.index.outpoints().clone(); - let balance = recv_graph - .canonical_view(recv_chain, chain_tip, CanonicalizationParams::default()) - .balance(outpoints, |_, _| true, 1); + let balance = recv_chain + .canonical_view( + recv_graph.graph(), + recv_chain.tip().block_id(), + Default::default(), + ) + .balance(outpoints, |_, _| true, 0); Ok(balance) } @@ -631,8 +634,8 @@ fn test_expect_tx_evicted() -> anyhow::Result<()> { let _txid_2 = core.send_raw_transaction(&tx1b)?; // Retrieve the expected unconfirmed txids and spks from the graph. - let exp_spk_txids = graph - .canonical_view(&chain, chain_tip, Default::default()) + let exp_spk_txids = chain + .canonical_view(graph.graph(), chain_tip, Default::default()) .list_expected_spk_txids(&graph.index, ..) .collect::>(); assert_eq!(exp_spk_txids, vec![(spk, txid_1)]); @@ -647,8 +650,8 @@ fn test_expect_tx_evicted() -> anyhow::Result<()> { // Update graph with evicted tx. let _ = graph.batch_insert_relevant_evicted_at(mempool_event.evicted); - let canonical_txids = graph - .canonical_view(&chain, chain_tip, CanonicalizationParams::default()) + let canonical_txids = chain + .canonical_view(graph.graph(), chain_tip, Default::default()) .txs() .map(|tx| tx.txid) .collect::>(); diff --git a/crates/chain/benches/canonicalization.rs b/crates/chain/benches/canonicalization.rs index 074e38cc..74e6c05f 100644 --- a/crates/chain/benches/canonicalization.rs +++ b/crates/chain/benches/canonicalization.rs @@ -1,4 +1,3 @@ -use bdk_chain::CanonicalizationParams; use bdk_chain::{keychain_txout::KeychainTxOutIndex, local_chain::LocalChain, IndexedTxGraph}; use bdk_core::{BlockId, CheckPoint}; use bdk_core::{ConfirmationBlockTime, TxUpdate}; @@ -95,31 +94,19 @@ fn setup(f: F) -> (KeychainTxGraph, Lo } fn run_list_canonical_txs(tx_graph: &KeychainTxGraph, chain: &LocalChain, exp_txs: usize) { - let view = tx_graph.canonical_view( - chain, - chain.tip().block_id(), - CanonicalizationParams::default(), - ); + let view = chain.canonical_view(tx_graph.graph(), chain.tip().block_id(), Default::default()); let txs = view.txs(); assert_eq!(txs.count(), exp_txs); } fn run_filter_chain_txouts(tx_graph: &KeychainTxGraph, chain: &LocalChain, exp_txos: usize) { - let view = tx_graph.canonical_view( - chain, - chain.tip().block_id(), - CanonicalizationParams::default(), - ); + let view = chain.canonical_view(tx_graph.graph(), chain.tip().block_id(), Default::default()); let utxos = view.filter_outpoints(tx_graph.index.outpoints().clone()); assert_eq!(utxos.count(), exp_txos); } fn run_filter_chain_unspents(tx_graph: &KeychainTxGraph, chain: &LocalChain, exp_utxos: usize) { - let view = tx_graph.canonical_view( - chain, - chain.tip().block_id(), - CanonicalizationParams::default(), - ); + let view = chain.canonical_view(tx_graph.graph(), chain.tip().block_id(), Default::default()); let utxos = view.filter_unspent_outpoints(tx_graph.index.outpoints().clone()); assert_eq!(utxos.count(), exp_utxos); } diff --git a/crates/chain/benches/indexer.rs b/crates/chain/benches/indexer.rs index 5907c76a..97917ce3 100644 --- a/crates/chain/benches/indexer.rs +++ b/crates/chain/benches/indexer.rs @@ -1,7 +1,7 @@ use bdk_chain::{ keychain_txout::{InsertDescriptorError, KeychainTxOutIndex}, local_chain::LocalChain, - CanonicalizationParams, IndexedTxGraph, + IndexedTxGraph, }; use bdk_core::{BlockId, CheckPoint, ConfirmationBlockTime, TxUpdate}; use bitcoin::{ @@ -82,10 +82,9 @@ fn do_bench(indexed_tx_graph: &KeychainTxGraph, chain: &LocalChain) { .unwrap(); // Check balance - let chain_tip = chain.tip().block_id(); let op = graph.index.outpoints().clone(); - let bal = graph - .canonical_view(chain, chain_tip, CanonicalizationParams::default()) + let bal = chain + .canonical_view(graph.graph(), chain.tip().block_id(), Default::default()) .balance(op, |_, _| false, 1); assert_eq!(bal.total(), AMOUNT * TX_CT as u64); } diff --git a/crates/chain/tests/test_canonical_view.rs b/crates/chain/tests/test_canonical_view.rs index 3c0d5438..2cbe0210 100644 --- a/crates/chain/tests/test_canonical_view.rs +++ b/crates/chain/tests/test_canonical_view.rs @@ -2,7 +2,7 @@ use std::collections::BTreeMap; -use bdk_chain::{local_chain::LocalChain, CanonicalizationParams, ConfirmationBlockTime, TxGraph}; +use bdk_chain::{local_chain::LocalChain, ConfirmationBlockTime, TxGraph}; use bdk_testenv::{hash, utils::new_tx}; use bitcoin::{Amount, BlockHash, OutPoint, ScriptBuf, Transaction, TxIn, TxOut}; @@ -53,9 +53,8 @@ fn test_min_confirmations_parameter() { }; let _ = tx_graph.insert_anchor(txid, anchor_height_5); - let chain_tip = chain.tip().block_id(); let canonical_view = - tx_graph.canonical_view(&chain, chain_tip, CanonicalizationParams::default()); + chain.canonical_view(&tx_graph, chain.tip().block_id(), Default::default()); // Test min_confirmations = 1: Should be confirmed (has 6 confirmations) let balance_1_conf = canonical_view.balance( @@ -142,11 +141,8 @@ fn test_min_confirmations_with_untrusted_tx() { }; let _ = tx_graph.insert_anchor(txid, anchor); - let canonical_view = tx_graph.canonical_view( - &chain, - chain.tip().block_id(), - CanonicalizationParams::default(), - ); + let canonical_view = + chain.canonical_view(&tx_graph, chain.tip().block_id(), Default::default()); // Test with min_confirmations = 5 and untrusted predicate let balance = canonical_view.balance( @@ -263,11 +259,8 @@ fn test_min_confirmations_multiple_transactions() { ); outpoints.push(((), outpoint2)); - let canonical_view = tx_graph.canonical_view( - &chain, - chain.tip().block_id(), - CanonicalizationParams::default(), - ); + let canonical_view = + chain.canonical_view(&tx_graph, chain.tip().block_id(), Default::default()); // Test with min_confirmations = 5 // tx0: 11 confirmations -> confirmed diff --git a/crates/chain/tests/test_indexed_tx_graph.rs b/crates/chain/tests/test_indexed_tx_graph.rs index 2a33f3b1..ad65bab8 100644 --- a/crates/chain/tests/test_indexed_tx_graph.rs +++ b/crates/chain/tests/test_indexed_tx_graph.rs @@ -10,8 +10,7 @@ use bdk_chain::{ indexer::keychain_txout::KeychainTxOutIndex, local_chain::LocalChain, spk_txout::SpkTxOutIndex, - tx_graph, Balance, CanonicalizationParams, ChainPosition, ConfirmationBlockTime, DescriptorExt, - SpkIterator, + tx_graph, Balance, ChainPosition, ConfirmationBlockTime, DescriptorExt, SpkIterator, }; use bdk_testenv::{ anyhow::{self}, @@ -469,23 +468,23 @@ fn test_list_owned_txouts() { .get(height) .map(|cp| cp.block_id()) .unwrap_or_else(|| panic!("block must exist at {height}")); - let txouts = graph - .canonical_view(&local_chain, chain_tip, CanonicalizationParams::default()) + + let canonical_view = + local_chain.canonical_view(graph.graph(), chain_tip, Default::default()); + + let txouts = canonical_view .filter_outpoints(graph.index.outpoints().iter().cloned()) .collect::>(); - let utxos = graph - .canonical_view(&local_chain, chain_tip, CanonicalizationParams::default()) + let utxos = canonical_view .filter_unspent_outpoints(graph.index.outpoints().iter().cloned()) .collect::>(); - let balance = graph - .canonical_view(&local_chain, chain_tip, CanonicalizationParams::default()) - .balance( - graph.index.outpoints().iter().cloned(), - |_, txout| trusted_spks.contains(&txout.txout.script_pubkey), - 1, - ); + let balance = canonical_view.balance( + graph.index.outpoints().iter().cloned(), + |_, txout| trusted_spks.contains(&txout.txout.script_pubkey), + 0, + ); let confirmed_txouts_txid = txouts .iter() @@ -788,12 +787,8 @@ fn test_get_chain_position() { } // check chain position - let chain_pos = graph - .canonical_view( - chain, - chain.tip().block_id(), - CanonicalizationParams::default(), - ) + let chain_pos = chain + .canonical_view(graph.graph(), chain.tip().block_id(), Default::default()) .txs() .find_map(|canon_tx| { if canon_tx.txid == txid { diff --git a/crates/chain/tests/test_tx_graph.rs b/crates/chain/tests/test_tx_graph.rs index b2a35960..3cbfe341 100644 --- a/crates/chain/tests/test_tx_graph.rs +++ b/crates/chain/tests/test_tx_graph.rs @@ -2,7 +2,7 @@ #[macro_use] mod common; -use bdk_chain::{collections::*, BlockId, CanonicalizationParams, ConfirmationBlockTime}; +use bdk_chain::{collections::*, BlockId, ConfirmationBlockTime}; use bdk_chain::{ local_chain::LocalChain, tx_graph::{self, CalculateFeeError}, @@ -1014,8 +1014,8 @@ fn test_chain_spends() { let build_canonical_spends = |chain: &LocalChain, tx_graph: &TxGraph| -> HashMap { - tx_graph - .canonical_view(chain, tip.block_id(), CanonicalizationParams::default()) + chain + .canonical_view(tx_graph, tip.block_id(), Default::default()) .filter_outpoints(tx_graph.all_txouts().map(|(op, _)| ((), op))) .filter_map(|(_, full_txo)| Some((full_txo.outpoint, full_txo.spent_by?))) .collect() @@ -1023,8 +1023,8 @@ fn test_chain_spends() { let build_canonical_positions = |chain: &LocalChain, tx_graph: &TxGraph| -> HashMap> { - tx_graph - .canonical_view(chain, tip.block_id(), CanonicalizationParams::default()) + chain + .canonical_view(tx_graph, tip.block_id(), Default::default()) .txs() .map(|canon_tx| (canon_tx.txid, canon_tx.pos)) .collect() @@ -1197,35 +1197,23 @@ fn transactions_inserted_into_tx_graph_are_not_canonical_until_they_have_an_anch .into_iter() .collect(); let chain = LocalChain::from_blocks(blocks).unwrap(); - let canonical_txs: Vec<_> = graph - .canonical_view( - &chain, - chain.tip().block_id(), - CanonicalizationParams::default(), - ) + let canonical_txs: Vec<_> = chain + .canonical_view(&graph, chain.tip().block_id(), Default::default()) .txs() .collect(); assert!(canonical_txs.is_empty()); // tx0 with seen_at should be returned by canonical txs let _ = graph.insert_seen_at(txids[0], 2); - let canonical_view = graph.canonical_view( - &chain, - chain.tip().block_id(), - CanonicalizationParams::default(), - ); - let mut canonical_txs = canonical_view.txs(); + let view = chain.canonical_view(&graph, chain.tip().block_id(), Default::default()); + let mut canonical_txs = view.txs(); assert_eq!(canonical_txs.next().map(|tx| tx.txid).unwrap(), txids[0]); drop(canonical_txs); // tx1 with anchor is also canonical let _ = graph.insert_anchor(txids[1], block_id!(2, "B")); - let canonical_txids: Vec<_> = graph - .canonical_view( - &chain, - chain.tip().block_id(), - CanonicalizationParams::default(), - ) + let canonical_txids: Vec<_> = chain + .canonical_view(&graph, chain.tip().block_id(), Default::default()) .txs() .map(|tx| tx.txid) .collect(); diff --git a/crates/chain/tests/test_tx_graph_conflicts.rs b/crates/chain/tests/test_tx_graph_conflicts.rs index 38f21365..f1f16698 100644 --- a/crates/chain/tests/test_tx_graph_conflicts.rs +++ b/crates/chain/tests/test_tx_graph_conflicts.rs @@ -970,9 +970,13 @@ fn test_tx_conflict_handling() { for scenario in scenarios { let env = init_graph(scenario.tx_templates.iter()); - let txs = env - .tx_graph - .canonical_view(&local_chain, chain_tip, env.canonicalization_params.clone()) + let canonical_view = local_chain.canonical_view( + &env.tx_graph, + chain_tip, + env.canonicalization_params.clone(), + ); + + let txs = canonical_view .txs() .map(|tx| tx.txid) .collect::>(); @@ -987,9 +991,7 @@ fn test_tx_conflict_handling() { scenario.name ); - let txouts = env - .tx_graph - .canonical_view(&local_chain, chain_tip, env.canonicalization_params.clone()) + let txouts = canonical_view .filter_outpoints(env.indexer.outpoints().iter().cloned()) .map(|(_, full_txout)| full_txout.outpoint) .collect::>(); @@ -1007,9 +1009,7 @@ fn test_tx_conflict_handling() { scenario.name ); - let utxos = env - .tx_graph - .canonical_view(&local_chain, chain_tip, env.canonicalization_params.clone()) + let utxos = canonical_view .filter_unspent_outpoints(env.indexer.outpoints().iter().cloned()) .map(|(_, full_txout)| full_txout.outpoint) .collect::>(); @@ -1027,18 +1027,15 @@ fn test_tx_conflict_handling() { scenario.name ); - let balance = env - .tx_graph - .canonical_view(&local_chain, chain_tip, env.canonicalization_params.clone()) - .balance( - env.indexer.outpoints().iter().cloned(), - |_, txout| { - env.indexer - .index_of_spk(txout.txout.script_pubkey.as_script()) - .is_some() - }, - 0, - ); + let balance = canonical_view.balance( + env.indexer.outpoints().iter().cloned(), + |_, txout| { + env.indexer + .index_of_spk(txout.txout.script_pubkey.as_script()) + .is_some() + }, + 0, + ); assert_eq!( balance, scenario.exp_balance, "\n[{}] 'balance' failed", diff --git a/crates/electrum/tests/test_electrum.rs b/crates/electrum/tests/test_electrum.rs index ef94c62f..c569b065 100644 --- a/crates/electrum/tests/test_electrum.rs +++ b/crates/electrum/tests/test_electrum.rs @@ -3,8 +3,7 @@ use bdk_chain::{ local_chain::LocalChain, spk_client::{FullScanRequest, SyncRequest, SyncResponse}, spk_txout::SpkTxOutIndex, - Balance, CanonicalizationParams, ConfirmationBlockTime, IndexedTxGraph, Indexer, Merge, - TxGraph, + Balance, ConfirmationBlockTime, IndexedTxGraph, Indexer, Merge, TxGraph, }; use bdk_core::bitcoin::{ key::{Secp256k1, UntweakedPublicKey}, @@ -56,11 +55,14 @@ fn get_balance( recv_chain: &LocalChain, recv_graph: &IndexedTxGraph>, ) -> anyhow::Result { - let chain_tip = recv_chain.tip().block_id(); let outpoints = recv_graph.index.outpoints().clone(); - let balance = recv_graph - .canonical_view(recv_chain, chain_tip, CanonicalizationParams::default()) - .balance(outpoints, |_, _| true, 1); + let balance = recv_chain + .canonical_view( + recv_graph.graph(), + recv_chain.tip().block_id(), + Default::default(), + ) + .balance(outpoints, |_, _| true, 0); Ok(balance) } @@ -174,8 +176,7 @@ pub fn detect_receive_tx_cancel() -> anyhow::Result<()> { .chain_tip(chain.tip()) .spks_with_indexes(graph.index.all_spks().clone()) .expected_spk_txids( - graph - .canonical_view(&chain, chain.tip().block_id(), Default::default()) + { chain.canonical_view(graph.graph(), chain.tip().block_id(), Default::default()) } .list_expected_spk_txids(&graph.index, ..), ); let sync_response = client.sync(sync_request, BATCH_SIZE, true)?; @@ -204,8 +205,7 @@ pub fn detect_receive_tx_cancel() -> anyhow::Result<()> { .chain_tip(chain.tip()) .spks_with_indexes(graph.index.all_spks().clone()) .expected_spk_txids( - graph - .canonical_view(&chain, chain.tip().block_id(), Default::default()) + { chain.canonical_view(graph.graph(), chain.tip().block_id(), Default::default()) } .list_expected_spk_txids(&graph.index, ..), ); let sync_response = client.sync(sync_request, BATCH_SIZE, true)?; diff --git a/crates/esplora/tests/async_ext.rs b/crates/esplora/tests/async_ext.rs index e6903591..2941e2a6 100644 --- a/crates/esplora/tests/async_ext.rs +++ b/crates/esplora/tests/async_ext.rs @@ -100,8 +100,7 @@ pub async fn detect_receive_tx_cancel() -> anyhow::Result<()> { .chain_tip(chain.tip()) .spks_with_indexes(graph.index.all_spks().clone()) .expected_spk_txids( - graph - .canonical_view(&chain, chain.tip().block_id(), Default::default()) + { chain.canonical_view(graph.graph(), chain.tip().block_id(), Default::default()) } .list_expected_spk_txids(&graph.index, ..), ); let sync_response = client.sync(sync_request, 1).await?; @@ -130,8 +129,7 @@ pub async fn detect_receive_tx_cancel() -> anyhow::Result<()> { .chain_tip(chain.tip()) .spks_with_indexes(graph.index.all_spks().clone()) .expected_spk_txids( - graph - .canonical_view(&chain, chain.tip().block_id(), Default::default()) + { chain.canonical_view(graph.graph(), chain.tip().block_id(), Default::default()) } .list_expected_spk_txids(&graph.index, ..), ); let sync_response = client.sync(sync_request, 1).await?; diff --git a/crates/esplora/tests/blocking_ext.rs b/crates/esplora/tests/blocking_ext.rs index 4619901c..8db59947 100644 --- a/crates/esplora/tests/blocking_ext.rs +++ b/crates/esplora/tests/blocking_ext.rs @@ -97,8 +97,7 @@ pub fn detect_receive_tx_cancel() -> anyhow::Result<()> { .chain_tip(chain.tip()) .spks_with_indexes(graph.index.all_spks().clone()) .expected_spk_txids( - graph - .canonical_view(&chain, chain.tip().block_id(), Default::default()) + { chain.canonical_view(graph.graph(), chain.tip().block_id(), Default::default()) } .list_expected_spk_txids(&graph.index, ..), ); let sync_response = client.sync(sync_request, 1)?; @@ -127,8 +126,7 @@ pub fn detect_receive_tx_cancel() -> anyhow::Result<()> { .chain_tip(chain.tip()) .spks_with_indexes(graph.index.all_spks().clone()) .expected_spk_txids( - graph - .canonical_view(&chain, chain.tip().block_id(), Default::default()) + { chain.canonical_view(graph.graph(), chain.tip().block_id(), Default::default()) } .list_expected_spk_txids(&graph.index, ..), ); let sync_response = client.sync(sync_request, 1)?;