Skip to content

zebra-rpc ships a stale indexer reflection descriptor: build.rs can never update binary generated filesΒ #11225

Description

@oxarbitrage

zebra-rpc checks its generated protobuf artifacts into proto/__generated__/ so the crate builds without protoc. When protoc is available, build.rs refreshes them β€” except the refresh can never fire for the binary descriptor.

zebra-rpc/build.rs:45:

if fs::read_to_string(&out_path).ok() != fs::read_to_string(&generated_path).ok() {
    fs::copy(out_path, generated_path)?;
}

indexer_descriptor.bin isn't valid UTF-8, so both reads fail, .ok() maps both to None, and None != None is false. The other branch of the same function (line 53) already uses binary-safe fs::read.

So the committed descriptor has been frozen since #9819 created the mechanism (2025-09-12), and went stale when #10776 added rpc GetBlock (2026-06-23). The .proto declares it:

$ curl -s https://raw.githubusercontent.com/ZcashFoundation/zebra/main/zebra-rpc/proto/indexer.proto | grep "rpc GetBlock"
  rpc GetBlock(BlockRequest) returns (BlockAndHash);

The shipped descriptor doesn't:

$ curl -sO https://raw.githubusercontent.com/ZcashFoundation/zebra/main/zebra-rpc/proto/__generated__/indexer_descriptor.bin
$ strings indexer_descriptor.bin | grep -E "^(ChainTipChange|MempoolChange|NonFinalizedStateChange|GetBlock)$"
ChainTipChange
NonFinalizedStateChange
MempoolChange

BlockRequest is missing too.

Impact is limited: the descriptor only feeds tonic_reflection, and the service comes from the generated .rs, which updates fine β€” so GetBlock works, it just isn't discoverable by reflection. Only builds without protoc read the committed file, i.e. crates.io consumers, for whom grpcurl and similar won't list it.

CI can't catch this. CI has protoc, so it regenerates into OUT_DIR and passes regardless of what's committed. Nothing compares the committed artifacts to the .proto. That matters more going forward β€” #10953 adds a second descriptor and ~2,300 lines of generated Rust under the same unverified path.

Fix

  • Use fs::read in the refresh comparison, matching line 53.
  • Commit the regenerated indexer_descriptor.bin.
  • Add a CI step that builds with protoc then runs git diff --exit-code -- zebra-rpc/proto/__generated__.

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-rpcArea: Remote Procedure Call interfacesC-bugCategory: This is a bugP-Low ❄️

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions