/// provides methods to query transaction data, unspent outputs, and balances.
///
/// The view maintains:
-/// - An ordered list of canonical transactions (WIP)
+/// - An ordered list of canonical transactions in topological-spending order
/// - A mapping of outpoints to the transactions that spend them
/// - The chain tip used for canonicalization
#[derive(Debug)]
pub struct CanonicalView<A> {
- /// Ordered list of transaction IDs in canonical order.
+ /// Ordered list of transaction IDs in in topological-spending order.
order: Vec<Txid>,
/// Map of transaction IDs to their transaction data and chain position.
txs: HashMap<Txid, (Arc<Transaction>, ChainPosition<A>)>,
pub fn balance<'v, O: Clone + 'v>(
&'v self,
outpoints: impl IntoIterator<Item = (O, OutPoint)> + 'v,
- mut trust_predicate: impl FnMut(&O, ScriptBuf) -> bool,
+ mut trust_predicate: impl FnMut(&O, &FullTxOut<A>) -> bool,
min_confirmations: u32,
) -> Balance {
let mut immature = Amount::ZERO;
if confirmations < min_confirmations {
// Not enough confirmations, treat as trusted/untrusted pending
- if trust_predicate(&spk_i, txout.txout.script_pubkey) {
+ if trust_predicate(&spk_i, &txout) {
trusted_pending += txout.txout.value;
} else {
untrusted_pending += txout.txout.value;
}
}
ChainPosition::Unconfirmed { .. } => {
- if trust_predicate(&spk_i, txout.txout.script_pubkey) {
+ if trust_predicate(&spk_i, &txout) {
trusted_pending += txout.txout.value;
} else {
untrusted_pending += txout.txout.value;
#![cfg(feature = "miniscript")]
+use std::collections::BTreeMap;
+
use bdk_chain::{local_chain::LocalChain, CanonicalizationParams, ConfirmationBlockTime, TxGraph};
use bdk_testenv::{hash, utils::new_tx};
-use bitcoin::{Amount, OutPoint, ScriptBuf, Transaction, TxIn, TxOut};
+use bitcoin::{Amount, BlockHash, OutPoint, ScriptBuf, Transaction, TxIn, TxOut};
#[test]
fn test_min_confirmations_parameter() {
// Create a local chain with several blocks
- let chain = LocalChain::from_blocks(
- [
- (0, hash!("block0")),
- (1, hash!("block1")),
- (2, hash!("block2")),
- (3, hash!("block3")),
- (4, hash!("block4")),
- (5, hash!("block5")),
- (6, hash!("block6")),
- (7, hash!("block7")),
- (8, hash!("block8")),
- (9, hash!("block9")),
- (10, hash!("block10")),
- ]
- .into(),
- )
- .unwrap();
+ let blocks: BTreeMap<u32, BlockHash> = [
+ (0, hash!("block0")),
+ (1, hash!("block1")),
+ (2, hash!("block2")),
+ (3, hash!("block3")),
+ (4, hash!("block4")),
+ (5, hash!("block5")),
+ (6, hash!("block6")),
+ (7, hash!("block7")),
+ (8, hash!("block8")),
+ (9, hash!("block9")),
+ (10, hash!("block10")),
+ ]
+ .into_iter()
+ .collect();
+ let chain = LocalChain::from_blocks(blocks).unwrap();
let mut tx_graph = TxGraph::default();
#[test]
fn test_min_confirmations_with_untrusted_tx() {
// Create a local chain
- let chain = LocalChain::from_blocks(
- [
- (0, hash!("genesis")),
- (1, hash!("b1")),
- (2, hash!("b2")),
- (3, hash!("b3")),
- (4, hash!("b4")),
- (5, hash!("b5")),
- (6, hash!("b6")),
- (7, hash!("b7")),
- (8, hash!("b8")),
- (9, hash!("b9")),
- (10, hash!("tip")),
- ]
- .into(),
- )
- .unwrap();
+ let blocks: BTreeMap<u32, BlockHash> = [
+ (0, hash!("genesis")),
+ (1, hash!("b1")),
+ (2, hash!("b2")),
+ (3, hash!("b3")),
+ (4, hash!("b4")),
+ (5, hash!("b5")),
+ (6, hash!("b6")),
+ (7, hash!("b7")),
+ (8, hash!("b8")),
+ (9, hash!("b9")),
+ (10, hash!("tip")),
+ ]
+ .into_iter()
+ .collect();
+ let chain = LocalChain::from_blocks(blocks).unwrap();
let mut tx_graph = TxGraph::default();
#[test]
fn test_min_confirmations_multiple_transactions() {
// Create a local chain
- let chain = LocalChain::from_blocks(
- [
- (0, hash!("genesis")),
- (1, hash!("b1")),
- (2, hash!("b2")),
- (3, hash!("b3")),
- (4, hash!("b4")),
- (5, hash!("b5")),
- (6, hash!("b6")),
- (7, hash!("b7")),
- (8, hash!("b8")),
- (9, hash!("b9")),
- (10, hash!("b10")),
- (11, hash!("b11")),
- (12, hash!("b12")),
- (13, hash!("b13")),
- (14, hash!("b14")),
- (15, hash!("tip")),
- ]
- .into(),
- )
- .unwrap();
+ let blocks: BTreeMap<u32, BlockHash> = [
+ (0, hash!("genesis")),
+ (1, hash!("b1")),
+ (2, hash!("b2")),
+ (3, hash!("b3")),
+ (4, hash!("b4")),
+ (5, hash!("b5")),
+ (6, hash!("b6")),
+ (7, hash!("b7")),
+ (8, hash!("b8")),
+ (9, hash!("b9")),
+ (10, hash!("b10")),
+ (11, hash!("b11")),
+ (12, hash!("b12")),
+ (13, hash!("b13")),
+ (14, hash!("b14")),
+ (15, hash!("tip")),
+ ]
+ .into_iter()
+ .collect();
+ let chain = LocalChain::from_blocks(blocks).unwrap();
let mut tx_graph = TxGraph::default();
.canonical_view(&local_chain, chain_tip, CanonicalizationParams::default())
.balance(
graph.index.outpoints().iter().cloned(),
- |_, spk: ScriptBuf| trusted_spks.contains(&spk),
+ |_, txout| trusted_spks.contains(&txout.txout.script_pubkey),
1,
);
use bdk_chain::{local_chain::LocalChain, Balance, BlockId};
use bdk_testenv::{block_id, hash, local_chain};
-use bitcoin::{Amount, BlockHash, OutPoint, ScriptBuf};
+use bitcoin::{Amount, BlockHash, OutPoint};
use common::*;
use std::collections::{BTreeSet, HashSet};
.canonical_view(&local_chain, chain_tip, env.canonicalization_params.clone())
.balance(
env.indexer.outpoints().iter().cloned(),
- |_, spk: ScriptBuf| env.indexer.index_of_spk(spk).is_some(),
- 1,
+ |_, txout| {
+ env.indexer
+ .index_of_spk(txout.txout.script_pubkey.clone())
+ .is_some()
+ },
+ 0,
);
assert_eq!(
balance, scenario.exp_balance,