diff --git a/crates/chain/src/lib.rs b/crates/chain/src/lib.rs index 04ca62c4c..206566971 100644 --- a/crates/chain/src/lib.rs +++ b/crates/chain/src/lib.rs @@ -1,4 +1,4 @@ -//! This crate is a collection of core structures for [Bitcoin Dev Kit] (alpha release). +//! This crate is a collection of core structures for [Bitcoin Dev Kit]. //! //! The goal of this crate is to give wallets the mechanisms needed to: //! diff --git a/crates/electrum/README.md b/crates/electrum/README.md index d3ada695e..1bafe04eb 100644 --- a/crates/electrum/README.md +++ b/crates/electrum/README.md @@ -1,3 +1,7 @@ # BDK Electrum -BDK Electrum client library for updating the keychain tracker. +BDK Electrum extends [`electrum-client`] to update [`bdk_chain`] structures +from an Electrum server. + +[`electrum-client`]: https://docs.rs/electrum-client/ +[`bdk_chain`]: https://docs.rs/bdk-chain/ diff --git a/crates/electrum/src/electrum_ext.rs b/crates/electrum/src/electrum_ext.rs index 216755a13..1c9ce9890 100644 --- a/crates/electrum/src/electrum_ext.rs +++ b/crates/electrum/src/electrum_ext.rs @@ -134,64 +134,54 @@ pub struct ElectrumUpdate { /// Trait to extend [`Client`] functionality. pub trait ElectrumExt { - /// Scan the blockchain (via electrum) for the data specified and returns updates for - /// [`bdk_chain`] data structures. + /// Full scan the keychain scripts specified with the blockchain (via an Electrum client) and + /// returns updates for [`bdk_chain`] data structures. /// /// - `prev_tip`: the most recent blockchain tip present locally /// - `keychain_spks`: keychains that we want to scan transactions for - /// - `txids`: transactions for which we want updated [`Anchor`]s - /// - `outpoints`: transactions associated with these outpoints (residing, spending) that we - /// want to included in the update /// - /// The scan for each keychain stops after a gap of `stop_gap` script pubkeys with no associated + /// The full 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. - fn scan( + fn full_scan( &self, prev_tip: CheckPoint, keychain_spks: BTreeMap>, - txids: impl IntoIterator, - outpoints: impl IntoIterator, stop_gap: usize, batch_size: usize, ) -> Result<(ElectrumUpdate, BTreeMap), Error>; - /// Convenience method to call [`scan`] without requiring a keychain. + /// Sync a set of scripts with the blockchain (via an Electrum client) for the data specified + /// and returns updates for [`bdk_chain`] data structures. /// - /// [`scan`]: ElectrumExt::scan - fn scan_without_keychain( + /// - `prev_tip`: the most recent blockchain tip present locally + /// - `misc_spks`: an iterator of scripts we want to sync transactions for + /// - `txids`: transactions for which we want updated [`Anchor`]s + /// - `outpoints`: transactions associated with these outpoints (residing, spending) that we + /// want to include in the update + /// + /// `batch_size` specifies the max number of script pubkeys to request for in a single batch + /// request. + /// + /// If the scripts to sync are unknown, such as when restoring or importing a keychain that + /// may include scripts that have been used, use [`full_scan`] with the keychain. + /// + /// [`full_scan`]: ElectrumExt::full_scan + fn sync( &self, prev_tip: CheckPoint, misc_spks: impl IntoIterator, txids: impl IntoIterator, outpoints: impl IntoIterator, batch_size: usize, - ) -> Result { - let spk_iter = misc_spks - .into_iter() - .enumerate() - .map(|(i, spk)| (i as u32, spk)); - - let (electrum_update, _) = self.scan( - prev_tip, - [((), spk_iter)].into(), - txids, - outpoints, - usize::MAX, - batch_size, - )?; - - Ok(electrum_update) - } + ) -> Result; } impl ElectrumExt for Client { - fn scan( + fn full_scan( &self, prev_tip: CheckPoint, keychain_spks: BTreeMap>, - txids: impl IntoIterator, - outpoints: impl IntoIterator, stop_gap: usize, batch_size: usize, ) -> Result<(ElectrumUpdate, BTreeMap), Error> { @@ -201,9 +191,6 @@ impl ElectrumExt for Client { .collect::>(); let mut scanned_spks = BTreeMap::<(K, u32), (ScriptBuf, bool)>::new(); - let txids = txids.into_iter().collect::>(); - let outpoints = outpoints.into_iter().collect::>(); - let (electrum_update, keychain_update) = loop { let (tip, _) = construct_update_tip(self, prev_tip.clone())?; let mut relevant_txids = RelevantTxids::default(); @@ -242,15 +229,6 @@ impl ElectrumExt for Client { } } - populate_with_txids(self, &cps, &mut relevant_txids, &mut txids.iter().cloned())?; - - let _txs = populate_with_outpoints( - self, - &cps, - &mut relevant_txids, - &mut outpoints.iter().cloned(), - )?; - // check for reorgs during scan process let server_blockhash = self.block_header(tip.height() as usize)?.block_hash(); if tip.hash() != server_blockhash { @@ -284,6 +262,41 @@ impl ElectrumExt for Client { Ok((electrum_update, keychain_update)) } + + fn sync( + &self, + prev_tip: CheckPoint, + misc_spks: impl IntoIterator, + txids: impl IntoIterator, + outpoints: impl IntoIterator, + batch_size: usize, + ) -> Result { + let spk_iter = misc_spks + .into_iter() + .enumerate() + .map(|(i, spk)| (i as u32, spk)); + + let (mut electrum_update, _) = self.full_scan( + prev_tip.clone(), + [((), spk_iter)].into(), + usize::MAX, + batch_size, + )?; + + let (tip, _) = construct_update_tip(self, prev_tip)?; + let cps = tip + .iter() + .take(10) + .map(|cp| (cp.height(), cp)) + .collect::>(); + + populate_with_txids(self, &cps, &mut electrum_update.relevant_txids, txids)?; + + let _txs = + populate_with_outpoints(self, &cps, &mut electrum_update.relevant_txids, outpoints)?; + + Ok(electrum_update) + } } /// Return a [`CheckPoint`] of the latest tip, that connects with `prev_tip`. @@ -405,7 +418,7 @@ fn populate_with_outpoints( client: &Client, cps: &BTreeMap, relevant_txids: &mut RelevantTxids, - outpoints: &mut impl Iterator, + outpoints: impl IntoIterator, ) -> Result, Error> { let mut full_txs = HashMap::new(); for outpoint in outpoints { @@ -466,7 +479,7 @@ fn populate_with_txids( client: &Client, cps: &BTreeMap, relevant_txids: &mut RelevantTxids, - txids: &mut impl Iterator, + txids: impl IntoIterator, ) -> Result<(), Error> { for txid in txids { let tx = match client.transaction_get(&txid) { diff --git a/crates/electrum/src/lib.rs b/crates/electrum/src/lib.rs index 1e4805379..87c0e4618 100644 --- a/crates/electrum/src/lib.rs +++ b/crates/electrum/src/lib.rs @@ -1,26 +1,26 @@ -//! This crate is used for updating structures of the [`bdk_chain`] crate with data from electrum. +//! This crate is used for updating structures of [`bdk_chain`] with data from an Electrum server. //! -//! 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: +//! The two primary methods are [`ElectrumExt::sync`] and [`ElectrumExt::full_scan`]. In most cases +//! [`ElectrumExt::sync`] is used to sync the transaction histories of scripts that the application +//! cares about, for example the scripts for all the receive addresses of a Wallet's keychain that it +//! has shown a user. [`ElectrumExt::full_scan`] is meant to be used when importing or restoring a +//! keychain where the range of possibly used scripts is not known. In this case it is necessary to +//! scan all keychain scripts until a number (the "stop gap") of unused scripts is discovered. For a +//! sync or full scan the user receives relevant blockchain data and output updates for +//! [`bdk_chain`] including [`RelevantTxids`]. //! -//! ([`bdk_chain::local_chain::Update`], [`RelevantTxids`], `keychain_update`) +//! The [`RelevantTxids`] only includes `txid`s and not full transactions. The caller is responsible +//! for obtaining full transactions before applying new data to their [`bdk_chain`]. This can be +//! done with these steps: //! -//! 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. Use [`RelevantTxids::missing_full_txs`]. //! -//! 1. Determine which full transactions are missing. The method [`missing_full_txs`] of -//! [`RelevantTxids`] can be used. +//! 2. Obtaining the full transactions. To do this via electrum use [`ElectrumApi::batch_transaction_get`]. //! -//! 2. Obtaining the full transactions. To do this via electrum, the method -//! [`batch_transaction_get`] can be used. +//! Refer to [`example_electrum`] for a complete example. //! -//! Refer to [`bdk_electrum_example`] for a complete example. -//! -//! [`ElectrumClient::scan`]: electrum_client::ElectrumClient::scan -//! [`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 +//! [`ElectrumApi::batch_transaction_get`]: electrum_client::ElectrumApi::batch_transaction_get +//! [`example_electrum`]: https://github.com/bitcoindevkit/bdk/tree/master/example-crates/example_electrum #![warn(missing_docs)] diff --git a/crates/esplora/src/async_ext.rs b/crates/esplora/src/async_ext.rs index b41050533..649cd6891 100644 --- a/crates/esplora/src/async_ext.rs +++ b/crates/esplora/src/async_ext.rs @@ -36,58 +36,45 @@ pub trait EsploraAsyncExt { request_heights: impl IntoIterator + Send> + Send, ) -> Result; - /// Scan Esplora for the data specified and return a [`TxGraph`] and a map of last active - /// indices. + /// Full scan the keychain scripts specified with the blockchain (via an Esplora client) and + /// returns a [`TxGraph`] and a map of last active indices. /// /// * `keychain_spks`: keychains that we want to scan transactions for - /// * `txids`: transactions for which we want updated [`ConfirmationTimeHeightAnchor`]s - /// * `outpoints`: transactions associated with these outpoints (residing, spending) that we - /// want to include in the update /// - /// The scan for each keychain stops after a gap of `stop_gap` script pubkeys with no associated + /// The full scan for each keychain stops after a gap of `stop_gap` script pubkeys with no associated /// transactions. `parallel_requests` specifies the max number of HTTP requests to make in /// parallel. #[allow(clippy::result_large_err)] - async fn scan_txs_with_keychains( + async fn full_scan( &self, keychain_spks: BTreeMap< K, impl IntoIterator + Send> + Send, >, - txids: impl IntoIterator + Send> + Send, - outpoints: impl IntoIterator + Send> + Send, stop_gap: usize, parallel_requests: usize, ) -> Result<(TxGraph, BTreeMap), Error>; - /// Convenience method to call [`scan_txs_with_keychains`] without requiring a keychain. + /// Sync a set of scripts with the blockchain (via an Esplora client) for the data + /// specified and return a [`TxGraph`]. /// - /// [`scan_txs_with_keychains`]: EsploraAsyncExt::scan_txs_with_keychains + /// * `misc_spks`: scripts that we want to sync transactions for + /// * `txids`: transactions for which we want updated [`ConfirmationTimeHeightAnchor`]s + /// * `outpoints`: transactions associated with these outpoints (residing, spending) that we + /// want to include in the update + /// + /// If the scripts to sync are unknown, such as when restoring or importing a keychain that + /// may include scripts that have been used, use [`full_scan`] with the keychain. + /// + /// [`full_scan`]: EsploraAsyncExt::full_scan #[allow(clippy::result_large_err)] - async fn scan_txs( + async fn sync( &self, misc_spks: impl IntoIterator + Send> + Send, txids: impl IntoIterator + Send> + Send, outpoints: impl IntoIterator + Send> + Send, parallel_requests: usize, - ) -> Result, Error> { - self.scan_txs_with_keychains( - [( - (), - misc_spks - .into_iter() - .enumerate() - .map(|(i, spk)| (i as u32, spk)), - )] - .into(), - txids, - outpoints, - usize::MAX, - parallel_requests, - ) - .await - .map(|(g, _)| g) - } + ) -> Result, Error>; } #[cfg_attr(target_arch = "wasm32", async_trait(?Send))] @@ -199,14 +186,12 @@ impl EsploraAsyncExt for esplora_client::AsyncClient { }) } - async fn scan_txs_with_keychains( + async fn full_scan( &self, keychain_spks: BTreeMap< K, impl IntoIterator + Send> + Send, >, - txids: impl IntoIterator + Send> + Send, - outpoints: impl IntoIterator + Send> + Send, stop_gap: usize, parallel_requests: usize, ) -> Result<(TxGraph, BTreeMap), Error> { @@ -275,6 +260,32 @@ impl EsploraAsyncExt for esplora_client::AsyncClient { } } + Ok((graph, last_active_indexes)) + } + + async fn sync( + &self, + misc_spks: impl IntoIterator + Send> + Send, + txids: impl IntoIterator + Send> + Send, + outpoints: impl IntoIterator + Send> + Send, + parallel_requests: usize, + ) -> Result, Error> { + let mut graph = self + .full_scan( + [( + (), + misc_spks + .into_iter() + .enumerate() + .map(|(i, spk)| (i as u32, spk)), + )] + .into(), + usize::MAX, + parallel_requests, + ) + .await + .map(|(g, _)| g)?; + let mut txids = txids.into_iter(); loop { let handles = txids @@ -323,7 +334,6 @@ impl EsploraAsyncExt for esplora_client::AsyncClient { } } } - - Ok((graph, last_active_indexes)) + Ok(graph) } } diff --git a/crates/esplora/src/blocking_ext.rs b/crates/esplora/src/blocking_ext.rs index bde24f832..493c4b8a7 100644 --- a/crates/esplora/src/blocking_ext.rs +++ b/crates/esplora/src/blocking_ext.rs @@ -19,8 +19,8 @@ use crate::{anchor_from_status, ASSUME_FINAL_DEPTH}; pub trait EsploraExt { /// Prepare an [`LocalChain`] update with blocks fetched from Esplora. /// - /// * `prev_tip` is the previous tip of [`LocalChain::tip`]. - /// * `get_heights` is the block heights that we are interested in fetching from Esplora. + /// * `local_tip` is the previous tip of [`LocalChain::tip`]. + /// * `request_heights` is the block heights that we are interested in fetching from Esplora. /// /// The result of this method can be applied to [`LocalChain::apply_update`]. /// @@ -34,54 +34,42 @@ pub trait EsploraExt { request_heights: impl IntoIterator, ) -> Result; - /// Scan Esplora for the data specified and return a [`TxGraph`] and a map of last active - /// indices. + /// Full scan the keychain scripts specified with the blockchain (via an Esplora client) and + /// returns a [`TxGraph`] and a map of last active indices. /// /// * `keychain_spks`: keychains that we want to scan transactions for - /// * `txids`: transactions for which we want updated [`ConfirmationTimeHeightAnchor`]s - /// * `outpoints`: transactions associated with these outpoints (residing, spending) that we - /// want to include in the update /// - /// The scan for each keychain stops after a gap of `stop_gap` script pubkeys with no associated + /// The full scan for each keychain stops after a gap of `stop_gap` script pubkeys with no associated /// transactions. `parallel_requests` specifies the max number of HTTP requests to make in /// parallel. #[allow(clippy::result_large_err)] - fn scan_txs_with_keychains( + fn full_scan( &self, keychain_spks: BTreeMap>, - txids: impl IntoIterator, - outpoints: impl IntoIterator, stop_gap: usize, parallel_requests: usize, ) -> Result<(TxGraph, BTreeMap), Error>; - /// Convenience method to call [`scan_txs_with_keychains`] without requiring a keychain. + /// Sync a set of scripts with the blockchain (via an Esplora client) for the data + /// specified and return a [`TxGraph`]. /// - /// [`scan_txs_with_keychains`]: EsploraExt::scan_txs_with_keychains + /// * `misc_spks`: scripts that we want to sync transactions for + /// * `txids`: transactions for which we want updated [`ConfirmationTimeHeightAnchor`]s + /// * `outpoints`: transactions associated with these outpoints (residing, spending) that we + /// want to include in the update + /// + /// If the scripts to sync are unknown, such as when restoring or importing a keychain that + /// may include scripts that have been used, use [`full_scan`] with the keychain. + /// + /// [`full_scan`]: EsploraExt::full_scan #[allow(clippy::result_large_err)] - fn scan_txs( + fn sync( &self, misc_spks: impl IntoIterator, txids: impl IntoIterator, outpoints: impl IntoIterator, parallel_requests: usize, - ) -> Result, Error> { - self.scan_txs_with_keychains( - [( - (), - misc_spks - .into_iter() - .enumerate() - .map(|(i, spk)| (i as u32, spk)), - )] - .into(), - txids, - outpoints, - usize::MAX, - parallel_requests, - ) - .map(|(g, _)| g) - } + ) -> Result, Error>; } impl EsploraExt for esplora_client::BlockingClient { @@ -190,11 +178,9 @@ impl EsploraExt for esplora_client::BlockingClient { }) } - fn scan_txs_with_keychains( + fn full_scan( &self, keychain_spks: BTreeMap>, - txids: impl IntoIterator, - outpoints: impl IntoIterator, stop_gap: usize, parallel_requests: usize, ) -> Result<(TxGraph, BTreeMap), Error> { @@ -266,6 +252,31 @@ impl EsploraExt for esplora_client::BlockingClient { } } + Ok((graph, last_active_indexes)) + } + + fn sync( + &self, + misc_spks: impl IntoIterator, + txids: impl IntoIterator, + outpoints: impl IntoIterator, + parallel_requests: usize, + ) -> Result, Error> { + let mut graph = self + .full_scan( + [( + (), + misc_spks + .into_iter() + .enumerate() + .map(|(i, spk)| (i as u32, spk)), + )] + .into(), + usize::MAX, + parallel_requests, + ) + .map(|(g, _)| g)?; + let mut txids = txids.into_iter(); loop { let handles = txids @@ -292,7 +303,7 @@ impl EsploraExt for esplora_client::BlockingClient { } } - for op in outpoints.into_iter() { + for op in outpoints { if graph.get_tx(op.txid).is_none() { if let Some(tx) = self.get_tx(&op.txid)? { let _ = graph.insert_tx(tx); @@ -317,7 +328,6 @@ impl EsploraExt for esplora_client::BlockingClient { } } } - - Ok((graph, last_active_indexes)) + Ok(graph) } } diff --git a/crates/esplora/src/lib.rs b/crates/esplora/src/lib.rs index e8c667277..727c8c53b 100644 --- a/crates/esplora/src/lib.rs +++ b/crates/esplora/src/lib.rs @@ -1,4 +1,21 @@ #![doc = include_str!("../README.md")] + +//! This crate is used for updating structures of [`bdk_chain`] with data from an Esplora server. +//! +//! The two primary methods are [`EsploraExt::sync`] and [`EsploraExt::full_scan`]. In most cases +//! [`EsploraExt::sync`] is used to sync the transaction histories of scripts that the application +//! cares about, for example the scripts for all the receive addresses of a Wallet's keychain that it +//! has shown a user. [`EsploraExt::full_scan`] is meant to be used when importing or restoring a +//! keychain where the range of possibly used scripts is not known. In this case it is necessary to +//! scan all keychain scripts until a number (the "stop gap") of unused scripts is discovered. For a +//! sync or full scan the user receives relevant blockchain data and output updates for [`bdk_chain`] +//! via a new [`TxGraph`] to be appended to any existing [`TxGraph`] data. +//! +//! Refer to [`example_esplora`] for a complete example. +//! +//! [`TxGraph`]: bdk_chain::tx_graph::TxGraph +//! [`example_esplora`]: https://github.com/bitcoindevkit/bdk/tree/master/example-crates/example_esplora + use bdk_chain::{BlockId, ConfirmationTimeHeightAnchor}; use esplora_client::TxStatus; diff --git a/crates/esplora/tests/async_ext.rs b/crates/esplora/tests/async_ext.rs index 38833f588..3124bd2d1 100644 --- a/crates/esplora/tests/async_ext.rs +++ b/crates/esplora/tests/async_ext.rs @@ -101,7 +101,7 @@ pub async fn test_update_tx_graph_without_keychain() -> anyhow::Result<()> { let graph_update = env .client - .scan_txs( + .sync( misc_spks.into_iter(), vec![].into_iter(), vec![].into_iter(), @@ -166,28 +166,10 @@ pub async fn test_async_update_tx_graph_gap_limit() -> anyhow::Result<()> { // A scan with a gap limit of 2 won't find the transaction, but a scan with a gap limit of 3 // will. - let (graph_update, active_indices) = env - .client - .scan_txs_with_keychains( - keychains.clone(), - vec![].into_iter(), - vec![].into_iter(), - 2, - 1, - ) - .await?; + let (graph_update, active_indices) = env.client.full_scan(keychains.clone(), 2, 1).await?; assert!(graph_update.full_txs().next().is_none()); assert!(active_indices.is_empty()); - let (graph_update, active_indices) = env - .client - .scan_txs_with_keychains( - keychains.clone(), - vec![].into_iter(), - vec![].into_iter(), - 3, - 1, - ) - .await?; + let (graph_update, active_indices) = env.client.full_scan(keychains.clone(), 3, 1).await?; assert_eq!(graph_update.full_txs().next().unwrap().txid, txid_4th_addr); assert_eq!(active_indices[&0], 3); @@ -209,24 +191,12 @@ pub async fn test_async_update_tx_graph_gap_limit() -> anyhow::Result<()> { // A scan with gap limit 4 won't find the second transaction, but a scan with gap limit 5 will. // The last active indice won't be updated in the first case but will in the second one. - let (graph_update, active_indices) = env - .client - .scan_txs_with_keychains( - keychains.clone(), - vec![].into_iter(), - vec![].into_iter(), - 4, - 1, - ) - .await?; + let (graph_update, active_indices) = env.client.full_scan(keychains.clone(), 4, 1).await?; let txs: HashSet<_> = graph_update.full_txs().map(|tx| tx.txid).collect(); assert_eq!(txs.len(), 1); assert!(txs.contains(&txid_4th_addr)); assert_eq!(active_indices[&0], 3); - let (graph_update, active_indices) = env - .client - .scan_txs_with_keychains(keychains, vec![].into_iter(), vec![].into_iter(), 5, 1) - .await?; + let (graph_update, active_indices) = env.client.full_scan(keychains, 5, 1).await?; let txs: HashSet<_> = graph_update.full_txs().map(|tx| tx.txid).collect(); assert_eq!(txs.len(), 2); assert!(txs.contains(&txid_4th_addr) && txs.contains(&txid_last_addr)); diff --git a/crates/esplora/tests/blocking_ext.rs b/crates/esplora/tests/blocking_ext.rs index 5a7617232..50b19d1cc 100644 --- a/crates/esplora/tests/blocking_ext.rs +++ b/crates/esplora/tests/blocking_ext.rs @@ -99,7 +99,7 @@ pub fn test_update_tx_graph_without_keychain() -> anyhow::Result<()> { sleep(Duration::from_millis(10)) } - let graph_update = env.client.scan_txs( + let graph_update = env.client.sync( misc_spks.into_iter(), vec![].into_iter(), vec![].into_iter(), @@ -164,22 +164,10 @@ pub fn test_update_tx_graph_gap_limit() -> anyhow::Result<()> { // A scan with a gap limit of 2 won't find the transaction, but a scan with a gap limit of 3 // will. - let (graph_update, active_indices) = env.client.scan_txs_with_keychains( - keychains.clone(), - vec![].into_iter(), - vec![].into_iter(), - 2, - 1, - )?; + let (graph_update, active_indices) = env.client.full_scan(keychains.clone(), 2, 1)?; assert!(graph_update.full_txs().next().is_none()); assert!(active_indices.is_empty()); - let (graph_update, active_indices) = env.client.scan_txs_with_keychains( - keychains.clone(), - vec![].into_iter(), - vec![].into_iter(), - 3, - 1, - )?; + let (graph_update, active_indices) = env.client.full_scan(keychains.clone(), 3, 1)?; assert_eq!(graph_update.full_txs().next().unwrap().txid, txid_4th_addr); assert_eq!(active_indices[&0], 3); @@ -201,24 +189,12 @@ pub fn test_update_tx_graph_gap_limit() -> anyhow::Result<()> { // A scan with gap limit 4 won't find the second transaction, but a scan with gap limit 5 will. // The last active indice won't be updated in the first case but will in the second one. - let (graph_update, active_indices) = env.client.scan_txs_with_keychains( - keychains.clone(), - vec![].into_iter(), - vec![].into_iter(), - 4, - 1, - )?; + let (graph_update, active_indices) = env.client.full_scan(keychains.clone(), 4, 1)?; let txs: HashSet<_> = graph_update.full_txs().map(|tx| tx.txid).collect(); assert_eq!(txs.len(), 1); assert!(txs.contains(&txid_4th_addr)); assert_eq!(active_indices[&0], 3); - let (graph_update, active_indices) = env.client.scan_txs_with_keychains( - keychains, - vec![].into_iter(), - vec![].into_iter(), - 5, - 1, - )?; + let (graph_update, active_indices) = env.client.full_scan(keychains, 5, 1)?; let txs: HashSet<_> = graph_update.full_txs().map(|tx| tx.txid).collect(); assert_eq!(txs.len(), 2); assert!(txs.contains(&txid_4th_addr) && txs.contains(&txid_last_addr)); diff --git a/example-crates/example_electrum/src/main.rs b/example-crates/example_electrum/src/main.rs index a96378f64..0041a20c8 100644 --- a/example-crates/example_electrum/src/main.rs +++ b/example-crates/example_electrum/src/main.rs @@ -172,14 +172,7 @@ fn main() -> anyhow::Result<()> { }; client - .scan( - tip, - keychain_spks, - core::iter::empty(), - core::iter::empty(), - stop_gap, - scan_options.batch_size, - ) + .full_scan(tip, keychain_spks, stop_gap, scan_options.batch_size) .context("scanning the blockchain")? } ElectrumCommands::Sync { @@ -279,7 +272,7 @@ fn main() -> anyhow::Result<()> { drop((graph, chain)); let electrum_update = client - .scan_without_keychain(tip, spks, txids, outpoints, scan_options.batch_size) + .sync(tip, spks, txids, outpoints, scan_options.batch_size) .context("scanning the blockchain")?; (electrum_update, BTreeMap::new()) } diff --git a/example-crates/example_esplora/src/main.rs b/example-crates/example_esplora/src/main.rs index cabd8ea82..101fd58ba 100644 --- a/example-crates/example_esplora/src/main.rs +++ b/example-crates/example_esplora/src/main.rs @@ -188,13 +188,7 @@ fn main() -> anyhow::Result<()> { // represents the last active spk derivation indices of keychains // (`keychain_indices_update`). let (graph_update, last_active_indices) = client - .scan_txs_with_keychains( - keychain_spks, - core::iter::empty(), - core::iter::empty(), - *stop_gap, - scan_options.parallel_requests, - ) + .full_scan(keychain_spks, *stop_gap, scan_options.parallel_requests) .context("scanning for transactions")?; let mut graph = graph.lock().expect("mutex must not be poisoned"); @@ -312,7 +306,7 @@ fn main() -> anyhow::Result<()> { } let graph_update = - client.scan_txs(spks, txids, outpoints, scan_options.parallel_requests)?; + client.sync(spks, txids, outpoints, scan_options.parallel_requests)?; graph.lock().unwrap().apply_update(graph_update) } diff --git a/example-crates/wallet_electrum/src/main.rs b/example-crates/wallet_electrum/src/main.rs index 9d4c6c5a4..e5c6b1466 100644 --- a/example-crates/wallet_electrum/src/main.rs +++ b/example-crates/wallet_electrum/src/main.rs @@ -61,7 +61,7 @@ fn main() -> Result<(), anyhow::Error> { relevant_txids, }, keychain_update, - ) = client.scan(prev_tip, keychain_spks, None, None, STOP_GAP, BATCH_SIZE)?; + ) = client.full_scan(prev_tip, keychain_spks, STOP_GAP, BATCH_SIZE)?; println!(); diff --git a/example-crates/wallet_esplora_async/src/main.rs b/example-crates/wallet_esplora_async/src/main.rs index fb8f7b510..755b39007 100644 --- a/example-crates/wallet_esplora_async/src/main.rs +++ b/example-crates/wallet_esplora_async/src/main.rs @@ -54,7 +54,7 @@ async fn main() -> Result<(), anyhow::Error> { }) .collect(); let (update_graph, last_active_indices) = client - .scan_txs_with_keychains(keychain_spks, None, None, STOP_GAP, PARALLEL_REQUESTS) + .full_scan(keychain_spks, STOP_GAP, PARALLEL_REQUESTS) .await?; let missing_heights = update_graph.missing_heights(wallet.local_chain()); let chain_update = client.update_local_chain(prev_tip, missing_heights).await?; diff --git a/example-crates/wallet_esplora_blocking/src/main.rs b/example-crates/wallet_esplora_blocking/src/main.rs index 09e7c3ad4..d0f35bea8 100644 --- a/example-crates/wallet_esplora_blocking/src/main.rs +++ b/example-crates/wallet_esplora_blocking/src/main.rs @@ -54,7 +54,7 @@ fn main() -> Result<(), anyhow::Error> { .collect(); let (update_graph, last_active_indices) = - client.scan_txs_with_keychains(keychain_spks, None, None, STOP_GAP, PARALLEL_REQUESTS)?; + client.full_scan(keychain_spks, STOP_GAP, PARALLEL_REQUESTS)?; let missing_heights = update_graph.missing_heights(wallet.local_chain()); let chain_update = client.update_local_chain(prev_tip, missing_heights)?; let update = Update {