Skip to content

PeerSource.requestBlock tries only one peer per request — a noblock from a leech masks a peer that has the block #2

Description

@melvincarvalho

Problem

requestBlock(hash) picks a single peer — the first one advertising the hash, or (with the forks anyPeer extension) the first free peer — sends one getblock, and resolves null on noblock/timeout. It never tries the next peer.

In a mixed room this is a coin flip per block. Example observed on fork·watch: two peers connected — a store-less forks tab (serves nothing, instant noblock) and a health Blocks tab with ~560 cached blocks. When the fetcher happens to ask the leech first, the request falls back to the explorer even though the other peer holds the block. Result: 'mesh: 2 peers · 0 blocks pulled' during a backfill that should have been largely peer-served.

Health's own catch-up _sync has the same single-shot pick per wanted block.

Proposed fix

Iterate candidates instead of picking one:

  1. Try peers that advertise the hash first (their have map).
  2. Then, when anyPeer is set, try remaining free peers — adverts only cover the newest 100 blocks, but peers serve their whole cache.
  3. Move on to the next candidate on noblock (cheap round-trip) or a short per-peer timeout; keep the overall deadline so the caller's fallback (esplora) isn't delayed much in the worst case.

Skip peers with an in-flight inboundReq as today. No wire-protocol change — purely client-side retry ordering.

Where

Canonical peer-source.js lives here (health); bitcoin-kernel/forks vendors it (with the anyPeer extension) — fix should land here and sync forks-ward, same flow as the mesh-hello/hardening changes.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions