Skip to content

getheaders with an empty result is never answered, stalling a following zcashd sidecar #198

Description

@arya2

When a peer's getheaders locator yields no headers, zakurad maps the empty result to Response::Nil, which sends nothing on the wire:

zs::Response::BlockHeaders(headers) if headers.is_empty() => zn::Response::Nil,

The getheaders protocol expects a headers reply even when empty (zcashd and Bitcoin Core always send one). With no reply, the requesting zcashd's headers-sync times out ("Peer=1 did not answer getheaders"), and a hard-locked single-peer sidecar enters disconnect/reconnect churn. On a fresh regtest chain (both nodes at genesis) the sidecar never leaves IBD, so its wallet RPCs stay disabled.

On mainnet the impact is bounded: the stall only occurs when the sidecar reaches tip-parity and issues a getheaders that returns empty, and it recovers on the next block inv (~75 s), so it shows up as reconnect churn and log noise rather than a hard failure. On regtest it is fatal.

Reproduce: start zakurad on regtest with a zcashd sidecar (valargroup v1.0.0, sha b861ea94…) pinned via -connect; the sidecar logs the getheaders timeout and never syncs.

Fix reference: fixed upstream in Zebra (ZcashFoundation/zebra#10952, commit de4d3c0e5): always reply with a (possibly empty) headers message. Note that Nil remains correct for getblocks, where sending nothing matches zcashd behavior.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions