refactor: move WalletChangeset to wallet module
Consequently, remove the `WalletChangeset` dependency from `example_electrum` and `example_esplora` examples.
This commit is contained in:
		
							parent
							
								
									2392e50fd9
								
							
						
					
					
						commit
						68572bfd2e
					
				| @ -22,10 +22,10 @@ use alloc::{ | |||||||
| pub use bdk_chain::keychain::Balance; | pub use bdk_chain::keychain::Balance; | ||||||
| use bdk_chain::{ | use bdk_chain::{ | ||||||
|     indexed_tx_graph, |     indexed_tx_graph, | ||||||
|     keychain::{KeychainTxOutIndex, WalletChangeSet}, |     keychain::{self, KeychainTxOutIndex}, | ||||||
|     local_chain::{self, CannotConnectError, CheckPoint, CheckPointIter, LocalChain}, |     local_chain::{self, CannotConnectError, CheckPoint, CheckPointIter, LocalChain}, | ||||||
|     tx_graph::{CanonicalTx, TxGraph}, |     tx_graph::{CanonicalTx, TxGraph}, | ||||||
|     Append, BlockId, ChainPosition, ConfirmationTime, ConfirmationTimeAnchor, FullTxOut, |     Anchor, Append, BlockId, ChainPosition, ConfirmationTime, ConfirmationTimeAnchor, FullTxOut, | ||||||
|     IndexedTxGraph, Persist, PersistBackend, |     IndexedTxGraph, Persist, PersistBackend, | ||||||
| }; | }; | ||||||
| use bitcoin::consensus::encode::serialize; | use bitcoin::consensus::encode::serialize; | ||||||
| @ -124,6 +124,62 @@ impl<K, A> WalletUpdate<K, A> { | |||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | /// A structure that records the corresponding changes as result of applying an [`WalletUpdate`].
 | ||||||
|  | #[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)] | ||||||
|  | pub struct WalletChangeSet<K, A> { | ||||||
|  |     /// Changes to the [`LocalChain`].
 | ||||||
|  |     ///
 | ||||||
|  |     /// [`LocalChain`]: local_chain::LocalChain
 | ||||||
|  |     pub chain: local_chain::ChangeSet, | ||||||
|  | 
 | ||||||
|  |     /// ChangeSet 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<A, keychain::ChangeSet<K>>, | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | impl<K, A> Default for WalletChangeSet<K, A> { | ||||||
|  |     fn default() -> Self { | ||||||
|  |         Self { | ||||||
|  |             chain: Default::default(), | ||||||
|  |             index_tx_graph: Default::default(), | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | impl<K: Ord, A: Anchor> Append for WalletChangeSet<K, A> { | ||||||
|  |     fn append(&mut self, other: Self) { | ||||||
|  |         Append::append(&mut self.chain, other.chain); | ||||||
|  |         Append::append(&mut self.index_tx_graph, other.index_tx_graph); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     fn is_empty(&self) -> bool { | ||||||
|  |         self.chain.is_empty() && self.index_tx_graph.is_empty() | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | impl<K, A> From<local_chain::ChangeSet> for WalletChangeSet<K, A> { | ||||||
|  |     fn from(chain: local_chain::ChangeSet) -> Self { | ||||||
|  |         Self { | ||||||
|  |             chain, | ||||||
|  |             ..Default::default() | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | impl<K, A> From<indexed_tx_graph::ChangeSet<A, keychain::ChangeSet<K>>> for WalletChangeSet<K, A> { | ||||||
|  |     fn from(index_tx_graph: indexed_tx_graph::ChangeSet<A, keychain::ChangeSet<K>>) -> Self { | ||||||
|  |         Self { | ||||||
|  |             index_tx_graph, | ||||||
|  |             ..Default::default() | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
| /// The update to a [`Wallet`] used in [`Wallet::apply_update`]. This is usually returned from blockchain data sources.
 | /// The update to a [`Wallet`] used in [`Wallet::apply_update`]. This is usually returned from blockchain data sources.
 | ||||||
| pub type Update = WalletUpdate<KeychainKind, ConfirmationTimeAnchor>; | pub type Update = WalletUpdate<KeychainKind, ConfirmationTimeAnchor>; | ||||||
| 
 | 
 | ||||||
| @ -277,7 +333,7 @@ impl<D> Wallet<D> { | |||||||
| 
 | 
 | ||||||
|         let changeset = db.load_from_persistence().map_err(NewError::Persist)?; |         let changeset = db.load_from_persistence().map_err(NewError::Persist)?; | ||||||
|         chain.apply_changeset(&changeset.chain); |         chain.apply_changeset(&changeset.chain); | ||||||
|         indexed_graph.apply_changeset(changeset.indexed_tx_graph); |         indexed_graph.apply_changeset(changeset.index_tx_graph); | ||||||
| 
 | 
 | ||||||
|         let persist = Persist::new(db); |         let persist = Persist::new(db); | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -10,7 +10,7 @@ | |||||||
| //!
 | //!
 | ||||||
| //! [`SpkTxOutIndex`]: crate::SpkTxOutIndex
 | //! [`SpkTxOutIndex`]: crate::SpkTxOutIndex
 | ||||||
| 
 | 
 | ||||||
| use crate::{collections::BTreeMap, indexed_tx_graph, local_chain, Anchor, Append}; | use crate::{collections::BTreeMap, Append}; | ||||||
| 
 | 
 | ||||||
| #[cfg(feature = "miniscript")] | #[cfg(feature = "miniscript")] | ||||||
| mod txout_index; | mod txout_index; | ||||||
| @ -80,69 +80,6 @@ impl<K> AsRef<BTreeMap<K, u32>> for ChangeSet<K> { | |||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| /// A structure that records the corresponding changes as result of applying an [`WalletUpdate`].
 |  | ||||||
| #[derive(Debug, Clone, PartialEq)] |  | ||||||
| #[cfg_attr(
 |  | ||||||
|     feature = "serde", |  | ||||||
|     derive(serde::Deserialize, serde::Serialize), |  | ||||||
|     serde( |  | ||||||
|         crate = "serde_crate", |  | ||||||
|         bound( |  | ||||||
|             deserialize = "K: Ord + serde::Deserialize<'de>, A: Ord + serde::Deserialize<'de>", |  | ||||||
|             serialize = "K: Ord + serde::Serialize, A: Ord + serde::Serialize", |  | ||||||
|         ) |  | ||||||
|     ) |  | ||||||
| )] |  | ||||||
| pub struct WalletChangeSet<K, A> { |  | ||||||
|     /// Changes to the [`LocalChain`].
 |  | ||||||
|     ///
 |  | ||||||
|     /// [`LocalChain`]: local_chain::LocalChain
 |  | ||||||
|     pub chain: local_chain::ChangeSet, |  | ||||||
| 
 |  | ||||||
|     /// ChangeSet to [`IndexedTxGraph`].
 |  | ||||||
|     ///
 |  | ||||||
|     /// [`IndexedTxGraph`]: crate::indexed_tx_graph::IndexedTxGraph
 |  | ||||||
|     pub indexed_tx_graph: indexed_tx_graph::ChangeSet<A, ChangeSet<K>>, |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| impl<K, A> Default for WalletChangeSet<K, A> { |  | ||||||
|     fn default() -> Self { |  | ||||||
|         Self { |  | ||||||
|             chain: Default::default(), |  | ||||||
|             indexed_tx_graph: Default::default(), |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| impl<K: Ord, A: Anchor> Append for WalletChangeSet<K, A> { |  | ||||||
|     fn append(&mut self, other: Self) { |  | ||||||
|         Append::append(&mut self.chain, other.chain); |  | ||||||
|         Append::append(&mut self.indexed_tx_graph, other.indexed_tx_graph); |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     fn is_empty(&self) -> bool { |  | ||||||
|         self.chain.is_empty() && self.indexed_tx_graph.is_empty() |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| impl<K, A> From<local_chain::ChangeSet> for WalletChangeSet<K, A> { |  | ||||||
|     fn from(chain: local_chain::ChangeSet) -> Self { |  | ||||||
|         Self { |  | ||||||
|             chain, |  | ||||||
|             ..Default::default() |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| impl<K, A> From<indexed_tx_graph::ChangeSet<A, ChangeSet<K>>> for WalletChangeSet<K, A> { |  | ||||||
|     fn from(indexed_tx_graph: indexed_tx_graph::ChangeSet<A, ChangeSet<K>>) -> Self { |  | ||||||
|         Self { |  | ||||||
|             indexed_tx_graph, |  | ||||||
|             ..Default::default() |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| /// Balance, differentiated into various categories.
 | /// Balance, differentiated into various categories.
 | ||||||
| #[derive(Debug, PartialEq, Eq, Clone, Default)] | #[derive(Debug, PartialEq, Eq, Clone, Default)] | ||||||
| #[cfg_attr(
 | #[cfg_attr(
 | ||||||
|  | |||||||
| @ -100,3 +100,11 @@ pub mod collections { | |||||||
| 
 | 
 | ||||||
| /// How many confirmations are needed f or a coinbase output to be spent.
 | /// How many confirmations are needed f or a coinbase output to be spent.
 | ||||||
| pub const COINBASE_MATURITY: u32 = 100; | pub const COINBASE_MATURITY: u32 = 100; | ||||||
|  | 
 | ||||||
|  | impl<A, IA> From<indexed_tx_graph::ChangeSet<A, IA>> | ||||||
|  |     for (local_chain::ChangeSet, indexed_tx_graph::ChangeSet<A, IA>) | ||||||
|  | { | ||||||
|  |     fn from(indexed_changeset: indexed_tx_graph::ChangeSet<A, IA>) -> Self { | ||||||
|  |         (local_chain::ChangeSet::default(), indexed_changeset) | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | |||||||
| @ -7,7 +7,7 @@ use std::{ | |||||||
| use bdk_chain::{ | use bdk_chain::{ | ||||||
|     bitcoin::{Address, Network, OutPoint, ScriptBuf, Txid}, |     bitcoin::{Address, Network, OutPoint, ScriptBuf, Txid}, | ||||||
|     indexed_tx_graph::{self, IndexedTxGraph}, |     indexed_tx_graph::{self, IndexedTxGraph}, | ||||||
|     keychain::WalletChangeSet, |     keychain, | ||||||
|     local_chain::{self, LocalChain}, |     local_chain::{self, LocalChain}, | ||||||
|     Append, ConfirmationHeightAnchor, |     Append, ConfirmationHeightAnchor, | ||||||
| }; | }; | ||||||
| @ -60,7 +60,10 @@ pub struct ScanOptions { | |||||||
|     pub batch_size: usize, |     pub batch_size: usize, | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| type ChangeSet = WalletChangeSet<Keychain, ConfirmationHeightAnchor>; | type ChangeSet = ( | ||||||
|  |     local_chain::ChangeSet, | ||||||
|  |     indexed_tx_graph::ChangeSet<ConfirmationHeightAnchor, keychain::ChangeSet<Keychain>>, | ||||||
|  | ); | ||||||
| 
 | 
 | ||||||
| fn main() -> anyhow::Result<()> { | fn main() -> anyhow::Result<()> { | ||||||
|     let (args, keymap, index, db, init_changeset) = |     let (args, keymap, index, db, init_changeset) = | ||||||
| @ -68,11 +71,11 @@ fn main() -> anyhow::Result<()> { | |||||||
| 
 | 
 | ||||||
|     let graph = Mutex::new({ |     let graph = Mutex::new({ | ||||||
|         let mut graph = IndexedTxGraph::new(index); |         let mut graph = IndexedTxGraph::new(index); | ||||||
|         graph.apply_changeset(init_changeset.indexed_tx_graph); |         graph.apply_changeset(init_changeset.1); | ||||||
|         graph |         graph | ||||||
|     }); |     }); | ||||||
| 
 | 
 | ||||||
|     let chain = Mutex::new(LocalChain::from_changeset(init_changeset.chain)); |     let chain = Mutex::new(LocalChain::from_changeset(init_changeset.0)); | ||||||
| 
 | 
 | ||||||
|     let electrum_url = match args.network { |     let electrum_url = match args.network { | ||||||
|         Network::Bitcoin => "ssl://electrum.blockstream.info:50002", |         Network::Bitcoin => "ssl://electrum.blockstream.info:50002", | ||||||
| @ -293,10 +296,7 @@ fn main() -> anyhow::Result<()> { | |||||||
|             changeset |             changeset | ||||||
|         }; |         }; | ||||||
| 
 | 
 | ||||||
|         ChangeSet { |         (chain, indexed_tx_graph) | ||||||
|             indexed_tx_graph, |  | ||||||
|             chain, |  | ||||||
|         } |  | ||||||
|     }; |     }; | ||||||
| 
 | 
 | ||||||
|     let mut db = db.lock().unwrap(); |     let mut db = db.lock().unwrap(); | ||||||
|  | |||||||
| @ -6,9 +6,9 @@ use std::{ | |||||||
| 
 | 
 | ||||||
| use bdk_chain::{ | use bdk_chain::{ | ||||||
|     bitcoin::{Address, Network, OutPoint, ScriptBuf, Txid}, |     bitcoin::{Address, Network, OutPoint, ScriptBuf, Txid}, | ||||||
|     indexed_tx_graph::IndexedTxGraph, |     indexed_tx_graph::{self, IndexedTxGraph}, | ||||||
|     keychain::WalletChangeSet, |     keychain, | ||||||
|     local_chain::{CheckPoint, LocalChain}, |     local_chain::{self, CheckPoint, LocalChain}, | ||||||
|     Append, ConfirmationTimeAnchor, |     Append, ConfirmationTimeAnchor, | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| @ -23,6 +23,11 @@ use example_cli::{ | |||||||
| const DB_MAGIC: &[u8] = b"bdk_example_esplora"; | const DB_MAGIC: &[u8] = b"bdk_example_esplora"; | ||||||
| const DB_PATH: &str = ".bdk_esplora_example.db"; | const DB_PATH: &str = ".bdk_esplora_example.db"; | ||||||
| 
 | 
 | ||||||
|  | type ChangeSet = ( | ||||||
|  |     local_chain::ChangeSet, | ||||||
|  |     indexed_tx_graph::ChangeSet<ConfirmationTimeAnchor, keychain::ChangeSet<Keychain>>, | ||||||
|  | ); | ||||||
|  | 
 | ||||||
| #[derive(Subcommand, Debug, Clone)] | #[derive(Subcommand, Debug, Clone)] | ||||||
| enum EsploraCommands { | enum EsploraCommands { | ||||||
|     /// Scans the addresses in the wallet using the esplora API.
 |     /// Scans the addresses in the wallet using the esplora API.
 | ||||||
| @ -60,22 +65,22 @@ pub struct ScanOptions { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| fn main() -> anyhow::Result<()> { | fn main() -> anyhow::Result<()> { | ||||||
|     let (args, keymap, index, db, init_changeset) = example_cli::init::< |     let (args, keymap, index, db, init_changeset) = | ||||||
|         EsploraCommands, |         example_cli::init::<EsploraCommands, ChangeSet>(DB_MAGIC, DB_PATH)?; | ||||||
|         WalletChangeSet<Keychain, ConfirmationTimeAnchor>, | 
 | ||||||
|     >(DB_MAGIC, DB_PATH)?; |     let (init_chain_changeset, init_indexed_tx_graph_changeset) = init_changeset; | ||||||
| 
 | 
 | ||||||
|     // Contruct `IndexedTxGraph` and `LocalChain` with our initial changeset. They are wrapped in
 |     // Contruct `IndexedTxGraph` and `LocalChain` with our initial changeset. They are wrapped in
 | ||||||
|     // `Mutex` to display how they can be used in a multithreaded context. Technically the mutexes
 |     // `Mutex` to display how they can be used in a multithreaded context. Technically the mutexes
 | ||||||
|     // aren't strictly needed here.
 |     // aren't strictly needed here.
 | ||||||
|     let graph = Mutex::new({ |     let graph = Mutex::new({ | ||||||
|         let mut graph = IndexedTxGraph::new(index); |         let mut graph = IndexedTxGraph::new(index); | ||||||
|         graph.apply_changeset(init_changeset.indexed_tx_graph); |         graph.apply_changeset(init_indexed_tx_graph_changeset); | ||||||
|         graph |         graph | ||||||
|     }); |     }); | ||||||
|     let chain = Mutex::new({ |     let chain = Mutex::new({ | ||||||
|         let mut chain = LocalChain::default(); |         let mut chain = LocalChain::default(); | ||||||
|         chain.apply_changeset(&init_changeset.chain); |         chain.apply_changeset(&init_chain_changeset); | ||||||
|         chain |         chain | ||||||
|     }); |     }); | ||||||
| 
 | 
 | ||||||
| @ -307,18 +312,17 @@ fn main() -> anyhow::Result<()> { | |||||||
|     println!("missing block heights: {:?}", missing_block_heights); |     println!("missing block heights: {:?}", missing_block_heights); | ||||||
| 
 | 
 | ||||||
|     // Here, we actually fetch the missing blocks and create a `local_chain::Update`.
 |     // Here, we actually fetch the missing blocks and create a `local_chain::Update`.
 | ||||||
|     let chain_update = client |     let chain_changeset = { | ||||||
|         .update_local_chain(tip, missing_block_heights) |         let chain_update = client | ||||||
|         .context("scanning for blocks")?; |             .update_local_chain(tip, missing_block_heights) | ||||||
| 
 |             .context("scanning for blocks")?; | ||||||
|     println!("new tip: {}", chain_update.tip.height()); |         println!("new tip: {}", chain_update.tip.height()); | ||||||
|  |         chain.lock().unwrap().apply_update(chain_update)? | ||||||
|  |     }; | ||||||
| 
 | 
 | ||||||
|     // We persist the changes
 |     // We persist the changes
 | ||||||
|     let mut db = db.lock().unwrap(); |     let mut db = db.lock().unwrap(); | ||||||
|     db.stage(WalletChangeSet { |     db.stage((chain_changeset, indexed_tx_graph_changeset)); | ||||||
|         chain: chain.lock().unwrap().apply_update(chain_update)?, |  | ||||||
|         indexed_tx_graph: indexed_tx_graph_changeset, |  | ||||||
|     }); |  | ||||||
|     db.commit()?; |     db.commit()?; | ||||||
|     Ok(()) |     Ok(()) | ||||||
| } | } | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user