ref(chain): move keychain::ChangeSet into txout_index.rs
				
					
				
			We plan to record `Descriptor` additions into persistence. Hence, we need to add `Descriptor`s to the changeset. This depends on `miniscript`. Moving this into `txout_index.rs` makes sense as this is consistent with all the other files. The only reason why this wasn't this way before, is because the changeset didn't need miniscript. Co-Authored-By: Daniela Brozzoni <danielabrozzoni@protonmail.com>
This commit is contained in:
		
							parent
							
								
									66abc73c3d
								
							
						
					
					
						commit
						b9902936a0
					
				| @ -320,6 +320,7 @@ impl<A, IA: Default> From<tx_graph::ChangeSet<A>> for ChangeSet<A, IA> { | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| #[cfg(feature = "miniscript")] | ||||
| impl<A, K> From<keychain::ChangeSet<K>> for ChangeSet<A, keychain::ChangeSet<K>> { | ||||
|     fn from(indexer: keychain::ChangeSet<K>) -> Self { | ||||
|         Self { | ||||
|  | ||||
| @ -10,78 +10,12 @@ | ||||
| //!
 | ||||
| //! [`SpkTxOutIndex`]: crate::SpkTxOutIndex
 | ||||
| 
 | ||||
| use crate::{collections::BTreeMap, Append}; | ||||
| 
 | ||||
| #[cfg(feature = "miniscript")] | ||||
| mod txout_index; | ||||
| use bitcoin::Amount; | ||||
| #[cfg(feature = "miniscript")] | ||||
| pub use txout_index::*; | ||||
| 
 | ||||
| /// Represents updates to the derivation index of a [`KeychainTxOutIndex`].
 | ||||
| /// It maps each keychain `K` to its last revealed index.
 | ||||
| ///
 | ||||
| /// It can be applied to [`KeychainTxOutIndex`] with [`apply_changeset`]. [`ChangeSet`]s are
 | ||||
| /// monotone in that they will never decrease the revealed derivation index.
 | ||||
| ///
 | ||||
| /// [`KeychainTxOutIndex`]: crate::keychain::KeychainTxOutIndex
 | ||||
| /// [`apply_changeset`]: crate::keychain::KeychainTxOutIndex::apply_changeset
 | ||||
| #[derive(Clone, Debug, PartialEq)] | ||||
| #[cfg_attr(
 | ||||
|     feature = "serde", | ||||
|     derive(serde::Deserialize, serde::Serialize), | ||||
|     serde( | ||||
|         crate = "serde_crate", | ||||
|         bound( | ||||
|             deserialize = "K: Ord + serde::Deserialize<'de>", | ||||
|             serialize = "K: Ord + serde::Serialize" | ||||
|         ) | ||||
|     ) | ||||
| )] | ||||
| #[must_use] | ||||
| pub struct ChangeSet<K>(pub BTreeMap<K, u32>); | ||||
| 
 | ||||
| impl<K> ChangeSet<K> { | ||||
|     /// Get the inner map of the keychain to its new derivation index.
 | ||||
|     pub fn as_inner(&self) -> &BTreeMap<K, u32> { | ||||
|         &self.0 | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| impl<K: Ord> Append for ChangeSet<K> { | ||||
|     /// Append another [`ChangeSet`] into self.
 | ||||
|     ///
 | ||||
|     /// If the keychain already exists, increase the index when the other's index > self's index.
 | ||||
|     /// If the keychain did not exist, append the new keychain.
 | ||||
|     fn append(&mut self, mut other: Self) { | ||||
|         self.0.iter_mut().for_each(|(key, index)| { | ||||
|             if let Some(other_index) = other.0.remove(key) { | ||||
|                 *index = other_index.max(*index); | ||||
|             } | ||||
|         }); | ||||
|         // We use `extend` instead of `BTreeMap::append` due to performance issues with `append`.
 | ||||
|         // Refer to https://github.com/rust-lang/rust/issues/34666#issuecomment-675658420
 | ||||
|         self.0.extend(other.0); | ||||
|     } | ||||
| 
 | ||||
|     /// Returns whether the changeset are empty.
 | ||||
|     fn is_empty(&self) -> bool { | ||||
|         self.0.is_empty() | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| impl<K> Default for ChangeSet<K> { | ||||
|     fn default() -> Self { | ||||
|         Self(Default::default()) | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| impl<K> AsRef<BTreeMap<K, u32>> for ChangeSet<K> { | ||||
|     fn as_ref(&self) -> &BTreeMap<K, u32> { | ||||
|         &self.0 | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| /// Balance, differentiated into various categories.
 | ||||
| #[derive(Debug, PartialEq, Eq, Clone, Default)] | ||||
| #[cfg_attr(
 | ||||
| @ -137,40 +71,3 @@ impl core::ops::Add for Balance { | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| #[cfg(test)] | ||||
| mod test { | ||||
|     use super::*; | ||||
| 
 | ||||
|     #[test] | ||||
|     fn append_keychain_derivation_indices() { | ||||
|         #[derive(Ord, PartialOrd, Eq, PartialEq, Clone, Debug)] | ||||
|         enum Keychain { | ||||
|             One, | ||||
|             Two, | ||||
|             Three, | ||||
|             Four, | ||||
|         } | ||||
|         let mut lhs_di = BTreeMap::<Keychain, u32>::default(); | ||||
|         let mut rhs_di = BTreeMap::<Keychain, u32>::default(); | ||||
|         lhs_di.insert(Keychain::One, 7); | ||||
|         lhs_di.insert(Keychain::Two, 0); | ||||
|         rhs_di.insert(Keychain::One, 3); | ||||
|         rhs_di.insert(Keychain::Two, 5); | ||||
|         lhs_di.insert(Keychain::Three, 3); | ||||
|         rhs_di.insert(Keychain::Four, 4); | ||||
| 
 | ||||
|         let mut lhs = ChangeSet(lhs_di); | ||||
|         let rhs = ChangeSet(rhs_di); | ||||
|         lhs.append(rhs); | ||||
| 
 | ||||
|         // Exiting index doesn't update if the new index in `other` is lower than `self`.
 | ||||
|         assert_eq!(lhs.0.get(&Keychain::One), Some(&7)); | ||||
|         // Existing index updates if the new index in `other` is higher than `self`.
 | ||||
|         assert_eq!(lhs.0.get(&Keychain::Two), Some(&5)); | ||||
|         // Existing index is unchanged if keychain doesn't exist in `other`.
 | ||||
|         assert_eq!(lhs.0.get(&Keychain::Three), Some(&3)); | ||||
|         // New keychain gets added if the keychain is in `other` but not in `self`.
 | ||||
|         assert_eq!(lhs.0.get(&Keychain::Four), Some(&4)); | ||||
|     } | ||||
| } | ||||
|  | ||||
| @ -13,6 +13,71 @@ use core::{ | ||||
| 
 | ||||
| use crate::Append; | ||||
| 
 | ||||
| 
 | ||||
| /// Represents updates to the derivation index of a [`KeychainTxOutIndex`].
 | ||||
| /// It maps each keychain `K` to its last revealed index.
 | ||||
| ///
 | ||||
| /// It can be applied to [`KeychainTxOutIndex`] with [`apply_changeset`]. [`ChangeSet] are
 | ||||
| /// monotone in that they will never decrease the revealed derivation index.
 | ||||
| ///
 | ||||
| /// [`KeychainTxOutIndex`]: crate::keychain::KeychainTxOutIndex
 | ||||
| /// [`apply_changeset`]: crate::keychain::KeychainTxOutIndex::apply_changeset
 | ||||
| #[derive(Clone, Debug, PartialEq)] | ||||
| #[cfg_attr(
 | ||||
|     feature = "serde", | ||||
|     derive(serde::Deserialize, serde::Serialize), | ||||
|     serde( | ||||
|         crate = "serde_crate", | ||||
|         bound( | ||||
|             deserialize = "K: Ord + serde::Deserialize<'de>", | ||||
|             serialize = "K: Ord + serde::Serialize" | ||||
|         ) | ||||
|     ) | ||||
| )] | ||||
| #[must_use] | ||||
| pub struct ChangeSet<K>(pub BTreeMap<K, u32>); | ||||
| 
 | ||||
| impl<K> ChangeSet<K> { | ||||
|     /// Get the inner map of the keychain to its new derivation index.
 | ||||
|     pub fn as_inner(&self) -> &BTreeMap<K, u32> { | ||||
|         &self.0 | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| impl<K: Ord> Append for ChangeSet<K> { | ||||
|     /// Append another [`ChangeSet`] into self.
 | ||||
|     ///
 | ||||
|     /// If the keychain already exists, increase the index when the other's index > self's index.
 | ||||
|     /// If the keychain did not exist, append the new keychain.
 | ||||
|     fn append(&mut self, mut other: Self) { | ||||
|         self.0.iter_mut().for_each(|(key, index)| { | ||||
|             if let Some(other_index) = other.0.remove(key) { | ||||
|                 *index = other_index.max(*index); | ||||
|             } | ||||
|         }); | ||||
|         // We use `extend` instead of `BTreeMap::append` due to performance issues with `append`.
 | ||||
|         // Refer to https://github.com/rust-lang/rust/issues/34666#issuecomment-675658420
 | ||||
|         self.0.extend(other.0); | ||||
|     } | ||||
| 
 | ||||
|     /// Returns whether the changeset are empty.
 | ||||
|     fn is_empty(&self) -> bool { | ||||
|         self.0.is_empty() | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| impl<K> Default for ChangeSet<K> { | ||||
|     fn default() -> Self { | ||||
|         Self(Default::default()) | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| impl<K> AsRef<BTreeMap<K, u32>> for ChangeSet<K> { | ||||
|     fn as_ref(&self) -> &BTreeMap<K, u32> { | ||||
|         &self.0 | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| const DEFAULT_LOOKAHEAD: u32 = 25; | ||||
| 
 | ||||
| /// [`KeychainTxOutIndex`] controls how script pubkeys are revealed for multiple keychains, and
 | ||||
|  | ||||
| @ -5,7 +5,7 @@ mod common; | ||||
| use bdk_chain::{ | ||||
|     collections::BTreeMap, | ||||
|     indexed_tx_graph::Indexer, | ||||
|     keychain::{self, KeychainTxOutIndex}, | ||||
|     keychain::{self, ChangeSet, KeychainTxOutIndex}, | ||||
|     Append, | ||||
| }; | ||||
| 
 | ||||
| @ -44,6 +44,38 @@ fn spk_at_index(descriptor: &Descriptor<DescriptorPublicKey>, index: u32) -> Scr | ||||
|         .script_pubkey() | ||||
| } | ||||
| 
 | ||||
| #[test] | ||||
| fn append_keychain_derivation_indices() { | ||||
|     #[derive(Ord, PartialOrd, Eq, PartialEq, Clone, Debug)] | ||||
|     enum Keychain { | ||||
|         One, | ||||
|         Two, | ||||
|         Three, | ||||
|         Four, | ||||
|     } | ||||
|     let mut lhs_di = BTreeMap::<Keychain, u32>::default(); | ||||
|     let mut rhs_di = BTreeMap::<Keychain, u32>::default(); | ||||
|     lhs_di.insert(Keychain::One, 7); | ||||
|     lhs_di.insert(Keychain::Two, 0); | ||||
|     rhs_di.insert(Keychain::One, 3); | ||||
|     rhs_di.insert(Keychain::Two, 5); | ||||
|     lhs_di.insert(Keychain::Three, 3); | ||||
|     rhs_di.insert(Keychain::Four, 4); | ||||
| 
 | ||||
|     let mut lhs = ChangeSet(lhs_di); | ||||
|     let rhs = ChangeSet(rhs_di); | ||||
|     lhs.append(rhs); | ||||
| 
 | ||||
|     // Exiting index doesn't update if the new index in `other` is lower than `self`.
 | ||||
|     assert_eq!(lhs.0.get(&Keychain::One), Some(&7)); | ||||
|     // Existing index updates if the new index in `other` is higher than `self`.
 | ||||
|     assert_eq!(lhs.0.get(&Keychain::Two), Some(&5)); | ||||
|     // Existing index is unchanged if keychain doesn't exist in `other`.
 | ||||
|     assert_eq!(lhs.0.get(&Keychain::Three), Some(&3)); | ||||
|     // New keychain gets added if the keychain is in `other` but not in `self`.
 | ||||
|     assert_eq!(lhs.0.get(&Keychain::Four), Some(&4)); | ||||
| } | ||||
| 
 | ||||
| #[test] | ||||
| fn test_set_all_derivation_indices() { | ||||
|     use bdk_chain::indexed_tx_graph::Indexer; | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user