Skip to main content

RPC Endpoints Reference

Why This Chapter Exists

The narrative for the RPC layer lives in chapter 05. This chapter is the flat reference: every JSON-RPC method and every gRPC streaming endpoint that zebra-rpc exposes, in a single grep-friendly index, with the signature, the source line, and the access category.

Use this page to answer "does Zebra implement <method>?" without reading the 3000-line zebra-rpc/src/methods.rs trait by hand.

Configuration

Both RPC servers are disabled by default. They are opted in through the [rpc] config section, with the following fields (from zebra-rpc/src/config/rpc.rs):

zebra-rpc/src/config/rpc.rs (Config struct)
loading...

Recommended ports follow the zcashd convention:

NetworkJSON-RPC default portIndexer gRPC default port
Mainnet127.0.0.1:8232127.0.0.1:8230 (suggested)
Testnet127.0.0.1:18232127.0.0.1:18230 (suggested)

The indexer gRPC server additionally requires the indexer Cargo feature at build time. See "Indexer gRPC" below.

Authentication and Exposure

  • Cookie auth is on by default for JSON-RPC (enable_cookie_auth = true). The cookie file is written under cookie_dir at startup and must accompany every request. Clients on the same host can read the file; remote clients cannot.
  • There is no built-in rate limiting. If listen_addr is bound to a public IP, every method below is reachable by every actor on the internet; some of them (sendrawtransaction, submitblock, generate, invalidateblock, addnode, stop) are state-changing. Bind to 127.0.0.1 unless a reverse proxy with auth and rate limiting sits in front.
  • max_response_body_size caps the per-response body in bytes. Default is large enough for full blocks but not unbounded.

For the broader security stance (rate limiting, header-based auth, binding discipline), see ~/.claude/rules/security-audit.md and chapter 09.

JSON-RPC: The Rpc Trait

Every method below is declared on a single jsonrpsee trait:

zebra-rpc/src/methods.rs (Rpc trait declaration)
loading...

The full trait is just under 800 lines; each #[method(name = "...")] attribute declares a JSON-RPC method name as zcashd would expect it. The tables below group the 37 methods by purpose.

Blockchain Queries

Read-only queries that need only the local chain state.

Method (RPC name)Signature (Rust)Source
getinfoasync fn get_info() -> Result<GetInfoResponse>methods.rs#L194-L195
getblockchaininfoasync fn get_blockchain_info() -> Result<GetBlockchainInfoResponse>methods.rs#L207-L208
getbestblockhashfn get_best_block_hash() -> Result<GetBlockHashResponse>methods.rs#L316-L317
getbestblockheightandhashfn get_best_block_height_and_hash() -> Result<GetBlockHeightAndHashResponse>methods.rs#L324-L325
getblockcountfn get_block_count() -> Result<u32>methods.rs#L484-L485
getblockhashasync fn get_block_hash(index: i32) -> Result<GetBlockHashResponse>methods.rs#L502-L503
getblockasync fn get_block(hash_or_height: String, verbosity: Option<u8>) -> Result<GetBlockResponse>methods.rs#L280-L281
getblockheaderasync fn get_block_header(hash_or_height: String, verbose: Option<bool>) -> Result<GetBlockHeaderResponse>methods.rs#L304-L305
getblocksubsidyasync fn get_block_subsidy(height: Option<u32>) -> Result<GetBlockSubsidyResponse>methods.rs#L665-L666
getdifficultyasync fn get_difficulty() -> Result<f64>methods.rs#L673-L674

Shielded-Aware Queries

Reads that touch the Sapling or Orchard note commitment trees. See chapter 03 on anchors for the underlying data structure.

MethodSignatureSource
z_gettreestateasync fn z_get_treestate(hash_or_height: String) -> Result<GetTreestateResponse>methods.rs#L361-L362
z_getsubtreesbyindexasync fn z_get_subtrees_by_index(pool: String, start_index: NoteCommitmentSubtreeIndex, limit: Option<u16>) -> ...methods.rs#L382-L383
z_validateaddressasync fn z_validate_address(address: String) -> Result<ZValidateAddressResponse>methods.rs#L648-L649
z_listunifiedreceiversasync fn z_list_unified_receivers(...)methods.rs#L689-L690

The z_getsubtreesbyindex method feeds ZIP-307 (lightwalletd-style streaming) clients. The matching indexing column families (sapling_note_commitment_subtree, orchard_note_commitment_subtree) are listed in chapter 04's storage section.

Transaction and Mempool

Mempool reads plus transaction submission. The sendrawtransaction endpoint is the only public-facing write that does not require an admin privilege.

MethodSignatureSource
getmempoolinfoasync fn get_mempool_info() -> Result<GetMempoolInfoResponse>methods.rs#L330-L331
getrawmempoolasync fn get_raw_mempool(verbose: Option<bool>) -> Result<GetRawMempoolResponse>methods.rs#L342-L343
getrawtransactionasync fn get_raw_transaction(txid: String, verbose: Option<u8>, block_hash: Option<String>) -> Result<GetRawTransactionResponse>methods.rs#L401-L402
sendrawtransactionasync fn send_raw_transaction(hex: String, max_fee_rate: Option<f64>) -> Result<SendRawTransactionResponse>methods.rs#L254-L255
gettxoutasync fn get_tx_out(txid: String, index: u32, include_mempool: Option<bool>) -> Result<...>methods.rs#L760-L761

Address-Indexed Lookups

These three rely on the per-transparent-address indexing column families (balance_by_transparent_addr, tx_loc_by_transparent_addr_loc, utxo_loc_by_transparent_addr_loc) catalogued in chapter 04's storage section. They are the surface that wallets and explorers consume.

