Skip to content

Commit

Permalink
Replace trait AnchorFromBlockPosition with new struct
Browse files Browse the repository at this point in the history
This change replaces a way of creating new generic anchor from block
and its height. Previous way was using conversion trait, newly it is
a struct and `From`.
  • Loading branch information
jirijakes committed Sep 8, 2024
1 parent 257c5f7 commit f2f74da
Show file tree
Hide file tree
Showing 3 changed files with 48 additions and 27 deletions.
2 changes: 1 addition & 1 deletion crates/bitcoind_rpc/tests/test_emitter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -281,7 +281,7 @@ fn process_block(
block_height: u32,
) -> anyhow::Result<()> {
recv_chain.apply_update(CheckPoint::from_header(&block.header, block_height))?;
let _ = recv_graph.apply_block(block, block_height);
let _ = recv_graph.apply_block(&block, block_height);
Ok(())
}

Expand Down
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 @@ -7,7 +7,7 @@ use bitcoin::{Block, OutPoint, Transaction, TxOut, Txid};

use crate::{
tx_graph::{self, TxGraph},
Anchor, AnchorFromBlockPosition, BlockId, Indexer, Merge,
Anchor, BlockId, BlockPosition, Indexer, Merge,
};

/// The [`IndexedTxGraph`] combines a [`TxGraph`] and an [`Indexer`] implementation.
Expand Down Expand Up @@ -253,10 +253,11 @@ where
}

/// Methods are available if the anchor (`A`) implements [`AnchorFromBlockPosition`].
impl<A: Anchor, I: Indexer> IndexedTxGraph<A, I>
impl<'b, A, I> IndexedTxGraph<A, I>
where
I::ChangeSet: Default + Merge,
A: AnchorFromBlockPosition,
A: Anchor + From<BlockPosition<'b>>,
I: Indexer,
{
/// Batch insert all transactions of the given `block` of `height`, filtering out those that are
/// irrelevant.
Expand All @@ -267,24 +268,24 @@ where
/// Relevancy is determined by the internal [`Indexer::is_tx_relevant`] implementation of `I`.
/// Irrelevant transactions in `txs` will be ignored.
pub fn apply_block_relevant(
&mut self,
block: &Block,
&'b mut self,
block: &'b Block,
height: u32,
) -> ChangeSet<A, I::ChangeSet> {
let block_id = BlockId {
hash: block.block_hash(),
height,
};
let mut changeset = ChangeSet::<A, I::ChangeSet>::default();
for (tx_pos, tx) in block.txdata.iter().enumerate() {
for tx in &block.txdata {
changeset.indexer.merge(self.index.index_tx(tx));
if self.index.is_tx_relevant(tx) {
let txid = tx.compute_txid();
let anchor = A::from_block_position(block, block_id, tx_pos);
changeset.tx_graph.merge(self.graph.insert_tx(tx.clone()));
changeset
.tx_graph
.merge(self.graph.insert_anchor(txid, anchor));
changeset.tx_graph.merge(
self.graph
.insert_anchor(txid, BlockPosition::new(block, block_id).into()),
);
}
}
changeset
Expand All @@ -298,15 +299,17 @@ where
/// To only insert relevant transactions, use [`apply_block_relevant`] instead.
///
/// [`apply_block_relevant`]: IndexedTxGraph::apply_block_relevant
pub fn apply_block(&mut self, block: Block, height: u32) -> ChangeSet<A, I::ChangeSet> {
pub fn apply_block(&'b mut self, block: &'b Block, height: u32) -> ChangeSet<A, I::ChangeSet> {
let block_id = BlockId {
hash: block.block_hash(),
height,
};
let mut graph = tx_graph::ChangeSet::default();
for (tx_pos, tx) in block.txdata.iter().enumerate() {
let anchor = A::from_block_position(&block, block_id, tx_pos);
graph.merge(self.graph.insert_anchor(tx.compute_txid(), anchor));
for tx in &block.txdata {
graph.merge(self.graph.insert_anchor(
tx.compute_txid(),
BlockPosition::new(block, block_id).into(),
));
graph.merge(self.graph.insert_tx(tx.clone()));
}
let indexer = self.index_tx_graph_changeset(&graph);
Expand Down
42 changes: 30 additions & 12 deletions crates/chain/src/tx_data_traits.rs
Original file line number Diff line number Diff line change
Expand Up @@ -100,24 +100,42 @@ impl Anchor for ConfirmationBlockTime {
}
}

/// An [`Anchor`] that can be constructed from a given block, block height and transaction position
/// within the block.
pub trait AnchorFromBlockPosition: Anchor {
/// Construct the anchor from a given `block`, block height and `tx_pos` within the block.
fn from_block_position(block: &bitcoin::Block, block_id: BlockId, tx_pos: usize) -> Self;
/// Minimal set of parameters that are needed to construct a generic [`Anchor`].
/// Typically used as an additional constraint on anchor:
/// `A: Anchor + From<BlockPosition<'b>>`.
pub struct BlockPosition<'b> {
block: &'b bitcoin::Block,
block_id: BlockId,
}

impl AnchorFromBlockPosition for BlockId {
fn from_block_position(_block: &bitcoin::Block, block_id: BlockId, _tx_pos: usize) -> Self {
block_id
impl<'b> BlockPosition<'b> {
/// Creates new [`BlockPosition`].
pub fn new(block: &'b bitcoin::Block, block_id: BlockId) -> Self {
Self { block, block_id }
}

/// Returns block associated with this [`BlockPosition`].
pub fn block(&self) -> &bitcoin::Block {
self.block
}

/// Returns block ID associated with this [`BlockPosition`].
pub fn block_id(&self) -> BlockId {
self.block_id
}
}

impl<'b> From<BlockPosition<'b>> for BlockId {
fn from(value: BlockPosition) -> Self {
value.block_id
}
}

impl AnchorFromBlockPosition for ConfirmationBlockTime {
fn from_block_position(block: &bitcoin::Block, block_id: BlockId, _tx_pos: usize) -> Self {
impl<'b> From<BlockPosition<'b>> for ConfirmationBlockTime {
fn from(value: BlockPosition) -> Self {
Self {
block_id,
confirmation_time: block.header.time as _,
block_id: value.block_id,
confirmation_time: value.block.header.time as _,
}
}
}
Expand Down

0 comments on commit f2f74da

Please sign in to comment.