Electrum: `batch_fetch_anchors` keeps returning the pre-reorg anchor once header and anchor caches are populated
Dieses Issue hat noch niemand übernommen.
Bewertung
- Schwierigkeit
- 3/5
- Geschätzter Aufwand
- 1-2 Tage
- Anfängerfreundlichkeit
- 76/100
- Issue-Typ
- Bug
- Klarheit
- Klar beschrieben
- Aktivitätsstatus
- Aktiv
- Tech-Stack
- rust
- Bereich
- blockchain
Rechercherichtung
Beginne in crates/electrum/src/bdk_electrum_client.rs bei batch_fetch_anchors und dem nahegelegenen test_batch_fetch_anchors_reorg_uses_new_hash. Führe cargo test -p bdk_electrum --lib batch_fetch_anchors_after_reorg_with_populated_caches mit der bereitgestellten Reproduktion aus. Fertig ist es, wenn der Reorg-Test mit befüllten Caches erfolgreich ist und der zurückgegebene anchor den Block-Hash verwendet, der sich derzeit auf dieser Höhe befindet.
Vom Indexierungsmodell aus dem Issue-Text verfasst.
Beschreibung
Describe the bug
batch_fetch_anchors (crates/electrum/src/bdk_electrum_client.rs) derives each height's block hash from block_header_cache and, on an anchor_cache hit for (txid, hash), returns the cached anchor without fetching a header or validating a merkle proof. The header cache is only refreshed when a proof fails to validate, which never happens on the cached path. So once both caches hold the pre-reorg state for a (txid, height), a reorg that re-includes the transaction in a different block at the same height goes unnoticed: every subsequent call returns the anchor with the replaced block's hash, for the lifetime of the BdkElectrumClient.
fetch_tip_and_latest_blocks does pick up the new hash for the LocalChain, so the sync result has a chain with the new hash at that height and an anchor pointing at the old one. Canonicalization then treats the transaction as unconfirmed even though it is confirmed, and later syncs with the same client do not correct it. The existing test_batch_fetch_anchors_reorg_uses_new_hash only covers the case where the anchor cache is empty.
This issue was found by AI.
To Reproduce
Add the following to the test module in crates/electrum/src/bdk_electrum_client.rs (next to test_batch_fetch_anchors_reorg_uses_new_hash) and run cargo test -p bdk_electrum --lib batch_fetch_anchors_after_reorg_with_populated_caches:
#[cfg(feature = "default")]
#[test]
fn batch_fetch_anchors_after_reorg_with_populated_caches() -> anyhow::Result<()> {
let env = TestEnv::new()?;
let client = electrum_client::Client::new(env.electrsd.electrum_url.as_str()).unwrap();
let electrum_client = BdkElectrumClient::new(client);
env.mine_blocks(101, None)?;
let addr = env
.rpc_client()
.get_new_address(None, None)?
.address()?
.assume_checked();
let txid = env.send(&addr, Amount::from_sat(50_000))?;
env.mine_blocks(1, None)?;
env.wait_until_electrum_sees_block(Duration::from_secs(6))?;
let height = env.rpc_client().get_block_count()?.into_model().0 as usize;
// First call populates both the header cache and the anchor cache.
let pre_reorg = electrum_client.batch_fetch_anchors(&[(txid, height)])?;
let stale_hash = pre_reorg[0].1.block_id.hash;
// Replace the confirming block; the tx is re-included at the same height.
env.reorg(1)?;
env.wait_until_electrum_sees_block(Duration::from_secs(6))?;
let new_hash = electrum_client.inner.block_header(height)?.block_hash();
assert_ne!(new_hash, stale_hash);
let anchors = electrum_client.batch_fetch_anchors(&[(txid, height)])?;
assert_eq!(anchors[0].1.block_id.hash, new_hash);
Ok(())
}
Current output:
assertion `left == right` failed
left: 5cb52f60b4f1ef75606e44e9dc8356fd6ca043eb887a613d6c498f1095930652
right: 34b9db58142dc754829f9094e68c48a5b1c911f5d1ea84a531758fa906789605
Expected behavior
After a reorg, anchors returned by batch_fetch_anchors should reflect the block currently at that height rather than a previously cached one.
- Vorherrschende Sprache
- Rust
- Sterne
- 1.1k
- Forks
- 491
- Ø Merge
- 1 T. 5 Std.
- Gemergte PRs (30 T.)
- 1
Beitragsleitfaden
Erste Schritte
- Lesen Sie das ganze Issue und danach den Beitragsleitfaden des Projekts.
- Schreiben Sie ins Issue, dass Sie es übernehmen — das erspart doppelte Arbeit.
- Forken Sie das Repository und arbeiten Sie in einem Branch.
- Öffnen Sie einen Pull Request, der die Issue-Nummer nennt.
Mehr aus bitcoindevkit/bdk
-
bug
Schwierigkeit 2/5 1-3 Stunden Anfängerfreundlichkeit 84/100
bitcoindevkit/bdk#2309 ·
-
bug
Schwierigkeit 2/5 1-3 Stunden Anfängerfreundlichkeit 84/100
bitcoindevkit/bdk#2308 ·
-
bug
Schwierigkeit 2/5 1-3 Stunden Anfängerfreundlichkeit 84/100
bitcoindevkit/bdk#2307 ·
-
bug
Schwierigkeit 2/5 1-3 Stunden Anfängerfreundlichkeit 82/100
bitcoindevkit/bdk#2294 ·
-
bug
Schwierigkeit 2/5 1-3 Stunden Anfängerfreundlichkeit 88/100
bitcoindevkit/bdk#2293 ·
Alle Issues in bitcoindevkit/bdk
Ähnliche Issues
-
Schwierigkeit 2/5 1-3 Stunden Anfängerfreundlichkeit 84/100
Eynzof/Hermes-CN-Desktop#610 ·
-
bug
Schwierigkeit 2/5 1-3 Stunden Anfängerfreundlichkeit 68/100
gitbutlerapp/gitbutler#15998 · 1 Kommentar ·
-
bug triage:deciding
Schwierigkeit 1/5 Unter einer Stunde Anfängerfreundlichkeit 88/100
open-telemetry/otel-arrow#4132 ·
-
Schwierigkeit 2/5 1-3 Stunden Anfängerfreundlichkeit 88/100
-
Schwierigkeit 2/5 1-3 Stunden Anfängerfreundlichkeit 84/100