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>> {
|
impl<A, K> From<keychain::ChangeSet<K>> for ChangeSet<A, keychain::ChangeSet<K>> {
|
||||||
fn from(indexer: keychain::ChangeSet<K>) -> Self {
|
fn from(indexer: keychain::ChangeSet<K>) -> Self {
|
||||||
Self {
|
Self {
|
||||||
|
@ -10,78 +10,12 @@
|
|||||||
//!
|
//!
|
||||||
//! [`SpkTxOutIndex`]: crate::SpkTxOutIndex
|
//! [`SpkTxOutIndex`]: crate::SpkTxOutIndex
|
||||||
|
|
||||||
use crate::{collections::BTreeMap, Append};
|
|
||||||
|
|
||||||
#[cfg(feature = "miniscript")]
|
#[cfg(feature = "miniscript")]
|
||||||
mod txout_index;
|
mod txout_index;
|
||||||
use bitcoin::Amount;
|
use bitcoin::Amount;
|
||||||
#[cfg(feature = "miniscript")]
|
#[cfg(feature = "miniscript")]
|
||||||
pub use txout_index::*;
|
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.
|
/// Balance, differentiated into various categories.
|
||||||
#[derive(Debug, PartialEq, Eq, Clone, Default)]
|
#[derive(Debug, PartialEq, Eq, Clone, Default)]
|
||||||
#[cfg_attr(
|
#[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;
|
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;
|
const DEFAULT_LOOKAHEAD: u32 = 25;
|
||||||
|
|
||||||
/// [`KeychainTxOutIndex`] controls how script pubkeys are revealed for multiple keychains, and
|
/// [`KeychainTxOutIndex`] controls how script pubkeys are revealed for multiple keychains, and
|
||||||
|
@ -5,7 +5,7 @@ mod common;
|
|||||||
use bdk_chain::{
|
use bdk_chain::{
|
||||||
collections::BTreeMap,
|
collections::BTreeMap,
|
||||||
indexed_tx_graph::Indexer,
|
indexed_tx_graph::Indexer,
|
||||||
keychain::{self, KeychainTxOutIndex},
|
keychain::{self, ChangeSet, KeychainTxOutIndex},
|
||||||
Append,
|
Append,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -44,6 +44,38 @@ fn spk_at_index(descriptor: &Descriptor<DescriptorPublicKey>, index: u32) -> Scr
|
|||||||
.script_pubkey()
|
.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]
|
#[test]
|
||||||
fn test_set_all_derivation_indices() {
|
fn test_set_all_derivation_indices() {
|
||||||
use bdk_chain::indexed_tx_graph::Indexer;
|
use bdk_chain::indexed_tx_graph::Indexer;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user