refactor!(chain): Unify ChangeSet nomenclature
This commit renames: - indexed_tx_graph::IndexedAdditions -> indexed_tx_graph::ChangeSet - indexed_tx_graph::IndexedAdditions::graph_additions -> indexed_tx_graph::ChangeSet::graph - indexed_tx_graph::IndexedAdditions::index_additions -> indexed_tx_graph::ChangeSet::indexer - tx_graph::Additions -> tx_graph::ChangeSet - keychain::DerivationAdditions -> keychain::ChangeSet - CanonicalTx::node -> CanonicalTx::tx_node - CanonicalTx::observed_as -> CanonicalTx::chain_position - LocalChangeSet -> WalletChangeSet - LocalChangeSet::chain_changeset -> WalletChangeSet::chain - LocalChangeSet::indexed_additions -> WalletChangeSet::indexed_tx_graph - LocalUpdate -> WalletUpdate This commit also changes the visibility of TxGraph::determine_changeset to be pub(crate), and the method accepts a TxGraph instead of &TxGraph This commit removes: - `TxGraph::insert_txout_preview` - `TxGraph::insert_tx_preview` - `insert_anchor_preview` - `insert_seen_at_preview` Solves #1022
This commit is contained in:
@@ -6,8 +6,8 @@ use alloc::vec::Vec;
|
||||
use bitcoin::{OutPoint, Transaction, TxOut};
|
||||
|
||||
use crate::{
|
||||
keychain::DerivationAdditions,
|
||||
tx_graph::{Additions, TxGraph},
|
||||
keychain,
|
||||
tx_graph::{self, TxGraph},
|
||||
Anchor, Append,
|
||||
};
|
||||
|
||||
@@ -46,48 +46,40 @@ impl<A, I> IndexedTxGraph<A, I> {
|
||||
}
|
||||
|
||||
impl<A: Anchor, I: Indexer> IndexedTxGraph<A, I> {
|
||||
/// Applies the [`IndexedAdditions`] to the [`IndexedTxGraph`].
|
||||
pub fn apply_additions(&mut self, additions: IndexedAdditions<A, I::Additions>) {
|
||||
let IndexedAdditions {
|
||||
graph_additions,
|
||||
index_additions,
|
||||
} = additions;
|
||||
/// Applies the [`ChangeSet`] to the [`IndexedTxGraph`].
|
||||
pub fn apply_changeset(&mut self, changeset: ChangeSet<A, I::ChangeSet>) {
|
||||
self.index.apply_changeset(changeset.indexer);
|
||||
|
||||
self.index.apply_additions(index_additions);
|
||||
|
||||
for tx in &graph_additions.txs {
|
||||
for tx in &changeset.graph.txs {
|
||||
self.index.index_tx(tx);
|
||||
}
|
||||
for (&outpoint, txout) in &graph_additions.txouts {
|
||||
for (&outpoint, txout) in &changeset.graph.txouts {
|
||||
self.index.index_txout(outpoint, txout);
|
||||
}
|
||||
|
||||
self.graph.apply_additions(graph_additions);
|
||||
self.graph.apply_changeset(changeset.graph);
|
||||
}
|
||||
}
|
||||
|
||||
impl<A: Anchor, I: Indexer> IndexedTxGraph<A, I>
|
||||
where
|
||||
I::Additions: Default + Append,
|
||||
I::ChangeSet: Default + Append,
|
||||
{
|
||||
/// Apply an `update` directly.
|
||||
///
|
||||
/// `update` is a [`TxGraph<A>`] and the resultant changes is returned as [`IndexedAdditions`].
|
||||
pub fn apply_update(&mut self, update: TxGraph<A>) -> IndexedAdditions<A, I::Additions> {
|
||||
let graph_additions = self.graph.apply_update(update);
|
||||
/// `update` is a [`TxGraph<A>`] and the resultant changes is returned as [`ChangeSet`].
|
||||
pub fn apply_update(&mut self, update: TxGraph<A>) -> ChangeSet<A, I::ChangeSet> {
|
||||
let graph = self.graph.apply_update(update);
|
||||
|
||||
let mut index_additions = I::Additions::default();
|
||||
for added_tx in &graph_additions.txs {
|
||||
index_additions.append(self.index.index_tx(added_tx));
|
||||
let mut indexer = I::ChangeSet::default();
|
||||
for added_tx in &graph.txs {
|
||||
indexer.append(self.index.index_tx(added_tx));
|
||||
}
|
||||
for (&added_outpoint, added_txout) in &graph_additions.txouts {
|
||||
index_additions.append(self.index.index_txout(added_outpoint, added_txout));
|
||||
for (&added_outpoint, added_txout) in &graph.txouts {
|
||||
indexer.append(self.index.index_txout(added_outpoint, added_txout));
|
||||
}
|
||||
|
||||
IndexedAdditions {
|
||||
graph_additions,
|
||||
index_additions,
|
||||
}
|
||||
ChangeSet { graph, indexer }
|
||||
}
|
||||
|
||||
/// Insert a floating `txout` of given `outpoint`.
|
||||
@@ -95,7 +87,7 @@ where
|
||||
&mut self,
|
||||
outpoint: OutPoint,
|
||||
txout: &TxOut,
|
||||
) -> IndexedAdditions<A, I::Additions> {
|
||||
) -> ChangeSet<A, I::ChangeSet> {
|
||||
let mut update = TxGraph::<A>::default();
|
||||
let _ = update.insert_txout(outpoint, txout.clone());
|
||||
self.apply_update(update)
|
||||
@@ -110,7 +102,7 @@ where
|
||||
tx: &Transaction,
|
||||
anchors: impl IntoIterator<Item = A>,
|
||||
seen_at: Option<u64>,
|
||||
) -> IndexedAdditions<A, I::Additions> {
|
||||
) -> ChangeSet<A, I::ChangeSet> {
|
||||
let txid = tx.txid();
|
||||
|
||||
let mut update = TxGraph::<A>::default();
|
||||
@@ -138,20 +130,20 @@ where
|
||||
&mut self,
|
||||
txs: impl IntoIterator<Item = (&'t Transaction, impl IntoIterator<Item = A>)>,
|
||||
seen_at: Option<u64>,
|
||||
) -> IndexedAdditions<A, I::Additions> {
|
||||
) -> ChangeSet<A, I::ChangeSet> {
|
||||
// The algorithm below allows for non-topologically ordered transactions by using two loops.
|
||||
// This is achieved by:
|
||||
// 1. insert all txs into the index. If they are irrelevant then that's fine it will just
|
||||
// not store anything about them.
|
||||
// 2. decide whether to insert them into the graph depending on whether `is_tx_relevant`
|
||||
// returns true or not. (in a second loop).
|
||||
let mut additions = IndexedAdditions::<A, I::Additions>::default();
|
||||
let mut changeset = ChangeSet::<A, I::ChangeSet>::default();
|
||||
let mut transactions = Vec::new();
|
||||
for (tx, anchors) in txs.into_iter() {
|
||||
additions.index_additions.append(self.index.index_tx(tx));
|
||||
changeset.indexer.append(self.index.index_tx(tx));
|
||||
transactions.push((tx, anchors));
|
||||
}
|
||||
additions.append(
|
||||
changeset.append(
|
||||
transactions
|
||||
.into_iter()
|
||||
.filter_map(|(tx, anchors)| match self.index.is_tx_relevant(tx) {
|
||||
@@ -163,7 +155,7 @@ where
|
||||
acc
|
||||
}),
|
||||
);
|
||||
additions
|
||||
changeset
|
||||
}
|
||||
}
|
||||
|
||||
@@ -181,64 +173,64 @@ where
|
||||
)
|
||||
)]
|
||||
#[must_use]
|
||||
pub struct IndexedAdditions<A, IA> {
|
||||
/// [`TxGraph`] additions.
|
||||
pub graph_additions: Additions<A>,
|
||||
/// [`Indexer`] additions.
|
||||
pub index_additions: IA,
|
||||
pub struct ChangeSet<A, IA> {
|
||||
/// [`TxGraph`] changeset.
|
||||
pub graph: tx_graph::ChangeSet<A>,
|
||||
/// [`Indexer`] changeset.
|
||||
pub indexer: IA,
|
||||
}
|
||||
|
||||
impl<A, IA: Default> Default for IndexedAdditions<A, IA> {
|
||||
impl<A, IA: Default> Default for ChangeSet<A, IA> {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
graph_additions: Default::default(),
|
||||
index_additions: Default::default(),
|
||||
graph: Default::default(),
|
||||
indexer: Default::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<A: Anchor, IA: Append> Append for IndexedAdditions<A, IA> {
|
||||
impl<A: Anchor, IA: Append> Append for ChangeSet<A, IA> {
|
||||
fn append(&mut self, other: Self) {
|
||||
self.graph_additions.append(other.graph_additions);
|
||||
self.index_additions.append(other.index_additions);
|
||||
self.graph.append(other.graph);
|
||||
self.indexer.append(other.indexer);
|
||||
}
|
||||
|
||||
fn is_empty(&self) -> bool {
|
||||
self.graph_additions.is_empty() && self.index_additions.is_empty()
|
||||
self.graph.is_empty() && self.indexer.is_empty()
|
||||
}
|
||||
}
|
||||
|
||||
impl<A, IA: Default> From<Additions<A>> for IndexedAdditions<A, IA> {
|
||||
fn from(graph_additions: Additions<A>) -> Self {
|
||||
impl<A, IA: Default> From<tx_graph::ChangeSet<A>> for ChangeSet<A, IA> {
|
||||
fn from(graph: tx_graph::ChangeSet<A>) -> Self {
|
||||
Self {
|
||||
graph_additions,
|
||||
graph,
|
||||
..Default::default()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<A, K> From<DerivationAdditions<K>> for IndexedAdditions<A, DerivationAdditions<K>> {
|
||||
fn from(index_additions: DerivationAdditions<K>) -> Self {
|
||||
impl<A, K> From<keychain::ChangeSet<K>> for ChangeSet<A, keychain::ChangeSet<K>> {
|
||||
fn from(indexer: keychain::ChangeSet<K>) -> Self {
|
||||
Self {
|
||||
graph_additions: Default::default(),
|
||||
index_additions,
|
||||
graph: Default::default(),
|
||||
indexer,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Represents a structure that can index transaction data.
|
||||
pub trait Indexer {
|
||||
/// The resultant "additions" when new transaction data is indexed.
|
||||
type Additions;
|
||||
/// The resultant "changeset" when new transaction data is indexed.
|
||||
type ChangeSet;
|
||||
|
||||
/// Scan and index the given `outpoint` and `txout`.
|
||||
fn index_txout(&mut self, outpoint: OutPoint, txout: &TxOut) -> Self::Additions;
|
||||
fn index_txout(&mut self, outpoint: OutPoint, txout: &TxOut) -> Self::ChangeSet;
|
||||
|
||||
/// Scan and index the given transaction.
|
||||
fn index_tx(&mut self, tx: &Transaction) -> Self::Additions;
|
||||
fn index_tx(&mut self, tx: &Transaction) -> Self::ChangeSet;
|
||||
|
||||
/// Apply additions to itself.
|
||||
fn apply_additions(&mut self, additions: Self::Additions);
|
||||
/// Apply changeset to itself.
|
||||
fn apply_changeset(&mut self, changeset: Self::ChangeSet);
|
||||
|
||||
/// Determines whether the transaction should be included in the index.
|
||||
fn is_tx_relevant(&self, tx: &Transaction) -> bool;
|
||||
|
||||
@@ -11,8 +11,7 @@
|
||||
//! [`SpkTxOutIndex`]: crate::SpkTxOutIndex
|
||||
|
||||
use crate::{
|
||||
collections::BTreeMap, indexed_tx_graph::IndexedAdditions, local_chain, tx_graph::TxGraph,
|
||||
Anchor, Append,
|
||||
collections::BTreeMap, indexed_tx_graph, local_chain, tx_graph::TxGraph, Anchor, Append,
|
||||
};
|
||||
|
||||
#[cfg(feature = "miniscript")]
|
||||
@@ -22,11 +21,11 @@ pub use txout_index::*;
|
||||
|
||||
/// Represents updates to the derivation index of a [`KeychainTxOutIndex`].
|
||||
///
|
||||
/// It can be applied to [`KeychainTxOutIndex`] with [`apply_additions`]. [`DerivationAdditions] are
|
||||
/// 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_additions`]: crate::keychain::KeychainTxOutIndex::apply_additions
|
||||
/// [`apply_changeset`]: crate::keychain::KeychainTxOutIndex::apply_changeset
|
||||
#[derive(Clone, Debug, PartialEq)]
|
||||
#[cfg_attr(
|
||||
feature = "serde",
|
||||
@@ -40,17 +39,17 @@ pub use txout_index::*;
|
||||
)
|
||||
)]
|
||||
#[must_use]
|
||||
pub struct DerivationAdditions<K>(pub BTreeMap<K, u32>);
|
||||
pub struct ChangeSet<K>(pub BTreeMap<K, u32>);
|
||||
|
||||
impl<K> DerivationAdditions<K> {
|
||||
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 DerivationAdditions<K> {
|
||||
/// Append another [`DerivationAdditions`] into self.
|
||||
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.
|
||||
@@ -64,19 +63,19 @@ impl<K: Ord> Append for DerivationAdditions<K> {
|
||||
self.0.append(&mut other.0);
|
||||
}
|
||||
|
||||
/// Returns whether the additions are empty.
|
||||
/// Returns whether the changeset are empty.
|
||||
fn is_empty(&self) -> bool {
|
||||
self.0.is_empty()
|
||||
}
|
||||
}
|
||||
|
||||
impl<K> Default for DerivationAdditions<K> {
|
||||
impl<K> Default for ChangeSet<K> {
|
||||
fn default() -> Self {
|
||||
Self(Default::default())
|
||||
}
|
||||
}
|
||||
|
||||
impl<K> AsRef<BTreeMap<K, u32>> for DerivationAdditions<K> {
|
||||
impl<K> AsRef<BTreeMap<K, u32>> for ChangeSet<K> {
|
||||
fn as_ref(&self) -> &BTreeMap<K, u32> {
|
||||
&self.0
|
||||
}
|
||||
@@ -86,7 +85,7 @@ impl<K> AsRef<BTreeMap<K, u32>> for DerivationAdditions<K> {
|
||||
///
|
||||
/// [`LocalChain`]: local_chain::LocalChain
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct LocalUpdate<K, A> {
|
||||
pub struct WalletUpdate<K, A> {
|
||||
/// Contains the last active derivation indices per keychain (`K`), which is used to update the
|
||||
/// [`KeychainTxOutIndex`].
|
||||
pub last_active_indices: BTreeMap<K, u32>,
|
||||
@@ -100,10 +99,8 @@ pub struct LocalUpdate<K, A> {
|
||||
pub chain: local_chain::Update,
|
||||
}
|
||||
|
||||
impl<K, A> LocalUpdate<K, A> {
|
||||
/// Construct a [`LocalUpdate`] with a given [`local_chain::Update`].
|
||||
///
|
||||
/// [`CheckPoint`]: local_chain::CheckPoint
|
||||
impl<K, A> WalletUpdate<K, A> {
|
||||
/// Construct a [`WalletUpdate`] with a given [`local_chain::Update`].
|
||||
pub fn new(chain_update: local_chain::Update) -> Self {
|
||||
Self {
|
||||
last_active_indices: BTreeMap::new(),
|
||||
@@ -113,7 +110,7 @@ impl<K, A> LocalUpdate<K, A> {
|
||||
}
|
||||
}
|
||||
|
||||
/// A structure that records the corresponding changes as result of applying an [`LocalUpdate`].
|
||||
/// A structure that records the corresponding changes as result of applying an [`WalletUpdate`].
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
#[cfg_attr(
|
||||
feature = "serde",
|
||||
@@ -126,51 +123,51 @@ impl<K, A> LocalUpdate<K, A> {
|
||||
)
|
||||
)
|
||||
)]
|
||||
pub struct LocalChangeSet<K, A> {
|
||||
pub struct WalletChangeSet<K, A> {
|
||||
/// Changes to the [`LocalChain`].
|
||||
///
|
||||
/// [`LocalChain`]: local_chain::LocalChain
|
||||
pub chain_changeset: local_chain::ChangeSet,
|
||||
pub chain: local_chain::ChangeSet,
|
||||
|
||||
/// Additions to [`IndexedTxGraph`].
|
||||
/// ChangeSet to [`IndexedTxGraph`].
|
||||
///
|
||||
/// [`IndexedTxGraph`]: crate::indexed_tx_graph::IndexedTxGraph
|
||||
pub indexed_additions: IndexedAdditions<A, DerivationAdditions<K>>,
|
||||
pub index_tx_graph: indexed_tx_graph::ChangeSet<A, ChangeSet<K>>,
|
||||
}
|
||||
|
||||
impl<K, A> Default for LocalChangeSet<K, A> {
|
||||
impl<K, A> Default for WalletChangeSet<K, A> {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
chain_changeset: Default::default(),
|
||||
indexed_additions: Default::default(),
|
||||
chain: Default::default(),
|
||||
index_tx_graph: Default::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<K: Ord, A: Anchor> Append for LocalChangeSet<K, A> {
|
||||
impl<K: Ord, A: Anchor> Append for WalletChangeSet<K, A> {
|
||||
fn append(&mut self, other: Self) {
|
||||
Append::append(&mut self.chain_changeset, other.chain_changeset);
|
||||
Append::append(&mut self.indexed_additions, other.indexed_additions);
|
||||
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_changeset.is_empty() && self.indexed_additions.is_empty()
|
||||
self.chain.is_empty() && self.index_tx_graph.is_empty()
|
||||
}
|
||||
}
|
||||
|
||||
impl<K, A> From<local_chain::ChangeSet> for LocalChangeSet<K, A> {
|
||||
fn from(chain_changeset: local_chain::ChangeSet) -> Self {
|
||||
impl<K, A> From<local_chain::ChangeSet> for WalletChangeSet<K, A> {
|
||||
fn from(chain: local_chain::ChangeSet) -> Self {
|
||||
Self {
|
||||
chain_changeset,
|
||||
chain,
|
||||
..Default::default()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<K, A> From<IndexedAdditions<A, DerivationAdditions<K>>> for LocalChangeSet<K, A> {
|
||||
fn from(indexed_additions: IndexedAdditions<A, DerivationAdditions<K>>) -> Self {
|
||||
impl<K, A> From<indexed_tx_graph::ChangeSet<A, ChangeSet<K>>> for WalletChangeSet<K, A> {
|
||||
fn from(index_tx_graph: indexed_tx_graph::ChangeSet<A, ChangeSet<K>>) -> Self {
|
||||
Self {
|
||||
indexed_additions,
|
||||
index_tx_graph,
|
||||
..Default::default()
|
||||
}
|
||||
}
|
||||
@@ -254,8 +251,8 @@ mod test {
|
||||
lhs_di.insert(Keychain::Three, 3);
|
||||
rhs_di.insert(Keychain::Four, 4);
|
||||
|
||||
let mut lhs = DerivationAdditions(lhs_di);
|
||||
let rhs = DerivationAdditions(rhs_di);
|
||||
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`.
|
||||
|
||||
@@ -11,8 +11,6 @@ use core::{fmt::Debug, ops::Deref};
|
||||
|
||||
use crate::Append;
|
||||
|
||||
use super::DerivationAdditions;
|
||||
|
||||
/// A convenient wrapper around [`SpkTxOutIndex`] that relates script pubkeys to miniscript public
|
||||
/// [`Descriptor`]s.
|
||||
///
|
||||
@@ -23,7 +21,7 @@ use super::DerivationAdditions;
|
||||
/// revealed. In addition to revealed scripts, we have a `lookahead` parameter for each keychain,
|
||||
/// which defines the number of script pubkeys to store ahead of the last revealed index.
|
||||
///
|
||||
/// Methods that could update the last revealed index will return [`DerivationAdditions`] to report
|
||||
/// Methods that could update the last revealed index will return [`super::ChangeSet`] to report
|
||||
/// these changes. This can be persisted for future recovery.
|
||||
///
|
||||
/// ## Synopsis
|
||||
@@ -90,18 +88,18 @@ impl<K> Deref for KeychainTxOutIndex<K> {
|
||||
}
|
||||
|
||||
impl<K: Clone + Ord + Debug> Indexer for KeychainTxOutIndex<K> {
|
||||
type Additions = DerivationAdditions<K>;
|
||||
type ChangeSet = super::ChangeSet<K>;
|
||||
|
||||
fn index_txout(&mut self, outpoint: OutPoint, txout: &TxOut) -> Self::Additions {
|
||||
fn index_txout(&mut self, outpoint: OutPoint, txout: &TxOut) -> Self::ChangeSet {
|
||||
self.scan_txout(outpoint, txout)
|
||||
}
|
||||
|
||||
fn index_tx(&mut self, tx: &bitcoin::Transaction) -> Self::Additions {
|
||||
fn index_tx(&mut self, tx: &bitcoin::Transaction) -> Self::ChangeSet {
|
||||
self.scan(tx)
|
||||
}
|
||||
|
||||
fn apply_additions(&mut self, additions: Self::Additions) {
|
||||
self.apply_additions(additions)
|
||||
fn apply_changeset(&mut self, changeset: Self::ChangeSet) {
|
||||
self.apply_changeset(changeset)
|
||||
}
|
||||
|
||||
fn is_tx_relevant(&self, tx: &bitcoin::Transaction) -> bool {
|
||||
@@ -113,7 +111,7 @@ impl<K: Clone + Ord + Debug> KeychainTxOutIndex<K> {
|
||||
/// Scans an object for relevant outpoints, which are stored and indexed internally.
|
||||
///
|
||||
/// If the matched script pubkey is part of the lookahead, the last stored index is updated for
|
||||
/// the script pubkey's keychain and the [`DerivationAdditions`] returned will reflect the
|
||||
/// the script pubkey's keychain and the [`super::ChangeSet`] returned will reflect the
|
||||
/// change.
|
||||
///
|
||||
/// Typically, this method is used in two situations:
|
||||
@@ -126,19 +124,19 @@ impl<K: Clone + Ord + Debug> KeychainTxOutIndex<K> {
|
||||
/// See [`ForEachTxout`] for the types that support this.
|
||||
///
|
||||
/// [`ForEachTxout`]: crate::ForEachTxOut
|
||||
pub fn scan(&mut self, txouts: &impl ForEachTxOut) -> DerivationAdditions<K> {
|
||||
let mut additions = DerivationAdditions::<K>::default();
|
||||
txouts.for_each_txout(|(op, txout)| additions.append(self.scan_txout(op, txout)));
|
||||
additions
|
||||
pub fn scan(&mut self, txouts: &impl ForEachTxOut) -> super::ChangeSet<K> {
|
||||
let mut changeset = super::ChangeSet::<K>::default();
|
||||
txouts.for_each_txout(|(op, txout)| changeset.append(self.scan_txout(op, txout)));
|
||||
changeset
|
||||
}
|
||||
|
||||
/// Scan a single outpoint for a matching script pubkey.
|
||||
///
|
||||
/// If it matches, this will store and index it.
|
||||
pub fn scan_txout(&mut self, op: OutPoint, txout: &TxOut) -> DerivationAdditions<K> {
|
||||
pub fn scan_txout(&mut self, op: OutPoint, txout: &TxOut) -> super::ChangeSet<K> {
|
||||
match self.inner.scan_txout(op, txout).cloned() {
|
||||
Some((keychain, index)) => self.reveal_to_target(&keychain, index).1,
|
||||
None => DerivationAdditions::default(),
|
||||
None => super::ChangeSet::default(),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -370,20 +368,20 @@ impl<K: Clone + Ord + Debug> KeychainTxOutIndex<K> {
|
||||
keychains: &BTreeMap<K, u32>,
|
||||
) -> (
|
||||
BTreeMap<K, SpkIterator<Descriptor<DescriptorPublicKey>>>,
|
||||
DerivationAdditions<K>,
|
||||
super::ChangeSet<K>,
|
||||
) {
|
||||
let mut additions = DerivationAdditions::default();
|
||||
let mut changeset = super::ChangeSet::default();
|
||||
let mut spks = BTreeMap::new();
|
||||
|
||||
for (keychain, &index) in keychains {
|
||||
let (new_spks, new_additions) = self.reveal_to_target(keychain, index);
|
||||
if !new_additions.is_empty() {
|
||||
let (new_spks, new_changeset) = self.reveal_to_target(keychain, index);
|
||||
if !new_changeset.is_empty() {
|
||||
spks.insert(keychain.clone(), new_spks);
|
||||
additions.append(new_additions.clone());
|
||||
changeset.append(new_changeset.clone());
|
||||
}
|
||||
}
|
||||
|
||||
(spks, additions)
|
||||
(spks, changeset)
|
||||
}
|
||||
|
||||
/// Reveals script pubkeys of the `keychain`'s descriptor **up to and including** the
|
||||
@@ -394,7 +392,7 @@ impl<K: Clone + Ord + Debug> KeychainTxOutIndex<K> {
|
||||
/// reveal up to the last possible index.
|
||||
///
|
||||
/// This returns an iterator of newly revealed indices (alongside their scripts) and a
|
||||
/// [`DerivationAdditions`], which reports updates to the latest revealed index. If no new script
|
||||
/// [`super::ChangeSet`], which reports updates to the latest revealed index. If no new script
|
||||
/// pubkeys are revealed, then both of these will be empty.
|
||||
///
|
||||
/// # Panics
|
||||
@@ -406,7 +404,7 @@ impl<K: Clone + Ord + Debug> KeychainTxOutIndex<K> {
|
||||
target_index: u32,
|
||||
) -> (
|
||||
SpkIterator<Descriptor<DescriptorPublicKey>>,
|
||||
DerivationAdditions<K>,
|
||||
super::ChangeSet<K>,
|
||||
) {
|
||||
let descriptor = self.keychains.get(keychain).expect("keychain must exist");
|
||||
let has_wildcard = descriptor.has_wildcard();
|
||||
@@ -450,7 +448,7 @@ impl<K: Clone + Ord + Debug> KeychainTxOutIndex<K> {
|
||||
debug_assert!(_old_index < Some(index));
|
||||
(
|
||||
SpkIterator::new_with_range(descriptor.clone(), next_reveal_index..index + 1),
|
||||
DerivationAdditions(core::iter::once((keychain.clone(), index)).collect()),
|
||||
super::ChangeSet(core::iter::once((keychain.clone(), index)).collect()),
|
||||
)
|
||||
}
|
||||
None => (
|
||||
@@ -458,7 +456,7 @@ impl<K: Clone + Ord + Debug> KeychainTxOutIndex<K> {
|
||||
descriptor.clone(),
|
||||
next_reveal_index..next_reveal_index,
|
||||
),
|
||||
DerivationAdditions::default(),
|
||||
super::ChangeSet::default(),
|
||||
),
|
||||
}
|
||||
}
|
||||
@@ -466,10 +464,10 @@ impl<K: Clone + Ord + Debug> KeychainTxOutIndex<K> {
|
||||
/// Attempts to reveal the next script pubkey for `keychain`.
|
||||
///
|
||||
/// Returns the derivation index of the revealed script pubkey, the revealed script pubkey and a
|
||||
/// [`DerivationAdditions`] which represents changes in the last revealed index (if any).
|
||||
/// [`super::ChangeSet`] which represents changes in the last revealed index (if any).
|
||||
///
|
||||
/// When a new script cannot be revealed, we return the last revealed script and an empty
|
||||
/// [`DerivationAdditions`]. There are two scenarios when a new script pubkey cannot be derived:
|
||||
/// [`super::ChangeSet`]. There are two scenarios when a new script pubkey cannot be derived:
|
||||
///
|
||||
/// 1. The descriptor has no wildcard and already has one script revealed.
|
||||
/// 2. The descriptor has already revealed scripts up to the numeric bound.
|
||||
@@ -477,14 +475,14 @@ impl<K: Clone + Ord + Debug> KeychainTxOutIndex<K> {
|
||||
/// # Panics
|
||||
///
|
||||
/// Panics if the `keychain` does not exist.
|
||||
pub fn reveal_next_spk(&mut self, keychain: &K) -> ((u32, &Script), DerivationAdditions<K>) {
|
||||
pub fn reveal_next_spk(&mut self, keychain: &K) -> ((u32, &Script), super::ChangeSet<K>) {
|
||||
let (next_index, _) = self.next_index(keychain);
|
||||
let additions = self.reveal_to_target(keychain, next_index).1;
|
||||
let changeset = self.reveal_to_target(keychain, next_index).1;
|
||||
let script = self
|
||||
.inner
|
||||
.spk_at_index(&(keychain.clone(), next_index))
|
||||
.expect("script must already be stored");
|
||||
((next_index, script), additions)
|
||||
((next_index, script), changeset)
|
||||
}
|
||||
|
||||
/// Gets the next unused script pubkey in the keychain. I.e., the script pubkey with the lowest
|
||||
@@ -499,7 +497,7 @@ impl<K: Clone + Ord + Debug> KeychainTxOutIndex<K> {
|
||||
/// # Panics
|
||||
///
|
||||
/// Panics if `keychain` has never been added to the index
|
||||
pub fn next_unused_spk(&mut self, keychain: &K) -> ((u32, &Script), DerivationAdditions<K>) {
|
||||
pub fn next_unused_spk(&mut self, keychain: &K) -> ((u32, &Script), super::ChangeSet<K>) {
|
||||
let need_new = self.unused_spks_of_keychain(keychain).next().is_none();
|
||||
// this rather strange branch is needed because of some lifetime issues
|
||||
if need_new {
|
||||
@@ -509,7 +507,7 @@ impl<K: Clone + Ord + Debug> KeychainTxOutIndex<K> {
|
||||
self.unused_spks_of_keychain(keychain)
|
||||
.next()
|
||||
.expect("we already know next exists"),
|
||||
DerivationAdditions::default(),
|
||||
super::ChangeSet::default(),
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -580,9 +578,9 @@ impl<K: Clone + Ord + Debug> KeychainTxOutIndex<K> {
|
||||
.collect()
|
||||
}
|
||||
|
||||
/// Applies the derivation additions to the [`KeychainTxOutIndex`], extending the number of
|
||||
/// derived scripts per keychain, as specified in the `additions`.
|
||||
pub fn apply_additions(&mut self, additions: DerivationAdditions<K>) {
|
||||
let _ = self.reveal_to_target_multi(&additions.0);
|
||||
/// Applies the derivation changeset to the [`KeychainTxOutIndex`], extending the number of
|
||||
/// derived scripts per keychain, as specified in the `changeset`.
|
||||
pub fn apply_changeset(&mut self, changeset: super::ChangeSet<K>) {
|
||||
let _ = self.reveal_to_target_multi(&changeset.0);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -54,19 +54,19 @@ impl<I> Default for SpkTxOutIndex<I> {
|
||||
}
|
||||
|
||||
impl<I: Clone + Ord> Indexer for SpkTxOutIndex<I> {
|
||||
type Additions = ();
|
||||
type ChangeSet = ();
|
||||
|
||||
fn index_txout(&mut self, outpoint: OutPoint, txout: &TxOut) -> Self::Additions {
|
||||
fn index_txout(&mut self, outpoint: OutPoint, txout: &TxOut) -> Self::ChangeSet {
|
||||
self.scan_txout(outpoint, txout);
|
||||
Default::default()
|
||||
}
|
||||
|
||||
fn index_tx(&mut self, tx: &Transaction) -> Self::Additions {
|
||||
fn index_tx(&mut self, tx: &Transaction) -> Self::ChangeSet {
|
||||
self.scan(tx);
|
||||
Default::default()
|
||||
}
|
||||
|
||||
fn apply_additions(&mut self, _additions: Self::Additions) {
|
||||
fn apply_changeset(&mut self, _changeset: Self::ChangeSet) {
|
||||
// This applies nothing.
|
||||
}
|
||||
|
||||
|
||||
@@ -1,17 +1,17 @@
|
||||
//! Module for structures that store and traverse transactions.
|
||||
//!
|
||||
//! [`TxGraph`] is a monotone structure that inserts transactions and indexes the spends. The
|
||||
//! [`Additions`] structure reports changes of [`TxGraph`] but can also be applied to a
|
||||
//! [`ChangeSet`] structure reports changes of [`TxGraph`] but can also be applied to a
|
||||
//! [`TxGraph`] as well. Lastly, [`TxDescendants`] is an [`Iterator`] that traverses descendants of
|
||||
//! a given transaction.
|
||||
//!
|
||||
//! Conflicting transactions are allowed to coexist within a [`TxGraph`]. This is useful for
|
||||
//! identifying and traversing conflicts and descendants of a given transaction.
|
||||
//!
|
||||
//! # Previewing and applying changes
|
||||
//! # Applying changes
|
||||
//!
|
||||
//! Methods that either preview or apply changes to [`TxGraph`] will return [`Additions`].
|
||||
//! [`Additions`] can be applied back to a [`TxGraph`] or be used to inform persistent storage
|
||||
//! Methods that apply changes to [`TxGraph`] will return [`ChangeSet`].
|
||||
//! [`ChangeSet`] can be applied back to a [`TxGraph`] or be used to inform persistent storage
|
||||
//! of the changes to [`TxGraph`].
|
||||
//!
|
||||
//! ```
|
||||
@@ -20,16 +20,14 @@
|
||||
//! # use bdk_chain::example_utils::*;
|
||||
//! # use bitcoin::Transaction;
|
||||
//! # let tx_a = tx_from_hex(RAW_TX_1);
|
||||
//! # let tx_b = tx_from_hex(RAW_TX_2);
|
||||
//! let mut graph: TxGraph = TxGraph::default();
|
||||
//! let mut another_graph: TxGraph = TxGraph::default();
|
||||
//!
|
||||
//! // preview a transaction insertion (not actually inserted)
|
||||
//! let additions = graph.insert_tx_preview(tx_a);
|
||||
//! // apply the insertion
|
||||
//! graph.apply_additions(additions);
|
||||
//! // insert a transaction
|
||||
//! let changeset = graph.insert_tx(tx_a);
|
||||
//!
|
||||
//! // you can also insert a transaction directly
|
||||
//! let already_applied_additions = graph.insert_tx(tx_b);
|
||||
//! // the resulting changeset can be applied to another tx graph
|
||||
//! another_graph.apply_changeset(changeset);
|
||||
//! ```
|
||||
//!
|
||||
//! A [`TxGraph`] can also be updated with another [`TxGraph`].
|
||||
@@ -44,15 +42,12 @@
|
||||
//! let mut graph: TxGraph = TxGraph::default();
|
||||
//! let update = TxGraph::new(vec![tx_a, tx_b]);
|
||||
//!
|
||||
//! // preview additions as the result of the update
|
||||
//! let additions = graph.determine_additions(&update);
|
||||
//! // apply the additions
|
||||
//! graph.apply_additions(additions);
|
||||
//! // apply the update graph
|
||||
//! let changeset = graph.apply_update(update.clone());
|
||||
//!
|
||||
//! // we can also apply the update graph directly
|
||||
//! // the additions will be empty as we have already applied the same update above
|
||||
//! let additions = graph.apply_update(update);
|
||||
//! assert!(additions.is_empty());
|
||||
//! // if we apply it again, the resulting changeset will be empty
|
||||
//! let changeset = graph.apply_update(update);
|
||||
//! assert!(changeset.is_empty());
|
||||
//! ```
|
||||
|
||||
use crate::{
|
||||
@@ -135,9 +130,9 @@ impl Default for TxNodeInternal {
|
||||
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
|
||||
pub struct CanonicalTx<'a, T, A> {
|
||||
/// How the transaction is observed as (confirmed or unconfirmed).
|
||||
pub observed_as: ChainPosition<&'a A>,
|
||||
pub chain_position: ChainPosition<&'a A>,
|
||||
/// The transaction node (as part of the graph).
|
||||
pub node: TxNode<'a, T, A>,
|
||||
pub tx_node: TxNode<'a, T, A>,
|
||||
}
|
||||
|
||||
impl<A> TxGraph<A> {
|
||||
@@ -371,15 +366,16 @@ impl<A: Clone + Ord> TxGraph<A> {
|
||||
new
|
||||
}
|
||||
|
||||
/// Returns the resultant [`Additions`] if the given `txout` is inserted at `outpoint`. Does not
|
||||
/// mutate `self`.
|
||||
/// Inserts the given [`TxOut`] at [`OutPoint`].
|
||||
///
|
||||
/// Inserting floating txouts are useful for determining fee/feerate of transactions we care
|
||||
/// about.
|
||||
///
|
||||
/// The [`Additions`] result will be empty if the `outpoint` (or a full transaction containing
|
||||
/// The [`ChangeSet`] result will be empty if the `outpoint` (or a full transaction containing
|
||||
/// the `outpoint`) already existed in `self`.
|
||||
pub fn insert_txout_preview(&self, outpoint: OutPoint, txout: TxOut) -> Additions<A> {
|
||||
///
|
||||
/// [`apply_changeset`]: Self::apply_changeset
|
||||
pub fn insert_txout(&mut self, outpoint: OutPoint, txout: TxOut) -> ChangeSet<A> {
|
||||
let mut update = Self::default();
|
||||
update.txs.insert(
|
||||
outpoint.txid,
|
||||
@@ -389,100 +385,62 @@ impl<A: Clone + Ord> TxGraph<A> {
|
||||
0,
|
||||
),
|
||||
);
|
||||
self.determine_additions(&update)
|
||||
}
|
||||
|
||||
/// Inserts the given [`TxOut`] at [`OutPoint`].
|
||||
///
|
||||
/// This is equivalent to calling [`insert_txout_preview`] and [`apply_additions`] in sequence.
|
||||
///
|
||||
/// [`insert_txout_preview`]: Self::insert_txout_preview
|
||||
/// [`apply_additions`]: Self::apply_additions
|
||||
pub fn insert_txout(&mut self, outpoint: OutPoint, txout: TxOut) -> Additions<A> {
|
||||
let additions = self.insert_txout_preview(outpoint, txout);
|
||||
self.apply_additions(additions.clone());
|
||||
additions
|
||||
}
|
||||
|
||||
/// Returns the resultant [`Additions`] if the given transaction is inserted. Does not actually
|
||||
/// mutate [`Self`].
|
||||
///
|
||||
/// The [`Additions`] result will be empty if `tx` already exists in `self`.
|
||||
pub fn insert_tx_preview(&self, tx: Transaction) -> Additions<A> {
|
||||
let mut update = Self::default();
|
||||
update
|
||||
.txs
|
||||
.insert(tx.txid(), (TxNodeInternal::Whole(tx), BTreeSet::new(), 0));
|
||||
self.determine_additions(&update)
|
||||
let changeset = self.determine_changeset(update);
|
||||
self.apply_changeset(changeset.clone());
|
||||
changeset
|
||||
}
|
||||
|
||||
/// Inserts the given transaction into [`TxGraph`].
|
||||
///
|
||||
/// The [`Additions`] returned will be empty if `tx` already exists.
|
||||
pub fn insert_tx(&mut self, tx: Transaction) -> Additions<A> {
|
||||
let additions = self.insert_tx_preview(tx);
|
||||
self.apply_additions(additions.clone());
|
||||
additions
|
||||
}
|
||||
|
||||
/// Returns the resultant [`Additions`] if the `txid` is set in `anchor`.
|
||||
pub fn insert_anchor_preview(&self, txid: Txid, anchor: A) -> Additions<A> {
|
||||
/// The [`ChangeSet`] returned will be empty if `tx` already exists.
|
||||
pub fn insert_tx(&mut self, tx: Transaction) -> ChangeSet<A> {
|
||||
let mut update = Self::default();
|
||||
update.anchors.insert((anchor, txid));
|
||||
self.determine_additions(&update)
|
||||
update
|
||||
.txs
|
||||
.insert(tx.txid(), (TxNodeInternal::Whole(tx), BTreeSet::new(), 0));
|
||||
let changeset = self.determine_changeset(update);
|
||||
self.apply_changeset(changeset.clone());
|
||||
changeset
|
||||
}
|
||||
|
||||
/// Inserts the given `anchor` into [`TxGraph`].
|
||||
///
|
||||
/// This is equivalent to calling [`insert_anchor_preview`] and [`apply_additions`] in sequence.
|
||||
/// The [`Additions`] returned will be empty if graph already knows that `txid` exists in
|
||||
/// The [`ChangeSet`] returned will be empty if graph already knows that `txid` exists in
|
||||
/// `anchor`.
|
||||
///
|
||||
/// [`insert_anchor_preview`]: Self::insert_anchor_preview
|
||||
/// [`apply_additions`]: Self::apply_additions
|
||||
pub fn insert_anchor(&mut self, txid: Txid, anchor: A) -> Additions<A> {
|
||||
let additions = self.insert_anchor_preview(txid, anchor);
|
||||
self.apply_additions(additions.clone());
|
||||
additions
|
||||
pub fn insert_anchor(&mut self, txid: Txid, anchor: A) -> ChangeSet<A> {
|
||||
let mut update = Self::default();
|
||||
update.anchors.insert((anchor, txid));
|
||||
let changeset = self.determine_changeset(update);
|
||||
self.apply_changeset(changeset.clone());
|
||||
changeset
|
||||
}
|
||||
|
||||
/// Returns the resultant [`Additions`] if the `txid` is set to `seen_at`.
|
||||
/// Inserts the given `seen_at` for `txid` into [`TxGraph`].
|
||||
///
|
||||
/// Note that [`TxGraph`] only keeps track of the lastest `seen_at`.
|
||||
pub fn insert_seen_at_preview(&self, txid: Txid, seen_at: u64) -> Additions<A> {
|
||||
pub fn insert_seen_at(&mut self, txid: Txid, seen_at: u64) -> ChangeSet<A> {
|
||||
let mut update = Self::default();
|
||||
let (_, _, update_last_seen) = update.txs.entry(txid).or_default();
|
||||
*update_last_seen = seen_at;
|
||||
self.determine_additions(&update)
|
||||
}
|
||||
|
||||
/// Inserts the given `seen_at` into [`TxGraph`].
|
||||
///
|
||||
/// This is equivalent to calling [`insert_seen_at_preview`] and [`apply_additions`] in
|
||||
/// sequence.
|
||||
///
|
||||
/// [`insert_seen_at_preview`]: Self::insert_seen_at_preview
|
||||
/// [`apply_additions`]: Self::apply_additions
|
||||
pub fn insert_seen_at(&mut self, txid: Txid, seen_at: u64) -> Additions<A> {
|
||||
let additions = self.insert_seen_at_preview(txid, seen_at);
|
||||
self.apply_additions(additions.clone());
|
||||
additions
|
||||
let changeset = self.determine_changeset(update);
|
||||
self.apply_changeset(changeset.clone());
|
||||
changeset
|
||||
}
|
||||
|
||||
/// Extends this graph with another so that `self` becomes the union of the two sets of
|
||||
/// transactions.
|
||||
///
|
||||
/// The returned [`Additions`] is the set difference between `update` and `self` (transactions that
|
||||
/// The returned [`ChangeSet`] is the set difference between `update` and `self` (transactions that
|
||||
/// exist in `update` but not in `self`).
|
||||
pub fn apply_update(&mut self, update: TxGraph<A>) -> Additions<A> {
|
||||
let additions = self.determine_additions(&update);
|
||||
self.apply_additions(additions.clone());
|
||||
additions
|
||||
pub fn apply_update(&mut self, update: TxGraph<A>) -> ChangeSet<A> {
|
||||
let changeset = self.determine_changeset(update);
|
||||
self.apply_changeset(changeset.clone());
|
||||
changeset
|
||||
}
|
||||
|
||||
/// Applies [`Additions`] to [`TxGraph`].
|
||||
pub fn apply_additions(&mut self, additions: Additions<A>) {
|
||||
for tx in additions.txs {
|
||||
/// Applies [`ChangeSet`] to [`TxGraph`].
|
||||
pub fn apply_changeset(&mut self, changeset: ChangeSet<A>) {
|
||||
for tx in changeset.txs {
|
||||
let txid = tx.txid();
|
||||
|
||||
tx.input
|
||||
@@ -513,7 +471,7 @@ impl<A: Clone + Ord> TxGraph<A> {
|
||||
}
|
||||
}
|
||||
|
||||
for (outpoint, txout) in additions.txouts {
|
||||
for (outpoint, txout) in changeset.txouts {
|
||||
let tx_entry = self
|
||||
.txs
|
||||
.entry(outpoint.txid)
|
||||
@@ -528,14 +486,14 @@ impl<A: Clone + Ord> TxGraph<A> {
|
||||
}
|
||||
}
|
||||
|
||||
for (anchor, txid) in additions.anchors {
|
||||
for (anchor, txid) in changeset.anchors {
|
||||
if self.anchors.insert((anchor.clone(), txid)) {
|
||||
let (_, anchors, _) = self.txs.entry(txid).or_insert_with(Default::default);
|
||||
anchors.insert(anchor);
|
||||
}
|
||||
}
|
||||
|
||||
for (txid, new_last_seen) in additions.last_seen {
|
||||
for (txid, new_last_seen) in changeset.last_seen {
|
||||
let (_, _, last_seen) = self.txs.entry(txid).or_insert_with(Default::default);
|
||||
if new_last_seen > *last_seen {
|
||||
*last_seen = new_last_seen;
|
||||
@@ -543,21 +501,21 @@ impl<A: Clone + Ord> TxGraph<A> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Previews the resultant [`Additions`] when [`Self`] is updated against the `update` graph.
|
||||
/// Previews the resultant [`ChangeSet`] when [`Self`] is updated against the `update` graph.
|
||||
///
|
||||
/// The [`Additions`] would be the set difference between `update` and `self` (transactions that
|
||||
/// The [`ChangeSet`] would be the set difference between `update` and `self` (transactions that
|
||||
/// exist in `update` but not in `self`).
|
||||
pub fn determine_additions(&self, update: &TxGraph<A>) -> Additions<A> {
|
||||
let mut additions = Additions::default();
|
||||
pub(crate) fn determine_changeset(&self, update: TxGraph<A>) -> ChangeSet<A> {
|
||||
let mut changeset = ChangeSet::default();
|
||||
|
||||
for (&txid, (update_tx_node, _, update_last_seen)) in &update.txs {
|
||||
let prev_last_seen: u64 = match (self.txs.get(&txid), update_tx_node) {
|
||||
(None, TxNodeInternal::Whole(update_tx)) => {
|
||||
additions.txs.insert(update_tx.clone());
|
||||
changeset.txs.insert(update_tx.clone());
|
||||
0
|
||||
}
|
||||
(None, TxNodeInternal::Partial(update_txos)) => {
|
||||
additions.txouts.extend(
|
||||
changeset.txouts.extend(
|
||||
update_txos
|
||||
.iter()
|
||||
.map(|(&vout, txo)| (OutPoint::new(txid, vout), txo.clone())),
|
||||
@@ -569,14 +527,14 @@ impl<A: Clone + Ord> TxGraph<A> {
|
||||
Some((TxNodeInternal::Partial(_), _, last_seen)),
|
||||
TxNodeInternal::Whole(update_tx),
|
||||
) => {
|
||||
additions.txs.insert(update_tx.clone());
|
||||
changeset.txs.insert(update_tx.clone());
|
||||
*last_seen
|
||||
}
|
||||
(
|
||||
Some((TxNodeInternal::Partial(txos), _, last_seen)),
|
||||
TxNodeInternal::Partial(update_txos),
|
||||
) => {
|
||||
additions.txouts.extend(
|
||||
changeset.txouts.extend(
|
||||
update_txos
|
||||
.iter()
|
||||
.filter(|(vout, _)| !txos.contains_key(*vout))
|
||||
@@ -587,13 +545,13 @@ impl<A: Clone + Ord> TxGraph<A> {
|
||||
};
|
||||
|
||||
if *update_last_seen > prev_last_seen {
|
||||
additions.last_seen.insert(txid, *update_last_seen);
|
||||
changeset.last_seen.insert(txid, *update_last_seen);
|
||||
}
|
||||
}
|
||||
|
||||
additions.anchors = update.anchors.difference(&self.anchors).cloned().collect();
|
||||
changeset.anchors = update.anchors.difference(&self.anchors).cloned().collect();
|
||||
|
||||
additions
|
||||
changeset
|
||||
}
|
||||
}
|
||||
|
||||
@@ -804,8 +762,8 @@ impl<A: Anchor> TxGraph<A> {
|
||||
self.try_get_chain_position(chain, chain_tip, tx.txid)
|
||||
.map(|v| {
|
||||
v.map(|observed_in| CanonicalTx {
|
||||
observed_as: observed_in,
|
||||
node: tx,
|
||||
chain_position: observed_in,
|
||||
tx_node: tx,
|
||||
})
|
||||
})
|
||||
.transpose()
|
||||
@@ -1026,7 +984,7 @@ impl<A: Anchor> TxGraph<A> {
|
||||
|
||||
/// A structure that represents changes to a [`TxGraph`].
|
||||
///
|
||||
/// It is named "additions" because [`TxGraph`] is monotone, so transactions can only be added and
|
||||
/// Since [`TxGraph`] is monotone "changeset" can only contain transactions to be added and
|
||||
/// not removed.
|
||||
///
|
||||
/// Refer to [module-level documentation] for more.
|
||||
@@ -1045,7 +1003,7 @@ impl<A: Anchor> TxGraph<A> {
|
||||
)
|
||||
)]
|
||||
#[must_use]
|
||||
pub struct Additions<A = ()> {
|
||||
pub struct ChangeSet<A = ()> {
|
||||
/// Added transactions.
|
||||
pub txs: BTreeSet<Transaction>,
|
||||
/// Added txouts.
|
||||
@@ -1056,7 +1014,7 @@ pub struct Additions<A = ()> {
|
||||
pub last_seen: BTreeMap<Txid, u64>,
|
||||
}
|
||||
|
||||
impl<A> Default for Additions<A> {
|
||||
impl<A> Default for ChangeSet<A> {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
txs: Default::default(),
|
||||
@@ -1067,13 +1025,13 @@ impl<A> Default for Additions<A> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<A> Additions<A> {
|
||||
/// Returns true if the [`Additions`] is empty (no transactions or txouts).
|
||||
impl<A> ChangeSet<A> {
|
||||
/// Returns true if the [`ChangeSet`] is empty (no transactions or txouts).
|
||||
pub fn is_empty(&self) -> bool {
|
||||
self.txs.is_empty() && self.txouts.is_empty()
|
||||
}
|
||||
|
||||
/// Iterates over all outpoints contained within [`Additions`].
|
||||
/// Iterates over all outpoints contained within [`ChangeSet`].
|
||||
pub fn txouts(&self) -> impl Iterator<Item = (OutPoint, &TxOut)> {
|
||||
self.txs
|
||||
.iter()
|
||||
@@ -1087,7 +1045,7 @@ impl<A> Additions<A> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<A: Ord> Append for Additions<A> {
|
||||
impl<A: Ord> Append for ChangeSet<A> {
|
||||
fn append(&mut self, mut other: Self) {
|
||||
self.txs.append(&mut other.txs);
|
||||
self.txouts.append(&mut other.txouts);
|
||||
@@ -1117,7 +1075,7 @@ impl<A> AsRef<TxGraph<A>> for TxGraph<A> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<A> ForEachTxOut for Additions<A> {
|
||||
impl<A> ForEachTxOut for ChangeSet<A> {
|
||||
fn for_each_txout(&self, f: impl FnMut((OutPoint, &TxOut))) {
|
||||
self.txouts().for_each(f)
|
||||
}
|
||||
|
||||
@@ -4,11 +4,10 @@ mod common;
|
||||
use std::collections::{BTreeMap, BTreeSet};
|
||||
|
||||
use bdk_chain::{
|
||||
indexed_tx_graph::{IndexedAdditions, IndexedTxGraph},
|
||||
keychain::{Balance, DerivationAdditions, KeychainTxOutIndex},
|
||||
indexed_tx_graph::{self, IndexedTxGraph},
|
||||
keychain::{self, Balance, KeychainTxOutIndex},
|
||||
local_chain::LocalChain,
|
||||
tx_graph::Additions,
|
||||
BlockId, ChainPosition, ConfirmationHeightAnchor,
|
||||
tx_graph, BlockId, ChainPosition, ConfirmationHeightAnchor,
|
||||
};
|
||||
use bitcoin::{
|
||||
secp256k1::Secp256k1, BlockHash, OutPoint, Script, ScriptBuf, Transaction, TxIn, TxOut,
|
||||
@@ -68,12 +67,12 @@ fn insert_relevant_txs() {
|
||||
|
||||
assert_eq!(
|
||||
graph.insert_relevant_txs(txs.iter().map(|tx| (tx, None)), None),
|
||||
IndexedAdditions {
|
||||
graph_additions: Additions {
|
||||
indexed_tx_graph::ChangeSet {
|
||||
graph: tx_graph::ChangeSet {
|
||||
txs: txs.into(),
|
||||
..Default::default()
|
||||
},
|
||||
index_additions: DerivationAdditions([((), 9_u32)].into()),
|
||||
indexer: keychain::ChangeSet([((), 9_u32)].into()),
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
mod common;
|
||||
use bdk_chain::{
|
||||
collections::BTreeMap,
|
||||
keychain::{DerivationAdditions, KeychainTxOutIndex},
|
||||
keychain::{self, KeychainTxOutIndex},
|
||||
Append,
|
||||
};
|
||||
|
||||
@@ -53,7 +53,7 @@ fn test_set_all_derivation_indices() {
|
||||
assert_eq!(txout_index.last_revealed_indices(), &derive_to);
|
||||
assert_eq!(
|
||||
txout_index.reveal_to_target_multi(&derive_to).1,
|
||||
DerivationAdditions::default(),
|
||||
keychain::ChangeSet::default(),
|
||||
"no changes if we set to the same thing"
|
||||
);
|
||||
}
|
||||
@@ -79,14 +79,14 @@ fn test_lookahead() {
|
||||
// - scripts cached in spk_txout_index should increase correctly
|
||||
// - stored scripts of external keychain should be of expected counts
|
||||
for index in (0..20).skip_while(|i| i % 2 == 1) {
|
||||
let (revealed_spks, revealed_additions) =
|
||||
let (revealed_spks, revealed_changeset) =
|
||||
txout_index.reveal_to_target(&TestKeychain::External, index);
|
||||
assert_eq!(
|
||||
revealed_spks.collect::<Vec<_>>(),
|
||||
vec![(index, spk_at_index(&external_desc, index))],
|
||||
);
|
||||
assert_eq!(
|
||||
revealed_additions.as_inner(),
|
||||
revealed_changeset.as_inner(),
|
||||
&[(TestKeychain::External, index)].into()
|
||||
);
|
||||
|
||||
@@ -129,7 +129,7 @@ fn test_lookahead() {
|
||||
// - derivation index is set ahead of current derivation index + lookahead
|
||||
// expect:
|
||||
// - scripts cached in spk_txout_index should increase correctly, a.k.a. no scripts are skipped
|
||||
let (revealed_spks, revealed_additions) =
|
||||
let (revealed_spks, revealed_changeset) =
|
||||
txout_index.reveal_to_target(&TestKeychain::Internal, 24);
|
||||
assert_eq!(
|
||||
revealed_spks.collect::<Vec<_>>(),
|
||||
@@ -138,7 +138,7 @@ fn test_lookahead() {
|
||||
.collect::<Vec<_>>(),
|
||||
);
|
||||
assert_eq!(
|
||||
revealed_additions.as_inner(),
|
||||
revealed_changeset.as_inner(),
|
||||
&[(TestKeychain::Internal, 24)].into()
|
||||
);
|
||||
assert_eq!(
|
||||
@@ -191,7 +191,7 @@ fn test_lookahead() {
|
||||
],
|
||||
..common::new_tx(external_index)
|
||||
};
|
||||
assert_eq!(txout_index.scan(&tx), DerivationAdditions::default());
|
||||
assert_eq!(txout_index.scan(&tx), keychain::ChangeSet::default());
|
||||
assert_eq!(
|
||||
txout_index.last_revealed_index(&TestKeychain::External),
|
||||
Some(last_external_index)
|
||||
@@ -245,9 +245,9 @@ fn test_scan_with_lookahead() {
|
||||
value: 0,
|
||||
};
|
||||
|
||||
let additions = txout_index.scan_txout(op, &txout);
|
||||
let changeset = txout_index.scan_txout(op, &txout);
|
||||
assert_eq!(
|
||||
additions.as_inner(),
|
||||
changeset.as_inner(),
|
||||
&[(TestKeychain::External, spk_i)].into()
|
||||
);
|
||||
assert_eq!(
|
||||
@@ -270,8 +270,8 @@ fn test_scan_with_lookahead() {
|
||||
script_pubkey: spk_41,
|
||||
value: 0,
|
||||
};
|
||||
let additions = txout_index.scan_txout(op, &txout);
|
||||
assert!(additions.is_empty());
|
||||
let changeset = txout_index.scan_txout(op, &txout);
|
||||
assert!(changeset.is_empty());
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -287,8 +287,8 @@ fn test_wildcard_derivations() {
|
||||
// - unused list is also empty
|
||||
//
|
||||
// - next_derivation_index() == (0, true)
|
||||
// - derive_new() == ((0, <spk>), DerivationAdditions)
|
||||
// - next_unused() == ((0, <spk>), DerivationAdditions:is_empty())
|
||||
// - derive_new() == ((0, <spk>), keychain::ChangeSet)
|
||||
// - next_unused() == ((0, <spk>), keychain::ChangeSet:is_empty())
|
||||
assert_eq!(txout_index.next_index(&TestKeychain::External), (0, true));
|
||||
let (spk, changeset) = txout_index.reveal_next_spk(&TestKeychain::External);
|
||||
assert_eq!(spk, (0_u32, external_spk_0.as_script()));
|
||||
@@ -303,8 +303,8 @@ fn test_wildcard_derivations() {
|
||||
// - unused list: [16, 18, 19, 21, 22, 24, 25]
|
||||
|
||||
// - next_derivation_index() = (26, true)
|
||||
// - derive_new() = ((26, <spk>), DerivationAdditions)
|
||||
// - next_unused() == ((16, <spk>), DerivationAdditions::is_empty())
|
||||
// - derive_new() = ((26, <spk>), keychain::ChangeSet)
|
||||
// - next_unused() == ((16, <spk>), keychain::ChangeSet::is_empty())
|
||||
let _ = txout_index.reveal_to_target(&TestKeychain::External, 25);
|
||||
|
||||
(0..=15)
|
||||
@@ -323,7 +323,7 @@ fn test_wildcard_derivations() {
|
||||
assert_eq!(changeset.as_inner(), &[].into());
|
||||
|
||||
// - Use all the derived till 26.
|
||||
// - next_unused() = ((27, <spk>), DerivationAdditions)
|
||||
// - next_unused() = ((27, <spk>), keychain::ChangeSet)
|
||||
(0..=26).for_each(|index| {
|
||||
txout_index.mark_used(&TestKeychain::External, index);
|
||||
});
|
||||
@@ -366,7 +366,7 @@ fn test_non_wildcard_derivations() {
|
||||
// expect:
|
||||
// - next derivation index should not be new
|
||||
// - derive new and next unused should return the old script
|
||||
// - store_up_to should not panic and return empty additions
|
||||
// - store_up_to should not panic and return empty changeset
|
||||
assert_eq!(txout_index.next_index(&TestKeychain::External), (0, false));
|
||||
txout_index.mark_used(&TestKeychain::External, 0);
|
||||
|
||||
@@ -377,8 +377,8 @@ fn test_non_wildcard_derivations() {
|
||||
let (spk, changeset) = txout_index.next_unused_spk(&TestKeychain::External);
|
||||
assert_eq!(spk, (0, external_spk.as_script()));
|
||||
assert_eq!(changeset.as_inner(), &[].into());
|
||||
let (revealed_spks, revealed_additions) =
|
||||
let (revealed_spks, revealed_changeset) =
|
||||
txout_index.reveal_to_target(&TestKeychain::External, 200);
|
||||
assert_eq!(revealed_spks.count(), 0);
|
||||
assert!(revealed_additions.is_empty());
|
||||
assert!(revealed_changeset.is_empty());
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@ mod common;
|
||||
use bdk_chain::{
|
||||
collections::*,
|
||||
local_chain::LocalChain,
|
||||
tx_graph::{Additions, TxGraph},
|
||||
tx_graph::{ChangeSet, TxGraph},
|
||||
Anchor, Append, BlockId, ChainPosition, ConfirmationHeightAnchor,
|
||||
};
|
||||
use bitcoin::{
|
||||
@@ -70,7 +70,7 @@ fn insert_txouts() {
|
||||
for (outpoint, txout) in &original_ops {
|
||||
assert_eq!(
|
||||
graph.insert_txout(*outpoint, txout.clone()),
|
||||
Additions {
|
||||
ChangeSet {
|
||||
txouts: [(*outpoint, txout.clone())].into(),
|
||||
..Default::default()
|
||||
}
|
||||
@@ -86,7 +86,7 @@ fn insert_txouts() {
|
||||
// Insert partials transactions
|
||||
assert_eq!(
|
||||
graph.insert_txout(*outpoint, txout.clone()),
|
||||
Additions {
|
||||
ChangeSet {
|
||||
txouts: [(*outpoint, txout.clone())].into(),
|
||||
..Default::default()
|
||||
}
|
||||
@@ -94,7 +94,7 @@ fn insert_txouts() {
|
||||
// Mark them unconfirmed.
|
||||
assert_eq!(
|
||||
graph.insert_anchor(outpoint.txid, unconf_anchor),
|
||||
Additions {
|
||||
ChangeSet {
|
||||
txs: [].into(),
|
||||
txouts: [].into(),
|
||||
anchors: [(unconf_anchor, outpoint.txid)].into(),
|
||||
@@ -104,7 +104,7 @@ fn insert_txouts() {
|
||||
// Mark them last seen at.
|
||||
assert_eq!(
|
||||
graph.insert_seen_at(outpoint.txid, 1000000),
|
||||
Additions {
|
||||
ChangeSet {
|
||||
txs: [].into(),
|
||||
txouts: [].into(),
|
||||
anchors: [].into(),
|
||||
@@ -115,7 +115,7 @@ fn insert_txouts() {
|
||||
// Insert the full transaction
|
||||
assert_eq!(
|
||||
graph.insert_tx(update_txs.clone()),
|
||||
Additions {
|
||||
ChangeSet {
|
||||
txs: [update_txs.clone()].into(),
|
||||
..Default::default()
|
||||
}
|
||||
@@ -124,7 +124,7 @@ fn insert_txouts() {
|
||||
// Mark it as confirmed.
|
||||
assert_eq!(
|
||||
graph.insert_anchor(update_txs.txid(), conf_anchor),
|
||||
Additions {
|
||||
ChangeSet {
|
||||
txs: [].into(),
|
||||
txouts: [].into(),
|
||||
anchors: [(conf_anchor, update_txs.txid())].into(),
|
||||
@@ -135,11 +135,11 @@ fn insert_txouts() {
|
||||
};
|
||||
|
||||
// Check the resulting addition.
|
||||
let additions = graph.determine_additions(&update);
|
||||
let changeset = graph.apply_update(update);
|
||||
|
||||
assert_eq!(
|
||||
additions,
|
||||
Additions {
|
||||
changeset,
|
||||
ChangeSet {
|
||||
txs: [update_txs.clone()].into(),
|
||||
txouts: update_ops.into(),
|
||||
anchors: [(conf_anchor, update_txs.txid()), (unconf_anchor, h!("tx2"))].into(),
|
||||
@@ -147,8 +147,8 @@ fn insert_txouts() {
|
||||
}
|
||||
);
|
||||
|
||||
// Apply addition and check the new graph counts.
|
||||
graph.apply_additions(additions);
|
||||
// Apply changeset and check the new graph counts.
|
||||
graph.apply_changeset(changeset);
|
||||
assert_eq!(graph.all_txouts().count(), 4);
|
||||
assert_eq!(graph.full_txs().count(), 1);
|
||||
assert_eq!(graph.floating_txouts().count(), 3);
|
||||
@@ -299,7 +299,7 @@ fn insert_tx_displaces_txouts() {
|
||||
},
|
||||
);
|
||||
|
||||
let _additions = tx_graph.insert_tx(tx.clone());
|
||||
let _changeset = tx_graph.insert_tx(tx.clone());
|
||||
|
||||
assert_eq!(
|
||||
tx_graph
|
||||
@@ -333,7 +333,7 @@ fn insert_txout_does_not_displace_tx() {
|
||||
}],
|
||||
};
|
||||
|
||||
let _additions = tx_graph.insert_tx(tx.clone());
|
||||
let _changeset = tx_graph.insert_tx(tx.clone());
|
||||
|
||||
let _ = tx_graph.insert_txout(
|
||||
OutPoint {
|
||||
@@ -794,7 +794,7 @@ fn test_chain_spends() {
|
||||
|
||||
/// Ensure that `last_seen` values only increase during [`Append::append`].
|
||||
#[test]
|
||||
fn test_additions_last_seen_append() {
|
||||
fn test_changeset_last_seen_append() {
|
||||
let txid: Txid = h!("test txid");
|
||||
|
||||
let test_cases: &[(Option<u64>, Option<u64>)] = &[
|
||||
@@ -806,11 +806,11 @@ fn test_additions_last_seen_append() {
|
||||
];
|
||||
|
||||
for (original_ls, update_ls) in test_cases {
|
||||
let mut original = Additions::<()> {
|
||||
let mut original = ChangeSet::<()> {
|
||||
last_seen: original_ls.map(|ls| (txid, ls)).into_iter().collect(),
|
||||
..Default::default()
|
||||
};
|
||||
let update = Additions::<()> {
|
||||
let update = ChangeSet::<()> {
|
||||
last_seen: update_ls.map(|ls| (txid, ls)).into_iter().collect(),
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user