Skip to content

Backport release/v6.6: Add frozen RPC router and Docker integration cluster (#3989) - #4024

Merged
bdchatham merged 2 commits into
release/v6.6from
backport-3989-to-release/v6.6
Aug 27, 2026
Merged

Backport release/v6.6: Add frozen RPC router and Docker integration cluster (#3989)#4024
bdchatham merged 2 commits into
release/v6.6from
backport-3989-to-release/v6.6

Conversation

@bdchatham

@bdchatham bdchatham commented Aug 26, 2026

Copy link
Copy Markdown
Contributor

Backport of #3989 to release/v6.6.

Describe your changes and provide context

Cherry-pick of 689f7d6, plus one branch adaptation. This adds:

  • frozen-rpc-router, an EVM JSON-RPC proxy that routes block-scoped requests to the matching frozen node and all other traffic to the live node.
  • A Docker Compose topology with non-validating archival nodes frozen before heights 10 and 20, two live validators, and the router on port 8553.
  • Integration coverage that proves heights 9, 15, and 20 reach the height-10 frozen node, the height-20 frozen node, and the live node. It also verifies that the router rejects cross-node block ranges.
  • Build and packaging for the router alongside seid, and the topology in the integration-test CI matrix.

All 8 new files are byte-identical to the merged commit on main. The base docker/docker-compose.yml is byte-identical between the two branches, as are the 4 localnode scripts after this change.

Commits

  1. feat: add frozen RPC router cluster — the cherry-pick, with the conflict resolutions below.
  2. fix(build): use the branch GOPATH convention in frozen RPC cluster targets — see "Branch adaptation".

Conflict resolution

Four conflicts came up. Every one is drift between main and release/v6.6, not part of the PR.

File Cause Resolution
.github/workflows/integration-test-matrix.json main extracted the matrix to JSON plus a set-matrix job. release/v6.6 keeps it inline in the workflow. Dropped the file. Added the Frozen RPC Router row inline, with cluster: "frozen-rpc-router", in the same position main uses. Nothing else in the JSON was needed, and nothing under .github/ still references it.
.github/workflows/integration-test.yml (2 sites) main has .github/scripts/docker-registry-retry.sh and an autobahn-integration-tests job. release/v6.6 has neither. The PR only reworded a comment at each site. Kept the release/v6.6 text. Nothing to port.
docker/localnode/scripts/step4_config_override.sh main defaults GIGA_EXECUTOR and GIGA_OCC to true. release/v6.6 defaults both to false. Kept the release/v6.6 defaults. Ported only the PR change: VALIDATOR=${VALIDATOR:-true} and the mode = "full" override. The overlay's explicit GIGA_*=false exists because main defaults to true; on this branch it agrees with the default, so behaviour is unchanged for this topology and for every other cluster.
docker/localnode/scripts/step5_start_sei.sh main carries SEID_PID=$!, which feeds a readiness loop that release/v6.6 does not have. The loop is context, not part of #3989. Ported only --freeze-height "${FREEZE_HEIGHT}". Left SEID_PID out, because this branch has no loop to consume it. See caveat 1.

Branch adaptation

The cherry-pick carried main's $(shell go env GOMODCACHE) into the two new frozen-rpc cluster targets. This branch hardcodes GO_PKG_PATH = $(HOME)/go/pkg at Makefile:23, and its other six cluster targets all create $(shell go env GOPATH)/pkg/mod. With a relocated GOMODCACHE the mkdir and the compose mount source diverge, the bind mount lands on a root-owned empty directory, and the node build hangs with no build.complete. CI is unaffected, because the runner's default GOPATH makes the two paths coincide. Commit 2 aligns the new targets with this branch's convention.

This does not address the pre-existing GO_PKG_PATH / go env GOPATH divergence on this branch, which affects all cluster targets identically and is out of scope here.

Branch dependencies confirmed

  • --freeze-height is registered on seid start at sei-cosmos/server/start.go:218. Freeze mode is already on this branch: 5b9a56ba7 "Disable mempool traffic in freeze mode (Backport release/v6.6: Disable mempool traffic in freeze mode #4006)".
  • The compose overlay sets VALIDATOR and FREEZE_HEIGHT to literal values, so it does not need the base docker-compose.yml to declare them. docker compose config confirms node1 gets FREEZE_HEIGHT=10 and VALIDATOR=false, node2 gets 20 and false, and node0 and node3 stay validators. Direct RPC ports 8547 / 8549 / 8545 match the test and the README. IP 192.168.10.14 is free.
  • sei-tendermint/node/public.go on this branch has validateFreezeMode, which rejects freezeHeight > 0 in validator mode. main removed that check. So the mode = "full" sed is load-bearing here, and a failed sed is a loud node-start failure rather than two frozen validators halting consensus at height 10. I verified the sed applies: docker/localnode/config/config.toml:18 is exactly mode = "validator", one match, and the piped result is mode = "full".
  • The startup barriers hold with 2 validators across 4 nodes. init.complete and persistent_peers.txt writes sit outside the new VALIDATOR guard, and step3_add_validator_to_genesis.sh iterates for FILE in * rather than a fixed count. The router container overrides entrypoint, so it never runs deploy.sh and never adds a 5th launch.complete line — the ungated 4-line wait stays correct.
  • ReadOnly in freeze mode (from Backport release/v6.6: Disable mempool traffic in freeze mode #4006) gates only mempool and evidence paths via requireWritable. Queries are untouched, so frozen nodes serve eth_blockNumber and eth_getBlockByNumber normally.

Caveats for the release owner

Neither is a backport defect. Both are consequences of this branch, and both are worth a decision before merge.

  1. launch.complete is a weaker barrier here than upstream. On main it means the node's query surface answers; on this branch it means seid was backgrounded. A seid start that dies immediately still writes it. The frozen row is the only matrix row with Verify Sei Chain is running gated off, so nothing between compose-up and the test checks node liveness. The test self-gates with a 3-minute waitForHead per endpoint, so this costs diagnosability, not correctness: a dead frozen node surfaces as a timeout with last height 0 instead of a pointed error. Backporting main's step5 readiness loop is a reasonable follow-up.

  2. The router's block-parameter table does not cover this branch's legacy sei_* / sei2_* surface. cmd/frozen-rpc-router/router.go:27 lists only eth_* and debug_*. main narrowed evmrpc/sei_legacy.go to 3 live methods (the address and Cosmos helpers); this branch still has 33, and docker/localnode/config/app.toml:294 enables the block-scoped ones on the localnet — sei_getBlockByNumber, sei_getBlockReceipts, sei_getLogs and more. A request for sei_getBlockByNumber at a pre-freeze height misses the table, falls through to the live node, and returns not-found with a header asserting the live route was deliberate. The integration test does not catch this, because the localnet's live node still holds block 9. Production exposure is limited: the default allowlist at evmrpc/config/config.go:531 is only the three non-block-scoped helpers, so an operator must widen enabled_legacy_sei_apis to reach it. The router code is byte-identical to main, so this is an upstream coverage gap that is simply wider on this branch.

Testing performed to validate your change

Check Result
go build ./cmd/frozen-rpc-router pass
go test -race ./cmd/frozen-rpc-router ok, 1.532s
go test -tags frozen_rpc_integration -run '^$' ./integration_test/frozen_rpc_router/... compiles
go vet ./cmd/frozen-rpc-router/... pass
staticcheck ./cmd/frozen-rpc-router/... pass
golangci-lint run --timeout 10m0s ./cmd/frozen-rpc-router/... at the CI pin v2.8.0 0 issues
gofmt -l cmd/frozen-rpc-router integration_test/frozen_rpc_router clean
git diff --check clean
sh -n on all 4 changed scripts pass
docker compose config on the merged overlay per-node env, ports and IPs verified
.github/workflows/integration-test.yml parsed as YAML 33 matrix rows, 1 frozen row, 4 cluster conditions
make -n on both new cluster targets mount paths verified after commit 2
go test ./sei-tendermint/node/ -run Freeze logs Freeze mode enabled ... mode=full, confirming freeze boots as a full node on this branch
docker/localnode/config/config.toml piped through the mode = "full" sed one match, correct result

Two notes on lint. golangci-lint 2.12.2 reports 5 findings on cmd/frozen-rpc-router (1 goconst, 4 gosec G704/G706 taint rules). CI pins v2.8.0, which reports 0. The Go sources are byte-identical to main, so those findings apply to main too. They are a linter-version difference, not a backport regression. Separately, make fmtcheck does not exist on this branch, so I ran gofmt -l directly.

I did not run make frozen-rpc-router-integration-test locally. It needs a full 4-node Docker cluster build. What it would prove and no static check can: that the 2-validator genesis produces blocks past height 20, and that the frozen nodes stop at exactly 9 and 19. That is what the new Integration Test (Frozen RPC Router) CI row is for. One data point in its favour: this branch's config.toml carries unsafe-commit-timeout-override = "50ms", which main does not, so the chain should reach height 20 faster here than upstream.

Note for whoever merges: Integration Test (Frozen RPC Router) is a new check name, so branch protection for release/v6.6 may need updating.

🤖 Generated with Claude Code

(cherry picked from commit 689f7d6)
@cursor

cursor Bot commented Aug 26, 2026

Copy link
Copy Markdown

PR Summary

Medium Risk
Introduces a new RPC routing layer whose misconfiguration or incomplete method coverage (e.g. legacy sei_* block APIs on this branch) could send historical queries to the live node; freeze-height and full-node mode changes affect localnet topology but are covered by unit and integration tests.

Overview
Adds frozen-rpc-router, an HTTP EVM JSON-RPC proxy that forwards latest / non-block traffic to a live node and routes block-scoped eth_* / debug_* calls to archival nodes configured with exclusive freeze-height intervals. eth_getLogs and eth_feeHistory only route when the full range sits in one interval; cross-interval ranges return JSON-RPC -32000. Responses can include Sei-RPC-Route (live, frozen:<height>, or mixed for split batches).

Build & localnet: New make build-frozen-rpc-router, a Compose overlay (two live validators, two non-validating frozen full nodes at heights 10 and 20, router on host 8553), and make frozen-rpc-router-integration-test. Localnode init now supports VALIDATOR=false, --freeze-height on seid start, and builds the router binary alongside seid.

CI: Integration prepare job packages build/frozen-rpc-router, adds an Integration Test (Frozen RPC Router) matrix row that starts the frozen topology (skipping the standard 4-node + RPC node path), and runs go test -tags frozen_rpc_integration against heights 9 / 15 / 20 plus cross-interval log rejection.

Reviewed by Cursor Bugbot for commit 3296241. Bugbot is set up for automated code reviews on this repo. Configure here.

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes using default effort and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit cd0b5d2. Configure here.

Comment thread Makefile
@codecov

codecov Bot commented Aug 26, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 59.95935% with 197 lines in your changes missing coverage. Please review.
✅ Project coverage is 57.99%. Comparing base (829785f) to head (3296241).

Files with missing lines Patch % Lines
cmd/frozen-rpc-router/router.go 63.76% 96 Missing and 54 partials ⚠️
cmd/frozen-rpc-router/main.go 0.00% 39 Missing ⚠️
cmd/frozen-rpc-router/config.go 79.48% 4 Missing and 4 partials ⚠️
Additional details and impacted files

Impacted file tree graph

@@               Coverage Diff                @@
##           release/v6.6    #4024      +/-   ##
================================================
- Coverage         58.87%   57.99%   -0.88%     
================================================
  Files              2228     2157      -71     
  Lines            183964   175837    -8127     
================================================
- Hits             108302   101978    -6324     
+ Misses            65894    64734    -1160     
+ Partials           9768     9125     -643     
Flag Coverage Δ
sei-chain-pr 59.95% <59.95%> (?)
sei-db 70.02% <ø> (+0.21%) ⬆️
sei-db-state-db ?

Flags with carried forward coverage won't be shown. Click here to find out more.

Files with missing lines Coverage Δ
cmd/frozen-rpc-router/config.go 79.48% <79.48%> (ø)
cmd/frozen-rpc-router/main.go 0.00% <0.00%> (ø)
cmd/frozen-rpc-router/router.go 63.76% <63.76%> (ø)

... and 75 files with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@github-actions

github-actions Bot commented Aug 26, 2026

Copy link
Copy Markdown

The latest Buf updates on your PR. Results from workflow Buf / buf (pull_request).

BuildFormatLintBreakingUpdated (UTC)
✅ passed✅ passed✅ passed✅ passedAug 26, 2026, 5:36 PM

…rgets

The cherry-pick carried main's $(shell go env GOMODCACHE) into the two new
frozen-rpc cluster targets. This branch hardcodes GO_PKG_PATH to $(HOME)/go/pkg
and every other cluster target creates $(shell go env GOPATH)/pkg/mod. With a
relocated GOMODCACHE the mkdir and the compose mount source diverge, so the
bind mount lands on a root-owned empty directory and the node build hangs.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@bdchatham
bdchatham requested review from codchen and masih August 26, 2026 17:39
@bdchatham
bdchatham enabled auto-merge (squash) August 26, 2026 17:40
@bdchatham
bdchatham merged commit f1ff484 into release/v6.6 Aug 27, 2026
63 checks passed
@bdchatham
bdchatham deleted the backport-3989-to-release/v6.6 branch August 27, 2026 07:47
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants