From ee01b0fd632c1ff4ab95ec6a50e6af61a1eab7df Mon Sep 17 00:00:00 2001 From: Vladimir Fomene Date: Wed, 6 Sep 2023 09:47:45 +0300 Subject: [PATCH] refactor: improve docs, cleanup unnecessary types and improve code --- crates/bdk/src/wallet/mod.rs | 79 +++++++------------ crates/chain/src/indexed_tx_graph.rs | 21 ++--- crates/chain/src/keychain/txout_index.rs | 17 ++-- crates/chain/src/lib.rs | 8 -- crates/chain/src/spk_txout_index.rs | 60 ++++++++------ crates/electrum/src/electrum_ext.rs | 79 ++++++++----------- crates/electrum/src/lib.rs | 8 +- example-crates/example_electrum/src/main.rs | 16 ++-- example-crates/wallet_electrum/src/main.rs | 11 ++- .../wallet_esplora_async/src/main.rs | 4 +- .../wallet_esplora_blocking/src/main.rs | 4 +- 11 files changed, 138 insertions(+), 169 deletions(-) diff --git a/crates/bdk/src/wallet/mod.rs b/crates/bdk/src/wallet/mod.rs index a7fe4d42a6..5a3918cf00 100644 --- a/crates/bdk/src/wallet/mod.rs +++ b/crates/bdk/src/wallet/mod.rs @@ -25,7 +25,7 @@ use bdk_chain::{ keychain::{self, KeychainTxOutIndex}, local_chain::{self, CannotConnectError, CheckPoint, CheckPointIter, LocalChain}, tx_graph::{CanonicalTx, TxGraph}, - Anchor, Append, BlockId, ChainPosition, ConfirmationTime, ConfirmationTimeAnchor, FullTxOut, + Append, BlockId, ChainPosition, ConfirmationTime, ConfirmationTimeAnchor, FullTxOut, IndexedTxGraph, Persist, PersistBackend, }; use bitcoin::consensus::encode::serialize; @@ -95,73 +95,51 @@ pub struct Wallet { secp: SecpCtx, } -/// A structure to update [`Wallet`]. +/// An update to [`Wallet`]. /// /// It updates [`bdk_chain::keychain::KeychainTxOutIndex`], [`bdk_chain::TxGraph`] and [`local_chain::LocalChain`] atomically. -#[derive(Debug, Clone)] -pub struct WalletUpdate { +#[derive(Debug, Clone, Default)] +pub struct Update { /// Contains the last active derivation indices per keychain (`K`), which is used to update the /// [`KeychainTxOutIndex`]. - pub last_active_indices: BTreeMap, + pub last_active_indices: BTreeMap, - /// Update for the [`TxGraph`]. - pub graph: TxGraph, + /// Update for the wallet's internal [`TxGraph`]. + pub graph: TxGraph, - /// Update for the [`LocalChain`]. + /// Update for the wallet's internal [`LocalChain`]. /// /// [`LocalChain`]: local_chain::LocalChain pub chain: Option, } -impl Default for WalletUpdate { - fn default() -> Self { - Self { - last_active_indices: BTreeMap::new(), - graph: TxGraph::default(), - chain: None, - } - } -} - -/// A structure that records the corresponding changes as result of applying an [`WalletUpdate`]. -#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)] -pub struct WalletChangeSet { +/// The changes made to a wallet by applying an [`Update`]. +#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize, Default)] +pub struct ChangeSet { /// Changes to the [`LocalChain`]. /// /// [`LocalChain`]: local_chain::LocalChain pub chain: local_chain::ChangeSet, - /// ChangeSet to [`IndexedTxGraph`]. + /// Changes to [`IndexedTxGraph`]. /// /// [`IndexedTxGraph`]: bdk_chain::indexed_tx_graph::IndexedTxGraph - #[serde(bound( - deserialize = "K: Ord + serde::Deserialize<'de>, A: Ord + serde::Deserialize<'de>", - serialize = "K: Ord + serde::Serialize, A: Ord + serde::Serialize", - ))] - pub index_tx_graph: indexed_tx_graph::ChangeSet>, + pub indexed_tx_graph: + indexed_tx_graph::ChangeSet>, } -impl Default for WalletChangeSet { - fn default() -> Self { - Self { - chain: Default::default(), - index_tx_graph: Default::default(), - } - } -} - -impl Append for WalletChangeSet { +impl Append for ChangeSet { fn append(&mut self, other: Self) { Append::append(&mut self.chain, other.chain); - Append::append(&mut self.index_tx_graph, other.index_tx_graph); + Append::append(&mut self.indexed_tx_graph, other.indexed_tx_graph); } fn is_empty(&self) -> bool { - self.chain.is_empty() && self.index_tx_graph.is_empty() + self.chain.is_empty() && self.indexed_tx_graph.is_empty() } } -impl From for WalletChangeSet { +impl From for ChangeSet { fn from(chain: local_chain::ChangeSet) -> Self { Self { chain, @@ -170,21 +148,22 @@ impl From for WalletChangeSet { } } -impl From>> for WalletChangeSet { - fn from(index_tx_graph: indexed_tx_graph::ChangeSet>) -> Self { +impl From>> + for ChangeSet +{ + fn from( + indexed_tx_graph: indexed_tx_graph::ChangeSet< + ConfirmationTimeAnchor, + keychain::ChangeSet, + >, + ) -> Self { Self { - index_tx_graph, + indexed_tx_graph, ..Default::default() } } } -/// The update to a [`Wallet`] used in [`Wallet::apply_update`]. This is usually returned from blockchain data sources. -pub type Update = WalletUpdate; - -/// The changeset produced internally by [`Wallet`] when mutated. -pub type ChangeSet = WalletChangeSet; - /// The address index selection strategy to use to derived an address from the wallet's external /// descriptor. See [`Wallet::get_address`]. If you're unsure which one to use use `WalletIndex::New`. #[derive(Debug)] @@ -332,7 +311,7 @@ impl Wallet { let changeset = db.load_from_persistence().map_err(NewError::Persist)?; chain.apply_changeset(&changeset.chain); - indexed_graph.apply_changeset(changeset.index_tx_graph); + indexed_graph.apply_changeset(changeset.indexed_tx_graph); let persist = Persist::new(db); diff --git a/crates/chain/src/indexed_tx_graph.rs b/crates/chain/src/indexed_tx_graph.rs index 4643a93ec9..aee2e54c8c 100644 --- a/crates/chain/src/indexed_tx_graph.rs +++ b/crates/chain/src/indexed_tx_graph.rs @@ -6,7 +6,7 @@ use alloc::vec::Vec; use bitcoin::{OutPoint, Transaction, TxOut}; use crate::{ - keychain, + keychain, local_chain, tx_graph::{self, TxGraph}, Anchor, Append, }; @@ -225,7 +225,13 @@ impl From> for ChangeSet> } } -/// Represents a structure that can index transaction data. +impl From> for (local_chain::ChangeSet, ChangeSet) { + fn from(indexed_changeset: ChangeSet) -> Self { + (local_chain::ChangeSet::default(), indexed_changeset) + } +} + +/// Defines methods to index transaction data. pub trait Indexer { /// The resultant "changeset" when new transaction data is indexed. type ChangeSet; @@ -234,17 +240,6 @@ pub trait Indexer { fn index_txout(&mut self, outpoint: OutPoint, txout: &TxOut) -> Self::ChangeSet; /// Scans a transaction for relevant outpoints, which are stored and indexed internally. - /// - /// If the matched script pubkey is part of the lookahead, the last stored index is updated for - /// the script pubkey's keychain and the [`ChangeSet`] returned will reflect the - /// change. - /// - /// Typically, this method is used in two situations: - /// - /// 1. After loading transaction data from the disk, you may scan over all the txouts to restore all - /// your txouts. - /// 2. When getting new data from the chain, you usually scan it before incorporating it into - /// your chain state. fn index_tx(&mut self, tx: &Transaction) -> Self::ChangeSet; /// Apply changeset to itself. diff --git a/crates/chain/src/keychain/txout_index.rs b/crates/chain/src/keychain/txout_index.rs index 5996d4d46d..6e2f25e7d0 100644 --- a/crates/chain/src/keychain/txout_index.rs +++ b/crates/chain/src/keychain/txout_index.rs @@ -91,11 +91,10 @@ impl Indexer for KeychainTxOutIndex { type ChangeSet = super::ChangeSet; fn index_txout(&mut self, outpoint: OutPoint, txout: &TxOut) -> Self::ChangeSet { - let mut changeset = super::ChangeSet::::default(); - for (keychain, index) in self.inner.index_txout(outpoint, txout) { - changeset.append(self.reveal_to_target(&keychain, index).1); + match self.inner.scan_txout(outpoint, txout).cloned() { + Some((keychain, index)) => self.reveal_to_target(&keychain, index).1, + None => super::ChangeSet::default(), } - changeset } fn index_tx(&mut self, tx: &bitcoin::Transaction) -> Self::ChangeSet { @@ -175,12 +174,10 @@ impl KeychainTxOutIndex { /// Set the lookahead count for `keychain`. /// - /// The lookahead is the number of scripts to cache ahead of the last stored script index. This - /// is useful during a scan via [`Indexer::index_tx`] or [`Indexer::index_txout`]. - /// - /// # Panics - /// - /// This will panic if the `keychain` does not exist. + /// The lookahead is the number of scripts to cache ahead of the last revealed script index. This + /// is useful to find outputs you own when processing block data that lie beyond the last revealed + /// index. This is because in certain scenarios we might not know the last revealed indexit in like + /// when scanning the blockchain for the first time on wallet import. pub fn set_lookahead(&mut self, keychain: &K, lookahead: u32) { self.lookahead.insert(keychain.clone(), lookahead); self.replenish_lookahead(keychain); diff --git a/crates/chain/src/lib.rs b/crates/chain/src/lib.rs index f38b7ee53d..ed167ebf6c 100644 --- a/crates/chain/src/lib.rs +++ b/crates/chain/src/lib.rs @@ -100,11 +100,3 @@ pub mod collections { /// How many confirmations are needed f or a coinbase output to be spent. pub const COINBASE_MATURITY: u32 = 100; - -impl From> - for (local_chain::ChangeSet, indexed_tx_graph::ChangeSet) -{ - fn from(indexed_changeset: indexed_tx_graph::ChangeSet) -> Self { - (local_chain::ChangeSet::default(), indexed_changeset) - } -} diff --git a/crates/chain/src/spk_txout_index.rs b/crates/chain/src/spk_txout_index.rs index 8bac74131b..9088b00c4c 100644 --- a/crates/chain/src/spk_txout_index.rs +++ b/crates/chain/src/spk_txout_index.rs @@ -53,35 +53,19 @@ impl Default for SpkTxOutIndex { } impl Indexer for SpkTxOutIndex { - type ChangeSet = BTreeSet; + type ChangeSet = (); fn index_txout(&mut self, outpoint: OutPoint, txout: &TxOut) -> Self::ChangeSet { - let spk_i = self.spk_indices.get(&txout.script_pubkey); - let mut scanned_indices = BTreeSet::new(); - if let Some(spk_i) = spk_i { - self.txouts.insert(outpoint, (spk_i.clone(), txout.clone())); - self.spk_txouts.insert((spk_i.clone(), outpoint)); - self.unused.remove(spk_i); - scanned_indices.insert(spk_i.clone()); - } - scanned_indices + self.scan_txout(outpoint, txout); + Default::default() } fn index_tx(&mut self, tx: &Transaction) -> Self::ChangeSet { - let mut scanned_indices = BTreeSet::new(); - - for (i, txout) in tx.output.iter().enumerate() { - let op = OutPoint::new(tx.txid(), i as u32); - let mut txout_indices = self.index_txout(op, txout); - scanned_indices.append(&mut txout_indices); - } - - scanned_indices + self.scan(tx); + Default::default() } - fn initial_changeset(&self) -> Self::ChangeSet { - self.spks.keys().cloned().collect() - } + fn initial_changeset(&self) -> Self::ChangeSet {} fn apply_changeset(&mut self, _changeset: Self::ChangeSet) { // This applies nothing. @@ -93,6 +77,38 @@ impl Indexer for SpkTxOutIndex { } impl SpkTxOutIndex { + /// Scans a transaction for txouts. + /// + /// Typically, this is used in two situations: + /// + /// 1. After loading transaction data from the disk, you may scan over all the txouts to restore all + /// your txouts. + /// 2. When getting new data from the chain, you usually scan it before incorporating it into your chain state. + pub fn scan(&mut self, tx: &Transaction) -> BTreeSet { + let mut scanned_indices = BTreeSet::new(); + + for (i, txout) in tx.output.iter().enumerate() { + let op = OutPoint::new(tx.txid(), i as u32); + if let Some(spk_i) = self.scan_txout(op, txout) { + scanned_indices.insert(spk_i.clone()); + } + } + + scanned_indices + } + + /// Scan a single `TxOut` for a matching script pubkey and returns the index that matches the + /// script pubkey (if any). + pub fn scan_txout(&mut self, op: OutPoint, txout: &TxOut) -> Option<&I> { + let spk_i = self.spk_indices.get(&txout.script_pubkey); + if let Some(spk_i) = spk_i { + self.txouts.insert(op, (spk_i.clone(), txout.clone())); + self.spk_txouts.insert((spk_i.clone(), op)); + self.unused.remove(spk_i); + } + spk_i + } + /// Get a reference to the set of indexed outpoints. pub fn outpoints(&self) -> &BTreeSet<(I, OutPoint)> { &self.spk_txouts diff --git a/crates/electrum/src/electrum_ext.rs b/crates/electrum/src/electrum_ext.rs index b743586272..ca287b80d1 100644 --- a/crates/electrum/src/electrum_ext.rs +++ b/crates/electrum/src/electrum_ext.rs @@ -14,19 +14,19 @@ use std::{ /// We assume that a block of this depth and deeper cannot be reorged. const ASSUME_FINAL_DEPTH: u32 = 8; -/// Represents a [`TxGraph`] update fetched from an Electrum server, but excludes full transactions. +/// Represents updates fetched from an Electrum server, but excludes full transactions. /// /// To provide a complete update to [`TxGraph`], you'll need to call [`Self::missing_full_txs`] to -/// determine the full transactions missing from [`TxGraph`]. Then call [`Self::finalize`] to +/// determine the full transactions missing from [`TxGraph`]. Then call [`Self::into_tx_graph`] to /// fetch the full transactions from Electrum and finalize the update. #[derive(Debug, Default, Clone)] -pub struct IncompleteTxGraph(HashMap>); +pub struct RelevantTxids(HashMap>); -impl IncompleteTxGraph { +impl RelevantTxids { /// Determine the full transactions that are missing from `graph`. /// - /// Refer to [`IncompleteTxGraph`] for more. - pub fn missing_full_txs(&self, graph: &TxGraph) -> Vec { + /// Refer to [`RelevantTxids`] for more details. + pub fn missing_full_txs(&self, graph: &TxGraph) -> Vec { self.0 .keys() .filter(move |&&txid| graph.as_ref().get_tx(txid).is_none()) @@ -36,15 +36,15 @@ impl IncompleteTxGraph { /// Finalizes the [`TxGraph`] update by fetching `missing` txids from the `client`. /// - /// Refer to [`IncompleteTxGraph`] for more. - pub fn finalize( + /// Refer to [`RelevantTxids`] for more details. + pub fn into_tx_graph( self, client: &Client, seen_at: Option, missing: Vec, - ) -> Result, Error> { + ) -> Result, Error> { let new_txs = client.batch_transaction_get(&missing)?; - let mut graph = TxGraph::::new(new_txs); + let mut graph = TxGraph::::new(new_txs); for (txid, anchors) in self.0 { if let Some(seen_at) = seen_at { let _ = graph.insert_seen_at(txid, seen_at); @@ -55,22 +55,20 @@ impl IncompleteTxGraph { } Ok(graph) } -} -impl IncompleteTxGraph { - /// Finalizes the [`IncompleteTxGraph`] with `new_txs` and anchors of type + /// Finalizes [`RelevantTxids`] with `new_txs` and anchors of type /// [`ConfirmationTimeAnchor`]. /// /// **Note:** The confirmation time might not be precisely correct if there has been a reorg. /// Electrum's API intends that we use the merkle proof API, we should change `bdk_electrum` to /// use it. - pub fn finalize_with_confirmation_time( + pub fn into_confirmation_time_tx_graph( self, client: &Client, seen_at: Option, missing: Vec, ) -> Result, Error> { - let graph = self.finalize(client, seen_at, missing)?; + let graph = self.into_tx_graph(client, seen_at, missing)?; let relevant_heights = { let mut visited_heights = HashSet::new(); @@ -122,8 +120,9 @@ impl IncompleteTxGraph { } } +type ElectrumUpdate = (local_chain::Update, RelevantTxids); /// Trait to extend [`Client`] functionality. -pub trait ElectrumExt { +pub trait ElectrumExt { /// Scan the blockchain (via electrum) for the data specified and returns updates for /// [`bdk_chain`] data structures. /// @@ -136,7 +135,6 @@ pub trait ElectrumExt { /// The scan for each keychain stops after a gap of `stop_gap` script pubkeys with no associated /// transactions. `batch_size` specifies the max number of script pubkeys to request for in a /// single batch request. - #[allow(clippy::type_complexity)] fn scan( &self, prev_tip: Option, @@ -145,7 +143,7 @@ pub trait ElectrumExt { outpoints: impl IntoIterator, stop_gap: usize, batch_size: usize, - ) -> Result<(local_chain::Update, IncompleteTxGraph, BTreeMap), Error>; + ) -> Result<(ElectrumUpdate, BTreeMap), Error>; /// Convenience method to call [`scan`] without requiring a keychain. /// @@ -157,13 +155,13 @@ pub trait ElectrumExt { txids: impl IntoIterator, outpoints: impl IntoIterator, batch_size: usize, - ) -> Result<(local_chain::Update, IncompleteTxGraph), Error> { + ) -> Result { let spk_iter = misc_spks .into_iter() .enumerate() .map(|(i, spk)| (i as u32, spk)); - let (chain, graph, _) = self.scan( + let (electrum_update, _) = self.scan( prev_tip, [((), spk_iter)].into(), txids, @@ -172,11 +170,11 @@ pub trait ElectrumExt { batch_size, )?; - Ok((chain, graph)) + Ok(electrum_update) } } -impl ElectrumExt for Client { +impl ElectrumExt for Client { fn scan( &self, prev_tip: Option, @@ -185,14 +183,7 @@ impl ElectrumExt for Client { outpoints: impl IntoIterator, stop_gap: usize, batch_size: usize, - ) -> Result< - ( - local_chain::Update, - IncompleteTxGraph, - BTreeMap, - ), - Error, - > { + ) -> Result<(ElectrumUpdate, BTreeMap), Error> { let mut request_spks = keychain_spks .into_iter() .map(|(k, s)| (k, s.into_iter())) @@ -202,9 +193,9 @@ impl ElectrumExt for Client { let txids = txids.into_iter().collect::>(); let outpoints = outpoints.into_iter().collect::>(); - let update = loop { + let (electrum_update, keychain_update) = loop { let (tip, _) = construct_update_tip(self, prev_tip.clone())?; - let mut graph_update = IncompleteTxGraph::::default(); + let mut relevant_txids = RelevantTxids::default(); let cps = tip .iter() .take(10) @@ -216,7 +207,7 @@ impl ElectrumExt for Client { scanned_spks.append(&mut populate_with_spks( self, &cps, - &mut graph_update, + &mut relevant_txids, &mut scanned_spks .iter() .map(|(i, (spk, _))| (i.clone(), spk.clone())), @@ -229,7 +220,7 @@ impl ElectrumExt for Client { populate_with_spks( self, &cps, - &mut graph_update, + &mut relevant_txids, keychain_spks, stop_gap, batch_size, @@ -240,12 +231,12 @@ impl ElectrumExt for Client { } } - populate_with_txids(self, &cps, &mut graph_update, &mut txids.iter().cloned())?; + populate_with_txids(self, &cps, &mut relevant_txids, &mut txids.iter().cloned())?; let _txs = populate_with_outpoints( self, &cps, - &mut graph_update, + &mut relevant_txids, &mut outpoints.iter().cloned(), )?; @@ -271,10 +262,10 @@ impl ElectrumExt for Client { }) .collect::>(); - break (chain_update, graph_update, keychain_update); + break ((chain_update, relevant_txids), keychain_update); }; - Ok(update) + Ok((electrum_update, keychain_update)) } } @@ -398,7 +389,7 @@ fn determine_tx_anchor( fn populate_with_outpoints( client: &Client, cps: &BTreeMap, - graph_update: &mut IncompleteTxGraph, + relevant_txids: &mut RelevantTxids, outpoints: &mut impl Iterator, ) -> Result, Error> { let mut full_txs = HashMap::new(); @@ -447,7 +438,7 @@ fn populate_with_outpoints( }; let anchor = determine_tx_anchor(cps, res.height, res.tx_hash); - let tx_entry = graph_update.0.entry(res.tx_hash).or_default(); + let tx_entry = relevant_txids.0.entry(res.tx_hash).or_default(); if let Some(anchor) = anchor { tx_entry.insert(anchor); } @@ -459,7 +450,7 @@ fn populate_with_outpoints( fn populate_with_txids( client: &Client, cps: &BTreeMap, - graph_update: &mut IncompleteTxGraph, + relevant_txids: &mut RelevantTxids, txids: &mut impl Iterator, ) -> Result<(), Error> { for txid in txids { @@ -484,7 +475,7 @@ fn populate_with_txids( None => continue, }; - let tx_entry = graph_update.0.entry(txid).or_default(); + let tx_entry = relevant_txids.0.entry(txid).or_default(); if let Some(anchor) = anchor { tx_entry.insert(anchor); } @@ -495,7 +486,7 @@ fn populate_with_txids( fn populate_with_spks( client: &Client, cps: &BTreeMap, - graph_update: &mut IncompleteTxGraph, + relevant_txids: &mut RelevantTxids, spks: &mut impl Iterator, stop_gap: usize, batch_size: usize, @@ -528,7 +519,7 @@ fn populate_with_spks( } for tx in spk_history { - let tx_entry = graph_update.0.entry(tx.tx_hash).or_default(); + let tx_entry = relevant_txids.0.entry(tx.tx_hash).or_default(); if let Some(anchor) = determine_tx_anchor(cps, tx.height, tx.tx_hash) { tx_entry.insert(anchor); } diff --git a/crates/electrum/src/lib.rs b/crates/electrum/src/lib.rs index 0977262685..1e4805379c 100644 --- a/crates/electrum/src/lib.rs +++ b/crates/electrum/src/lib.rs @@ -3,14 +3,14 @@ //! The star of the show is the [`ElectrumExt::scan`] method, which scans for relevant blockchain //! data (via electrum) and outputs updates for [`bdk_chain`] structures as a tuple of form: //! -//! ([`bdk_chain::local_chain::Update`], [`IncompleteTxGraph`], `keychain_update`) +//! ([`bdk_chain::local_chain::Update`], [`RelevantTxids`], `keychain_update`) //! -//! An [`IncompleteTxGraph`] only includes `txid`s and no full transactions. The caller is +//! An [`RelevantTxids`] only includes `txid`s and no full transactions. The caller is //! responsible for obtaining full transactions before applying. This can be done with //! these steps: //! //! 1. Determine which full transactions are missing. The method [`missing_full_txs`] of -//! [`IncompleteTxGraph`] can be used. +//! [`RelevantTxids`] can be used. //! //! 2. Obtaining the full transactions. To do this via electrum, the method //! [`batch_transaction_get`] can be used. @@ -18,7 +18,7 @@ //! Refer to [`bdk_electrum_example`] for a complete example. //! //! [`ElectrumClient::scan`]: electrum_client::ElectrumClient::scan -//! [`missing_full_txs`]: IncompleteTxGraph::missing_full_txs +//! [`missing_full_txs`]: RelevantTxids::missing_full_txs //! [`batch_transaction_get`]: electrum_client::ElectrumApi::batch_transaction_get //! [`bdk_electrum_example`]: https://github.com/LLFourn/bdk_core_staging/tree/master/bdk_electrum_example diff --git a/example-crates/example_electrum/src/main.rs b/example-crates/example_electrum/src/main.rs index 84501358cb..179cd328c8 100644 --- a/example-crates/example_electrum/src/main.rs +++ b/example-crates/example_electrum/src/main.rs @@ -66,16 +66,16 @@ type ChangeSet = ( ); fn main() -> anyhow::Result<()> { - let (args, keymap, index, db, init_changeset) = + let (args, keymap, index, db, (disk_local_chain, disk_tx_graph)) = example_cli::init::(DB_MAGIC, DB_PATH)?; let graph = Mutex::new({ let mut graph = IndexedTxGraph::new(index); - graph.apply_changeset(init_changeset.1); + graph.apply_changeset(disk_tx_graph); graph }); - let chain = Mutex::new(LocalChain::from_changeset(init_changeset.0)); + let chain = Mutex::new(LocalChain::from_changeset(disk_local_chain)); let electrum_url = match args.network { Network::Bitcoin => "ssl://electrum.blockstream.info:50002", @@ -251,18 +251,18 @@ fn main() -> anyhow::Result<()> { // drop lock on graph and chain drop((graph, chain)); - let (chain_update, graph_update) = client + let (chain_update, relevant_txids) = client .scan_without_keychain(tip, spks, txids, outpoints, scan_options.batch_size) .context("scanning the blockchain")?; - (chain_update, graph_update, BTreeMap::new()) + ((chain_update, relevant_txids), BTreeMap::new()) } }; - let (chain_update, incomplete_graph_update, keychain_update) = response; + let ((chain_update, relevant_txids), keychain_update) = response; let missing_txids = { let graph = &*graph.lock().unwrap(); - incomplete_graph_update.missing_full_txs(graph.graph()) + relevant_txids.missing_full_txs(graph.graph()) }; let now = std::time::UNIX_EPOCH @@ -270,7 +270,7 @@ fn main() -> anyhow::Result<()> { .expect("must get time") .as_secs(); - let graph_update = incomplete_graph_update.finalize(&client, Some(now), missing_txids)?; + let graph_update = relevant_txids.into_tx_graph(&client, Some(now), missing_txids)?; let db_changeset = { let mut chain = chain.lock().unwrap(); diff --git a/example-crates/wallet_electrum/src/main.rs b/example-crates/wallet_electrum/src/main.rs index f723d6655a..8fbffef87f 100644 --- a/example-crates/wallet_electrum/src/main.rs +++ b/example-crates/wallet_electrum/src/main.rs @@ -7,7 +7,7 @@ use std::io::Write; use std::str::FromStr; use bdk::bitcoin::Address; -use bdk::wallet::WalletUpdate; +use bdk::wallet::Update; use bdk::SignOptions; use bdk::{bitcoin::Network, Wallet}; use bdk_electrum::electrum_client::{self, ElectrumApi}; @@ -53,16 +53,15 @@ fn main() -> Result<(), Box> { }) .collect(); - let (chain_update, incomplete_graph_update, keychain_update) = + let ((chain_update, relevant_txids), keychain_update) = client.scan(prev_tip, keychain_spks, None, None, STOP_GAP, BATCH_SIZE)?; println!(); - let missing = incomplete_graph_update.missing_full_txs(wallet.as_ref()); - let graph_update = - incomplete_graph_update.finalize_with_confirmation_time(&client, None, missing)?; + let missing = relevant_txids.missing_full_txs(wallet.as_ref()); + let graph_update = relevant_txids.into_confirmation_time_tx_graph(&client, None, missing)?; - let wallet_update = WalletUpdate { + let wallet_update = Update { last_active_indices: keychain_update, graph: graph_update, chain: Some(chain_update), diff --git a/example-crates/wallet_esplora_async/src/main.rs b/example-crates/wallet_esplora_async/src/main.rs index 49692b5cb2..87a48b1bd6 100644 --- a/example-crates/wallet_esplora_async/src/main.rs +++ b/example-crates/wallet_esplora_async/src/main.rs @@ -2,7 +2,7 @@ use std::{io::Write, str::FromStr}; use bdk::{ bitcoin::{Address, Network}, - wallet::{AddressIndex, WalletUpdate}, + wallet::{AddressIndex, Update}, SignOptions, Wallet, }; use bdk_esplora::{esplora_client, EsploraAsyncExt}; @@ -58,7 +58,7 @@ async fn main() -> Result<(), Box> { .await?; let missing_heights = wallet.tx_graph().missing_heights(wallet.local_chain()); let chain_update = client.update_local_chain(prev_tip, missing_heights).await?; - let update = WalletUpdate { + let update = Update { last_active_indices, graph: update_graph, chain: Some(chain_update), diff --git a/example-crates/wallet_esplora_blocking/src/main.rs b/example-crates/wallet_esplora_blocking/src/main.rs index fb6e0e8778..8034dabfc6 100644 --- a/example-crates/wallet_esplora_blocking/src/main.rs +++ b/example-crates/wallet_esplora_blocking/src/main.rs @@ -7,7 +7,7 @@ use std::{io::Write, str::FromStr}; use bdk::{ bitcoin::{Address, Network}, - wallet::{AddressIndex, WalletUpdate}, + wallet::{AddressIndex, Update}, SignOptions, Wallet, }; use bdk_esplora::{esplora_client, EsploraExt}; @@ -57,7 +57,7 @@ fn main() -> Result<(), Box> { client.update_tx_graph(keychain_spks, None, None, STOP_GAP, PARALLEL_REQUESTS)?; let missing_heights = wallet.tx_graph().missing_heights(wallet.local_chain()); let chain_update = client.update_local_chain(prev_tip, missing_heights)?; - let update = WalletUpdate { + let update = Update { last_active_indices, graph: update_graph, chain: Some(chain_update),