コンテンツにスキップ

JSON-RPC

UMNode serves its API over JSON-RPC 2.0 on HTTP. The server is built for throughput — Go's net/http for the transport, sonic for JSON encoding/decoding, and pooled gzip writers for optional response compression — so it can answer many small reads quickly.

It is enabled by default and binds 0.0.0.0:8550. Each call is timed: a Debug log line, plus — when --metrics-addr is set — a per-method latency histogram. See Observability.

Browser explorer at /docs

Open the RPC address in a browser and you're redirected to /docs — a small built-in explorer (no external assets), laid out in three columns: a method outline on the left (grouped by namespace), the selected method's documentation filling the middle, and a 60%-wide request / response pane on the right. Pick a method from the outline and it pre-fills a ready-to-send request; edit it and press ⌘/Ctrl + Enter to see the pretty-printed reply below, with its HTTP status, round-trip time and response size, and a Wrap toggle for wide JSON. Under the documentation, a cURL panel mirrors the request as a ready-to-run shell command against the page's own endpoint — it follows every edit to the request (valid JSON is compacted onto one line; anything else is passed through verbatim and flagged) — and its Copy button puts the command on the clipboard for a terminal. The method list and per-method docs come from GET /docs/methods; the explorer POSTs to the same endpoint your own client would. It's served wherever RPC is, so a node behind --rpc-addr exposes it too — keep that in mind on a public bind.

A small, growing surface

Standard Ethereum methods: block and transaction reads (eth_blockNumber, eth_getBlockByNumber, eth_getBlockByHash, eth_getTransactionByHash), receipts and logs (eth_getTransactionReceipt, eth_getBlockReceipts, eth_getLogs), and the state methods (eth_call, the getters, eth_chainId, the callTracer traces). Plus UMNode-specific debug methods: debug_getBlockArtifact (a block exactly as the store persists it), debug_listPeers (the live p2p peer set), debug_getP2PBlockArtifact (force-fetch a block over p2p and see the wire exchange), and node / index / state / receipts management. More methods register as the store gains the data to back them.

Settings

Flag Default Meaning
--rpc-addr 0.0.0.0:8550 host:port to bind the HTTP server. Empty disables RPC.
--rpc-compression true gzip responses when the client advertises Accept-Encoding: gzip.

These are node-wide settings (like --discovery-addr), so they are configured by flag only — there is no per-network YAML equivalent. To turn the server off, pass an empty address:

umnode --rpc-addr ""

The protocol

  • Send a JSON-RPC 2.0 request object with POST to the bind address. A GET returns a short plain-text banner.
  • Batches are supported: POST a JSON array of request objects and receive an array of responses.
  • Errors use the standard codes: -32700 parse error, -32600 invalid request, -32601 method not found, -32602 invalid params, -32603 internal error, and -32000 for application errors such as a missing block.

Compression

When --rpc-compression is on (the default), responses are gzip-compressed only when the client sends Accept-Encoding: gzip and the payload is large enough to be worth it (small replies like errors are sent uncompressed). The response then carries Content-Encoding: gzip. Block artifacts are large and compress well, so most real clients should advertise gzip.

eth_blockNumber

Returns the number of the most recent block in the store, as a hex quantity.

Params — none.

Result — the highest stored block number (e.g. "0x18103f3"). Errors if the block store is disabled (--block-db "") or still empty (nothing imported yet). This is the head of the local store, which can trail the live chain while syncing, and is not necessarily contiguous down to genesis — backfill fills history downward separately.

curl -s http://127.0.0.1:8550 \
  -d '{"jsonrpc":"2.0","id":1,"method":"eth_blockNumber"}'
{"jsonrpc":"2.0","id":1,"result":"0x18103f3"}

eth_getBlockByNumber

Returns a block by number in the canonical eth_ JSON shape (the same shape geth/reth return), assembled from the stored header, body and transactions.

