Skip to content

Conversation

shesek
Copy link
Collaborator

@shesek shesek commented Sep 30, 2025

Prior to this change, the local electrs mempool was only updated with new transactions once we were able to get a complete snapshot of every transaction in bitcoind's mempool, which could require multiple rounds of attempts if any transactions are replaced (or otherwise evicted) between querying for the mempool txids and querying for the transactions themselves.

PR #89 made each round more efficient, but obtaining a complete snapshot can still potentially take many rounds the more RBF is used, with each round taking longer the larger the mempool gets (just listing the mempool txids to find the delta becomes costly).

With this change, the local mempool is instead updated with whatever transactions we are able to get, without waiting for a fully consistent snapshot - which should improve performance and reduce latency.

Making partial updates requires some extra care on the electrs side to ensure mempool consistency (i.e., no double-spends or missing input txos), since we can no longer fully rely on bitcoind validating consistency for us. Specifically:

  • If any mempool transactions became unavailable (replaced) by the time we queried for them, we explicitly check for transactions that depend on the missing transactions (or their descendants) and remove them too.

  • Mempool evictions are processed first before any additions, even if the replacing transactions aren't available. This ensures double-spend conflicts are not possible. (technically this was already the case, but now it became more critical)

Prior to this change, the local electrs mempool was only updated with new transactions
once we were able to get a complete snapshot of every transaction in bitcoind's mempool,
which could require multiple rounds of attempts if any transactions are replaced (or otherwise
evicted) between querying for the mempool txids and querying for the transactions themselves.

PR romanz#89 made each round more efficient, but obtaining a complete snapshot can still potentially
take many rounds the more RBF is used, with each round taking longer the larger the mempool gets
(just listing the mempool txids to find the delta becomes costly).

With this change, the local mempool is instead updated with whatever transactions we are able to get,
without waiting for a fully consistent snapshot - which should improve performance and reduce latency.

Making partial updates requires some extra care on the electrs side to ensure mempool consistency
(i.e., no double-spends or missing input txos), since we can no longer fully rely on bitcoind
validating consistency for us. Specifically:

- If any transactions were RBF'd and gone by the time we queried for them, we explicitly check for
  transactions that depend on the missing transactions (or their descendants) and remove them too.

- Mempool evictions must be processed first before any additions, even if the replacing transactions
  aren't available. This ensures double-spend conflicts are not possible.
@shesek shesek force-pushed the 202509-partial-mempool-sync branch from c7285eb to 3ff2156 Compare September 30, 2025 16:02
@shesek
Copy link
Collaborator Author

shesek commented Sep 30, 2025

This could definitely use some tests, but testing the edge-cases here is pretty tricky (in particular, the case where we manage to get the child tx before the parent is RBF'd, but then miss the parent). Still thinking on ways to approach it.

@philippem
Copy link
Collaborator

tack

Comment on lines +542 to +545
let new_txids = bitcoind_txids
.iter()
.filter(|&txid| !indexed_txids.contains(txid))
.collect::<Vec<_>>();
Copy link
Collaborator

@RCasatta RCasatta Oct 10, 2025

Choose a reason for hiding this comment

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

nit: shouldn't this be another difference() ?

@RCasatta
Copy link
Collaborator

just listing the mempool txids to find the delta becomes costly

just mentioning it is usually pretty fast, I am doing similar logic in another repo

image image

Copy link
Collaborator

@RCasatta RCasatta left a comment

Choose a reason for hiding this comment

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

utACK 3ff2156

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants