Skip to content

Commit

Permalink
[persist_redesign] Add is_empty method to Append trait
Browse files Browse the repository at this point in the history
`Store::append_changeset` logic now checks whether the changeset is
empty, and if so, it skips persisting.
  • Loading branch information
evanlinjin committed May 4, 2023
1 parent 6ac7d25 commit d2e7b48
Show file tree
Hide file tree
Showing 9 changed files with 52 additions and 29 deletions.
4 changes: 4 additions & 0 deletions crates/chain/src/indexed_tx_graph.rs
Original file line number Diff line number Diff line change
Expand Up @@ -301,6 +301,10 @@ impl<A: Anchor, IA: Append> Append for IndexedAdditions<A, IA> {
self.graph_additions.append(other.graph_additions);
self.index_additions.append(other.index_additions);
}

fn is_empty(&self) -> bool {
self.graph_additions.is_empty() && self.index_additions.is_empty()
}
}

/// Represents a structure that can index transaction data.
Expand Down
14 changes: 8 additions & 6 deletions crates/chain/src/keychain.rs
Original file line number Diff line number Diff line change
Expand Up @@ -59,11 +59,6 @@ pub use txout_index::*;
pub struct DerivationAdditions<K>(pub BTreeMap<K, u32>);

impl<K> DerivationAdditions<K> {
/// Returns whether the additions are empty.
pub fn is_empty(&self) -> bool {
self.0.is_empty()
}

/// Get the inner map of the keychain to its new derivation index.
pub fn as_inner(&self) -> &BTreeMap<K, u32> {
&self.0
Expand All @@ -84,6 +79,10 @@ impl<K: Ord> Append for DerivationAdditions<K> {

self.0.append(&mut other.0);
}

fn is_empty(&self) -> bool {
self.0.is_empty()
}
}

impl<K> Default for DerivationAdditions<K> {
Expand Down Expand Up @@ -159,7 +158,10 @@ impl<K, P> Default for KeychainChangeSet<K, P> {

impl<K, P> KeychainChangeSet<K, P> {
/// Returns whether the [`KeychainChangeSet`] is empty (no changes recorded).
pub fn is_empty(&self) -> bool {
pub fn is_empty(&self) -> bool
where
K: Ord,
{
self.chain_graph.is_empty() && self.derivation_indices.is_empty()
}

Expand Down
4 changes: 4 additions & 0 deletions crates/chain/src/remote_chain.rs
Original file line number Diff line number Diff line change
Expand Up @@ -86,4 +86,8 @@ impl Append for ChangeSet {
*self = other;
}
}

fn is_empty(&self) -> bool {
self.is_none()
}
}
16 changes: 2 additions & 14 deletions crates/chain/src/tracker.rs
Original file line number Diff line number Diff line change
Expand Up @@ -341,20 +341,8 @@ impl<K: Ord, A: Anchor, CC: Append> Append for ChangeSet<K, A, CC> {
Append::append(&mut self.indexed_additions, other.indexed_additions);
Append::append(&mut self.chain_changeset, other.chain_changeset)
}
}

impl<K, A> LocalChangeSet<K, A> {
pub fn is_empty(&self) -> bool {
self.indexed_additions.index_additions.is_empty()
&& self.indexed_additions.graph_additions.is_empty()
&& self.chain_changeset.is_empty()
}
}

impl<K, A> RemoteChangeSet<K, A> {
pub fn is_empty(&self) -> bool {
self.indexed_additions.index_additions.is_empty()
&& self.indexed_additions.graph_additions.is_empty()
&& self.chain_changeset.is_none()
fn is_empty(&self) -> bool {
self.indexed_additions.is_empty() && self.chain_changeset.is_empty()
}
}
15 changes: 15 additions & 0 deletions crates/chain/src/tx_data_traits.rs
Original file line number Diff line number Diff line change
Expand Up @@ -64,20 +64,35 @@ impl<A: Anchor> Anchor for &'static A {
pub trait Append {
/// Append another object of the same type onto `self`.
fn append(&mut self, other: Self);

/// Determines whether the structure is empty.
fn is_empty(&self) -> bool;
}

impl Append for () {
fn append(&mut self, _other: Self) {}

fn is_empty(&self) -> bool {
true
}
}

impl<K: Ord, V> Append for BTreeMap<K, V> {
fn append(&mut self, mut other: Self) {
BTreeMap::append(self, &mut other)
}

fn is_empty(&self) -> bool {
BTreeMap::is_empty(self)
}
}

impl<T: Ord> Append for BTreeSet<T> {
fn append(&mut self, mut other: Self) {
BTreeSet::append(self, &mut other)
}

fn is_empty(&self) -> bool {
BTreeSet::is_empty(self)
}
}
13 changes: 8 additions & 5 deletions crates/chain/src/tx_graph.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
//! # use bdk_chain::BlockId;
//! # use bdk_chain::tx_graph::TxGraph;
//! # use bdk_chain::example_utils::*;
//! # use bdk_chain::Append;
//! # use bitcoin::Transaction;
//! # let tx_a = tx_from_hex(RAW_TX_1);
//! # let tx_b = tx_from_hex(RAW_TX_2);
Expand Down Expand Up @@ -906,11 +907,6 @@ impl<A> Default for Additions<A> {
}

impl<A> Additions<A> {
/// Returns true if the [`Additions`] is empty (no transactions or txouts).
pub fn is_empty(&self) -> bool {
self.tx.is_empty() && self.txout.is_empty()
}

/// Iterates over all outpoints contained within [`Additions`].
pub fn txouts(&self) -> impl Iterator<Item = (OutPoint, &TxOut)> {
self.tx
Expand Down Expand Up @@ -940,6 +936,13 @@ impl<A: Ord> Append for Additions<A> {
.collect::<Vec<_>>(),
);
}

fn is_empty(&self) -> bool {
self.tx.is_empty()
&& self.txout.is_empty()
&& self.anchors.is_empty()
&& self.last_seen.is_empty()
}
}

impl<A> AsRef<TxGraph<A>> for TxGraph<A> {
Expand Down
1 change: 1 addition & 0 deletions crates/chain/tests/test_keychain_txout_index.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ mod common;
use bdk_chain::{
collections::BTreeMap,
keychain::{DerivationAdditions, KeychainTxOutIndex},
Append,
};

use bitcoin::{secp256k1::Secp256k1, OutPoint, Script, Transaction, TxOut};
Expand Down
2 changes: 1 addition & 1 deletion crates/file_store/src/keychain_store.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
//! [`KeychainChangeSet`]s which can be used to restore a [`KeychainTracker`].
use bdk_chain::{
keychain::{KeychainChangeSet, KeychainTracker},
sparse_chain,
sparse_chain, Append,
};
use bincode::Options;
use std::{
Expand Down
12 changes: 9 additions & 3 deletions crates/file_store/src/store.rs
Original file line number Diff line number Diff line change
Expand Up @@ -172,10 +172,12 @@ where
///
/// The truncation is to avoid the possibility of having a valid but inconsistent changeset
/// directly after the appended changeset.
///
/// **WARNING**: This method does not detect whether the changeset is empty or not, and will
/// append an empty changeset to the file (not catastrophic, just a waste of space).
pub fn append_changeset(&mut self, changeset: &C) -> Result<(), io::Error> {
// no need to write anything if changeset is empty
if changeset.is_empty() {
return Ok(());
}

bincode_options()
.serialize_into(&mut self.db_file, changeset)
.map_err(|e| match *e {
Expand Down Expand Up @@ -243,6 +245,10 @@ mod test {
fn append(&mut self, mut other: Self) {
self.changes.append(&mut other.changes)
}

fn is_empty(&self) -> bool {
self.changes.is_empty()
}
}

#[derive(Debug)]
Expand Down

0 comments on commit d2e7b48

Please sign in to comment.