Params:

  1. the block — a hex quantity ("0x18103f3"), a decimal/number, or a tag: "latest", "earliest", or "pending" / "safe" / "finalized" (all map to the store head — UMNode tracks no pending block or finality).
  2. fullTransactions (boolean) — true returns full transaction objects (including the recovered from sender and block location); false returns only the transaction hashes.

Result — the block object (number, hash, parentHash, the stateRoot / transactionsRoot / receiptsRoot, miner, gasLimit / gasUsed, timestamp, size, baseFeePerGas, transactions, uncles, and post-Shanghai withdrawals, plus the post-fork fields when the header carries them), or null if the block is not in the store.

Differences from a full node

totalDifficulty is omitted — UMNode does not track it. Receipts are not part of this response; read them from the stored artifact via debug_getBlockArtifact.

curl -s http://127.0.0.1:8550 \
  -d '{"jsonrpc":"2.0","id":1,"method":"eth_getBlockByNumber","params":["latest", false]}'

A block not in the store returns a null result (not an error):

{"jsonrpc":"2.0","id":1,"result":null}

eth_getBlockByHash

Returns a block by its hash, in the same canonical eth_ shape as eth_getBlockByNumber. Needs the hash index (--index, on by default).

Params:

  1. blockHash — the 32-byte block hash, hex ("0x…").
  2. fullTransactions (boolean) — true for full transaction objects, false for just their hashes.

Result — the block object (identical shape to eth_getBlockByNumber), or null if the block is not stored. A recent block is served from the in-memory tail, an older one from the on-disk index; with --index=false the method returns a "hash indexing is disabled" error.

curl -s http://127.0.0.1:8550 \
  -d '{"jsonrpc":"2.0","id":1,"method":"eth_getBlockByHash","params":["0x…", false]}'

eth_getTransactionByHash

Returns a transaction by its hash, in the canonical eth_ shape. Needs the hash index.

Params:

  1. transactionHash — the 32-byte transaction hash, hex ("0x…").

Result — the transaction object: the signed fields, the recovered from sender, the per-type fee fields, and its block location (blockHash, blockNumber, transactionIndex), or null if it is not in any stored block. Pending (unmined) transactions are not tracked.

curl -s http://127.0.0.1:8550 \
  -d '{"jsonrpc":"2.0","id":1,"method":"eth_getTransactionByHash","params":["0x…"]}'

Receipts and logs

Receipts are derived data: executing a block yields exactly the receipts its header's receiptsRoot commits to. UMNode therefore has three ways to treat them, chosen by --receipts:

  • fetch — receipts are downloaded with each block and stored inline in the block record. Blocks an earlier run stored without receipts (under derive or none) are backfilled: a background worker fetches their receipts from peers on start and attaches them in place — a tail or open-segment block is rewritten in the pending area, a sealed segment is re-packed with its receipts and swapped in atomically — until the store matches a fetch-mode import. Progress is in debug_receiptsStatus; debug_fillReceipts re-runs the pass.
  • derive (the default) — receipts are not downloaded: the executor produces every block's receipts and keeps them in a receipts stream, a second slim segmented store under <state-db>/receipts built from the same machinery as the changeset store. Download volume drops by about a quarter and eth/68 peers serve the whole exchange. The pre-Byzantium range (mainnet blocks below 4,370,000) is still fetched: those receipts carry a per-transaction state root that a trie-free executor cannot recompute. --receipts-history N bounds the stream to the most recent N blocks; receipts below that floor are reclaimed by deleting whole sealed segments. Without --execute nothing derives them: blocks are imported without receipts and the methods below report them not available until execution is enabled or the mode is switched to fetch, which backfills them.
  • none — receipts are neither downloaded nor stored: the lightest import for a node that serves blocks and transactions only. With --execute the two point lookups still re-execute a block on request; eth_getLogs has nothing to scan.

Deriving is the default whatever --execute says; downloading has to be asked for with an explicit --receipts fetch (auto, the former default, follows --execute: derive with it, fetch without).

