Skip to content

Commit

Permalink
feat(chain,wallet)!: change methods to take in generic instead of `&T…
Browse files Browse the repository at this point in the history
…ransaction`

* `Wallet::apply_unconfirmed_txs`
* `IndexedTxGraph::batch_insert_relevant`
* `IndexedTxGraph::batch_insert_relevant_unconfirmed`
  • Loading branch information
evanlinjin committed Sep 3, 2024
1 parent c39284d commit 87e6121
Show file tree
Hide file tree
Showing 5 changed files with 30 additions and 27 deletions.
31 changes: 17 additions & 14 deletions crates/chain/src/indexed_tx_graph.rs
Original file line number Diff line number Diff line change
Expand Up @@ -156,38 +156,38 @@ where
///
/// Relevancy is determined by the [`Indexer::is_tx_relevant`] implementation of `I`. Irrelevant
/// transactions in `txs` will be ignored. `txs` do not need to be in topological order.
pub fn batch_insert_relevant<'t>(
pub fn batch_insert_relevant<T: Into<Arc<Transaction>>>(
&mut self,
txs: impl IntoIterator<Item = (&'t Transaction, impl IntoIterator<Item = A>)>,
txs: impl IntoIterator<Item = (T, impl IntoIterator<Item = A>)>,
) -> 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 txs = txs.into_iter().collect::<Vec<_>>();
let txs = txs
.into_iter()
.map(|(tx, anchors)| (<T as Into<Arc<Transaction>>>::into(tx), anchors))
.collect::<Vec<_>>();

let mut indexer = I::ChangeSet::default();
for (tx, _) in &txs {
indexer.merge(self.index.index_tx(tx));
}

let mut graph = tx_graph::ChangeSet::default();
let mut tx_graph = tx_graph::ChangeSet::default();
for (tx, anchors) in txs {
if self.index.is_tx_relevant(tx) {
if self.index.is_tx_relevant(&tx) {
let txid = tx.compute_txid();
graph.merge(self.graph.insert_tx(tx.clone()));
tx_graph.merge(self.graph.insert_tx(tx.clone()));
for anchor in anchors {
graph.merge(self.graph.insert_anchor(txid, anchor));
tx_graph.merge(self.graph.insert_anchor(txid, anchor));
}
}
}

ChangeSet {
tx_graph: graph,
indexer,
}
ChangeSet { tx_graph, indexer }
}

/// Batch insert unconfirmed transactions, filtering out those that are irrelevant.
Expand All @@ -198,17 +198,20 @@ where
/// Items of `txs` are tuples containing the transaction and a *last seen* timestamp. The
/// *last seen* communicates when the transaction is last seen in the mempool which is used for
/// conflict-resolution in [`TxGraph`] (refer to [`TxGraph::insert_seen_at`] for details).
pub fn batch_insert_relevant_unconfirmed<'t>(
pub fn batch_insert_relevant_unconfirmed<T: Into<Arc<Transaction>>>(
&mut self,
unconfirmed_txs: impl IntoIterator<Item = (&'t Transaction, u64)>,
unconfirmed_txs: impl IntoIterator<Item = (T, u64)>,
) -> 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 txs = unconfirmed_txs.into_iter().collect::<Vec<_>>();
let txs = unconfirmed_txs
.into_iter()
.map(|(tx, last_seen)| (<T as Into<Arc<Transaction>>>::into(tx), last_seen))
.collect::<Vec<_>>();

let mut indexer = I::ChangeSet::default();
for (tx, _) in &txs {
Expand Down
9 changes: 5 additions & 4 deletions crates/chain/tests/test_indexed_tx_graph.rs
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ fn insert_relevant_txs() {
};

assert_eq!(
graph.batch_insert_relevant(txs.iter().map(|tx| (tx, None))),
graph.batch_insert_relevant(txs.iter().cloned().map(|tx| (tx, None))),
changeset,
);

Expand Down Expand Up @@ -237,10 +237,10 @@ fn test_list_owned_txouts() {
// Insert unconfirmed txs with a last_seen timestamp

let _ =
graph.batch_insert_relevant([&tx1, &tx2, &tx3, &tx6].iter().enumerate().map(|(i, tx)| {
graph.batch_insert_relevant([&tx1, &tx2, &tx3, &tx6].iter().enumerate().map(|(i, &tx)| {
let height = i as u32;
(
*tx,
tx.clone(),
local_chain
.get(height)
.map(|cp| cp.block_id())
Expand All @@ -251,7 +251,8 @@ fn test_list_owned_txouts() {
)
}));

let _ = graph.batch_insert_relevant_unconfirmed([&tx4, &tx5].iter().map(|tx| (*tx, 100)));
let _ =
graph.batch_insert_relevant_unconfirmed([&tx4, &tx5].iter().map(|&tx| (tx.clone(), 100)));

// A helper lambda to extract and filter data from the graph.
let fetch =
Expand Down
4 changes: 2 additions & 2 deletions crates/wallet/src/wallet/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2441,9 +2441,9 @@ impl Wallet {
/// **WARNING**: You must persist the changes resulting from one or more calls to this method
/// if you need the applied unconfirmed transactions to be reloaded after closing the wallet.
/// See [`Wallet::reveal_next_address`].
pub fn apply_unconfirmed_txs<'t>(
pub fn apply_unconfirmed_txs<T: Into<Arc<Transaction>>>(
&mut self,
unconfirmed_txs: impl IntoIterator<Item = (&'t Transaction, u64)>,
unconfirmed_txs: impl IntoIterator<Item = (T, u64)>,
) {
let indexed_graph_changeset = self
.indexed_graph
Expand Down
11 changes: 5 additions & 6 deletions example-crates/example_bitcoind_rpc_polling/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -201,9 +201,10 @@ fn main() -> anyhow::Result<()> {
}

let mempool_txs = emitter.mempool()?;
let graph_changeset = graph.lock().unwrap().batch_insert_relevant_unconfirmed(
mempool_txs.iter().map(|(tx, time)| (tx, *time)),
);
let graph_changeset = graph
.lock()
.unwrap()
.batch_insert_relevant_unconfirmed(mempool_txs);
{
let db = &mut *db.lock().unwrap();
db_stage.merge(ChangeSet {
Expand Down Expand Up @@ -286,9 +287,7 @@ fn main() -> anyhow::Result<()> {
(chain_changeset, graph_changeset)
}
Emission::Mempool(mempool_txs) => {
let graph_changeset = graph.batch_insert_relevant_unconfirmed(
mempool_txs.iter().map(|(tx, time)| (tx, *time)),
);
let graph_changeset = graph.batch_insert_relevant_unconfirmed(mempool_txs);
(local_chain::ChangeSet::default(), graph_changeset)
}
Emission::Tip(h) => {
Expand Down
2 changes: 1 addition & 1 deletion example-crates/wallet_rpc/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,7 @@ fn main() -> anyhow::Result<()> {
}
Emission::Mempool(mempool_emission) => {
let start_apply_mempool = Instant::now();
wallet.apply_unconfirmed_txs(mempool_emission.iter().map(|(tx, time)| (tx, *time)));
wallet.apply_unconfirmed_txs(mempool_emission);
wallet.persist(&mut db)?;
println!(
"Applied unconfirmed transactions in {}s",
Expand Down

0 comments on commit 87e6121

Please sign in to comment.