bitcoindevkit / bitcoindevkit/bdk
Electrum tip height is truncated with `as u32`
- Dominant language
- Rust
- Stars
- 1.1k
- Forks
- 483
- Avg merge
- 20d 3h
- Merged PRs (30d)
- 3
Description
**Describe the bug**
`fetch_tip_and_latest_blocks` (used by `BdkElectrumClient::sync` and `full_scan` whenever the request has a `chain_tip`) converts the server-reported tip height with a plain cast (`crates/electrum/src/bdk_electrum_client.rs:656-657`):
```rust
let HeaderNotification { height, .. } = client.block_headers_subscribe()?;
let new_tip_height = height as u32;
```
`HeaderNotification::height` is a `usize` deserialized from the server's JSON response. On 64-bit targets a value of `2^32 + k` silently becomes `k`, so an out-of-range value from a buggy or misbehaving server is processed as a plausible low tip instead of being rejected. Depending on `k`, the function either takes the "server tip is lower than ours" early return or builds the checkpoint update around height `k`, far below the server's real tip. Every height-derived value in the update is then wrong.
The `h as u32` / `height as u32` casts on history heights later in the file cannot overflow today because `GetHistoryRes::height` is `i32`, but they follow the same pattern.
This issue was found by AI.
**To Reproduce**
1. Point a `BdkElectrumClient` at a stub server whose `blockchain.headers.subscribe` response contains `"height": 4294967396` (`2^32 + 100`) and a valid header hex.
2. Call `sync` or `full_scan` with a request whose `chain_tip` is above height 100.
3. `fetch_tip_and_latest_blocks` treats the tip as height 100 and takes the early return, and the sync completes without any error.
**Expected behavior**
A reported tip height that does not fit in `u32` should not be silently truncated into a different, valid-looking height.
Contributor guide
Research direction
Start in crates/electrum/src/bdk_electrum_client.rs at fetch_tip_and_latest_blocks, which is reached by BdkElectrumClient::sync and full_scan when a chain_tip is present. Reproduce the issue with the stub response containing height 4294967396 and inspect the resulting behavior. Done means an out-of-range server-reported height is rejected rather than silently becoming a low, plausible height.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- rust
- Domain
- backend, networking
- Issue type
- Bug
- Difficulty
- 2/5
- Estimated time
- 1-3 hours
- Activity status
- Active
- Clarity
- Clearly specified
- Newbie friendliness
- 82/100