The three methods below resolve a block's receipts in this order: inline with the block, else the receipts stream, else — for the two point lookups only — by re-executing the block on its parent's state, exactly as debug_traceTransaction re-executes (the result is verified against the header and cached by block hash). eth_getLogs scans a range and serves stored receipts only: a range of re-executions is minutes of work per thousand blocks, so a block whose receipts were pruned or not derived yet fails the query with an error naming the block and the cause, rather than silently crawling.

A block whose receipts are not available now — stored without them, and nothing to derive them with — answers with an error that names the remedy for the running mode: wait for the backfill (fetch), enable --execute or switch to fetch (derive), or switch mode (none). Nothing is lost meanwhile: switching to --receipts fetch later fills every such block retroactively.

latest for receipts

In derive mode the receipts stream trails execution, so for these methods "latest" is the receipts head: the executed head when it is below the store head. A block above it is served by eth_getBlockReceipts only once execution reaches it (or via re-execution, which needs the parent executed).

eth_getTransactionReceipt

Returns the receipt of a mined transaction in the canonical eth_ shape, or null if the transaction is not in any stored block. Needs the hash index.

Params: 1. transactionHash — the 32-byte transaction hash, hex.

Result — transactionHash, transactionIndex, blockHash, blockNumber, from, to (null for a contract creation) and contractAddress (the created contract, else null), gasUsed and cumulativeGasUsed, effectiveGasPrice, type, status (or root for a pre-Byzantium receipt), logs — each with its blockNumber, transactionHash, transactionIndex, logIndex, blockHash and blockTimestamp — and logsBloom; blobGasUsed and blobGasPrice for a blob transaction.

curl -s http://127.0.0.1:8550 \
  -d '{"jsonrpc":"2.0","id":1,"method":"eth_getTransactionReceipt","params":["0x…"]}'

eth_getBlockReceipts

Returns every receipt of a block, in transaction order.

Params: 1. the block — a hex quantity, a number, a tag ("latest", "earliest", "pending" / "safe" / "finalized"), or an object {"blockHash": "0x…"} / {"blockNumber": "0x…"} (by hash needs the hash index).

Result — an array of receipt objects (the eth_getTransactionReceipt shape), empty for a block without transactions, or null if the block is not stored.

curl -s http://127.0.0.1:8550 \
  -d '{"jsonrpc":"2.0","id":1,"method":"eth_getBlockReceipts","params":["latest"]}'

eth_getLogs

Returns the logs matching a filter over a block range, or within one block.

Params — one filter object:

  • fromBlock / toBlock — a quantity or tag; both default to "latest" (the receipts head, see above). A toBlock past the head is clamped to it; fromBlock above toBlock is rejected.
  • blockHash — instead of a range: the one block to search (needs the hash index; cannot be combined with fromBlock / toBlock).
  • address — a single address or an array; absent matches every address.
  • topics — positional: each entry is null (any topic), one 32-byte topic, or an array of alternatives. A log with fewer topics than positions given never matches.

Result — an array of log objects (address, topics, data, blockNumber, transactionHash, transactionIndex, blockHash, blockTimestamp, logIndex, removed: false), in block, transaction and log order.

Limits. The range may span at most --rpc-logs-max-blocks blocks (default 10000); wider queries are rejected so clients page. Blocks are pre-filtered on the header's logs bloom, so a filter that cannot match reads no receipts. A block in the range that is not in the store yet, whose receipts were pruned (below the --receipts-history floor), whose receipts execution has not derived yet, or that was stored without receipts fails the query with an error naming it and the remedy.

curl -s http://127.0.0.1:8550 \
  -d '{"jsonrpc":"2.0","id":1,"method":"eth_getLogs","params":[{"fromBlock":"0x18103f3","toBlock":"latest","address":"0x…","topics":["0x…"]}]}'

State methods (the execution subsystem)

The methods below read the executed state built by the execution subsystem, which is on by default (--execute=false disables it). They share these rules:

  • The trailing block argument accepts a quantity or a tag; "latest" / "pending" / "safe" / "finalized" resolve to the executed head (which can trail the stored head while execution catches up), "earliest" is genesis. It defaults to "latest".
  • Until the backfill has reached genesis and execution has caught up to the requested block, they error with state not ready — never an approximation. Below the --state-history pruning floor they error with state history not available. With execution disabled (or its prerequisites missing) they error with state is disabled.