MethodSignatureSource
getaddressbalanceasync fn get_address_balance(address_strings: AddressStrings) -> Result<AddressBalance>methods.rs#L232-L233
getaddresstxidsasync fn get_address_tx_ids(request: GetAddressTxIdsRequest) -> Result<Vec<String>>methods.rs#L438-L439
getaddressutxosasync fn get_address_utxos(address_strings: AddressStrings) -> Result<Vec<GetAddressUtxos>>methods.rs#L459-L460

Mining

The getblocktemplate / submitblock pair is the miner-facing surface; the mining-info, hash-rate, and network-solps queries support it. generate is regtest-only and panics on mainnet.

MethodSignatureSource
getblocktemplateasync fn get_block_template(parameters: Option<JsonParameters>) -> Result<...>methods.rs#L526-L527
submitblockasync fn submit_block(hex_data: HexData, _options: Option<...>) -> Result<...>methods.rs#L547-L548
getmininginfoasync fn get_mining_info() -> Result<GetMiningInfoResponse>methods.rs#L559-L560
getnetworksolpsasync fn get_network_sol_ps(num_blocks: Option<i32>, height: Option<i32>) -> Result<u64>methods.rs#L572-L573
getnetworkhashpsasync fn get_network_hash_ps(num_blocks: Option<i32>, height: Option<i32>) -> Result<u64>methods.rs#L585-L586
generateasync fn generate(num_blocks: u32) -> Result<Vec<GetBlockHashResponse>>methods.rs#L713-L727

Network and Peer Management

MethodSignatureSource
getnetworkinfoasync fn get_network_info() -> Result<GetNetworkInfoResponse>methods.rs#L599-L600
getpeerinfoasync fn get_peer_info() -> Result<Vec<PeerInfo>>methods.rs#L607-L608
pingasync fn ping() -> Result<()>methods.rs#L618-L619
addnodeasync fn add_node(addr: PeerSocketAddr, command: AddNodeCommand) -> Result<()>methods.rs#L729-L744
validateaddressasync fn validate_address(address: String) -> Result<ValidateAddressResponse>methods.rs#L631-L632

Admin and Chain Surgery

State-changing endpoints used for node administration and (in the case of invalidateblock / reconsiderblock) manual fork management. Treat as production-dangerous; do not expose externally.

MethodSignatureSource
stopfn stop() -> Result<String>methods.rs#L475-L476
invalidateblockasync fn invalidate_block(block_hash: String) -> Result<()>methods.rs#L702-L703
reconsiderblockasync fn reconsider_block(block_hash: String) -> Result<Vec<block::Hash>>methods.rs#L710-L711

Discovery

A single OpenRPC discovery endpoint returns the machine-readable schema for all of the above.

MethodSignatureSource
rpc.discoverfn openrpc() -> openrpsee::openrpc::Responsemethods.rs#L747-L748

Indexer gRPC (Streaming)

Opt-in via the indexer Cargo feature plus rpc.indexer_listen_addr. The protobuf is at zebra-rpc/proto/indexer.proto:

zebra-rpc/proto/indexer.proto (service)
loading...
RPCDirectionPayloadPurpose
ChainTipChangeserver-streamingBlockHashAndHeightNotify every change of the best chain tip.
NonFinalizedStateChangeserver-streamingBlockAndHashNotify every block appended to the non-finalized fork forest.
MempoolChangeserver-streamingMempoolChangeMessageNotify ADDED / INVALIDATED / MINED for every mempool transition.

These streams are how Zaino and similar indexers stay live without polling. Server-streaming means one request, many responses; the client closes the stream to unsubscribe.

Failure Modes

  • Public binding without a reverse proxy. Every write endpoint becomes attacker-controlled. Bind to 127.0.0.1 or put a reverse proxy with auth and rate limiting in front. The listen_addr doc comment in zebra-rpc/src/config/rpc.rs calls this out explicitly.
  • Cookie auth disabled in error. Setting enable_cookie_auth = false makes every method on listen_addr unauthenticated. Only do this when something else (mutual TLS, network ACL) provides the boundary.
  • generate on mainnet. The method exists but panics outside regtest. If you see it called, the caller is confused, not malicious.
  • invalidateblock outside a coordinated rollback. The finalized state cannot be rewound; calling this on a finalized block is a no-op but logs an error.
  • gRPC stream backpressure. The three indexer streams will drop notifications under sustained slow consumers. A client that treats stream delivery as a write-ahead log will diverge from the node.

Spec Pointers

Exercises

  1. Pick one method from the Admin table and trace its implementation under zebra-rpc/src/methods/. Identify every state mutation it performs and the Tower service it goes through.
  2. The getrawtransaction method accepts an optional block_hash. Find the code path that uses it and explain in two sentences what the parameter changes about the lookup.
  3. Start Zebra with [rpc] listen_addr = '127.0.0.1:8232' and enable_cookie_auth = true. From the same host, invoke getinfo using curl and the cookie file. From a different host on the LAN, confirm the same call fails with 401.
  4. Add a debug log inside MempoolChange that prints change_type per notification. Run against testnet for ten minutes and summarise the distribution of ADDED vs INVALIDATED vs MINED.

Further Reading

  • Chapter 05 for the narrative introduction to the RPC layer.
  • Chapter 18 for how this surface composes with mining (getblocktemplate) and wallets (Zaino / Zallet).
  • Chapter 04 for the indexing column families that back the address-indexed and shielded subtree methods.