}
}
+#[cfg(feature = "miniscript")]
impl<A, K> From<keychain::ChangeSet<K>> for ChangeSet<A, keychain::ChangeSet<K>> {
fn from(indexer: keychain::ChangeSet<K>) -> Self {
Self {
//!
//! [`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(
}
}
}
-
-#[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));
- }
-}
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
use bdk_chain::{
collections::BTreeMap,
indexed_tx_graph::Indexer,
- keychain::{self, KeychainTxOutIndex},
+ keychain::{self, ChangeSet, KeychainTxOutIndex},
Append,
};
.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;