Skip to content

docs(operators): document the send-only sequencer endpoint and the missing minimal node tier - #2296

Open
GigaHierz wants to merge 2 commits into
mainfrom
GigaHierz/verify-sequencer-endpoint-reply
Open

docs(operators): document the send-only sequencer endpoint and the missing minimal node tier#2296
GigaHierz wants to merge 2 commits into
mainfrom
GigaHierz/verify-sequencer-endpoint-reply

Conversation

@GigaHierz

Copy link
Copy Markdown
Contributor

The hole, and the fix

A builder running a node asked where to send transactions directly. Answering it surfaced two gaps in the docs, both fixed here.

1. The sequencer endpoint is send-only, and nothing said so. The URLs are documented on three operator pages, but none mention that the endpoints reject every method except eth_sendRawTransaction. Anyone who takes the URL from those pages and configures it as a provider endpoint gets an opaque 403 / -32601 "rpc method is not whitelisted" on their first read call, with nothing in the docs to explain it. Separately, no builder-facing page mentioned the sequencer at all, so the question arrived as support traffic instead of resolving in the docs. Adds a <Note> on Run a public RPC node, and one sentence on Forno routing readers to the operator page.

2. The minimal node tier was missing. celo-l2-node-docker-compose supports minimal, full and archive, and NODE_TYPE selects both the snapshot downloaded and reth's prune profile. The docs listed two, presenting the Values column of configuration.mdx as exhaustive when it isn't — so an operator sizing a node against our reference had no way to learn the smallest tier exists. Adds it to the reference row, the "Node types" list, and the run-node step.

Two trade-offs picked the wording. The Forno sentence deliberately does not repeat the sequencer URL — publishing it on a builder page would promote direct submission to an endpoint with no published rate limit or SLA, so it points at the operator page instead. And the minimal description says what the tier costs (little historical RPC), not only what it saves; a tier listed by name alone invites operators to pick the smallest number and discover the limitation in production.

What this does NOT do / residual risk

  • Does not document a rate limit. Celo Sepolia returns x-ratelimit-limit: 200; mainnet sits behind Cloudflare and exposes no rate-limit header. No published policy exists for either, and a number sourced only from a response header is a guess. Left out deliberately — tracked as an ops step below.
  • Does not state an SLA or uptime guarantee for direct sequencer submission.
  • The send-only claim has no CI gate and cannot have one. It asserts a third-party endpoint's server-side config, which this repo does not control and CI cannot test. If the allowed method set changes, the Note goes stale silently. Verified true 2026-08-31 — that is the scope of the evidence.
  • 2 of the 3 pages carrying the sequencer URL are untouched (troubleshooting.mdx, configuration.mdx); they still give the URL without the caveat. Deliberate — one fact, one home. Flagged as a question below.
  • Does not audit the rest of configuration.mdx against the node repo. Only the NODE_TYPE row was verified, because that is what the question surfaced. The other rows are unverified and could carry the same staleness.
  • No CI compares our tables against upstream, so the NODE_TYPE row can go stale again exactly the way it just did.
  • Does not add a minimal guide page, and does not copy the repo's disk-size figures (~7 GB / ~20 GB) — those change per snapshot, and duplicating them into a second location is the drift this PR is fixing.

Judgement calls

Bundling. This is two concerns in one PR — a live builder-facing fix and reference staleness — bundled at the maintainer's direction. They share no files and split cleanly (public-rpc-node.mdx + forno.mdx / configuration.mdx + overview.mdx + run-node.mdx); happy to split on request, either half stands alone.

  1. Send-only Note on public-rpc-node.mdx only, not on all three pages carrying the URL. Duplicating a fact across three pages is where drift starts. Reversal cost: copy 5 lines per page.
  2. No sequencer URL on the Forno page — reasoning above. Reversal cost: one line.
  3. No rate-limit number. I measured 200 on Sepolia but could not source it; an unsourced number in reference docs is worse than silence. Reversal cost: one row, once infra confirms.
  4. minimal listed first, full still marked (default). Ordering is smallest→largest to match the repo's own table; the (default) marker carries the recommendation rather than the ordering. Reversal cost: reorder one row.
  5. minimal described as validating every block. The repo README calls it reth's "most aggressive prune profile" and confirms it "syncs to tip, validates consensus". Stated explicitly so nobody reads minimal as a light client — Celo L2 has none, and that exact misreading is what prompted this work. Reversal cost: delete one clause.
  6. Left archive-node.mdx untouched — archive-specific and correct as-is.

No product change bundled.

Issues

No linked issue — this came from inbound builder traffic rather than a ticket, and no open issue covers it. Happy to file retroactively for the trail.

Stacking / conflicts

Branched off main, independent of my other open PRs. Checked all 8 open PRs for file overlap against the 5 changed files — none.

Verification evidence

Claim 1 — the sequencer endpoint accepts only eth_sendRawTransaction. Tested against both live endpoints on 2026-08-31:

