Skip to content

fix(electrum): refresh header cache with headers fetched for the chain update - #2320

Open
evanlinjin wants to merge 2 commits into
bitcoindevkit:masterfrom
evanlinjin:fix/electrum-stale-header-cache-master
Open

evanlinjin wants to merge 2 commits into
bitcoindevkit:masterfrom
evanlinjin:fix/electrum-stale-header-cache-master

Conversation

@evanlinjin

Copy link
Copy Markdown
Member

Description

Forward-port of #2319 to master.

block_header_cache was only written by batch_fetch_anchors, so after a reorg it kept the pre-reorg header for that height. A tx re-mined at the same height then hit the anchor cache under the stale block hash, skipped proof validation, and was never re-anchored to the replacement block. This happens even for a 1-block reorg.

fetch_tip_and_latest_blocks now writes the headers it fetches (the chain suffix and the agreement-walk checkpoints) into the header cache.

Notes to the reviewers

Only differences from #2319: the fetch_tip_and_latest_blocks signature keeps master's CheckPoint<BlockHash>, and the test uses master's TestEnv / LocalChain APIs. The test fails on master without the fix.

Related: #2312.

Changelog notice

  • Fixed bdk_electrum returning a stale anchor for a transaction re-mined at the same height after a reorg.

Checklists

All Submissions:

Bugfixes:

  • This pull request breaks the existing API
  • I've added tests to reproduce the issue which are now passing
  • I'm linking the issue being fixed by this PR

🤖 Generated with Claude Code

@codecov

codecov Bot commented Sep 18, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 94.73684% with 1 line in your changes missing coverage. Please review.
✅ Project coverage is 78.87%. Comparing base (e417c43) to head (6c5e977).

Files with missing lines Patch % Lines
crates/electrum/src/bdk_electrum_client.rs 94.73% 1 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##           master    #2320      +/-   ##
==========================================
+ Coverage   78.84%   78.87%   +0.02%     
==========================================
  Files          31       31              
  Lines        6060     6072      +12     
  Branches      288      288              
==========================================
+ Hits         4778     4789      +11     
- Misses       1203     1204       +1     
  Partials       79       79              
Flag Coverage Δ
rust 78.87% <94.73%> (+0.02%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

evanlinjin and others added 2 commits September 18, 2026 10:14
…n update

`block_header_cache` was only written by `batch_fetch_anchors`, so after a
reorg it kept serving the pre-reorg header for that height. The anchor
cache is keyed by `(txid, hash)` from that header, so a tx re-mined at the
same height hit the anchor cache with the stale hash, skipped proof
validation, and was never re-anchored to the replacement block.

`fetch_tip_and_latest_blocks` now writes the headers it fetches (the
chain suffix and the agreement-walk checkpoints) into the header cache.
Checks the tx is re-anchored to the replacement block both when the
reorged height is still in the synced chain suffix and when 20 blocks are
mined before the next sync.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@evanlinjin
evanlinjin force-pushed the fix/electrum-stale-header-cache-master branch from 6444d74 to 6c5e977 Compare September 18, 2026 10:14
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: No status

Development

Successfully merging this pull request may close these issues.

1 participant