From 0c623c73c8360f5107bc7003663926a75b5e9362 Mon Sep 17 00:00:00 2001 From: alchemy-bot <80712764+alchemy-bot@users.noreply.github.com> Date: Tue, 14 Jul 2026 20:04:40 +0000 Subject: [PATCH 1/2] [docs-agent] Add debug_executePayload and debug_proofsSyncStatus method definitions for Base Adds OpenRPC method definitions for two Base debug endpoints served by Base's historical proofs execution extension (ExEx): * debug_executePayload: re-execute a payload on top of a parent block and return the execution witness (state / codes / keys / headers preimages). Used by fault-proof provers and stateless clients. * debug_proofsSyncStatus: return the currently indexed block range of the historical proofs store as { earliest, latest }. Definitions land in src/openrpc/chains/_components/custom/methods.yaml (matching the location of the existing debug_executionWitness / debug_executionWitnessByHash entries). Supporting schemas (ExecutionWitness, OpPayloadAttributes) live in a new src/openrpc/chains/_components/custom/debug.yaml. Does NOT modify base.yaml $ref list or base-api-overview.mdx: those additions are handled by Daikon in PR #1447, which was blocked on these two definitions being missing. Once this PR merges, #1447 can rebase and its $refs will resolve cleanly. Sources for the schema: * base/base crates/execution/rpc/src/{debug,witness}.rs: canonical trait definitions for DebugExecutionWitnessApi::execute_payload and DebugApiOverride::proofs_sync_status, plus the ProofsSyncStatus struct. * ethereum-optimism/optimism rust/op-reth/crates/rpc/src/debug.rs and docs/public-docs/node-operators/{reference/op-reth-historical-proof-config,tutorials/reth-historical-proofs}.mdx: identical signatures and "{ earliest, latest }" result envelope. * alloy-rs/alloy crates/rpc-types-debug/src/execution_witness.rs: authoritative ExecutionWitness struct (state, codes, keys, headers). * alloy-rs/op-alloy crates/rpc-types-engine/src/attributes.rs: authoritative OpPayloadAttributes struct (payload_attributes flattened via serde flatten, plus transactions/no_tx_pool/gas_limit/eip_1559_params/min_base_fee, camelCase serialization). * Base's official docs at docs.base.org/base-chain/node-operators/run-a-base-node reference both methods. * Live smoke test against https://base-mainnet.g.alchemy.com/v2/docs-demo: - debug_proofsSyncStatus with params [] returned {earliest: 47338810, latest: 48634815}, matching the two-field envelope. - debug_executePayload with a real parent hash and full OpPayloadAttributes (including eip1559Params and minBaseFee, since Jovian is active on Base mainnet) returned an ExecutionWitness with fields state (50 entries), codes (2), keys (6), headers (0), matching the schema field-for-field. - debug_executePayload with an all-zero parent hash returned -32603 "no header found for Hash(...)", matching the documented error path. Validation: pnpm run generate:rpc + pnpm run validate:rpc both pass; prettier clean on both files. Refs DOCS-137 Requested-by: @dslovinsky --- .../chains/_components/custom/debug.yaml | 136 +++++++++++++++++ .../chains/_components/custom/methods.yaml | 142 ++++++++++++++++++ 2 files changed, 278 insertions(+) create mode 100644 src/openrpc/chains/_components/custom/debug.yaml diff --git a/src/openrpc/chains/_components/custom/debug.yaml b/src/openrpc/chains/_components/custom/debug.yaml new file mode 100644 index 000000000..3b2a628ec --- /dev/null +++ b/src/openrpc/chains/_components/custom/debug.yaml @@ -0,0 +1,136 @@ +components: + schemas: + ExecutionWitness: + title: Execution witness + type: object + description: >- + Preimages and headers required to re-execute a payload independently. + Used by fault-proof provers and stateless clients. + additionalProperties: false + properties: + state: + title: Trie node preimages + description: >- + The preimages of every hashed trie node that was required during + execution of the payload, including during state root + recomputation. Each entry is an RLP-encoded trie node. + type: array + items: + $ref: "../evm/base-types.yaml#/components/schemas/bytes" + codes: + title: Contract code preimages + description: >- + The preimages (deployed bytecode) of every contract that was + created or accessed during execution of the payload. + type: array + items: + $ref: "../evm/base-types.yaml#/components/schemas/bytes" + keys: + title: Key preimages + description: >- + The unhashed preimages of every account address and storage slot + that was required during execution of the payload. Used to + reconstruct the trie paths from their hashes. + type: array + items: + $ref: "../evm/base-types.yaml#/components/schemas/bytes" + headers: + title: RLP-encoded block headers + description: >- + RLP-encoded block headers required for stateless verification. + Includes at minimum the parent header (so the pre-state root can + be verified) plus any additional headers referenced by the + `BLOCKHASH` opcode during execution. + type: array + items: + $ref: "../evm/base-types.yaml#/components/schemas/bytes" + + OpPayloadAttributes: + title: Optimism payload attributes + type: object + description: >- + Payload attributes for building or re-executing an OP Stack block. + The fields of the underlying Engine API `PayloadAttributes` object + (`timestamp`, `prevRandao`, `suggestedFeeRecipient`, `withdrawals`, + `parentBeaconBlockRoot`) are flattened onto this object; the + rollup-specific fields (`transactions`, `noTxPool`, `gasLimit`, + `eip1559Params`, `minBaseFee`) are siblings. + additionalProperties: false + required: + - timestamp + - prevRandao + - suggestedFeeRecipient + properties: + timestamp: + title: Block timestamp + description: The block timestamp in seconds since the Unix epoch. + $ref: "../evm/base-types.yaml#/components/schemas/uint" + prevRandao: + title: prevRandao + description: >- + The `prevRandao` value for the block, sourced from the L1 beacon + chain's `RANDAO` output. 32 bytes. + $ref: "../evm/base-types.yaml#/components/schemas/hash32" + suggestedFeeRecipient: + title: Suggested fee recipient + description: >- + The address to receive the coinbase reward. On OP Stack chains + this is typically `0x4200000000000000000000000000000000000011` + (`SequencerFeeVault`). + $ref: "../evm/base-types.yaml#/components/schemas/address" + withdrawals: + title: Withdrawals + description: >- + Post-Shanghai validator withdrawals list. On OP Stack chains this + is always an empty array. + type: array + items: + $ref: "../evm/withdrawal.yaml#/components/schemas/Withdrawal" + parentBeaconBlockRoot: + title: Parent beacon block root + description: >- + The parent beacon block root, from the Cancun-Deneb fork. 32 + bytes. Omit or set to `null` on chains where this fork is not + active. + oneOf: + - $ref: "../evm/base-types.yaml#/components/schemas/hash32" + - type: "null" + transactions: + title: Forced transactions + description: >- + Transactions to force-include at the top of the block, as raw + EIP-2718 encoded bytes. On OP Stack this is used for deposit + transactions and sequencer-inserted L1 attributes calls. + type: array + items: + $ref: "../evm/base-types.yaml#/components/schemas/bytes" + noTxPool: + title: Skip transaction pool + description: >- + If `true`, only the transactions in the `transactions` field are + included in the block; the mempool is not consulted. Verifiers + replaying batch transactions from L1 set this to `true`; the + sequencer sets it to `false` while producing blocks. + type: boolean + gasLimit: + title: Gas limit + description: >- + Exact block gas limit. If unset the block uses the chain's + configured default. + $ref: "../evm/base-types.yaml#/components/schemas/uint" + eip1559Params: + title: EIP-1559 parameters + description: >- + Holocene-era EIP-1559 parameters, encoded as an 8-byte value + where the high 4 bytes are the base fee update denominator and + the low 4 bytes are the elasticity multiplier. Required once the + Holocene hardfork is active; before then, omit or set to `null`. + $ref: "../evm/base-types.yaml#/components/schemas/bytes8" + minBaseFee: + title: Minimum base fee + description: >- + Jovian-era minimum base fee (in wei) for the block. Required + once the Jovian hardfork is active on the chain; before then, + omit or set to `null`. + type: integer + minimum: 0 diff --git a/src/openrpc/chains/_components/custom/methods.yaml b/src/openrpc/chains/_components/custom/methods.yaml index a6381ce5a..83afe822a 100644 --- a/src/openrpc/chains/_components/custom/methods.yaml +++ b/src/openrpc/chains/_components/custom/methods.yaml @@ -1999,6 +1999,148 @@ components: schema: type: object + debug_executePayload: + name: debug_executePayload + summary: Re-execute a payload and return the execution witness + description: >- + Re-executes a payload on top of the state at `parent_block_hash` and + returns the resulting execution witness. The witness comprises the + preimages of every hashed trie node, contract code, and unhashed + account/storage key that was required during execution, plus any block + headers referenced by the `BLOCKHASH` opcode. Together they are the + minimum data needed to prove that the payload executes correctly + against the parent state, without access to a full node. + + + This method is used by fault-proof provers and stateless clients on OP + Stack chains. On Base it is served from the historical proofs + execution extension (`ExEx`); the currently indexed block range can be + queried via `debug_proofsSyncStatus`. + x-compute-units: 40 + x-rate-limit-cus: 1000 + params: + - name: Parent block hash + required: true + description: >- + The 32-byte hash of the parent block. The payload is executed on + top of the post-state of this parent. + schema: + $ref: "../evm/base-types.yaml#/components/schemas/hash32" + - name: Payload attributes + required: true + description: >- + The Optimism-style payload attributes describing the block to + re-execute on top of the parent. The base Engine API + `PayloadAttributes` fields (`timestamp`, `prevRandao`, + `suggestedFeeRecipient`, `withdrawals`, `parentBeaconBlockRoot`) + are flattened onto this object; the rollup-specific fields + (`transactions`, `noTxPool`, `gasLimit`, `eip1559Params`, + `minBaseFee`) are siblings. + schema: + $ref: "./debug.yaml#/components/schemas/OpPayloadAttributes" + result: + name: Execution witness + description: >- + The execution witness of the payload. Contains hashed-trie-node + preimages, contract-code preimages, unhashed key preimages, and any + block headers required for stateless verification. + schema: + $ref: "./debug.yaml#/components/schemas/ExecutionWitness" + examples: + - name: debug_executePayload example + params: + - name: Parent block hash + value: "0x63db51ce4d0ed91c956090d8b413abb85f113442c6a4d8c89fbe1bd535f011ba" + - name: Payload attributes + value: + timestamp: "0x6a569479" + prevRandao: "0x6c6ae66debdd034422a41803af19c8855938f8cca2805d858dc17679cef58c26" + suggestedFeeRecipient: "0x4200000000000000000000000000000000000011" + withdrawals: [] + parentBeaconBlockRoot: "0xb61925b723172852becabbd1ae58da86f59598aedde6983a5ec4144fc5d33eaa" + transactions: [] + noTxPool: true + gasLimit: "0x17d78400" + eip1559Params: "0x000000fa00000006" + minBaseFee: 0 + result: + name: Execution witness + value: + state: + - "0xf90211a0..." + codes: + - "0x60806040..." + keys: + - "0x0000000000000000000000004200000000000000000000000000000000000011" + headers: [] + errors: + - code: -32602 + message: >- + Invalid params. Common causes include a missing or malformed + `parent_block_hash`, or missing/mistyped payload attribute fields. + Note that after the Jovian hardfork activates on the chain, + `minBaseFee` is required; before then it must be omitted. + - code: -32603 + message: >- + Internal error. Examples include `no header found for + Hash()` when the parent block is not indexed by the + historical proofs store (see `debug_proofsSyncStatus` for the + current coverage window), and execution failures while producing + the witness. + + debug_proofsSyncStatus: + name: debug_proofsSyncStatus + summary: Get the historical proofs store sync status + description: >- + Returns the currently indexed block range of the node's historical + proofs execution extension (`ExEx`). Once `latest` tracks chain tip, + `eth_getProof`, `debug_executePayload`, and `debug_executionWitness` + calls for any block within `[earliest, latest]` are served directly + from this versioned proof store rather than by reverting in-memory + state diffs. + + + Both fields can be `null` if the proofs store has not yet indexed any + blocks (for example, immediately after the node starts and before the + first block is committed). + x-compute-units: 0 + x-rate-limit-cus: 5 + params: [] + result: + name: Proofs sync status + description: >- + Object describing the range of blocks currently served from the + historical proofs store. + schema: + title: ProofsSyncStatus + type: object + additionalProperties: false + properties: + earliest: + title: Earliest indexed block + description: >- + The earliest block number for which proofs are available in + the historical proofs store, or `null` if the store is empty. + oneOf: + - $ref: "../evm/base-types.yaml#/components/schemas/uint64" + - type: "null" + latest: + title: Latest indexed block + description: >- + The latest block number for which proofs are available in the + historical proofs store, or `null` if the store is empty. + oneOf: + - $ref: "../evm/base-types.yaml#/components/schemas/uint64" + - type: "null" + examples: + - name: debug_proofsSyncStatus example + params: [] + result: + name: Proofs sync status + value: + earliest: 47338810 + latest: 48634815 + # Stellar Soroban RPC methods getHealth: name: getHealth From 44196d326799da1f699a20715adb030d52236587 Mon Sep 17 00:00:00 2001 From: alchemy-bot <80712764+alchemy-bot@users.noreply.github.com> Date: Tue, 14 Jul 2026 23:46:52 +0000 Subject: [PATCH 2/2] [docs-agent] debug_proofsSyncStatus: model earliest/latest as JSON numbers, not hex uint64 Addresses Codex P2 review comment on PR #1453: my previous schema declared `earliest` and `latest` as `oneOf: [uint64, null]`, but Base's `uint64` schema is a hex-encoded string (`^0x([1-9a-f]+[0-9a-f]{0,15})|0$`). The server actually returns raw JSON numbers, so generated clients and response validators would reject valid non-null responses. Verified with a fresh live call to `base-mainnet.g.alchemy.com/v2/docs-demo`: `result.earliest` = 47345687 (jq `type` -> "number") `result.latest` = 48641705 (jq `type` -> "number") Fix: replace the `uint64` $ref with an inline `{ type: integer, minimum: 0 }` in the `oneOf`, and add a description note that the serialization is a JSON number (not hex) so future readers do not re-introduce the mistake. Validation: `pnpm run generate:rpc` + `pnpm run validate:rpc` both pass; prettier clean. Refs DOCS-137 Requested-by: @dslovinsky --- src/openrpc/chains/_components/custom/methods.yaml | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/openrpc/chains/_components/custom/methods.yaml b/src/openrpc/chains/_components/custom/methods.yaml index 83afe822a..4c6a06acc 100644 --- a/src/openrpc/chains/_components/custom/methods.yaml +++ b/src/openrpc/chains/_components/custom/methods.yaml @@ -2121,16 +2121,20 @@ components: description: >- The earliest block number for which proofs are available in the historical proofs store, or `null` if the store is empty. + Serialized as a JSON number, not a hex-encoded string. oneOf: - - $ref: "../evm/base-types.yaml#/components/schemas/uint64" + - type: integer + minimum: 0 - type: "null" latest: title: Latest indexed block description: >- The latest block number for which proofs are available in the historical proofs store, or `null` if the store is empty. + Serialized as a JSON number, not a hex-encoded string. oneOf: - - $ref: "../evm/base-types.yaml#/components/schemas/uint64" + - type: integer + minimum: 0 - type: "null" examples: - name: debug_proofsSyncStatus example