diff --git a/crates/chain/src/local_chain.rs b/crates/chain/src/local_chain.rs index 9fcd7a706..7aa263f41 100644 --- a/crates/chain/src/local_chain.rs +++ b/crates/chain/src/local_chain.rs @@ -151,8 +151,7 @@ impl CheckPoint { /// Iterate checkpoints over a height range. /// - /// Note that we always iterate checkpoints in reverse height order (iteration starts at tip - /// height). + /// Note that we always iterate checkpoints in reverse height order (iteration starts with highest). pub fn range(&self, range: R) -> impl Iterator where R: RangeBounds, diff --git a/crates/chain/src/spk_client.rs b/crates/chain/src/spk_client.rs index 3457dfef7..a916e4b30 100644 --- a/crates/chain/src/spk_client.rs +++ b/crates/chain/src/spk_client.rs @@ -3,176 +3,153 @@ use crate::{ collections::BTreeMap, local_chain::CheckPoint, ConfirmationBlockTime, Indexed, TxGraph, }; -use alloc::boxed::Box; +use alloc::{borrow::ToOwned, boxed::Box, collections::VecDeque}; use bitcoin::{OutPoint, Script, ScriptBuf, Txid}; -use core::marker::PhantomData; +use core::fmt::Debug; /// Data required to perform a spk-based blockchain client sync. /// /// A client sync fetches relevant chain data for a known list of scripts, transaction ids and /// outpoints. The sync process also updates the chain from the given [`CheckPoint`]. -pub struct SyncRequest { +pub struct SyncRequest { /// A checkpoint for the current chain [`LocalChain::tip`]. /// The sync process will return a new chain update that extends this tip. /// /// [`LocalChain::tip`]: crate::local_chain::LocalChain::tip - pub chain_tip: CheckPoint, + chain_tip: CheckPoint, /// Transactions that spend from or to these indexed script pubkeys. - pub spks: Box + Send>, + spks: VecDeque<(I, ScriptBuf)>, /// Transactions with these txids. - pub txids: Box + Send>, + txids: VecDeque, /// Transactions with these outpoints or spent from these outpoints. - pub outpoints: Box + Send>, + outpoints: VecDeque, + inspect: InspectFn, + consumed: usize, } -impl SyncRequest { +type InspectFn = Box, usize, usize) + Send>; + +impl SyncRequest { /// Construct a new [`SyncRequest`] from a given `cp` tip. - pub fn from_chain_tip(cp: CheckPoint) -> Self { + pub fn new(cp: CheckPoint) -> Self { Self { chain_tip: cp, - spks: Box::new(core::iter::empty()), - txids: Box::new(core::iter::empty()), - outpoints: Box::new(core::iter::empty()), + spks: Default::default(), + txids: Default::default(), + outpoints: Default::default(), + consumed: Default::default(), + inspect: Box::new(|_, _, _| {}), } } + /// Get the chain tip to update the chain against + pub fn chain_tip(&self) -> CheckPoint { + self.chain_tip.clone() + } + /// Set the [`Script`]s that will be synced against. /// /// This consumes the [`SyncRequest`] and returns the updated one. - #[must_use] - pub fn set_spks( + pub fn add_spks( mut self, - spks: impl IntoIterator + Send + 'static>, + spks: impl IntoIterator)>, ) -> Self { - self.spks = Box::new(spks.into_iter()); + self.spks + .extend(spks.into_iter().map(|(i, spk)| (i, spk.to_owned()))); self } - /// Set the [`Txid`]s that will be synced against. - /// - /// This consumes the [`SyncRequest`] and returns the updated one. - #[must_use] - pub fn set_txids( - mut self, - txids: impl IntoIterator + Send + 'static>, - ) -> Self { - self.txids = Box::new(txids.into_iter()); + /// Add transactions to be synced. The sync backend will fetch the current status of the + /// corresponding transactions. + pub fn add_txids(mut self, txids: impl IntoIterator) -> Self { + self.txids.extend(txids); self } - /// Set the [`OutPoint`]s that will be synced against. - /// - /// This consumes the [`SyncRequest`] and returns the updated one. - #[must_use] - pub fn set_outpoints( - mut self, - outpoints: impl IntoIterator< - IntoIter = impl ExactSizeIterator + Send + 'static, - >, - ) -> Self { - self.outpoints = Box::new(outpoints.into_iter()); + /// Add the outpoints `OutPoints` to be synced. The sync backend will fetch any transactions + /// that spend from the outpoint. + pub fn add_outpoints(mut self, outpoints: impl IntoIterator) -> Self { + self.outpoints.extend(outpoints); self } - /// Chain on additional [`Script`]s that will be synced against. - /// - /// This consumes the [`SyncRequest`] and returns the updated one. - #[must_use] - pub fn chain_spks( - mut self, - spks: impl IntoIterator< - IntoIter = impl ExactSizeIterator + Send + 'static, - Item = ScriptBuf, - >, - ) -> Self { - self.spks = Box::new(ExactSizeChain::new(self.spks, spks.into_iter())); + /// Sets the inspect callback for the `SyncRequest`. This will be called for any item pulled + /// from the sync. + pub fn inspect(mut self, inspect: F) -> Self + where + for<'a> F: FnMut(SyncItem<'a, I>, usize, usize) + 'static + Send, + { + self.inspect = Box::new(inspect); self } - /// Chain on additional [`Txid`]s that will be synced against. - /// - /// This consumes the [`SyncRequest`] and returns the updated one. - #[must_use] - pub fn chain_txids( - mut self, - txids: impl IntoIterator< - IntoIter = impl ExactSizeIterator + Send + 'static, - Item = Txid, - >, - ) -> Self { - self.txids = Box::new(ExactSizeChain::new(self.txids, txids.into_iter())); - self + /// How many items (spks, txids, and outpoints) are there remaining to be processed + pub fn remaining(&self) -> usize { + self.spks.len() + self.txids.len() + self.outpoints.len() } - /// Chain on additional [`OutPoint`]s that will be synced against. + /// Get the next script pubkey to be processed. /// - /// This consumes the [`SyncRequest`] and returns the updated one. - #[must_use] - pub fn chain_outpoints( - mut self, - outpoints: impl IntoIterator< - IntoIter = impl ExactSizeIterator + Send + 'static, - Item = OutPoint, - >, - ) -> Self { - self.outpoints = Box::new(ExactSizeChain::new(self.outpoints, outpoints.into_iter())); - self + /// The sync backend should find all transactions spending to or from this script pubkey + pub fn next_spk(&mut self) -> Option { + let (index, spk) = self.spks.pop_front()?; + self._call_inspect(SyncItem::Spk(index, spk.as_script())); + Some(spk) } - /// Add a closure that will be called for [`Script`]s previously added to this request. - /// - /// This consumes the [`SyncRequest`] and returns the updated one. - #[must_use] - pub fn inspect_spks( - mut self, - mut inspect: impl FnMut(&Script) + Send + Sync + 'static, - ) -> Self { - self.spks = Box::new(self.spks.inspect(move |spk| inspect(spk))); - self + /// Iterate over the script pubkeys to be synced. + pub fn iter_spks(&mut self) -> impl Iterator + '_ { + core::iter::from_fn(|| self.next_spk()) } - /// Add a closure that will be called for [`Txid`]s previously added to this request. - /// - /// This consumes the [`SyncRequest`] and returns the updated one. - #[must_use] - pub fn inspect_txids(mut self, mut inspect: impl FnMut(&Txid) + Send + Sync + 'static) -> Self { - self.txids = Box::new(self.txids.inspect(move |txid| inspect(txid))); - self + /// Iterate over the transactions to be synced. + pub fn iter_txids(&mut self) -> impl Iterator + '_ { + core::iter::from_fn(|| self.next_txid()) } - /// Add a closure that will be called for [`OutPoint`]s previously added to this request. + /// Iterate over the outpoints to be synced. + pub fn iter_outpoints(&mut self) -> impl Iterator + '_ { + core::iter::from_fn(|| self.next_outpoint()) + } + + /// Get the next txid to be processed. /// - /// This consumes the [`SyncRequest`] and returns the updated one. - #[must_use] - pub fn inspect_outpoints( - mut self, - mut inspect: impl FnMut(&OutPoint) + Send + Sync + 'static, - ) -> Self { - self.outpoints = Box::new(self.outpoints.inspect(move |op| inspect(op))); - self + /// The sync backend should get the status of this transaction. + pub fn next_txid(&mut self) -> Option { + let txid = self.txids.pop_front()?; + self._call_inspect(SyncItem::Txid(txid)); + Some(txid) } - /// Populate the request with revealed script pubkeys from `index` with the given `spk_range`. + /// Get the next outpoint to be processed. /// - /// This consumes the [`SyncRequest`] and returns the updated one. - #[cfg(feature = "miniscript")] - #[must_use] - pub fn populate_with_revealed_spks( - self, - index: &crate::indexer::keychain_txout::KeychainTxOutIndex, - spk_range: impl core::ops::RangeBounds, - ) -> Self { - use alloc::borrow::ToOwned; - use alloc::vec::Vec; - self.chain_spks( - index - .revealed_spks(spk_range) - .map(|(_, spk)| spk.to_owned()) - .collect::>(), - ) + /// The sync backend should get the status of any transactions spending from this outpoint. + pub fn next_outpoint(&mut self) -> Option { + let op = self.outpoints.pop_front()?; + self._call_inspect(SyncItem::OutPoint(op)); + Some(op) + } + + fn _call_inspect(&mut self, item: SyncItem) { + let remaining_items = self.remaining(); + (self.inspect)(item, self.consumed, remaining_items); + self.consumed += 1; } } +#[derive(Copy, Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)] +/// An item reported to [`inspect`] +/// +/// [`inspect`]: SyncRequest::inspect +pub enum SyncItem<'a, I> { + /// Script pubkey sycn item + Spk(I, &'a Script), + /// Transaction id sync item + Txid(Txid), + /// Transaction outpoint sync item + OutPoint(OutPoint), +} + /// Data returned from a spk-based blockchain client sync. /// /// See also [`SyncRequest`]. @@ -227,30 +204,16 @@ impl FullScanRequest { { let mut req = Self::from_chain_tip(chain_tip); for (keychain, spks) in index.all_unbounded_spk_iters() { - req = req.set_spks_for_keychain(keychain, spks); + req = req.add_spks_for_keychain(keychain, spks); } req } - /// Set the [`Script`]s for a given `keychain`. - /// - /// This consumes the [`FullScanRequest`] and returns the updated one. - #[must_use] - pub fn set_spks_for_keychain( - mut self, - keychain: K, - spks: impl IntoIterator> + Send + 'static>, - ) -> Self { - self.spks_by_keychain - .insert(keychain, Box::new(spks.into_iter())); - self - } - /// Chain on additional [`Script`]s that will be synced against. /// /// This consumes the [`FullScanRequest`] and returns the updated one. #[must_use] - pub fn chain_spks_for_keychain( + pub fn add_spks_for_keychain( mut self, keychain: K, spks: impl IntoIterator> + Send + 'static>, @@ -274,7 +237,7 @@ impl FullScanRequest { /// /// This consumes the [`SyncRequest`] and returns the updated one. #[must_use] - pub fn inspect_spks_for_all_keychains( + pub fn inspect_spks( mut self, inspect: impl FnMut(K, u32, &Script) + Send + Sync + Clone + 'static, ) -> Self @@ -290,28 +253,6 @@ impl FullScanRequest { } self } - - /// Add a closure that will be called for every [`Script`] previously added to a given - /// `keychain` in this request. - /// - /// This consumes the [`SyncRequest`] and returns the updated one. - #[must_use] - pub fn inspect_spks_for_keychain( - mut self, - keychain: K, - mut inspect: impl FnMut(u32, &Script) + Send + Sync + 'static, - ) -> Self - where - K: Send + 'static, - { - if let Some(spks) = self.spks_by_keychain.remove(&keychain) { - self.spks_by_keychain.insert( - keychain, - Box::new(spks.inspect(move |(i, spk)| inspect(*i, spk))), - ); - } - self - } } /// Data returned from a spk-based blockchain client full scan. @@ -325,64 +266,3 @@ pub struct FullScanResult { /// Last active indices for the corresponding keychains (`K`). pub last_active_indices: BTreeMap, } - -/// A version of [`core::iter::Chain`] which can combine two [`ExactSizeIterator`]s to form a new -/// [`ExactSizeIterator`]. -/// -/// The danger of this is explained in [the `ExactSizeIterator` docs] -/// (https://doc.rust-lang.org/core/iter/trait.ExactSizeIterator.html#when-shouldnt-an-adapter-be-exactsizeiterator). -/// This does not apply here since it would be impossible to scan an item count that overflows -/// `usize` anyway. -struct ExactSizeChain { - a: Option, - b: Option, - i: PhantomData, -} - -impl ExactSizeChain { - fn new(a: A, b: B) -> Self { - ExactSizeChain { - a: Some(a), - b: Some(b), - i: PhantomData, - } - } -} - -impl Iterator for ExactSizeChain -where - A: Iterator, - B: Iterator, -{ - type Item = I; - - fn next(&mut self) -> Option { - if let Some(a) = &mut self.a { - let item = a.next(); - if item.is_some() { - return item; - } - self.a = None; - } - if let Some(b) = &mut self.b { - let item = b.next(); - if item.is_some() { - return item; - } - self.b = None; - } - None - } -} - -impl ExactSizeIterator for ExactSizeChain -where - A: ExactSizeIterator, - B: ExactSizeIterator, -{ - fn len(&self) -> usize { - let a_len = self.a.as_ref().map(|a| a.len()).unwrap_or(0); - let b_len = self.b.as_ref().map(|a| a.len()).unwrap_or(0); - a_len + b_len - } -} diff --git a/crates/esplora/src/async_ext.rs b/crates/esplora/src/async_ext.rs index 70895a43a..2f3efb198 100644 --- a/crates/esplora/src/async_ext.rs +++ b/crates/esplora/src/async_ext.rs @@ -64,11 +64,13 @@ pub trait EsploraAsyncExt { /// may include scripts that have been used, use [`full_scan`] with the keychain. /// /// [`full_scan`]: EsploraAsyncExt::full_scan - async fn sync( + async fn sync( &self, - request: SyncRequest, + request: SyncRequest, parallel_requests: usize, - ) -> Result; + ) -> Result + where + SyncRequest: Send; } #[cfg_attr(target_arch = "wasm32", async_trait(?Send))] @@ -102,24 +104,87 @@ impl EsploraAsyncExt for esplora_client::AsyncClient { }) } - async fn sync( + async fn sync( &self, - request: SyncRequest, + mut request: SyncRequest, parallel_requests: usize, - ) -> Result { + ) -> Result + where + SyncRequest: Send, + { let latest_blocks = fetch_latest_blocks(self).await?; - let graph_update = sync_for_index_and_graph( - self, - request.spks, - request.txids, - request.outpoints, - parallel_requests, - ) - .await?; + let graph_update = { + let (mut tx_graph, _) = full_scan_for_index_and_graph( + self, + [( + (), + request + .iter_spks() + .enumerate() + .map(|(i, spk)| (i as u32, spk)), + )] + .into(), + usize::MAX, + parallel_requests, + ) + .await?; + + let mut txids = request.iter_txids(); + loop { + let handles = txids + .by_ref() + .take(parallel_requests) + .filter(|&txid| tx_graph.get_tx(txid).is_none()) + .map(|txid| { + let client = self.clone(); + async move { client.get_tx_status(&txid).await.map(|s| (txid, s)) } + }) + .collect::>(); + + if handles.is_empty() { + break; + } + + for (txid, status) in handles.try_collect::>().await? { + if let Some(anchor) = anchor_from_status(&status) { + let _ = tx_graph.insert_anchor(txid, anchor); + } + } + } + + drop(txids); + + for op in request.iter_outpoints() { + if tx_graph.get_tx(op.txid).is_none() { + if let Some(tx) = self.get_tx(&op.txid).await? { + let _ = tx_graph.insert_tx(tx); + } + let status = self.get_tx_status(&op.txid).await?; + if let Some(anchor) = anchor_from_status(&status) { + let _ = tx_graph.insert_anchor(op.txid, anchor); + } + } + + if let Some(op_status) = self.get_output_status(&op.txid, op.vout as _).await? { + if let Some(txid) = op_status.txid { + if tx_graph.get_tx(txid).is_none() { + if let Some(tx) = self.get_tx(&txid).await? { + let _ = tx_graph.insert_tx(tx); + } + let status = self.get_tx_status(&txid).await?; + if let Some(anchor) = anchor_from_status(&status) { + let _ = tx_graph.insert_anchor(txid, anchor); + } + } + } + } + } + tx_graph + }; let chain_update = chain_update( self, &latest_blocks, - &request.chain_tip, + &request.chain_tip(), graph_update.all_anchors(), ) .await?; @@ -327,81 +392,6 @@ async fn full_scan_for_index_and_graph( Ok((graph, last_active_indexes)) } -async fn sync_for_index_and_graph( - client: &esplora_client::AsyncClient, - misc_spks: impl IntoIterator + Send> + Send, - txids: impl IntoIterator + Send> + Send, - outpoints: impl IntoIterator + Send> + Send, - parallel_requests: usize, -) -> Result, Error> { - let mut graph = full_scan_for_index_and_graph( - client, - [( - (), - 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 - .by_ref() - .take(parallel_requests) - .filter(|&txid| graph.get_tx(txid).is_none()) - .map(|txid| { - let client = client.clone(); - async move { client.get_tx_status(&txid).await.map(|s| (txid, s)) } - }) - .collect::>(); - - if handles.is_empty() { - break; - } - - for (txid, status) in handles.try_collect::>().await? { - if let Some(anchor) = anchor_from_status(&status) { - let _ = graph.insert_anchor(txid, anchor); - } - } - } - - for op in outpoints.into_iter() { - if graph.get_tx(op.txid).is_none() { - if let Some(tx) = client.get_tx(&op.txid).await? { - let _ = graph.insert_tx(tx); - } - let status = client.get_tx_status(&op.txid).await?; - if let Some(anchor) = anchor_from_status(&status) { - let _ = graph.insert_anchor(op.txid, anchor); - } - } - - if let Some(op_status) = client.get_output_status(&op.txid, op.vout as _).await? { - if let Some(txid) = op_status.txid { - if graph.get_tx(txid).is_none() { - if let Some(tx) = client.get_tx(&txid).await? { - let _ = graph.insert_tx(tx); - } - let status = client.get_tx_status(&txid).await?; - if let Some(anchor) = anchor_from_status(&status) { - let _ = graph.insert_anchor(txid, anchor); - } - } - } - } - } - - Ok(graph) -} - #[cfg(test)] mod test { use std::{collections::BTreeSet, time::Duration}; diff --git a/crates/esplora/src/blocking_ext.rs b/crates/esplora/src/blocking_ext.rs index dc95a350b..55b8e9624 100644 --- a/crates/esplora/src/blocking_ext.rs +++ b/crates/esplora/src/blocking_ext.rs @@ -61,7 +61,11 @@ pub trait EsploraExt { /// may include scripts that have been used, use [`full_scan`] with the keychain. /// /// [`full_scan`]: EsploraExt::full_scan - fn sync(&self, request: SyncRequest, parallel_requests: usize) -> Result; + fn sync( + &self, + request: SyncRequest, + parallel_requests: usize, + ) -> Result; } impl EsploraExt for esplora_client::BlockingClient { @@ -91,19 +95,95 @@ impl EsploraExt for esplora_client::BlockingClient { }) } - fn sync(&self, request: SyncRequest, parallel_requests: usize) -> Result { + fn sync( + &self, + mut request: SyncRequest, + parallel_requests: usize, + ) -> Result { let latest_blocks = fetch_latest_blocks(self)?; - let graph_update = sync_for_index_and_graph_blocking( - self, - request.spks, - request.txids, - request.outpoints, - parallel_requests, - )?; + let graph_update = { + let (mut tx_graph, _) = full_scan_for_index_and_graph_blocking( + self, + { + let mut keychains = BTreeMap::new(); + keychains.insert( + (), + request + .iter_spks() + .enumerate() + .map(|(i, spk)| (i as u32, spk)), + ); + keychains + }, + usize::MAX, + parallel_requests, + )?; + + let mut txids = request.iter_txids(); + loop { + let handles = txids + .by_ref() + .take(parallel_requests) + .filter(|&txid| tx_graph.get_tx(txid).is_none()) + .map(|txid| { + std::thread::spawn({ + let client = self.clone(); + move || { + client + .get_tx_status(&txid) + .map_err(Box::new) + .map(|s| (txid, s)) + } + }) + }) + .collect::>>>(); + + if handles.is_empty() { + break; + } + + for handle in handles { + let (txid, status) = handle.join().expect("thread must not panic")?; + if let Some(anchor) = anchor_from_status(&status) { + let _ = tx_graph.insert_anchor(txid, anchor); + } + } + } + + drop(txids); + + for op in request.iter_outpoints() { + if tx_graph.get_tx(op.txid).is_none() { + if let Some(tx) = self.get_tx(&op.txid)? { + let _ = tx_graph.insert_tx(tx); + } + let status = self.get_tx_status(&op.txid)?; + if let Some(anchor) = anchor_from_status(&status) { + let _ = tx_graph.insert_anchor(op.txid, anchor); + } + } + + if let Some(op_status) = self.get_output_status(&op.txid, op.vout as _)? { + if let Some(txid) = op_status.txid { + if tx_graph.get_tx(txid).is_none() { + if let Some(tx) = self.get_tx(&txid)? { + let _ = tx_graph.insert_tx(tx); + } + let status = self.get_tx_status(&txid)?; + if let Some(anchor) = anchor_from_status(&status) { + let _ = tx_graph.insert_anchor(txid, anchor); + } + } + } + } + } + + tx_graph + }; let chain_update = chain_update( self, &latest_blocks, - &request.chain_tip, + &request.chain_tip(), graph_update.all_anchors(), )?; Ok(SyncResult { @@ -309,90 +389,6 @@ fn full_scan_for_index_and_graph_blocking( Ok((tx_graph, last_active_indices)) } -fn sync_for_index_and_graph_blocking( - client: &esplora_client::BlockingClient, - misc_spks: impl IntoIterator, - txids: impl IntoIterator, - outpoints: impl IntoIterator, - parallel_requests: usize, -) -> Result, Error> { - let (mut tx_graph, _) = full_scan_for_index_and_graph_blocking( - client, - { - let mut keychains = BTreeMap::new(); - keychains.insert( - (), - misc_spks - .into_iter() - .enumerate() - .map(|(i, spk)| (i as u32, spk)), - ); - keychains - }, - usize::MAX, - parallel_requests, - )?; - - let mut txids = txids.into_iter(); - loop { - let handles = txids - .by_ref() - .take(parallel_requests) - .filter(|&txid| tx_graph.get_tx(txid).is_none()) - .map(|txid| { - std::thread::spawn({ - let client = client.clone(); - move || { - client - .get_tx_status(&txid) - .map_err(Box::new) - .map(|s| (txid, s)) - } - }) - }) - .collect::>>>(); - - if handles.is_empty() { - break; - } - - for handle in handles { - let (txid, status) = handle.join().expect("thread must not panic")?; - if let Some(anchor) = anchor_from_status(&status) { - let _ = tx_graph.insert_anchor(txid, anchor); - } - } - } - - for op in outpoints { - if tx_graph.get_tx(op.txid).is_none() { - if let Some(tx) = client.get_tx(&op.txid)? { - let _ = tx_graph.insert_tx(tx); - } - let status = client.get_tx_status(&op.txid)?; - if let Some(anchor) = anchor_from_status(&status) { - let _ = tx_graph.insert_anchor(op.txid, anchor); - } - } - - if let Some(op_status) = client.get_output_status(&op.txid, op.vout as _)? { - if let Some(txid) = op_status.txid { - if tx_graph.get_tx(txid).is_none() { - if let Some(tx) = client.get_tx(&txid)? { - let _ = tx_graph.insert_tx(tx); - } - let status = client.get_tx_status(&txid)?; - if let Some(anchor) = anchor_from_status(&status) { - let _ = tx_graph.insert_anchor(txid, anchor); - } - } - } - } - } - - Ok(tx_graph) -} - #[cfg(test)] mod test { use crate::blocking_ext::{chain_update, fetch_latest_blocks}; diff --git a/crates/esplora/tests/async_ext.rs b/crates/esplora/tests/async_ext.rs index 2258c9d60..8033a8821 100644 --- a/crates/esplora/tests/async_ext.rs +++ b/crates/esplora/tests/async_ext.rs @@ -21,8 +21,8 @@ pub async fn test_update_tx_graph_without_keychain() -> anyhow::Result<()> { Address::from_str("bcrt1qfjg5lv3dvc9az8patec8fjddrs4aqtauadnagr")?.assume_checked(); let misc_spks = [ - receive_address0.script_pubkey(), - receive_address1.script_pubkey(), + (0, receive_address0.script_pubkey()), + (1, receive_address1.script_pubkey()), ]; let _block_hashes = env.mine_blocks(101, None)?; @@ -55,7 +55,7 @@ pub async fn test_update_tx_graph_without_keychain() -> anyhow::Result<()> { let cp_tip = env.make_checkpoint_tip(); let sync_update = { - let request = SyncRequest::from_chain_tip(cp_tip.clone()).set_spks(misc_spks); + let request = SyncRequest::new(cp_tip.clone()).add_spks(misc_spks); client.sync(request, 1).await? }; diff --git a/crates/esplora/tests/blocking_ext.rs b/crates/esplora/tests/blocking_ext.rs index 2e363f4e6..06f2fa879 100644 --- a/crates/esplora/tests/blocking_ext.rs +++ b/crates/esplora/tests/blocking_ext.rs @@ -55,7 +55,7 @@ pub fn test_update_tx_graph_without_keychain() -> anyhow::Result<()> { let cp_tip = env.make_checkpoint_tip(); let sync_update = { - let request = SyncRequest::from_chain_tip(cp_tip.clone()).set_spks(misc_spks); + let request = SyncRequest::new(cp_tip.clone()).set_spks(misc_spks); client.sync(request, 1)? }; diff --git a/crates/wallet/src/wallet/mod.rs b/crates/wallet/src/wallet/mod.rs index df22c8a64..8aae17167 100644 --- a/crates/wallet/src/wallet/mod.rs +++ b/crates/wallet/src/wallet/mod.rs @@ -2320,7 +2320,7 @@ impl Wallet { /// [`SyncRequest`] collects all revealed script pubkeys from the wallet keychain needed to /// start a blockchain sync with a spk based blockchain client. pub fn start_sync_with_revealed_spks(&self) -> SyncRequest { - SyncRequest::from_chain_tip(self.chain.tip()) + SyncRequest::new(self.chain.tip()) .populate_with_revealed_spks(&self.indexed_graph.index, ..) } diff --git a/example-crates/example_electrum/src/main.rs b/example-crates/example_electrum/src/main.rs index 083a4fe46..3d25ae924 100644 --- a/example-crates/example_electrum/src/main.rs +++ b/example-crates/example_electrum/src/main.rs @@ -221,7 +221,7 @@ fn main() -> anyhow::Result<()> { } let chain_tip = chain.tip(); - let mut request = SyncRequest::from_chain_tip(chain_tip.clone()); + let mut request = SyncRequest::new(chain_tip.clone()); if all_spks { let all_spks = graph diff --git a/example-crates/example_esplora/src/main.rs b/example-crates/example_esplora/src/main.rs index af6422689..edc1cd305 100644 --- a/example-crates/example_esplora/src/main.rs +++ b/example-crates/example_esplora/src/main.rs @@ -233,7 +233,7 @@ fn main() -> anyhow::Result<()> { let local_tip = chain.lock().expect("mutex must not be poisoned").tip(); // Spks, outpoints and txids we want updates on will be accumulated here. - let mut request = SyncRequest::from_chain_tip(local_tip.clone()); + let mut request = SyncRequest::new(local_tip.clone()); // Get a short lock on the structures to get spks, utxos, and txs that we are interested // in.