feat(chain)!: make IndexedTxGraph::apply_block_relevant more efficient

Previously, `apply_block_relevant` used `batch_insert_relevant` which
allows inserting non-topologically-ordered transactions. However,
transactions from blocks are always ordered, so we can avoid looping
through block transactions twice (as done in `batch_insert_relevant`).

Additionally, `apply_block_relevant` now takes in a reference to a
`Block` instead of consuming the `Block`. This makes sense as typically
very few of the transactions in the block are inserted.
This commit is contained in:
志宇 2024-01-02 17:31:34 +08:00
parent e0512acf94
commit a7d01dc39a
No known key found for this signature in database
GPG Key ID: F6345C9837C2BDE8
3 changed files with 18 additions and 12 deletions

View File

@ -2385,7 +2385,7 @@ impl<D> Wallet<D> {
/// with `prev_blockhash` and `height-1` as the `connected_to` parameter. /// with `prev_blockhash` and `height-1` as the `connected_to` parameter.
/// ///
/// [`apply_block_connected_to`]: Self::apply_block_connected_to /// [`apply_block_connected_to`]: Self::apply_block_connected_to
pub fn apply_block(&mut self, block: Block, height: u32) -> Result<(), CannotConnectError> pub fn apply_block(&mut self, block: &Block, height: u32) -> Result<(), CannotConnectError>
where where
D: PersistBackend<ChangeSet>, D: PersistBackend<ChangeSet>,
{ {
@ -2416,7 +2416,7 @@ impl<D> Wallet<D> {
/// internal [`TxGraph`]. /// internal [`TxGraph`].
pub fn apply_block_connected_to( pub fn apply_block_connected_to(
&mut self, &mut self,
block: Block, block: &Block,
height: u32, height: u32,
connected_to: BlockId, connected_to: BlockId,
) -> Result<(), ApplyHeaderError> ) -> Result<(), ApplyHeaderError>

View File

@ -298,7 +298,7 @@ fn test_into_tx_graph() -> anyhow::Result<()> {
tip: emission.checkpoint, tip: emission.checkpoint,
introduce_older_blocks: false, introduce_older_blocks: false,
})?; })?;
let indexed_additions = indexed_tx_graph.apply_block_relevant(emission.block, height); let indexed_additions = indexed_tx_graph.apply_block_relevant(&emission.block, height);
assert!(indexed_additions.is_empty()); assert!(indexed_additions.is_empty());
} }
@ -362,7 +362,7 @@ fn test_into_tx_graph() -> anyhow::Result<()> {
tip: emission.checkpoint, tip: emission.checkpoint,
introduce_older_blocks: false, introduce_older_blocks: false,
})?; })?;
let indexed_additions = indexed_tx_graph.apply_block_relevant(emission.block, height); let indexed_additions = indexed_tx_graph.apply_block_relevant(&emission.block, height);
assert!(indexed_additions.graph.txs.is_empty()); assert!(indexed_additions.graph.txs.is_empty());
assert!(indexed_additions.graph.txouts.is_empty()); assert!(indexed_additions.graph.txouts.is_empty());
assert_eq!(indexed_additions.graph.anchors, exp_anchors); assert_eq!(indexed_additions.graph.anchors, exp_anchors);

View File

@ -224,20 +224,26 @@ where
/// Irrelevant transactions in `txs` will be ignored. /// Irrelevant transactions in `txs` will be ignored.
pub fn apply_block_relevant( pub fn apply_block_relevant(
&mut self, &mut self,
block: Block, block: &Block,
height: u32, height: u32,
) -> ChangeSet<A, I::ChangeSet> { ) -> ChangeSet<A, I::ChangeSet> {
let block_id = BlockId { let block_id = BlockId {
hash: block.block_hash(), hash: block.block_hash(),
height, height,
}; };
let txs = block.txdata.iter().enumerate().map(|(tx_pos, tx)| { let mut changeset = ChangeSet::<A, I::ChangeSet>::default();
( for (tx_pos, tx) in block.txdata.iter().enumerate() {
tx, changeset.indexer.append(self.index.index_tx(tx));
core::iter::once(A::from_block_position(&block, block_id, tx_pos)), if self.index.is_tx_relevant(tx) {
) let txid = tx.txid();
}); let anchor = A::from_block_position(block, block_id, tx_pos);
self.batch_insert_relevant(txs) changeset.graph.append(self.graph.insert_tx(tx.clone()));
changeset
.graph
.append(self.graph.insert_anchor(txid, anchor));
}
}
changeset
} }
/// Batch insert all transactions of the given `block` of `height`. /// Batch insert all transactions of the given `block` of `height`.