Self::is_compatible_with_core(&descriptor)?;
let blockheight = if include_blockheight {
- wallet
- .transactions()
- .next()
- .map_or(0, |canonical_tx| match canonical_tx.observed_as {
+ wallet.transactions().next().map_or(0, |canonical_tx| {
+ match canonical_tx.chain_position {
bdk_chain::ChainPosition::Confirmed(a) => a.confirmation_height,
bdk_chain::ChainPosition::Unconfirmed(_) => 0,
- })
+ }
+ })
} else {
0
};
};
pub use bdk_chain::keychain::Balance;
use bdk_chain::{
- indexed_tx_graph::IndexedAdditions,
- keychain::{KeychainTxOutIndex, LocalChangeSet, LocalUpdate},
+ indexed_tx_graph,
+ keychain::{KeychainTxOutIndex, WalletChangeSet, WalletUpdate},
local_chain::{self, CannotConnectError, CheckPoint, CheckPointIter, LocalChain},
tx_graph::{CanonicalTx, TxGraph},
Append, BlockId, ChainPosition, ConfirmationTime, ConfirmationTimeAnchor, FullTxOut,
}
/// The update to a [`Wallet`] used in [`Wallet::apply_update`]. This is usually returned from blockchain data sources.
-pub type Update = LocalUpdate<KeychainKind, ConfirmationTimeAnchor>;
+pub type Update = WalletUpdate<KeychainKind, ConfirmationTimeAnchor>;
/// The changeset produced internally by [`Wallet`] when mutated.
-pub type ChangeSet = LocalChangeSet<KeychainKind, ConfirmationTimeAnchor>;
+pub type ChangeSet = WalletChangeSet<KeychainKind, ConfirmationTimeAnchor>;
/// The address index selection strategy to use to derived an address from the wallet's external
/// descriptor. See [`Wallet::get_address`]. If you're unsure which one to use use `WalletIndex::New`.
};
let changeset = db.load_from_persistence().map_err(NewError::Persist)?;
- chain.apply_changeset(&changeset.chain_changeset);
- indexed_graph.apply_additions(changeset.indexed_additions);
+ chain.apply_changeset(&changeset.chain);
+ indexed_graph.apply_changeset(changeset.index_tx_graph);
let persist = Persist::new(db);
{
let keychain = self.map_keychain(keychain);
let txout_index = &mut self.indexed_graph.index;
- let (index, spk, additions) = match address_index {
+ let (index, spk, changeset) = match address_index {
AddressIndex::New => {
- let ((index, spk), index_additions) = txout_index.reveal_next_spk(&keychain);
- (index, spk.into(), Some(index_additions))
+ let ((index, spk), index_changeset) = txout_index.reveal_next_spk(&keychain);
+ (index, spk.into(), Some(index_changeset))
}
AddressIndex::LastUnused => {
- let ((index, spk), index_additions) = txout_index.next_unused_spk(&keychain);
- (index, spk.into(), Some(index_additions))
+ let ((index, spk), index_changeset) = txout_index.next_unused_spk(&keychain);
+ (index, spk.into(), Some(index_changeset))
}
AddressIndex::Peek(index) => {
let (index, spk) = txout_index
}
};
- if let Some(additions) = additions {
+ if let Some(changeset) = changeset {
self.persist
- .stage(ChangeSet::from(IndexedAdditions::from(additions)));
+ .stage(ChangeSet::from(indexed_tx_graph::ChangeSet::from(
+ changeset,
+ )));
self.persist.commit()?;
}
let graph = self.indexed_graph.graph();
let canonical_tx = CanonicalTx {
- observed_as: graph.get_chain_position(
+ chain_position: graph.get_chain_position(
&self.chain,
self.chain.tip().map(|cp| cp.block_id()).unwrap_or_default(),
txid,
)?,
- node: graph.get_tx_node(txid)?,
+ tx_node: graph.get_tx_node(txid)?,
};
Some(new_tx_details(
Some(ref drain_recipient) => drain_recipient.clone(),
None => {
let change_keychain = self.map_keychain(KeychainKind::Internal);
- let ((index, spk), index_additions) =
+ let ((index, spk), index_changeset) =
self.indexed_graph.index.next_unused_spk(&change_keychain);
let spk = spk.into();
self.indexed_graph.index.mark_used(&change_keychain, index);
self.persist
- .stage(ChangeSet::from(IndexedAdditions::from(index_additions)));
+ .stage(ChangeSet::from(indexed_tx_graph::ChangeSet::from(
+ index_changeset,
+ )));
self.persist.commit().expect("TODO");
spk
}
.indexed_graph
.graph()
.get_chain_position(&self.chain, chain_tip, input.previous_output.txid)
- .map(|observed_as| match observed_as {
+ .map(|chain_position| match chain_position {
ChainPosition::Confirmed(a) => a.confirmation_height,
ChainPosition::Unconfirmed(_) => u32::MAX,
});
.graph()
.get_chain_position(&self.chain, chain_tip, txid)
{
- Some(observed_as) => observed_as.cloned().into(),
+ Some(chain_position) => chain_position.cloned().into(),
None => return false,
};
D: PersistBackend<ChangeSet>,
{
let mut changeset = ChangeSet::from(self.chain.apply_update(update.chain)?);
- let (_, index_additions) = self
+ let (_, index_changeset) = self
.indexed_graph
.index
.reveal_to_target_multi(&update.last_active_indices);
- changeset.append(ChangeSet::from(IndexedAdditions::from(index_additions)));
+ changeset.append(ChangeSet::from(indexed_tx_graph::ChangeSet::from(
+ index_changeset,
+ )));
changeset.append(ChangeSet::from(
self.indexed_graph.apply_update(update.graph),
));
) -> TransactionDetails {
let graph = indexed_graph.graph();
let index = &indexed_graph.index;
- let tx = canonical_tx.node.tx;
+ let tx = canonical_tx.tx_node.tx;
let received = tx
.output
TransactionDetails {
transaction: if include_raw { Some(tx.clone()) } else { None },
- txid: canonical_tx.node.txid,
+ txid: canonical_tx.tx_node.txid,
received,
sent,
fee,
- confirmation_time: canonical_tx.observed_as.cloned().into(),
+ confirmation_time: canonical_tx.chain_position.cloned().into(),
}
}
.transactions()
.last()
.unwrap()
- .observed_as
+ .chain_position
.cloned()
.into(),
)
.transactions()
.last()
.unwrap()
- .observed_as
+ .chain_position
.cloned()
.into();
wallet.insert_tx(init_tx, pos).unwrap();
use bitcoin::{OutPoint, Transaction, TxOut};
use crate::{
- keychain::DerivationAdditions,
- tx_graph::{Additions, TxGraph},
+ keychain,
+ tx_graph::{self, TxGraph},
Anchor, Append,
};
}
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`.
&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)
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();
&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) {
acc
}),
);
- additions
+ changeset
}
}
)
)]
#[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;
//! [`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")]
/// 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",
)
)]
#[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.
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
}
///
/// [`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>,
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(),
}
}
-/// 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",
)
)
)]
-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()
}
}
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`.
use crate::Append;
-use super::DerivationAdditions;
-
/// A convenient wrapper around [`SpkTxOutIndex`] that relates script pubkeys to miniscript public
/// [`Descriptor`]s.
///
/// 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
}
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 {
/// 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:
/// 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(),
}
}
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
/// 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
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();
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 => (
descriptor.clone(),
next_reveal_index..next_reveal_index,
),
- DerivationAdditions::default(),
+ super::ChangeSet::default(),
),
}
}
/// 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.
/// # 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
/// # 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 {
self.unused_spks_of_keychain(keychain)
.next()
.expect("we already know next exists"),
- DerivationAdditions::default(),
+ super::ChangeSet::default(),
)
}
}
.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);
}
}
}
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.
}
//! 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`].
//!
//! ```
//! # 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`].
//! 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::{
#[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> {
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,
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
+ let changeset = self.determine_changeset(update);
+ self.apply_changeset(changeset.clone());
+ changeset
}
- /// Returns the resultant [`Additions`] if the given transaction is inserted. Does not actually
- /// mutate [`Self`].
+ /// Inserts the given transaction into [`TxGraph`].
///
- /// The [`Additions`] result will be empty if `tx` already exists in `self`.
- pub fn insert_tx_preview(&self, tx: Transaction) -> 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
.txs
.insert(tx.txid(), (TxNodeInternal::Whole(tx), BTreeSet::new(), 0));
- self.determine_additions(&update)
- }
-
- /// 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> {
- let mut update = Self::default();
- update.anchors.insert((anchor, txid));
- self.determine_additions(&update)
+ 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
}
}
- for (outpoint, txout) in additions.txouts {
+ for (outpoint, txout) in changeset.txouts {
let tx_entry = self
.txs
.entry(outpoint.txid)
}
}
- 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;
}
}
- /// 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())),
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))
};
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
}
}
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()
/// 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.
)
)]
#[must_use]
-pub struct Additions<A = ()> {
+pub struct ChangeSet<A = ()> {
/// Added transactions.
pub txs: BTreeSet<Transaction>,
/// Added txouts.
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(),
}
}
-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()
}
}
-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);
}
}
-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)
}
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,
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()),
}
)
}
mod common;
use bdk_chain::{
collections::BTreeMap,
- keychain::{DerivationAdditions, KeychainTxOutIndex},
+ keychain::{self, KeychainTxOutIndex},
Append,
};
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"
);
}
// - 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()
);
// - 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<_>>(),
.collect::<Vec<_>>(),
);
assert_eq!(
- revealed_additions.as_inner(),
+ revealed_changeset.as_inner(),
&[(TestKeychain::Internal, 24)].into()
);
assert_eq!(
],
..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)
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!(
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]
// - 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()));
// - 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)
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);
});
// 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);
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());
}
use bdk_chain::{
collections::*,
local_chain::LocalChain,
- tx_graph::{Additions, TxGraph},
+ tx_graph::{ChangeSet, TxGraph},
Anchor, Append, BlockId, ChainPosition, ConfirmationHeightAnchor,
};
use bitcoin::{
for (outpoint, txout) in &original_ops {
assert_eq!(
graph.insert_txout(*outpoint, txout.clone()),
- Additions {
+ ChangeSet {
txouts: [(*outpoint, txout.clone())].into(),
..Default::default()
}
// Insert partials transactions
assert_eq!(
graph.insert_txout(*outpoint, txout.clone()),
- Additions {
+ ChangeSet {
txouts: [(*outpoint, txout.clone())].into(),
..Default::default()
}
// Mark them unconfirmed.
assert_eq!(
graph.insert_anchor(outpoint.txid, unconf_anchor),
- Additions {
+ ChangeSet {
txs: [].into(),
txouts: [].into(),
anchors: [(unconf_anchor, outpoint.txid)].into(),
// Mark them last seen at.
assert_eq!(
graph.insert_seen_at(outpoint.txid, 1000000),
- Additions {
+ ChangeSet {
txs: [].into(),
txouts: [].into(),
anchors: [].into(),
// Insert the full transaction
assert_eq!(
graph.insert_tx(update_txs.clone()),
- Additions {
+ ChangeSet {
txs: [update_txs.clone()].into(),
..Default::default()
}
// 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(),
};
// 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(),
}
);
- // 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);
},
);
- let _additions = tx_graph.insert_tx(tx.clone());
+ let _changeset = tx_graph.insert_tx(tx.clone());
assert_eq!(
tx_graph
}],
};
- let _additions = tx_graph.insert_tx(tx.clone());
+ let _changeset = tx_graph.insert_tx(tx.clone());
let _ = tx_graph.insert_txout(
OutPoint {
/// 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>)] = &[
];
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()
};
use bdk_chain::{
bitcoin::{OutPoint, ScriptBuf, Transaction, Txid},
- keychain::LocalUpdate,
+ keychain::WalletUpdate,
local_chain::{self, CheckPoint},
tx_graph::{self, TxGraph},
Anchor, BlockId, ConfirmationHeightAnchor, ConfirmationTimeAnchor,
client: &Client,
seen_at: Option<u64>,
missing: Vec<Txid>,
- ) -> Result<LocalUpdate<K, A>, Error> {
+ ) -> Result<WalletUpdate<K, A>, Error> {
let new_txs = client.batch_transaction_get(&missing)?;
let mut graph_update = TxGraph::<A>::new(new_txs);
for (txid, anchors) in self.graph_update {
let _ = graph_update.insert_anchor(txid, anchor);
}
}
- Ok(LocalUpdate {
+ Ok(WalletUpdate {
last_active_indices: self.keychain_update,
graph: graph_update,
chain: local_chain::Update {
client: &Client,
seen_at: Option<u64>,
missing: Vec<Txid>,
- ) -> Result<LocalUpdate<K, ConfirmationTimeAnchor>, Error> {
+ ) -> Result<WalletUpdate<K, ConfirmationTimeAnchor>, Error> {
let update = self.finalize(client, seen_at, missing)?;
let relevant_heights = {
)
.collect::<HashMap<u32, u64>>();
- let graph_additions = {
- let old_additions = TxGraph::default().determine_additions(&update.graph);
- tx_graph::Additions {
- txs: old_additions.txs,
- txouts: old_additions.txouts,
- last_seen: old_additions.last_seen,
- anchors: old_additions
+ let graph_changeset = {
+ let old_changeset = TxGraph::default().apply_update(update.graph.clone());
+ tx_graph::ChangeSet {
+ txs: old_changeset.txs,
+ txouts: old_changeset.txouts,
+ last_seen: old_changeset.last_seen,
+ anchors: old_changeset
.anchors
.into_iter()
.map(|(height_anchor, txid)| {
}
};
- Ok(LocalUpdate {
+ Ok(WalletUpdate {
last_active_indices: update.last_active_indices,
graph: {
let mut graph = TxGraph::default();
- graph.apply_additions(graph_additions);
+ graph.apply_changeset(graph_changeset);
graph
},
chain: update.chain,
absolute, address, psbt::Prevouts, secp256k1::Secp256k1, sighash::SighashCache, Address,
Network, Sequence, Transaction, TxIn, TxOut,
},
- indexed_tx_graph::{IndexedAdditions, IndexedTxGraph},
- keychain::{DerivationAdditions, KeychainTxOutIndex},
+ indexed_tx_graph::{self, IndexedTxGraph},
+ keychain::{self, KeychainTxOutIndex},
miniscript::{
descriptor::{DescriptorSecretKey, KeyMap},
Descriptor, DescriptorPublicKey,
use clap::{Parser, Subcommand};
pub type KeychainTxGraph<A> = IndexedTxGraph<A, KeychainTxOutIndex<Keychain>>;
-pub type KeychainAdditions<A> = IndexedAdditions<A, DerivationAdditions<Keychain>>;
+pub type KeychainChangeSet<A> = indexed_tx_graph::ChangeSet<A, keychain::ChangeSet<Keychain>>;
pub type Database<'m, C> = Persist<Store<'m, C>, C>;
#[derive(Parser)]
cmd: AddressCmd,
) -> anyhow::Result<()>
where
- C: Default + Append + DeserializeOwned + Serialize + From<KeychainAdditions<A>>,
+ C: Default + Append + DeserializeOwned + Serialize + From<KeychainChangeSet<A>>,
{
let index = &mut graph.index;
_ => unreachable!("only these two variants exist in match arm"),
};
- let ((spk_i, spk), index_additions) = spk_chooser(index, &Keychain::External);
+ let ((spk_i, spk), index_changeset) = spk_chooser(index, &Keychain::External);
let db = &mut *db.lock().unwrap();
- db.stage(C::from(KeychainAdditions::from(index_additions)));
+ db.stage(C::from(KeychainChangeSet::from(index_changeset)));
db.commit()?;
let addr = Address::from_script(spk, network).context("failed to derive address")?;
println!("[address @ {}] {}", spk_i, addr);
) -> anyhow::Result<()>
where
O::Error: std::error::Error + Send + Sync + 'static,
- C: Default + Append + DeserializeOwned + Serialize + From<KeychainAdditions<A>>,
+ C: Default + Append + DeserializeOwned + Serialize + From<KeychainChangeSet<A>>,
{
let (transaction, change_index) = {
let graph = &mut *graph.lock().unwrap();
// take mutable ref to construct tx -- it is only open for a short time while building it.
let (tx, change_info) = create_tx(graph, chain, keymap, cs_algorithm, address, value)?;
- if let Some((index_additions, (change_keychain, index))) = change_info {
+ if let Some((index_changeset, (change_keychain, index))) = change_info {
// We must first persist to disk the fact that we've got a new address from the
// change keychain so future scans will find the tx we're about to broadcast.
// If we're unable to persist this, then we don't want to broadcast.
{
let db = &mut *db.lock().unwrap();
- db.stage(C::from(KeychainAdditions::from(index_additions)));
+ db.stage(C::from(KeychainChangeSet::from(index_changeset)));
db.commit()?;
}
Ok(_) => {
println!("Broadcasted Tx : {}", transaction.txid());
- let keychain_additions = graph.lock().unwrap().insert_tx(&transaction, None, None);
+ let keychain_changeset = graph.lock().unwrap().insert_tx(&transaction, None, None);
// We know the tx is at least unconfirmed now. Note if persisting here fails,
// it's not a big deal since we can always find it again form
// blockchain.
- db.lock().unwrap().stage(C::from(keychain_additions));
+ db.lock().unwrap().stage(C::from(keychain_changeset));
Ok(())
}
Err(e) => {
value: u64,
) -> anyhow::Result<(
Transaction,
- Option<(DerivationAdditions<Keychain>, (Keychain, u32))>,
+ Option<(keychain::ChangeSet<Keychain>, (Keychain, u32))>,
)>
where
O::Error: std::error::Error + Send + Sync + 'static,
{
- let mut additions = DerivationAdditions::default();
+ let mut changeset = keychain::ChangeSet::default();
let assets = bdk_tmp_plan::Assets {
keys: keymap.iter().map(|(pk, _)| pk.clone()).collect(),
Keychain::External
};
- let ((change_index, change_script), change_additions) =
+ let ((change_index, change_script), change_changeset) =
graph.index.next_unused_spk(&internal_keychain);
- additions.append(change_additions);
+ changeset.append(change_changeset);
// Clone to drop the immutable reference.
let change_script = change_script.into();
}
let change_info = if selection_meta.drain_value.is_some() {
- Some((additions, (internal_keychain, change_index)))
+ Some((changeset, (internal_keychain, change_index)))
} else {
None
};
) -> anyhow::Result<()>
where
O::Error: std::error::Error + Send + Sync + 'static,
- C: Default + Append + DeserializeOwned + Serialize + From<KeychainAdditions<A>>,
+ C: Default + Append + DeserializeOwned + Serialize + From<KeychainChangeSet<A>>,
{
match cmd {
Commands::ChainSpecific(_) => unreachable!("example code should handle this!"),
use bdk_chain::{
bitcoin::{Address, Network, OutPoint, ScriptBuf, Txid},
- indexed_tx_graph::{IndexedAdditions, IndexedTxGraph},
- keychain::LocalChangeSet,
+ indexed_tx_graph::{self, IndexedTxGraph},
+ keychain::WalletChangeSet,
local_chain::LocalChain,
Append, ConfirmationHeightAnchor,
};
pub batch_size: usize,
}
-type ChangeSet = LocalChangeSet<Keychain, ConfirmationHeightAnchor>;
+type ChangeSet = WalletChangeSet<Keychain, ConfirmationHeightAnchor>;
fn main() -> anyhow::Result<()> {
let (args, keymap, index, db, init_changeset) =
let graph = Mutex::new({
let mut graph = IndexedTxGraph::new(index);
- graph.apply_additions(init_changeset.indexed_additions);
+ graph.apply_changeset(init_changeset.index_tx_graph);
graph
});
- let chain = Mutex::new(LocalChain::from_changeset(init_changeset.chain_changeset));
+ let chain = Mutex::new(LocalChain::from_changeset(init_changeset.chain));
let electrum_url = match args.network {
Network::Bitcoin => "ssl://electrum.blockstream.info:50002",
let unconfirmed_txids = graph
.graph()
.list_chain_txs(&*chain, chain_tip)
- .filter(|canonical_tx| !canonical_tx.observed_as.is_confirmed())
- .map(|canonical_tx| canonical_tx.node.txid)
+ .filter(|canonical_tx| !canonical_tx.chain_position.is_confirmed())
+ .map(|canonical_tx| canonical_tx.tx_node.txid)
.collect::<Vec<Txid>>();
txids = Box::new(unconfirmed_txids.into_iter().inspect(|txid| {
let mut chain = chain.lock().unwrap();
let mut graph = graph.lock().unwrap();
- let chain_changeset = chain.apply_update(final_update.chain)?;
+ let chain = chain.apply_update(final_update.chain)?;
- let indexed_additions = {
- let mut additions = IndexedAdditions::<ConfirmationHeightAnchor, _>::default();
- let (_, index_additions) = graph
+ let index_tx_graph = {
+ let mut changeset =
+ indexed_tx_graph::ChangeSet::<ConfirmationHeightAnchor, _>::default();
+ let (_, indexer) = graph
.index
.reveal_to_target_multi(&final_update.last_active_indices);
- additions.append(IndexedAdditions {
- index_additions,
+ changeset.append(indexed_tx_graph::ChangeSet {
+ indexer,
..Default::default()
});
- additions.append(graph.apply_update(final_update.graph));
- additions
+ changeset.append(graph.apply_update(final_update.graph));
+ changeset
};
ChangeSet {
- indexed_additions,
- chain_changeset,
+ index_tx_graph,
+ chain,
}
};
use bdk::{
bitcoin::{Address, Network},
- chain::keychain::LocalUpdate,
+ chain::keychain::WalletUpdate,
wallet::AddressIndex,
SignOptions, Wallet,
};
client.update_tx_graph(keychain_spks, None, None, STOP_GAP, PARALLEL_REQUESTS)?;
let missing_heights = wallet.tx_graph().missing_heights(wallet.local_chain());
let chain_update = client.update_local_chain(prev_tip, missing_heights)?;
- let update = LocalUpdate {
+ let update = WalletUpdate {
last_active_indices,
graph: update_graph,
- ..LocalUpdate::new(chain_update)
+ ..WalletUpdate::new(chain_update)
};
wallet.apply_update(update)?;
use bdk::{
bitcoin::{Address, Network},
- chain::keychain::LocalUpdate,
+ chain::keychain::WalletUpdate,
wallet::AddressIndex,
SignOptions, Wallet,
};
.await?;
let missing_heights = wallet.tx_graph().missing_heights(wallet.local_chain());
let chain_update = client.update_local_chain(prev_tip, missing_heights).await?;
- let update = LocalUpdate {
+ let update = WalletUpdate {
last_active_indices,
graph: update_graph,
- ..LocalUpdate::new(chain_update)
+ ..WalletUpdate::new(chain_update)
};
wallet.apply_update(update)?;
wallet.commit()?;