Skip to content
Merged
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
85 changes: 85 additions & 0 deletions wallet/src/wallet/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2560,6 +2560,41 @@ impl Wallet {
})
}

/// Introduces a `block` of `height` to the wallet, and tries to connect it to the
/// `prev_blockhash` of the block's header.
///
/// This is a convenience method that is equivalent to calling
/// [`apply_block_connected_to_events`] with `prev_blockhash` and `height-1` as the
/// `connected_to` parameter.
///
/// See [`apply_update_events`] for more information on the returned [`WalletEvent`]s.
///
/// [`apply_block_connected_to_events`]: Self::apply_block_connected_to_events
/// [`apply_update_events`]: Self::apply_update_events
pub fn apply_block_events(
&mut self,
block: &Block,
height: u32,
) -> Result<Vec<WalletEvent>, CannotConnectError> {
let connected_to = match height.checked_sub(1) {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for working on this. I noticed apply_block_events seems to duplicate logic from apply_block. Could we move the event handling from apply_block_connected_to_events into apply_block_events, then have it call apply_block instead of apply_block_connected_to? Would be more consistent with how apply_update_event works and avoid the duplication.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, I intentionally added variants for apply_block as well as for apply_block_connected_to as we may also want to use apply_block_connected_to_events at some point.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You could have apply_block call the new apply_block_events and map the return value to ().

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You could have apply_block call the new apply_block_events and map the return value to ().

Hmm, but that would run the (possibly costly) delta calculation for everybody, even if they wouldn't make use of the events. I believe this is why @notmandatory added separate _event variants of the methods in the first place.

Copy link
Member

@notmandatory notmandatory Oct 30, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In #319 (in v3.0) my plan is to always return events. But for this PR I agree it's best keep the two paths separate so events are only calculated on the _events functions.

Some(prev_height) => BlockId {
height: prev_height,
hash: block.header.prev_blockhash,
},
None => BlockId {
height,
hash: block.block_hash(),
},
};
self.apply_block_connected_to_events(block, height, connected_to)
.map_err(|err| match err {
ApplyHeaderError::InconsistentBlocks => {
unreachable!("connected_to is derived from the block so must be consistent")
}
ApplyHeaderError::CannotConnect(err) => err,
})
}

/// Applies relevant transactions from `block` of `height` to the wallet, and connects the
/// block to the internal chain.
///
Expand Down Expand Up @@ -2591,6 +2626,56 @@ impl Wallet {
Ok(())
}

/// Applies relevant transactions from `block` of `height` to the wallet, and connects the
/// block to the internal chain.
///
/// See [`apply_block_connected_to`] for more information.
///
/// See [`apply_update_events`] for more information on the returned [`WalletEvent`]s.
///
/// [`apply_block_connected_to`]: Self::apply_block_connected_to
/// [`apply_update_events`]: Self::apply_update_events
pub fn apply_block_connected_to_events(
&mut self,
block: &Block,
height: u32,
connected_to: BlockId,
) -> Result<Vec<WalletEvent>, ApplyHeaderError> {
// snapshot of chain tip and transactions before update
let chain_tip1 = self.chain.tip().block_id();
let wallet_txs1 = self
.transactions()
.map(|wtx| {
(
wtx.tx_node.txid,
(wtx.tx_node.tx.clone(), wtx.chain_position),
)
})
.collect::<BTreeMap<Txid, (Arc<Transaction>, ChainPosition<ConfirmationBlockTime>)>>();

self.apply_block_connected_to(block, height, connected_to)?;

// chain tip and transactions after update
let chain_tip2 = self.chain.tip().block_id();
let wallet_txs2 = self
.transactions()
.map(|wtx| {
(
wtx.tx_node.txid,
(wtx.tx_node.tx.clone(), wtx.chain_position),
)
})
.collect::<BTreeMap<Txid, (Arc<Transaction>, ChainPosition<ConfirmationBlockTime>)>>();

Ok(wallet_events(
self,
chain_tip1,
chain_tip2,
wallet_txs1,
wallet_txs2,
))
}

/// Apply relevant unconfirmed transactions to the wallet.
///
/// Transactions that are not relevant are filtered out.
Expand Down
Loading