bitcoindevkit / bitcoindevkit/bdk

Electrum tip height is truncated with `as u32`

Open Beginner friendly
#2,294 0 comments 0 reactions 0 assignees View on GitHub
bug
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

Open the contributing 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

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.