eth_chainId

Returns the chain id from the execution chain config, as a hex quantity ("0x1" on mainnet). No parameters.

eth_getBalance

Params: 1. address; 2. block (optional). Result — the balance in wei as a hex quantity ("0x0" for a non-existent account).

curl -s http://127.0.0.1:8550 \
  -d '{"jsonrpc":"2.0","id":1,"method":"eth_getBalance","params":["0x…","latest"]}'

eth_getTransactionCount

Params: 1. address; 2. block (optional). Result — the account nonce as a hex quantity.

eth_getCode

Params: 1. address; 2. block (optional). Result — the contract bytecode, hex ("0x" for a code-less account).

eth_getStorageAt

Params: 1. address; 2. slot (hex, short forms like "0x0" accepted); 3. block (optional). Result — the 32-byte slot value, zero-padded hex.

eth_call

Executes a read-only call against the executed state at the requested block, in that block's context (BASEFEE, TIMESTAMP, BLOCKHASH, …). This is the method behind token balances of any standard — ERC-20/721/1155 balanceOf is just calldata.

Params:

  1. callObject — { from?, to, gas?, gasPrice? | maxFeePerGas? / maxPriorityFeePerGas?, value?, input? (alias data), accessList? }. Gas defaults to (and is capped at) --rpc-gas-cap; fees default to zero, which is always accepted.
  2. block (optional).

Result — the return data, hex. A revert returns error code 3 with execution reverted[: reason] and the raw revert data in the error's data field. Calls running longer than --rpc-call-timeout are aborted.

curl -s http://127.0.0.1:8550 \
  -d '{"jsonrpc":"2.0","id":1,"method":"eth_call","params":[{"to":"0x…","input":"0x70a08231…"},"latest"]}'

debug_traceBlockByNumber / debug_traceBlockByHash

Re-executes a block on its parent's post-state and returns the call tracer's frames for every transaction. UMNode serves the callTracer only — it must be named explicitly; the default struct logger and every other tracer are rejected.

Params:

  1. block — quantity or tag (by-number), or the 32-byte block hash (by-hash; needs the hash index).
  2. traceConfig — {"tracer": "callTracer", "tracerConfig": {"onlyTopCall": bool, "withLog": bool}?, "timeout": "10s"?}. Required.

Result — [{ "txHash", "result": <call frame> }, …] in transaction order (a transaction whose tracer failed carries "error" instead). The call frame is geth's schema — type, from, to, value, gas, gasUsed, input, output, error?, revertReason?, calls?, logs? — so existing tooling works unmodified.

Tracing block N needs the parent's state: the same readiness and --state-history floor errors apply. Each transaction's execution is bounded by --rpc-trace-timeout.

curl -s http://127.0.0.1:8550 \
  -d '{"jsonrpc":"2.0","id":1,"method":"debug_traceBlockByNumber","params":["0x96bed7", {"tracer": "callTracer"}]}'

debug_traceTransaction

Re-executes the transaction's block up to and including the transaction (prefix untraced — only its state effects matter) and returns the transaction's call frame. Needs the hash index to locate the transaction.

Params: 1. transactionHash; 2. traceConfig — as above ({"tracer": "callTracer"} required).

Result — the call frame object.

debug_getBlockArtifact

Returns the stored artifact for one block: its header, body and receipts, exactly as they live in the segmented block store — no node-side derivation.

Params — a single positional argument identifying the block:

  • a block number as a JSON integer (25232371),
  • a hex quantity string ("0x18103f3"),
  • a decimal string ("25232371"), or
  • the tag "latest" (the store head) or "earliest" (block 0).

Result — an object with:

Field Meaning
number Block number (hex quantity).
hash Block hash (derived from the header; not part of the header JSON).
header The full header, in go-ethereum's canonical JSON form.
body transactions, and uncles / withdrawals when present.
receipts One entry per transaction (see below).

