feat(chain)!: wrap TxGraph txs with Arc

Wrapping transactions as `Arc<Transaction>` allows us to share
transactions cheaply between the chain-source and receiving structures.
Therefore the chain-source can keep already-fetched transactions (save
bandwidth) and have a shared pointer to the transactions (save memory).

This is better than the current way we do things, which is to refer back
to the receiving structures mid-sync.

Documentation for `TxGraph` is also updated.
This commit is contained in:
志宇
2024-03-14 14:20:51 +08:00
parent 80e190b3e7
commit 8ab58af093
8 changed files with 150 additions and 114 deletions

View File

@@ -1,7 +1,7 @@
#[macro_use]
mod common;
use std::collections::BTreeSet;
use std::{collections::BTreeSet, sync::Arc};
use bdk_chain::{
indexed_tx_graph::{self, IndexedTxGraph},
@@ -66,7 +66,7 @@ fn insert_relevant_txs() {
let changeset = indexed_tx_graph::ChangeSet {
graph: tx_graph::ChangeSet {
txs: txs.clone().into(),
txs: txs.iter().cloned().map(Arc::new).collect(),
..Default::default()
},
indexer: keychain::ChangeSet([((), 9_u32)].into()),
@@ -80,7 +80,6 @@ fn insert_relevant_txs() {
assert_eq!(graph.initial_changeset(), changeset,);
}
#[test]
/// Ensure consistency IndexedTxGraph list_* and balance methods. These methods lists
/// relevant txouts and utxos from the information fetched from a ChainOracle (here a LocalChain).
///
@@ -108,7 +107,7 @@ fn insert_relevant_txs() {
///
/// Finally Add more blocks to local chain until tx1 coinbase maturity hits.
/// Assert maturity at coinbase maturity inflection height. Block height 98 and 99.
#[test]
fn test_list_owned_txouts() {
// Create Local chains
let local_chain = LocalChain::from_blocks((0..150).map(|i| (i as u32, h!("random"))).collect())

View File

@@ -13,6 +13,7 @@ use bitcoin::{
use common::*;
use core::iter;
use rand::RngCore;
use std::sync::Arc;
use std::vec;
#[test]
@@ -119,7 +120,7 @@ fn insert_txouts() {
assert_eq!(
graph.insert_tx(update_txs.clone()),
ChangeSet {
txs: [update_txs.clone()].into(),
txs: [Arc::new(update_txs.clone())].into(),
..Default::default()
}
);
@@ -143,7 +144,7 @@ fn insert_txouts() {
assert_eq!(
changeset,
ChangeSet {
txs: [update_txs.clone()].into(),
txs: [Arc::new(update_txs.clone())].into(),
txouts: update_ops.clone().into(),
anchors: [(conf_anchor, update_txs.txid()), (unconf_anchor, h!("tx2"))].into(),
last_seen: [(h!("tx2"), 1000000)].into()
@@ -194,7 +195,7 @@ fn insert_txouts() {
assert_eq!(
graph.initial_changeset(),
ChangeSet {
txs: [update_txs.clone()].into(),
txs: [Arc::new(update_txs.clone())].into(),
txouts: update_ops.into_iter().chain(original_ops).collect(),
anchors: [(conf_anchor, update_txs.txid()), (unconf_anchor, h!("tx2"))].into(),
last_seen: [(h!("tx2"), 1000000)].into()
@@ -276,7 +277,10 @@ fn insert_tx_can_retrieve_full_tx_from_graph() {
let mut graph = TxGraph::<()>::default();
let _ = graph.insert_tx(tx.clone());
assert_eq!(graph.get_tx(tx.txid()), Some(&tx));
assert_eq!(
graph.get_tx(tx.txid()).map(|tx| tx.as_ref().clone()),
Some(tx)
);
}
#[test]
@@ -643,7 +647,7 @@ fn test_walk_ancestors() {
..common::new_tx(0)
};
let mut graph = TxGraph::<BlockId>::new(vec![
let mut graph = TxGraph::<BlockId>::new([
tx_a0.clone(),
tx_b0.clone(),
tx_b1.clone(),
@@ -664,17 +668,17 @@ fn test_walk_ancestors() {
let ancestors = [
graph
.walk_ancestors(&tx_c0, |depth, tx| Some((depth, tx)))
.walk_ancestors(tx_c0.clone(), |depth, tx| Some((depth, tx)))
.collect::<Vec<_>>(),
graph
.walk_ancestors(&tx_d0, |depth, tx| Some((depth, tx)))
.walk_ancestors(tx_d0.clone(), |depth, tx| Some((depth, tx)))
.collect::<Vec<_>>(),
graph
.walk_ancestors(&tx_e0, |depth, tx| Some((depth, tx)))
.walk_ancestors(tx_e0.clone(), |depth, tx| Some((depth, tx)))
.collect::<Vec<_>>(),
// Only traverse unconfirmed ancestors of tx_e0 this time
graph
.walk_ancestors(&tx_e0, |depth, tx| {
.walk_ancestors(tx_e0.clone(), |depth, tx| {
let tx_node = graph.get_tx_node(tx.txid())?;
for block in tx_node.anchors {
match local_chain.is_block_in_chain(block.anchor_block(), tip.block_id()) {
@@ -701,8 +705,14 @@ fn test_walk_ancestors() {
vec![(1, &tx_d1), (2, &tx_c2), (2, &tx_c3), (3, &tx_b2)],
];
for (txids, expected_txids) in ancestors.iter().zip(expected_ancestors.iter()) {
assert_eq!(txids, expected_txids);
for (txids, expected_txids) in ancestors.into_iter().zip(expected_ancestors) {
assert_eq!(
txids,
expected_txids
.into_iter()
.map(|(i, tx)| (i, Arc::new(tx.clone())))
.collect::<Vec<_>>()
);
}
}