feat: accept and send cookies with JSON-RPC - #25162
Conversation
60b2228 to
10007f1
Compare
e103355 to
69c6bb9
Compare
| if (!responseOk) { | ||
| throw new Error('HTTP ' + resp.statusCode); | ||
| } | ||
| throw new Error(`Failed to parse body as JSON. encoding: ${contentEncoding}, body: ${responseText!}`); |
There was a problem hiding this comment.
This error needs to be updated, right?
| method: 'POST', | ||
| body: jsonStringify(body), | ||
| headers: { 'content-type': 'application/json', ...extraHeaders }, | ||
| credentials: config.credentials ?? 'omit', |
There was a problem hiding this comment.
I'm missing where we set 'include' here for the json rpc client
There was a problem hiding this comment.
I didn't set this as a default. I'd rather the app do it.
| if (cookieJar) { | ||
| const setCookieHeaders = resp.headers['set-cookie']; | ||
| const cookies = typeof setCookieHeaders === 'string' ? [setCookieHeaders] : (setCookieHeaders ?? []); | ||
| for (const cookie of cookies) { | ||
| cookieJar.setCookie(cookie, requestUrl.href); | ||
| } | ||
| } |
There was a problem hiding this comment.
I'm surprised this needs to be done manually tbh
There was a problem hiding this comment.
Yep, undici only offers helpers to work with cookie headers but no cookie jar
https://undici.nodejs.org/api/Cookies
There's tough-cookie available but I'd rather not add a new dependency and let the app choose https://www.npmjs.com/package/tough-cookie
| rpcCorsAllowedOrigins: { | ||
| env: 'RPC_CORS_ALLOWED_ORIGINS', | ||
| description: 'Origins allowed to make credentialed cross-origin JSON RPC requests, separated by commas.', | ||
| parseEnv: (value: string) => | ||
| value | ||
| .split(',') | ||
| .map(origin => origin.trim()) | ||
| .filter(Boolean), | ||
| defaultValue: [], | ||
| }, |
There was a problem hiding this comment.
Where would we be using this? Or is this intended just for operators who'd be running a node to serve json-rpc to their app? I'm tempted to suggest deleting this in favor of just the "allow cors" below.
Or should this be handled by another layer in front of the node?
There was a problem hiding this comment.
We can't send access-control-allow-origin: * when working with cookies so we need to reflect the origin header on request back to the browser. I thought maybe node operators might need to control for which origins to do that? We'd use continue using * but now instead of returning a literal * we just reflect back the origin header.
| setCookie(cookie: string, url: string): void; | ||
| } | ||
|
|
||
| export function makeUndiciFetch(client: Dispatcher = new Agent(), cookieJar?: CookieJar): JsonRpcFetch { |
There was a problem hiding this comment.
I think we are never setting the cookie jar, are we? Do we really care about this undici client supporting session cookies then?
There was a problem hiding this comment.
App concern. I'll add some docs!
| export function makeFetch( | ||
| retries: number[], | ||
| defaultNoRetry: boolean, | ||
| log?: Logger, | ||
| config: JsonRpcFetchConfig = {}, | ||
| ): JsonRpcFetch { |
There was a problem hiding this comment.
Is makeFetch actually called by clients? Don't they go via createAztecNodeClient, which doesn't expose a way to set the credentials config?
| body: unknown, | ||
| extraHeaders: Record<string, string> = {}, | ||
| noRetry = false, | ||
| config: JsonRpcFetchConfig = {}, |
There was a problem hiding this comment.
Since we're on it, could we add a maxBatchSize to client as well?
10007f1 to
7824433
Compare
5e3bd96 to
7049d54
Compare
7824433 to
3b7c6ea
Compare
7049d54 to
be6077b
Compare
3b7c6ea to
849195d
Compare
be6077b to
83ff922
Compare
849195d to
36c1dc4
Compare
83ff922 to
c926fa8
Compare
|
I dropped the |
c926fa8 to
d5fdb5d
Compare
d5fdb5d to
f4a59f6
Compare
f4a59f6 to
4da81db
Compare
4da81db to
f10ab76
Compare
Promotes `v5-next` onto `v5` for the **v5.2.0** release. Frozen at `ee5d2d367e` — the `v5-next` tip at cut time. Both `merge-train/spartan-v5` and `merge-train/fairies-v5` are drained to that same commit, so nothing staged is left behind. ### Testnet validation This branch was cut at `a4db216abf`, which is byte-identical to the `v5.2.0-nightly.20260815` tag — same commit, same tree (`0b22572eace2419ede6bbab173514d6965d4e0d0`). That nightly's CI3 run is green, its artifacts are published to npm and Docker Hub, and it has been **running healthily on testnet since 2026-08-15**: | Component | Image / reported version | |---|---| | validators, prover node, prover broker, prover agents (`testnet` ns) | `aztecprotocol/aztec:5.2.0-nightly.20260815` | | `v5.testnet.rpc.aztec-labs.com` | `nodeVersion=5.2.0-nightly.20260815` | | `canonical.testnet.rpc.aztec-labs.com` | `nodeVersion=5.2.0-nightly.20260815` | Chain advancing normally, no prunes or reorgs, no WARN/ERROR across node pods since rollout. The branch has since been fast-forwarded to `ee5d2d367e` to pick up #25242 (configurable RPC server HTTP timeouts and CORS allowed-headers). That is the only delta from the soaked tree — 8 files, +131/−10, no nightly covers it yet. Its config defaults were checked against Node's built-ins (`keepAliveTimeout` 5000 ms, `headersTimeout` 60000 ms) and match exactly, and the CORS default path resolves to the same `cors()` call as before, so a node that sets none of the new env vars behaves identically. It touches no circuits, protocol contracts, or generated constants. ### Manifest `.release-please-manifest.json` reads `5.2.0` on this branch, which is the released version — correct as-is, no change needed in this PR. `v5-next` moves to `5.3.0` separately in #25240; this branch is frozen and cannot pick that up, so the two can merge in either order. `v5` is a strict ancestor of `v5-next` this cycle, so there was no manifest conflict to pre-resolve. ### Scope 139 commits (86 non-merge, 23 PR-level) spanning 2026-07-14 to 2026-08-17. | Area | Theme | |---|---| | `prover-node` / `prover-client` | Epoch-proving robustness: retry-to-converge with failure declared only at submission-window expiry, ticker-driven expiry, per-checkpoint post-mortem upload, checkpoint-only re-proving, prune-induced fault handling (#24678, #24982, #24983, #24990, #25027) | | `pxe` | Sync performance: hash-pinned node read cache (#24969), anchor-bounded tag log caching (#25074), note/event validation from cached tx data (#25076), constrained tag sync (#24275), sender tagging finalization from log blocks (#25045) | | `p2p` / `validator-client` | Gossip tx validation no longer stalls behind tx-pool finalization (#25148); startup fails when p2p fails to start (#25177); slashing/proposing/health/`sendTx` gated on p2p connectivity (#25185); duplicate time-sensitive proposal validation removed (#25207); `ValidatedProposal` branding (#25222) | | `ethereum` / `aztec-node` | L1 watchers poll `getLogs` instead of `eth_newFilter` (#25176); block stream sync no longer resolves against an earlier pass (#25206) | | `stdlib` / `foundation` | Deserialization bounds hardening (#25026, #25028, #25029, #25109); checkpoint block-shape and block-count validation (#25229); JSON-RPC cookies (#25231) | | `archiver` | Removed-block cleanup and ownership-checked tx-effect deletes (#24765); L2→L1 witness from a single store snapshot (#24754) | | `aztec` | Declarative deployment framework at `@aztec/aztec/deploy` (#24685) | | `slasher` | Own-validator slash-target warnings and metrics (#25058) | | telemetry | JSON-RPC metrics (#25159) | | JSON-RPC server | Configurable HTTP keep-alive / headers timeouts and CORS allowed-headers, defaults preserving current behaviour (#25242) | | toolchain | Noir bumped to `v1.0.0-beta.25` (#24907) | **One breaking change**, inherited from the Noir bump: note types declared directly inside a `contract` module must now be `pub`. Everything else is additive or internal. ### Protocol constants Built from source and compared against `v5` — a cache-free rebuild of every protocol circuit with each ref's own nargo and bb, then regeneration of `vk_tree.ts` and `protocol_contract_data.ts`: - `vkTreeRoot` = `0x2b3b6ea4412b9c8f6457a37f91a2870306f8641e07e16a49b68bda6f8bc02892` — unchanged from v5.1.0 - `protocolContractsHash` = `0x2c075866eafc88a1f6f9addc7e337c6e64e45d1cb7fd7c0d612ebcec72aab2ca` — unchanged from v5.1.0 The Noir beta.24 → beta.25 bump does not reach the circuits: the release build consumes the committed `pinned-build.tar.gz`, which is bit-identical between v5.1.0 and this commit (blob `3bedcb1fd1…`), so the protocol-circuit bytecode is frozen rather than recompiled. The 47 verification keys were recomputed locally from that pinned bytecode with the cache disabled, and all 47 `check_pinned_vk` checks passed. `protocolContractsHash` is likewise backed by the new `pinned-protocol-contracts.tar.gz`, whose three artifacts were byte-compared against the build. Both values were also confirmed inside the published `@aztec/protocol-contracts` and `@aztec/noir-protocol-circuits-types` packages for `5.2.0-nightly.20260815`. That makes v5.2.0 a drop-in upgrade against the current rollup rather than a coordinated one. ✅ **Gate re-run against `ee5d2d367e` (the current head) and passed** — both values reproduced exactly from a build at this commit, with `vkTreeRoot` numerically evaluated rather than inferred. `29556326ce..ee5d2d3` touches no `noir-projects/**`, `l1-contracts/src/**`, `ConstantsGen.sol`, `constants.gen.ts` or `constants.nr`. Scope of the check: it verifies that the pinned circuit bytecode plus locally recomputed VKs agree with the pin — not that a from-source recompile reproduces v5.1.0's bytecode. <details> <summary>Commits added after the original constants check at 2955632</summary> `#25207` `#25222` `#25206` `#25185` `#25176` `#25163` `#25229` `#25159` `#25162` `#25231` `#25224` `#25228` `#25230` `#25242` plus their merge commits. </details> ### Known gap Migration notes carry entries under `## TBD` that arrived with the docs baseline backport (#25017) and describe `next`-line changes not present on the v5 line — protocol contracts removed from `@aztec/noir-contracts.js`, and the `at(wallet)` → `withWallet(wallet)` deprecation. Neither exists on this branch. There is also no `## 5.1.0` heading, and the entries that ship in v5.2.0 sit under `## TBD` rather than a version heading. This ships in the release docs, so it is worth correcting on `v5-next` and backporting to `v5` before the tag, rather than after.
Implements cookie support in the JSON-RPC clients. This is useful for load balancer session affinity.
This PR is stacked on top of #25159
Fix A-1628 A-1676