Faithful to what is stored

This is a debug method: it shows the stored artifact, not a fully-derived block. The storage encoding keeps only a receipt's status (or pre-Byzantium post-state root), cumulativeGasUsed and logs (each log's address, topics and data). The transaction type and the logs bloom are not stored — the type defaults to legacy on read and the bloom is recomputed from the logs at serve time — so both are omitted here, as are a log's derived fields (block hash/number, transaction hash/index, log index). Cross-reference a receipt with its transaction in the same body to recover them. A block imported without receipts (--receipts derive) shows the executor-derived ones from the receipts stream once execution has reached it; until then its receipts array is empty.

Example

curl -s http://127.0.0.1:8550 \
  -H 'Content-Type: application/json' \
  -d '{"jsonrpc":"2.0","id":1,"method":"debug_getBlockArtifact","params":["latest"]}'
{
  "jsonrpc": "2.0",
  "id": 1,
  "result": {
    "number": "0x18103f3",
    "hash": "0xbde13a4a8d725a8ba8ef1fbc8b0cd968e6377cfb5291a35e8936964b54c51bfe",
    "header": {
      "parentHash": "0x…",
      "number": "0x18103f3",
      "gasUsed": "0x…",
      "timestamp": "0x…"
    },
    "body": {
      "transactions": [
        { "type": "0x0", "nonce": "0x7", "to": "0x…", "value": "0x3e8", "hash": "0x…" }
      ],
      "withdrawals": [
        { "index": "0x…", "validatorIndex": "0x…", "address": "0x…", "amount": "0x…" }
      ]
    },
    "receipts": [
      {
        "status": "0x1",
        "cumulativeGasUsed": "0x5208",
        "logs": [
          { "address": "0x…", "topics": ["0x…"], "data": "0x…" }
        ]
      }
    ]
  }
}

Request a specific block by number instead of the head:

curl -s http://127.0.0.1:8550 \
  -d '{"jsonrpc":"2.0","id":1,"method":"debug_getBlockArtifact","params":["0x18103f3"]}'

A block that is not in the store yet returns an application error:

{"jsonrpc":"2.0","id":1,"error":{"code":-32000,"message":"block 99999999 not found"}}

debug_listPeers

A snapshot of every currently-connected (handshaked) peer — a window into what the p2p layer is talking to right now — plus the configured RPC peers, when there are any.

Params — none.

Result — { "count": N, "peers": [ … ], "rpcPeers": [ … ] }, each p2p peer carrying its node id, enode, client name, inbound flag, remoteAddr, negotiated ethVersion and advertised caps, the handshake's networkID / forkHash / forkNext, the peer's best-block head hash, its served range (earliestBlock / latestBlock, eth/69+), and how long it has been connected (connectedFor). rpcPeers is present only with --rpc-peers; each endpoint carries its id (scheme and host — never the path or credentials), status (ready; down, resting after a failure, with retryIn until the next probe; unverified, not reached yet; rejected, it serves another chain), chainId, its latest block as last probed (head, headHash, headAge), whether it serves eth_getBlockReceipts (receipts), its batch-call requests, transport failures and invalid-response faults, and lastError while one is current.

curl -s http://127.0.0.1:8550 \
  -d '{"jsonrpc":"2.0","id":1,"method":"debug_listPeers"}'
{
  "count": 4,
  "peers": [
    {
      "id": "6b36f791…a20507",
      "enode": "enode://4aeb4ab6…@157.90.35.166:30303",
      "name": "Geth/v1.17.2-stable-…",
      "inbound": false,
      "ethVersion": 69,
      "caps": ["eth/69", "snap/1"],
      "networkID": 1,
      "forkHash": "0x07c9462e",
      "head": "0xa811afa1…b48cc",
      "latestBlock": 25244452,
      "connectedFor": "1s"
    }
  ],
  "rpcPeers": [
    {
      "id": "http://127.0.0.1:8545",
      "status": "ready",
      "chainId": 1,
      "head": 25244452,
      "headHash": "0xa811afa1…b48cc",
      "headAge": "2s",
      "receipts": true,
      "requests": 1483,
      "failures": 0,
      "faults": 0
    }
  ]
}

