Skip to content

Commit

Permalink
refactor(chain)!: remove IndexedTxGraph 🗑
Browse files Browse the repository at this point in the history
in favour of adding a type parameter to TxGraph.
When the second type parameter `X: Indexer` is set then TxGraph behaves
like `IndexedTxGraph` used to.

I reworked the internals of `TxGraph` as I thought things were a bit
convoluted.

- feat: allow changing the indexer on TxGraph

Co-authored: LLFourn
  • Loading branch information
ValuedMammal committed Feb 4, 2025
1 parent 88330f6 commit c6047a0
Show file tree
Hide file tree
Showing 17 changed files with 609 additions and 735 deletions.
5 changes: 2 additions & 3 deletions crates/bitcoind_rpc/examples/filter_iter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use bdk_chain::bitcoin::{constants::genesis_block, secp256k1::Secp256k1, Network
use bdk_chain::indexer::keychain_txout::KeychainTxOutIndex;
use bdk_chain::local_chain::LocalChain;
use bdk_chain::miniscript::Descriptor;
use bdk_chain::{BlockId, ConfirmationBlockTime, IndexedTxGraph, SpkIterator};
use bdk_chain::{BlockId, ConfirmationBlockTime, SpkIterator, TxGraph};
use bdk_testenv::anyhow;
use bitcoin::Address;

Expand All @@ -31,7 +31,7 @@ fn main() -> anyhow::Result<()> {
let (descriptor, _) = Descriptor::parse_descriptor(&secp, EXTERNAL)?;
let (change_descriptor, _) = Descriptor::parse_descriptor(&secp, INTERNAL)?;
let (mut chain, _) = LocalChain::from_genesis_hash(genesis_block(NETWORK).block_hash());
let mut graph = IndexedTxGraph::<ConfirmationBlockTime, KeychainTxOutIndex<&str>>::new({
let mut graph = TxGraph::<ConfirmationBlockTime, KeychainTxOutIndex<&str>>::new({
let mut index = KeychainTxOutIndex::default();
index.insert_descriptor("external", descriptor.clone())?;
index.insert_descriptor("internal", change_descriptor.clone())?;
Expand Down Expand Up @@ -88,7 +88,6 @@ fn main() -> anyhow::Result<()> {
println!("\ntook: {}s", start.elapsed().as_secs());
println!("Local tip: {}", chain.tip().height());
let unspent: Vec<_> = graph
.graph()
.filter_chain_unspents(
&chain,
chain.tip().block_id(),
Expand Down
35 changes: 16 additions & 19 deletions crates/bitcoind_rpc/tests/test_emitter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use bdk_chain::{
bitcoin::{Address, Amount, Txid},
local_chain::{CheckPoint, LocalChain},
spk_txout::SpkTxOutIndex,
Balance, BlockId, IndexedTxGraph, Merge,
Balance, BlockId, Merge, TxGraph,
};
use bdk_testenv::{anyhow, TestEnv};
use bitcoin::{hashes::Hash, Block, OutPoint, ScriptBuf, WScriptHash};
Expand Down Expand Up @@ -148,7 +148,7 @@ fn test_into_tx_graph() -> anyhow::Result<()> {
env.mine_blocks(101, None)?;

let (mut chain, _) = LocalChain::from_genesis_hash(env.rpc_client().get_block_hash(0)?);
let mut indexed_tx_graph = IndexedTxGraph::<BlockId, _>::new({
let mut tx_graph = TxGraph::<BlockId, _>::new({
let mut index = SpkTxOutIndex::<usize>::default();
index.insert_spk(0, addr_0.script_pubkey());
index.insert_spk(1, addr_1.script_pubkey());
Expand All @@ -161,8 +161,8 @@ fn test_into_tx_graph() -> anyhow::Result<()> {
while let Some(emission) = emitter.next_block()? {
let height = emission.block_height();
let _ = chain.apply_update(emission.checkpoint)?;
let indexed_additions = indexed_tx_graph.apply_block_relevant(&emission.block, height);
assert!(indexed_additions.is_empty());
let tx_graph_changeset = tx_graph.apply_block_relevant(&emission.block, height);
assert!(tx_graph_changeset.is_empty());
}

// send 3 txs to a tracked address, these txs will be in the mempool
Expand All @@ -189,18 +189,17 @@ fn test_into_tx_graph() -> anyhow::Result<()> {
assert!(emitter.next_block()?.is_none());

let mempool_txs = emitter.mempool()?;
let indexed_additions = indexed_tx_graph.batch_insert_unconfirmed(mempool_txs);
let tx_graph_changeset = tx_graph.batch_insert_unconfirmed(mempool_txs);
assert_eq!(
indexed_additions
.tx_graph
tx_graph_changeset
.txs
.iter()
.map(|tx| tx.compute_txid())
.collect::<BTreeSet<Txid>>(),
exp_txids,
"changeset should have the 3 mempool transactions",
);
assert!(indexed_additions.tx_graph.anchors.is_empty());
assert!(tx_graph_changeset.anchors.is_empty());
}

// mine a block that confirms the 3 txs
Expand All @@ -222,10 +221,10 @@ fn test_into_tx_graph() -> anyhow::Result<()> {
let emission = emitter.next_block()?.expect("must get mined block");
let height = emission.block_height();
let _ = chain.apply_update(emission.checkpoint)?;
let indexed_additions = indexed_tx_graph.apply_block_relevant(&emission.block, height);
assert!(indexed_additions.tx_graph.txs.is_empty());
assert!(indexed_additions.tx_graph.txouts.is_empty());
assert_eq!(indexed_additions.tx_graph.anchors, exp_anchors);
let tx_graph_changeset = tx_graph.apply_block_relevant(&emission.block, height);
assert!(tx_graph_changeset.txs.is_empty());
assert!(tx_graph_changeset.txouts.is_empty());
assert_eq!(tx_graph_changeset.anchors, exp_anchors);
}

Ok(())
Expand Down Expand Up @@ -276,7 +275,7 @@ fn ensure_block_emitted_after_reorg_is_at_reorg_height() -> anyhow::Result<()> {

fn process_block(
recv_chain: &mut LocalChain,
recv_graph: &mut IndexedTxGraph<BlockId, SpkTxOutIndex<()>>,
recv_graph: &mut TxGraph<BlockId, SpkTxOutIndex<()>>,
block: Block,
block_height: u32,
) -> anyhow::Result<()> {
Expand All @@ -287,7 +286,7 @@ fn process_block(

fn sync_from_emitter<C>(
recv_chain: &mut LocalChain,
recv_graph: &mut IndexedTxGraph<BlockId, SpkTxOutIndex<()>>,
recv_graph: &mut TxGraph<BlockId, SpkTxOutIndex<()>>,
emitter: &mut Emitter<C>,
) -> anyhow::Result<()>
where
Expand All @@ -302,13 +301,11 @@ where

fn get_balance(
recv_chain: &LocalChain,
recv_graph: &IndexedTxGraph<BlockId, SpkTxOutIndex<()>>,
recv_graph: &TxGraph<BlockId, SpkTxOutIndex<()>>,
) -> anyhow::Result<Balance> {
let chain_tip = recv_chain.tip().block_id();
let outpoints = recv_graph.index.outpoints().clone();
let balance = recv_graph
.graph()
.balance(recv_chain, chain_tip, outpoints, |_, _| true);
let balance = recv_graph.balance(recv_chain, chain_tip, outpoints, |_, _| true);
Ok(balance)
}

Expand Down Expand Up @@ -340,7 +337,7 @@ fn tx_can_become_unconfirmed_after_reorg() -> anyhow::Result<()> {

// setup receiver
let (mut recv_chain, _) = LocalChain::from_genesis_hash(env.rpc_client().get_block_hash(0)?);
let mut recv_graph = IndexedTxGraph::<BlockId, _>::new({
let mut recv_graph = TxGraph::<BlockId, _>::new({
let mut recv_index = SpkTxOutIndex::default();
recv_index.insert_spk((), spk_to_track.clone());
recv_index
Expand Down
12 changes: 5 additions & 7 deletions crates/chain/benches/canonicalization.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use bdk_chain::{keychain_txout::KeychainTxOutIndex, local_chain::LocalChain, IndexedTxGraph};
use bdk_chain::{keychain_txout::KeychainTxOutIndex, local_chain::LocalChain, TxGraph};
use bdk_core::{BlockId, CheckPoint};
use bdk_core::{ConfirmationBlockTime, TxUpdate};
use bdk_testenv::hash;
Expand All @@ -11,7 +11,7 @@ use miniscript::{Descriptor, DescriptorPublicKey};
use std::sync::Arc;

type Keychain = ();
type KeychainTxGraph = IndexedTxGraph<ConfirmationBlockTime, KeychainTxOutIndex<Keychain>>;
type KeychainTxGraph = TxGraph<ConfirmationBlockTime, KeychainTxOutIndex<Keychain>>;

/// New tx guaranteed to have at least one output
fn new_tx(lt: u32) -> Transaction {
Expand Down Expand Up @@ -90,14 +90,12 @@ fn setup<F: Fn(&mut KeychainTxGraph, &LocalChain)>(f: F) -> (KeychainTxGraph, Lo
}

fn run_list_canonical_txs(tx_graph: &KeychainTxGraph, chain: &LocalChain, exp_txs: usize) {
let txs = tx_graph
.graph()
.list_canonical_txs(chain, chain.tip().block_id());
let txs = tx_graph.list_canonical_txs(chain, chain.tip().block_id());
assert_eq!(txs.count(), exp_txs);
}

fn run_filter_chain_txouts(tx_graph: &KeychainTxGraph, chain: &LocalChain, exp_txos: usize) {
let utxos = tx_graph.graph().filter_chain_txouts(
let utxos = tx_graph.filter_chain_txouts(
chain,
chain.tip().block_id(),
tx_graph.index.outpoints().clone(),
Expand All @@ -106,7 +104,7 @@ fn run_filter_chain_txouts(tx_graph: &KeychainTxGraph, chain: &LocalChain, exp_t
}

fn run_filter_chain_unspents(tx_graph: &KeychainTxGraph, chain: &LocalChain, exp_utxos: usize) {
let utxos = tx_graph.graph().filter_chain_unspents(
let utxos = tx_graph.filter_chain_unspents(
chain,
chain.tip().block_id(),
tx_graph.index.outpoints().clone(),
Expand Down
10 changes: 5 additions & 5 deletions crates/chain/src/canonical_iter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@ use bdk_core::BlockId;
use bitcoin::{Transaction, Txid};

/// Iterates over canonical txs.
pub struct CanonicalIter<'g, A, C> {
tx_graph: &'g TxGraph<A>,
pub struct CanonicalIter<'g, A, X, C> {
tx_graph: &'g TxGraph<A, X>,
chain: &'g C,
chain_tip: BlockId,

Expand All @@ -24,9 +24,9 @@ pub struct CanonicalIter<'g, A, C> {
queue: VecDeque<Txid>,
}

impl<'g, A: Anchor, C: ChainOracle> CanonicalIter<'g, A, C> {
impl<'g, A: Anchor, X, C: ChainOracle> CanonicalIter<'g, A, X, C> {
/// Constructs [`CanonicalIter`].
pub fn new(tx_graph: &'g TxGraph<A>, chain: &'g C, chain_tip: BlockId) -> Self {
pub fn new(tx_graph: &'g TxGraph<A, X>, chain: &'g C, chain_tip: BlockId) -> Self {
let anchors = tx_graph.all_anchors();
let pending_anchored = Box::new(
tx_graph
Expand Down Expand Up @@ -133,7 +133,7 @@ impl<'g, A: Anchor, C: ChainOracle> CanonicalIter<'g, A, C> {
}
}

impl<A: Anchor, C: ChainOracle> Iterator for CanonicalIter<'_, A, C> {
impl<A: Anchor, X, C: ChainOracle> Iterator for CanonicalIter<'_, A, X, C> {
type Item = Result<(Txid, Arc<Transaction>, CanonicalReason<A>), C::Error>;

fn next(&mut self) -> Option<Self::Item> {
Expand Down
Loading

0 comments on commit c6047a0

Please sign in to comment.