Skip to content

Commit e536307

Browse files
committed
[bdk_chain_redesign] Fix tx_graph::Additions::append logic
* `Additions` now implements `Append` and uses `Append` to implement `append()`. * `append()` logic enforces that `last_seen` values should only increase. * Test written for `append()` with `last_seen` behaviour.
1 parent f101dde commit e536307

3 files changed

Lines changed: 49 additions & 22 deletions

File tree

crates/chain/src/chain_graph.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ use crate::{
33
collections::HashSet,
44
sparse_chain::{self, ChainPosition, SparseChain},
55
tx_graph::{self, TxGraph},
6-
BlockId, ForEachTxOut, FullTxOut, TxHeight,
6+
Append, BlockId, ForEachTxOut, FullTxOut, TxHeight,
77
};
88
use alloc::{string::ToString, vec::Vec};
99
use bitcoin::{OutPoint, Transaction, TxOut, Txid};

crates/chain/src/tx_graph.rs

Lines changed: 16 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,9 @@
5555
//! assert!(additions.is_empty());
5656
//! ```
5757
58-
use crate::{collections::*, Anchor, BlockId, ChainOracle, ForEachTxOut, FullTxOut, ObservedAs};
58+
use crate::{
59+
collections::*, Anchor, Append, BlockId, ChainOracle, ForEachTxOut, FullTxOut, ObservedAs,
60+
};
5961
use alloc::vec::Vec;
6062
use bitcoin::{OutPoint, Transaction, TxOut, Txid};
6163
use core::{
@@ -112,17 +114,6 @@ impl<'a, T, A> Deref for TxNode<'a, T, A> {
112114
}
113115
}
114116

115-
impl<'a, A> TxNode<'a, Transaction, A> {
116-
pub fn from_tx(tx: &'a Transaction, anchors: &'a BTreeSet<A>) -> Self {
117-
Self {
118-
txid: tx.txid(),
119-
tx,
120-
anchors,
121-
last_seen_unconfirmed: 0,
122-
}
123-
}
124-
}
125-
126117
/// Internal representation of a transaction node of a [`TxGraph`].
127118
///
128119
/// This can either be a whole transaction, or a partial transaction (where we only have select
@@ -602,7 +593,7 @@ impl<A: Clone + Ord> TxGraph<A> {
602593

603594
impl<A: Anchor> TxGraph<A> {
604595
/// Get all heights that are relevant to the graph.
605-
pub fn relevant_heights(&self) -> impl DoubleEndedIterator<Item = u32> + '_ {
596+
pub fn relevant_heights(&self) -> impl Iterator<Item = u32> + '_ {
606597
let mut last_height = Option::<u32>::None;
607598
self.anchors
608599
.iter()
@@ -944,17 +935,22 @@ impl<A> Additions<A> {
944935
})
945936
.chain(self.txout.iter().map(|(op, txout)| (*op, txout)))
946937
}
938+
}
947939

948-
/// Appends the changes in `other` into self such that applying `self` afterward has the same
949-
/// effect as sequentially applying the original `self` and `other`.
950-
pub fn append(&mut self, mut other: Additions<A>)
951-
where
952-
A: Ord,
953-
{
940+
impl<A: Ord> Append for Additions<A> {
941+
fn append(&mut self, mut other: Self) {
954942
self.tx.append(&mut other.tx);
955943
self.txout.append(&mut other.txout);
956944
self.anchors.append(&mut other.anchors);
957-
self.last_seen.append(&mut other.last_seen);
945+
946+
// last_seen timestamps should only increase
947+
self.last_seen.extend(
948+
other
949+
.last_seen
950+
.into_iter()
951+
.filter(|(txid, update_ls)| self.last_seen.get(txid) < Some(update_ls))
952+
.collect::<Vec<_>>(),
953+
);
958954
}
959955
}
960956

crates/chain/tests/test_tx_graph.rs

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ use bdk_chain::{
44
collections::*,
55
local_chain::LocalChain,
66
tx_graph::{Additions, TxGraph},
7-
BlockId, ObservedAs,
7+
Append, BlockId, ObservedAs,
88
};
99
use bitcoin::{
1010
hashes::Hash, BlockHash, OutPoint, PackedLockTime, Script, Transaction, TxIn, TxOut, Txid,
@@ -849,3 +849,34 @@ fn test_relevant_heights() {
849849
"anchor for non-existant tx is inserted at height 5, must still be in relevant heights",
850850
);
851851
}
852+
853+
/// Ensure that `last_seen` values only increase during [`Append::append`].
854+
#[test]
855+
fn test_additions_last_seen_append() {
856+
let txid: Txid = h!("test txid");
857+
858+
let test_cases: &[(Option<u64>, Option<u64>)] = &[
859+
(Some(5), Some(6)),
860+
(Some(5), Some(5)),
861+
(Some(6), Some(5)),
862+
(None, Some(5)),
863+
(Some(5), None),
864+
];
865+
866+
for (original_ls, update_ls) in test_cases {
867+
let mut original = Additions::<()> {
868+
last_seen: original_ls.map(|ls| (txid, ls)).into_iter().collect(),
869+
..Default::default()
870+
};
871+
let update = Additions::<()> {
872+
last_seen: update_ls.map(|ls| (txid, ls)).into_iter().collect(),
873+
..Default::default()
874+
};
875+
876+
original.append(update);
877+
assert_eq!(
878+
&original.last_seen.get(&txid).cloned(),
879+
Ord::max(original_ls, update_ls),
880+
);
881+
}
882+
}

0 commit comments

Comments
 (0)