latestBlock (or an RPC peer's head) is that peer's view of the chain head — handy for spotting that a block you're chasing is simply above the current head.

debug_getP2PBlockArtifact

A force-fetch: pull one block straight from peers over the wire — bypassing the store entirely — and report what we sent and what each peer sent back. It's a diagnostic for "why won't this block fetch?"; it writes nothing to the store.

Params:

  1. the block (a number, hex/decimal string, or "latest"/"earliest" when a store is present), and
  2. (optional) a peer id to target a single peer instead of trying each.

Result — { number, peer?, note?, attempts: [ … ], artifact }. Each entry in attempts describes one peer's exchange (headers, then bodies and receipts once a header comes back, plus ok / error). artifact is the assembled block (same shape as debug_getBlockArtifact) once a peer serves a valid one, or null if none do.

curl -s http://127.0.0.1:8550 \
  -d '{"jsonrpc":"2.0","id":1,"method":"debug_getP2PBlockArtifact","params":[25244400]}'

A successful fetch — one peer lacked the block, the next served it:

{
  "number": "0x18104d0",
  "attempts": [
    { "peer": "fde63ae0…", "ethVersion": 69,
      "headers": "GetBlockHeaders{origin:25244400, amount:1} → 0 header(s)",
      "ok": false, "error": "empty header response (block above the chain head, or peer lacks it)" },
    { "peer": "96f65494…", "ethVersion": 69,
      "headers": "GetBlockHeaders{origin:25244400, amount:1} → 1 header(s) 0x6bbbbf62…",
      "bodies": "GetBlockBodies{1 hash} → 1 body(ies), 242 txs",
      "receipts": "GetReceipts{1 hash} → 1 list",
      "ok": true }
  ],
  "artifact": { "number": "0x18104d0", "header": { … }, "body": { … }, "receipts": [ … ] }
}

When a block is above the chain head, every peer returns an empty header response and artifact is null — the unambiguous signature of "this block doesn't exist yet" (cross-check the head via debug_listPeers):

{
  "number": "0x180a4cf",
  "attempts": [
    { "peer": "6b36f791…", "ethVersion": 69, "headers": "GetBlockHeaders{origin:25249999, amount:1} → 0 header(s)", "ok": false, "error": "empty header response (block above the chain head, or peer lacks it)" }
  ],
  "artifact": null
}

Target one peer (e.g. to check whether a specific peer serves a range):

curl -s http://127.0.0.1:8550 \
  -d '{"jsonrpc":"2.0","id":1,"method":"debug_getP2PBlockArtifact","params":[25244400,"96f65494…"]}'

debug_indexStatus

The hash index's configuration and how far the background reindexer has covered already-stored data. Takes no parameters.

Result — { enabled, keyBytes, target, next, done, running, percent, diskBytes, compacting }:

  • enabled — whether hash indexing is on (--index).
  • keyBytes — leading hash bytes per index key (the --index-key-bytes the DB was created with).
  • target / next — the confirmed ceiling the current backlog pass covers, and the next block it will index.
  • done — the backlog is fully indexed; the live import path keeps it current.
  • running — a reindex worker is active now.
  • percent — progress of the current backlog pass (0–100).
  • diskBytes — the index DB's on-disk size (what du reports).
  • compacting — an index compaction is running now.
curl -s http://127.0.0.1:8550 \
  -d '{"jsonrpc":"2.0","id":1,"method":"debug_indexStatus","params":[]}'

debug_reindex

Force a fresh background reindex pass (current floor → confirmed head), then return the status. The escape hatch for filling gaps left when --index was turned off for a while and back on. A no-op that just reports the live status if a reindex is already running. Takes no parameters.

Result — the debug_indexStatus shape, plus "started": true.

curl -s http://127.0.0.1:8550 \
  -d '{"jsonrpc":"2.0","id":1,"method":"debug_reindex","params":[]}'

debug_compactIndex

Trigger a background compaction of the hash-index DB to reclaim space from churn — old key versions and levels left un-merged by abrupt restarts. Heavy for a large index, so it is operator-triggered; a no-op that just reports the live status if a compaction is already running. Takes no parameters.

Result — the debug_indexStatus shape, plus "started": true. Watch compacting and diskBytes via debug_indexStatus.

curl -s http://127.0.0.1:8550 \
  -d '{"jsonrpc":"2.0","id":1,"method":"debug_compactIndex","params":[]}'

debug_rebuildState

Queues a state rebuild on the execution worker and returns immediately; the rebuild runs between execution steps — watch the execution section of debug_status. A parked executor (halted on an execution divergence) is revived by this call.

Params:

  1. block (optional) — rebuild from this block: the state is unwound through the recorded changesets to the block's post-state and re-executed forward. Must be at or above the --state-history floor and below the executed head. Omitted or 0: the state is discarded entirely and rebuilt from genesis.

Result — { "accepted": true, "previousHead": "0x…", "rebuildFrom": "genesis" | "0x…" }. Errors when the execution subsystem is off or a rebuild is already pending.

curl -s http://127.0.0.1:8550 \
  -d '{"jsonrpc":"2.0","id":1,"method":"debug_rebuildState","params":[]}'

debug_snapshotState

Takes a state snapshot now and publishes it to the segment archive, due or not by --state-snapshot-every. The request is queued for the archive uploader's next pass, which it wakes for; the snapshot is taken at the executed head the store is at then — once every sealed history segment is in the archive, as any snapshot waits for. The pass runs the checkpoint (commits pause for a few seconds), the digest, the pack and the upload; debug_status shows the progress under archive.upload.snapshot, and debug_cancelStateSnapshot interrupts it. Older snapshots beyond --state-snapshot-keep are deleted as it lands, and the schedule, if any, counts from it. Takes no parameters.

Result — { started, …the snapshot status }: started is true when the request was queued, false when one is already queued or being taken (the call is then a no-op). The status:

  • every — blocks between scheduled snapshots (0: on request only); uploaded (since start), published (the archive lists), latest (the newest one's head) and nextDue (the head the schedule takes the next one at).
  • requested — a request is queued for the next pass.
  • running — one is being taken: its head, trigger (request or schedule), phase (checkpoint, digest, pack, upload or manifest), the bytes / total of the pack or upload so far, startedAt, and cancelling once a cancel has interrupted it.
  • last, lastHead, lastAt — how the last one ended: published, cancelled or failed (the upload status's lastError names the failure; a failed snapshot is retried by the next pass until it lands or is cancelled).

Errors unless the node backs up to an archive (--backup) with --execute.

curl -s http://127.0.0.1:8550 \
  -d '{"jsonrpc":"2.0","id":1,"method":"debug_snapshotState","params":[]}'

debug_cancelStateSnapshot

Interrupts the state snapshot being taken — its digest, pack or upload stops within a read, the scratch files are removed and the archive's manifest is left as it was — or drops a queued request (debug_snapshotState) no pass has picked up yet. A snapshot whose upload has landed is past interrupting: it is listed. A scheduled snapshot that is cancelled is not retaken a minute later: the schedule moves on by one period, as if it had been taken, until the node restarts or a snapshot on request lands first. Cancelling also ends the retries of a snapshot that keeps failing. Takes no parameters.

Result — { cancelled, …the snapshot status } (the debug_snapshotState shape): cancelled is true when a snapshot was interrupted (again, while it winds down) or a request dropped, false when nothing was queued or being taken. Errors unless the node backs up to an archive (--backup) with --execute.

curl -s http://127.0.0.1:8550 \
  -d '{"jsonrpc":"2.0","id":1,"method":"debug_cancelStateSnapshot","params":[]}'

debug_receiptsStatus

Reports where receipts come from and how complete the stored receipts are. Takes no parameters.

Result — { mode, missing, stream?, fill? }:

  • mode — the resolved --receipts mode: fetch, derive or none.
  • missing — { blocks, segments }: how many stored blocks have transactions but no receipts (imported under derive or none), and the segments holding them.
  • stream — with --receipts derive and --execute: the receipts stream's floor, sealedSegments and tip (the highest block whose receipts it holds).
  • fill — with --receipts fetch: the backfill worker — running, filled (blocks given receipts since start), passes, the segment being filled while running, and lastError after a failed step (the worker retries on its own).

A block counted in missing answers eth_getLogs with an error naming the remedy; eth_getTransactionReceipt and eth_getBlockReceipts still derive its receipts by re-execution when --execute is on.

curl -s http://127.0.0.1:8550 \
  -d '{"jsonrpc":"2.0","id":1,"method":"debug_receiptsStatus","params":[]}'

debug_fillReceipts

Starts a receipts backfill pass: fetches receipts from peers for every stored block that lacks them and attaches them in place (rewriting sealed segments — see Receipts backfill). The worker runs one pass on start under --receipts fetch; this re-runs it, for instance once peers that serve old receipts (eth/69+ with a deep served range) are connected. Takes no parameters.

Result — the debug_receiptsStatus shape plus started: true when a new pass was queued, false when one is already running or queued (the request is then a no-op). Errors unless the node runs --receipts fetch.

curl -s http://127.0.0.1:8550 \
  -d '{"jsonrpc":"2.0","id":1,"method":"debug_fillReceipts","params":[]}'

debug_status

A one-call overview of the node. Takes no parameters.

Result — { version, uptime, uptimeSeconds, blocks, transactions, db, memory, execution, rpcPeers, archive }:

  • blocks — { total, sealed, open, tail, floor, head, missingReceipts, prunedBelow, extraRanges? }: block counts across the store tiers, the stored range (floor–head), how many stored blocks have transactions but no receipts (see debug_receiptsStatus), the pruning floor (0 when nothing was pruned) and, with --extra-archive-blocks, the ranges kept outside the window as the store keeps them (padded below, whole segments), each { from, to, filledDownTo?, complete } — a range is filled downward from its top, so filledDownTo is where its fill stands.
  • transactions — the running total of transactions across all stored blocks.
  • db — on-disk bytes per area: sealedBytes (.seg + .idx), openBytes (.seg.open), tailBytes (the pending DB), indexBytes (the hash index), and their totalBytes.
  • memory — Go runtime use: heapBytes (live heap) and sysBytes (reserved from the OS).
  • execution — the execution subsystem: { enabled } when off; with --execute also ready (genesis state initialized), the executed head/headHash, the history floor, lag (how far execution trails the stored head), and receipts — { stream: false } when receipts are fetched and stored inline, else the receipts stream's retention floor, tip and sealedSegments; unverified: true marks a debug state seeded mid-chain by --execute-from (wrong by construction, see Debugging a block range); historyExtension — pruned history being fetched back after a retention window grew: running, historyWanted (where the window reaches), historyFloor / receiptsFloor, the kind, segment and phase (download, adopt, index) in progress with the blocks indexed, adopted since start, done, lastError.
  • rpcPeers — only with --rpc-peers: { configured, ready }, how many RPC peers are configured and how many are serving requests right now (debug_listPeers has each one's state).
  • archive — with --backup and/or an archive source (the public archive unless --archive-source none): the segment archive workers — upload (destination, verified, segments, bytes, published, pending, holdsPruning — per kind, the first block of the lowest sealed segment pruning is waiting on the archive for, absent when none — lastUploadAt, lastError, and with --execute snapshot, the state snapshots' schedule, queued request and progress in the debug_snapshotState shape) and download (source, state, segments, bytes, lastSegment, lastError).

The db byte figures are measured by walking the store directories.

curl -s http://127.0.0.1:8550 \
  -d '{"jsonrpc":"2.0","id":1,"method":"debug_status","params":[]}'