Skip to content

Commit

Permalink
feat(chain): Introduce tx_graph::Update WIP
Browse files Browse the repository at this point in the history
  • Loading branch information
LagginTimes committed Aug 15, 2024
1 parent caef3f4 commit 9411021
Showing 1 changed file with 55 additions and 31 deletions.
86 changes: 55 additions & 31 deletions crates/chain/src/tx_graph.rs
Original file line number Diff line number Diff line change
Expand Up @@ -640,15 +640,15 @@ impl<A: Clone + Ord> TxGraph<A> {
///
/// 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>) -> ChangeSet<A> {
let changeset = self.determine_changeset(update);
pub fn apply_update(&mut self, update: impl Into<Update<A>>) -> ChangeSet<A> {
let changeset = self.determine_changeset(update.into());
self.apply_changeset(changeset.clone());
changeset
}

/// Determines the [`ChangeSet`] between `self` and an empty [`TxGraph`].
pub fn initial_changeset(&self) -> ChangeSet<A> {
Self::default().determine_changeset(self.clone())
Self::default().determine_changeset(Update::from(self.clone()))
}

/// Applies [`ChangeSet`] to [`TxGraph`].
Expand Down Expand Up @@ -715,36 +715,24 @@ impl<A: Clone + Ord> TxGraph<A> {
///
/// The [`ChangeSet`] would be the set difference between `update` and `self` (transactions that
/// exist in `update` but not in `self`).
pub(crate) fn determine_changeset(&self, update: TxGraph<A>) -> ChangeSet<A> {
pub(crate) fn determine_changeset(&self, update: Update<A>) -> ChangeSet<A> {
let mut changeset = ChangeSet::<A>::default();

for (&txid, (update_tx_node, _)) in &update.txs {
match (self.txs.get(&txid), update_tx_node) {
(None, TxNodeInternal::Whole(update_tx)) => {
changeset.txs.insert(update_tx.clone());
}
(None, TxNodeInternal::Partial(update_txos)) => {
changeset.txouts.extend(
update_txos
.iter()
.map(|(&vout, txo)| (OutPoint::new(txid, vout), txo.clone())),
);
}
(Some((TxNodeInternal::Whole(_), _)), _) => {}
(Some((TxNodeInternal::Partial(_), _)), TxNodeInternal::Whole(update_tx)) => {
changeset.txs.insert(update_tx.clone());
}
(
Some((TxNodeInternal::Partial(txos), _)),
TxNodeInternal::Partial(update_txos),
) => {
changeset.txouts.extend(
update_txos
.iter()
.filter(|(vout, _)| !txos.contains_key(*vout))
.map(|(&vout, txo)| (OutPoint::new(txid, vout), txo.clone())),
);
}
for (txid, tx) in update.whole_txs {
if matches!(
self.txs.get(&txid),
None | Some((TxNodeInternal::Partial(_), _))
) {
changeset.txs.insert(tx);
}
}

for (op, txout) in update.partial_txs {
if matches!(
self.txs.get(&op.txid),
None | Some((TxNodeInternal::Partial(_), _))
) {
changeset.txouts.insert(op, txout);
}
}

Expand All @@ -761,6 +749,42 @@ impl<A: Clone + Ord> TxGraph<A> {
}
}

/// An update to [`TxGraph`].
pub struct Update<A> {
whole_txs: HashMap<Txid, Arc<Transaction>>,
partial_txs: HashMap<OutPoint, TxOut>,
last_seen: HashMap<Txid, u64>,
anchors: BTreeSet<(A, Txid)>,
}

impl<A> Default for Update<A> {
fn default() -> Self {
Update {
whole_txs: HashMap::new(),
partial_txs: HashMap::new(),
last_seen: HashMap::new(),
anchors: BTreeSet::new(),
}
}
}

impl<A> From<TxGraph<A>> for Update<A> {
fn from(graph: TxGraph<A>) -> Self {
Update {
whole_txs: graph
.full_txs()
.map(|value| (value.txid, value.tx))
.collect::<HashMap<_, _>>(),
partial_txs: graph
.floating_txouts()
.map(|(op, txout)| (op, txout.clone()))
.collect::<HashMap<_, _>>(),
last_seen: graph.last_seen,
anchors: graph.anchors,
}
}
}

impl<A: Anchor> TxGraph<A> {
/// Get the position of the transaction in `chain` with tip `chain_tip`.
///
Expand Down

0 comments on commit 9411021

Please sign in to comment.