From a0727a1fcc0d6e7dfa1071b53eb6e346531372d2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BF=97=E5=AE=87?= Date: Tue, 2 Jan 2024 17:31:34 +0800 Subject: [PATCH] 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. --- crates/bdk/src/wallet/mod.rs | 4 ++-- crates/bitcoind_rpc/tests/test_emitter.rs | 4 ++-- crates/chain/src/indexed_tx_graph.rs | 22 ++++++++++++++-------- 3 files changed, 18 insertions(+), 12 deletions(-) diff --git a/crates/bdk/src/wallet/mod.rs b/crates/bdk/src/wallet/mod.rs index ca16fbf8f2..0fa73dd788 100644 --- a/crates/bdk/src/wallet/mod.rs +++ b/crates/bdk/src/wallet/mod.rs @@ -2383,7 +2383,7 @@ impl Wallet { /// with `prev_blockhash` and `height-1` as the `connected_to` parameter. /// /// [`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 D: PersistBackend, { @@ -2414,7 +2414,7 @@ impl Wallet { /// internal [`TxGraph`]. pub fn apply_block_connected_to( &mut self, - block: Block, + block: &Block, height: u32, connected_to: BlockId, ) -> Result<(), ApplyBlockError> diff --git a/crates/bitcoind_rpc/tests/test_emitter.rs b/crates/bitcoind_rpc/tests/test_emitter.rs index 384df92d06..52d7093010 100644 --- a/crates/bitcoind_rpc/tests/test_emitter.rs +++ b/crates/bitcoind_rpc/tests/test_emitter.rs @@ -298,7 +298,7 @@ fn test_into_tx_graph() -> anyhow::Result<()> { tip: emission.checkpoint, 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()); } @@ -362,7 +362,7 @@ fn test_into_tx_graph() -> anyhow::Result<()> { tip: emission.checkpoint, 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.txouts.is_empty()); assert_eq!(indexed_additions.graph.anchors, exp_anchors); diff --git a/crates/chain/src/indexed_tx_graph.rs b/crates/chain/src/indexed_tx_graph.rs index 777b5d978b..c2b83600b1 100644 --- a/crates/chain/src/indexed_tx_graph.rs +++ b/crates/chain/src/indexed_tx_graph.rs @@ -224,20 +224,26 @@ where /// Irrelevant transactions in `txs` will be ignored. pub fn apply_block_relevant( &mut self, - block: Block, + block: &Block, height: u32, ) -> ChangeSet { let block_id = BlockId { hash: block.block_hash(), height, }; - let txs = block.txdata.iter().enumerate().map(|(tx_pos, tx)| { - ( - tx, - core::iter::once(A::from_block_position(&block, block_id, tx_pos)), - ) - }); - self.batch_insert_relevant(txs) + let mut changeset = ChangeSet::::default(); + for (tx_pos, tx) in block.txdata.iter().enumerate() { + changeset.indexer.append(self.index.index_tx(tx)); + if self.index.is_tx_relevant(tx) { + let txid = tx.txid(); + let anchor = A::from_block_position(block, block_id, tx_pos); + 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`.