diff --git a/crates/bdk/src/wallet/mod.rs b/crates/bdk/src/wallet/mod.rs index 846878823c..f11abb30bc 100644 --- a/crates/bdk/src/wallet/mod.rs +++ b/crates/bdk/src/wallet/mod.rs @@ -107,7 +107,7 @@ pub struct Update { /// Update for the wallet's internal [`LocalChain`]. /// /// [`LocalChain`]: local_chain::LocalChain - pub chain: Option, + pub chain: Option, } /// The changes made to a wallet by applying an [`Update`]. diff --git a/crates/bitcoind_rpc/tests/test_emitter.rs b/crates/bitcoind_rpc/tests/test_emitter.rs index f2e2a5d59c..c517740f51 100644 --- a/crates/bitcoind_rpc/tests/test_emitter.rs +++ b/crates/bitcoind_rpc/tests/test_emitter.rs @@ -4,7 +4,7 @@ use bdk_bitcoind_rpc::Emitter; use bdk_chain::{ bitcoin::{Address, Amount, Txid}, keychain::Balance, - local_chain::{self, CheckPoint, LocalChain}, + local_chain::{CheckPoint, LocalChain}, Append, BlockId, IndexedTxGraph, SpkTxOutIndex, }; use bdk_testenv::TestEnv; @@ -47,10 +47,7 @@ pub fn test_sync_local_chain() -> anyhow::Result<()> { ); assert_eq!( - local_chain.apply_update(local_chain::Update { - tip: emission.checkpoint, - introduce_older_blocks: false, - })?, + local_chain.apply_update(emission.checkpoint,)?, BTreeMap::from([(height, Some(hash))]), "chain update changeset is unexpected", ); @@ -95,10 +92,7 @@ pub fn test_sync_local_chain() -> anyhow::Result<()> { ); assert_eq!( - local_chain.apply_update(local_chain::Update { - tip: emission.checkpoint, - introduce_older_blocks: false, - })?, + local_chain.apply_update(emission.checkpoint,)?, if exp_height == exp_hashes.len() - reorged_blocks.len() { core::iter::once((height, Some(hash))) .chain((height + 1..exp_hashes.len() as u32).map(|h| (h, None))) @@ -168,10 +162,7 @@ fn test_into_tx_graph() -> anyhow::Result<()> { while let Some(emission) = emitter.next_block()? { let height = emission.block_height(); - let _ = chain.apply_update(local_chain::Update { - tip: emission.checkpoint, - introduce_older_blocks: false, - })?; + let _ = chain.apply_update(emission.checkpoint)?; let indexed_additions = indexed_tx_graph.apply_block_relevant(&emission.block, height); assert!(indexed_additions.is_empty()); } @@ -232,10 +223,7 @@ 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(local_chain::Update { - tip: emission.checkpoint, - introduce_older_blocks: false, - })?; + let _ = chain.apply_update(emission.checkpoint)?; let indexed_additions = indexed_tx_graph.apply_block_relevant(&emission.block, height); assert!(indexed_additions.graph.txs.is_empty()); assert!(indexed_additions.graph.txouts.is_empty()); @@ -294,8 +282,7 @@ fn process_block( block: Block, block_height: u32, ) -> anyhow::Result<()> { - recv_chain - .apply_update(CheckPoint::from_header(&block.header, block_height).into_update(false))?; + recv_chain.apply_update(CheckPoint::from_header(&block.header, block_height))?; let _ = recv_graph.apply_block(block, block_height); Ok(()) } diff --git a/crates/chain/src/local_chain.rs b/crates/chain/src/local_chain.rs index 6fa85d422e..34724ed971 100644 --- a/crates/chain/src/local_chain.rs +++ b/crates/chain/src/local_chain.rs @@ -96,16 +96,6 @@ impl CheckPoint { .expect("must construct checkpoint") } - /// Convenience method to convert the [`CheckPoint`] into an [`Update`]. - /// - /// For more information, refer to [`Update`]. - pub fn into_update(self, introduce_older_blocks: bool) -> Update { - Update { - tip: self, - introduce_older_blocks, - } - } - /// Puts another checkpoint onto the linked list representing the blockchain. /// /// Returns an `Err(self)` if the block you are pushing on is not at a greater height that the one you @@ -251,31 +241,6 @@ impl IntoIterator for CheckPoint { } } -/// Used to update [`LocalChain`]. -/// -/// This is used as input for [`LocalChain::apply_update`]. It contains the update's chain `tip` and -/// a flag `introduce_older_blocks` which signals whether this update intends to introduce missing -/// blocks to the original chain. -/// -/// Block-by-block syncing mechanisms would typically create updates that builds upon the previous -/// tip. In this case, `introduce_older_blocks` would be `false`. -/// -/// Script-pubkey based syncing mechanisms may not introduce transactions in a chronological order -/// so some updates require introducing older blocks (to anchor older transactions). For -/// script-pubkey based syncing, `introduce_older_blocks` would typically be `true`. -#[derive(Debug, Clone, PartialEq)] -pub struct Update { - /// The update chain's new tip. - pub tip: CheckPoint, - - /// Whether the update allows for introducing older blocks. - /// - /// Refer to [struct-level documentation] for more. - /// - /// [struct-level documentation]: Update - pub introduce_older_blocks: bool, -} - /// This is a local implementation of [`ChainOracle`]. #[derive(Debug, Clone, PartialEq)] pub struct LocalChain { @@ -401,12 +366,8 @@ impl LocalChain { /// Refer to [`Update`] for more about the update struct. /// /// [module-level documentation]: crate::local_chain - pub fn apply_update(&mut self, update: Update) -> Result { - let changeset = merge_chains( - self.tip.clone(), - update.tip.clone(), - update.introduce_older_blocks, - )?; + pub fn apply_update(&mut self, update: CheckPoint) -> Result { + let changeset = merge_chains(self.tip.clone(), update.clone())?; // `._check_index_is_consistent_with_tip` and `._check_changeset_is_applied` is called in // `.apply_changeset` self.apply_changeset(&changeset) @@ -464,11 +425,8 @@ impl LocalChain { conn => Some(conn), }; - let update = Update { - tip: CheckPoint::from_block_ids([conn, prev, Some(this)].into_iter().flatten()) - .expect("block ids must be in order"), - introduce_older_blocks: false, - }; + let update = CheckPoint::from_block_ids([conn, prev, Some(this)].into_iter().flatten()) + .expect("block ids must be in order"); self.apply_update(update) .map_err(ApplyHeaderError::CannotConnect) @@ -769,7 +727,6 @@ impl std::error::Error for ApplyHeaderError {} fn merge_chains( original_tip: CheckPoint, update_tip: CheckPoint, - introduce_older_blocks: bool, ) -> Result { let mut changeset = ChangeSet::default(); let mut orig = original_tip.into_iter(); @@ -829,11 +786,9 @@ fn merge_chains( } point_of_agreement_found = true; prev_orig_was_invalidated = false; - // OPTIMIZATION 1 -- If we know that older blocks cannot be introduced without - // invalidation, we can break after finding the point of agreement. // OPTIMIZATION 2 -- if we have the same underlying pointer at this point, we // can guarantee that no older blocks are introduced. - if !introduce_older_blocks || Arc::as_ptr(&o.0) == Arc::as_ptr(&u.0) { + if Arc::as_ptr(&o.0) == Arc::as_ptr(&u.0) { return Ok(changeset); } } else { diff --git a/crates/chain/tests/common/mod.rs b/crates/chain/tests/common/mod.rs index 6116484ce9..586e640432 100644 --- a/crates/chain/tests/common/mod.rs +++ b/crates/chain/tests/common/mod.rs @@ -32,12 +32,9 @@ macro_rules! local_chain { macro_rules! chain_update { [ $(($height:expr, $hash:expr)), * ] => {{ #[allow(unused_mut)] - bdk_chain::local_chain::Update { - tip: bdk_chain::local_chain::LocalChain::from_blocks([$(($height, $hash).into()),*].into_iter().collect()) - .expect("chain must have genesis block") - .tip(), - introduce_older_blocks: true, - } + bdk_chain::local_chain::LocalChain::from_blocks([$(($height, $hash).into()),*].into_iter().collect()) + .expect("chain must have genesis block") + .tip() }}; } diff --git a/crates/chain/tests/test_local_chain.rs b/crates/chain/tests/test_local_chain.rs index c331008db8..cff4a8e73c 100644 --- a/crates/chain/tests/test_local_chain.rs +++ b/crates/chain/tests/test_local_chain.rs @@ -3,7 +3,7 @@ use std::ops::{Bound, RangeBounds}; use bdk_chain::{ local_chain::{ AlterCheckPointError, ApplyHeaderError, CannotConnectError, ChangeSet, CheckPoint, - LocalChain, MissingGenesisError, Update, + LocalChain, MissingGenesisError, }, BlockId, }; @@ -17,7 +17,7 @@ mod common; struct TestLocalChain<'a> { name: &'static str, chain: LocalChain, - update: Update, + update: CheckPoint, exp: ExpectedResult<'a>, } diff --git a/crates/electrum/src/electrum_ext.rs b/crates/electrum/src/electrum_ext.rs index 3ff467fcee..5a6c5d1163 100644 --- a/crates/electrum/src/electrum_ext.rs +++ b/crates/electrum/src/electrum_ext.rs @@ -1,6 +1,6 @@ use bdk_chain::{ bitcoin::{OutPoint, ScriptBuf, Transaction, Txid}, - local_chain::{self, CheckPoint}, + local_chain::CheckPoint, tx_graph::{self, TxGraph}, Anchor, BlockId, ConfirmationHeightAnchor, ConfirmationTimeHeightAnchor, }; @@ -124,7 +124,7 @@ impl RelevantTxids { #[derive(Debug)] pub struct ElectrumUpdate { /// Chain update - pub chain_update: local_chain::Update, + pub chain_update: CheckPoint, /// Transaction updates from electrum pub relevant_txids: RelevantTxids, } @@ -232,10 +232,7 @@ impl ElectrumExt for A { continue; // reorg } - let chain_update = local_chain::Update { - tip, - introduce_older_blocks: true, - }; + let chain_update = tip; let keychain_update = request_spks .into_keys() diff --git a/crates/esplora/src/async_ext.rs b/crates/esplora/src/async_ext.rs index 1abc28c816..fa7e4508dd 100644 --- a/crates/esplora/src/async_ext.rs +++ b/crates/esplora/src/async_ext.rs @@ -5,7 +5,7 @@ use bdk_chain::Anchor; use bdk_chain::{ bitcoin::{BlockHash, OutPoint, ScriptBuf, TxOut, Txid}, collections::BTreeMap, - local_chain::{self, CheckPoint}, + local_chain::CheckPoint, BlockId, ConfirmationTimeHeightAnchor, TxGraph, }; use esplora_client::{Amount, TxStatus}; @@ -180,7 +180,7 @@ async fn chain_update( latest_blocks: &BTreeMap, local_tip: &CheckPoint, anchors: &BTreeSet<(A, Txid)>, -) -> Result { +) -> Result { let mut point_of_agreement = None; let mut conflicts = vec![]; for local_cp in local_tip.iter() { @@ -225,10 +225,7 @@ async fn chain_update( tip = tip.insert(BlockId { height, hash }); } - Ok(local_chain::Update { - tip, - introduce_older_blocks: true, - }) + Ok(tip) } /// This performs a full scan to get an update for the [`TxGraph`] and diff --git a/crates/esplora/src/blocking_ext.rs b/crates/esplora/src/blocking_ext.rs index 5b7cd62889..444fa1169c 100644 --- a/crates/esplora/src/blocking_ext.rs +++ b/crates/esplora/src/blocking_ext.rs @@ -6,7 +6,7 @@ use bdk_chain::collections::BTreeMap; use bdk_chain::Anchor; use bdk_chain::{ bitcoin::{Amount, BlockHash, OutPoint, ScriptBuf, TxOut, Txid}, - local_chain::{self, CheckPoint}, + local_chain::CheckPoint, BlockId, ConfirmationTimeHeightAnchor, TxGraph, }; use esplora_client::TxStatus; @@ -178,7 +178,7 @@ fn chain_update( latest_blocks: &BTreeMap, local_tip: &CheckPoint, anchors: &BTreeSet<(A, Txid)>, -) -> Result { +) -> Result { let mut point_of_agreement = None; let mut conflicts = vec![]; for local_cp in local_tip.iter() { @@ -223,10 +223,7 @@ fn chain_update( tip = tip.insert(BlockId { height, hash }); } - Ok(local_chain::Update { - tip, - introduce_older_blocks: true, - }) + Ok(tip) } /// This performs a full scan to get an update for the [`TxGraph`] and @@ -752,7 +749,6 @@ mod test { )?; let update_blocks = chain_update - .tip .iter() .map(|cp| cp.block_id()) .collect::>(); diff --git a/crates/esplora/src/lib.rs b/crates/esplora/src/lib.rs index c422a0833b..f6fa9adc79 100644 --- a/crates/esplora/src/lib.rs +++ b/crates/esplora/src/lib.rs @@ -18,7 +18,7 @@ use std::collections::BTreeMap; -use bdk_chain::{local_chain, BlockId, ConfirmationTimeHeightAnchor, TxGraph}; +use bdk_chain::{local_chain::CheckPoint, BlockId, ConfirmationTimeHeightAnchor, TxGraph}; use esplora_client::TxStatus; pub use esplora_client; @@ -54,7 +54,7 @@ fn anchor_from_status(status: &TxStatus) -> Option /// Update returns from a full scan. pub struct FullScanUpdate { /// The update to apply to the receiving [`LocalChain`](local_chain::LocalChain). - pub local_chain: local_chain::Update, + pub local_chain: CheckPoint, /// The update to apply to the receiving [`TxGraph`]. pub tx_graph: TxGraph, /// Last active indices for the corresponding keychains (`K`). @@ -64,7 +64,7 @@ pub struct FullScanUpdate { /// Update returned from a sync. pub struct SyncUpdate { /// The update to apply to the receiving [`LocalChain`](local_chain::LocalChain). - pub local_chain: local_chain::Update, + pub local_chain: CheckPoint, /// The update to apply to the receiving [`TxGraph`]. pub tx_graph: TxGraph, } diff --git a/crates/esplora/tests/async_ext.rs b/crates/esplora/tests/async_ext.rs index 5946bb4d84..f6954fe11f 100644 --- a/crates/esplora/tests/async_ext.rs +++ b/crates/esplora/tests/async_ext.rs @@ -69,7 +69,6 @@ pub async fn test_update_tx_graph_without_keychain() -> anyhow::Result<()> { { let update_cps = sync_update .local_chain - .tip .iter() .map(|cp| cp.block_id()) .collect::>(); diff --git a/crates/esplora/tests/blocking_ext.rs b/crates/esplora/tests/blocking_ext.rs index 3f8ff69320..40e446a4ed 100644 --- a/crates/esplora/tests/blocking_ext.rs +++ b/crates/esplora/tests/blocking_ext.rs @@ -67,7 +67,6 @@ pub fn test_update_tx_graph_without_keychain() -> anyhow::Result<()> { { let update_cps = sync_update .local_chain - .tip .iter() .map(|cp| cp.block_id()) .collect::>(); diff --git a/example-crates/example_bitcoind_rpc_polling/src/main.rs b/example-crates/example_bitcoind_rpc_polling/src/main.rs index 88b83067b5..be9e1839f4 100644 --- a/example-crates/example_bitcoind_rpc_polling/src/main.rs +++ b/example-crates/example_bitcoind_rpc_polling/src/main.rs @@ -188,10 +188,7 @@ fn main() -> anyhow::Result<()> { let mut db = db.lock().unwrap(); let chain_changeset = chain - .apply_update(local_chain::Update { - tip: emission.checkpoint, - introduce_older_blocks: false, - }) + .apply_update(emission.checkpoint) .expect("must always apply as we receive blocks in order from emitter"); let graph_changeset = graph.apply_block_relevant(&emission.block, height); db.stage((chain_changeset, graph_changeset)); @@ -301,12 +298,8 @@ fn main() -> anyhow::Result<()> { let changeset = match emission { Emission::Block(block_emission) => { let height = block_emission.block_height(); - let chain_update = local_chain::Update { - tip: block_emission.checkpoint, - introduce_older_blocks: false, - }; let chain_changeset = chain - .apply_update(chain_update) + .apply_update(block_emission.checkpoint) .expect("must always apply as we receive blocks in order from emitter"); let graph_changeset = graph.apply_block_relevant(&block_emission.block, height);