$ curl -s -X POST https://cel2-sequencer.celo.org -H 'Content-Type: application/json' \
    -d '{"jsonrpc":"2.0","method":"eth_blockNumber","params":[],"id":1}' -w ' [HTTP:%{http_code}]'
{"jsonrpc":"2.0","error":{"code":-32601,"message":"rpc method is not whitelisted"},"id":1} [HTTP:403]

$ curl -s -X POST https://cel2-sequencer.celo.org -H 'Content-Type: application/json' \
    -d '{"jsonrpc":"2.0","method":"eth_sendRawTransaction","params":["0x"],"id":1}' -w ' [HTTP:%{http_code}]'
{"jsonrpc":"2.0","error":{"code":-32602,"message":"typed transaction too short"},"id":1} [HTTP:400]

eth_sendRawTransaction reaches transaction decoding. eth_blockNumber, eth_getBlockByNumber, eth_call, eth_gasPrice, eth_getTransactionCount, net_version and web3_clientVersion all return -32601. Identical results on https://sequencer.celo-sepolia.celo-testnet.org.

Claim 2 — minimal is a real tier that prunes but still executes every block. Upstream pinned to SHA bde11361b578 of celo-org/celo-l2-node-docker-compose:

README.md:55-56

- **NODE_TYPE** - The node tier, which sets both the snapshot download size and the prune mode. One of `minimal`, `full`, or `archive`:
  - `minimal` - Runs reth's most aggressive prune profile (`--minimal`): prunes transaction lookups fully and keeps only ~64 blocks of receipts. Smallest disk, limited historical RPC.

scripts/start-op-reth.sh:30-33,48-51 — confirms NODE_TYPE does double duty, which is why the row now reads "prune profile and the snapshot tier":

  # NODE_TYPE doubles as the snapshot tier, matching celo-reth's download
  # presets: minimal | full | archive. Defaults to full.
  SNAPSHOT_PRESET="--${NODE_TYPE:-full}"
...
# NODE_TYPE also selects reth's prune profile: --minimal (most aggressive) or
# --full. An archive node passes no flag and retains all historical state.
if [ "$NODE_TYPE" != "archive" ]; then
  export EXTENDED_ARG="${EXTENDED_ARG:-} --${NODE_TYPE:-full}"

Supporting — the forwarding claim the Note sits next to. scripts/start-op-reth.sh:116-117 at the same SHA starts op-reth with --rollup.sequencer="$OP_RETH__SEQUENCER_URL" and --rollup.disable-tx-pool-gossip; envs/mainnet/op-reth.env and envs/celo-sepolia/op-reth.env carry the two URLs the docs quote, matching character for character.

Both CI gates, run on this head — not CI's cached result:

$ npx mintlify broken-links
success no broken links found

$ bash scripts/check-orphans.sh          # report-only in CI, tracked by #2253
(pre-existing orphans only; none of the 5 changed files appear)

Mutation count: 2. This repo has no test suite, so the link checker is the only executable gate. Both links this PR adds were broken deliberately and restored, to confirm the gate is live rather than a no-op:

$ sed -i '' 's#(/operate/operators/public-rpc-node)#(...-DOES-NOT-EXIST)#' tooling/nodes/forno.mdx
$ npx mintlify broken-links
found 1 broken links in 1 files
tooling/nodes/forno.mdx   ⎿  /operate/operators/public-rpc-node-DOES-NOT-EXIST

$ sed -i '' 's#(/operate/operators/configuration)#(...-NOPE)#' operate/operators/run-node.mdx
$ npx mintlify broken-links
found 1 broken links in 1 files
operate/operators/run-node.mdx   ⎿  /operate/operators/configuration-NOPE

$ # both restored; green again

To be explicit about what that does and does not buy: the gate covers the two links, nothing else. Every prose claim in this diff is ungated — they rest on the curl output and the pinned upstream SHA above, and nothing stronger.

Remaining ops steps

  • Confirm with infra whether a rate limit / SLA for direct sequencer submission can be published; if so, add it to the operator pages.

Questions for the maintainer

  1. Should the send-only caveat also go on troubleshooting.mdx and configuration.mdx, or is one home right?
  2. Is Forno the right builder-facing home for the cross-link, or would you rather it sat on build-on-celo/network-overview?
  3. Does minimal warrant its own guide page like archive-node.mdx, or is reference coverage enough for now?
  4. Worth filing an issue to audit the rest of configuration.mdx against the node repo? Only the NODE_TYPE row was verified.

…ssing minimal node tier

The sequencer URLs were documented on three operator pages without noting
that the endpoints reject every method except eth_sendRawTransaction, and
no builder-facing page mentioned the sequencer at all. Separately, the
NODE_TYPE reference listed only full and archive, omitting the minimal
tier the compose setup supports.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@GigaHierz
GigaHierz requested review from a team as code owners August 31, 2026 12:54
@GigaHierz
GigaHierz requested review from piersy and seolaoh and removed request for a team August 31, 2026 12:54
@GigaHierz
GigaHierz requested a review from palango August 31, 2026 12:57
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant