Skip to content

feat: enable gRPC on validator mode (parity with sei-infra canonical)#19

Merged
bdchatham merged 1 commit into
mainfrom
feat/validator-grpc-parity-with-sei-infra
May 20, 2026
Merged

feat: enable gRPC on validator mode (parity with sei-infra canonical)#19
bdchatham merged 1 commit into
mainfrom
feat/validator-grpc-parity-with-sei-infra

Conversation

@bdchatham
Copy link
Copy Markdown
Collaborator

@bdchatham bdchatham commented May 20, 2026

Summary

applyValidatorOverrides previously disabled API.GRPC.Enable, diverging from canonical sei-infra EC2 validators. This PR aligns the validator-mode default with what the seid binary + sei-infra deploy scripts actually do on EC2. GRPCWeb stays disabled (no current consumer); REST/EVM/StateStore overrides are untouched (separate posture questions).

Bumps version.json to v0.0.15 so downstream consumers (seictl, sei-k8s-controller) can pin explicitly.

Canonical evidence

  • sei-chain/docker/localnode/config/app.toml — seid built-in default ships with [grpc] enable = true.
  • sei-infra/validators/deploy/scripts/init_configure.sh — sed-edits pruning/indexer/sc-enable/concurrency, never touches [grpc], so the default carries through.
  • sei-infra/validators/deploy/scripts/post_init.sh:23 — starts the oracle price feeder after chain liftoff.
  • sei-infra/validators/deploy/scripts/price_feeder_config.toml:47 — hard-coded grpc_endpoint = "localhost:9090". A canonical validator without gRPC would fail to feed prices.

Motivating problem

K8s validators (where seictl writes app.toml from these defaults) have been diverging from canonical for sei-config's entire history. The divergence is also what makes the cosmos-exporter sidecar Fatal-loop on K8s validators: cosmos-exporter dials :9090 at startup. EC2 validators never hit this because they have gRPC up.

Cross-review

Dispatched the trio (security-specialist, platform-engineer, kubernetes-specialist) on the diff before opening. All three came back proceed-with-conditions. Key conditions baked into this PR:

  • GRPCWeb stays off (security-specialist call). No current consumer needs gRPCWeb; the price feeder and cosmos-exporter both use raw gRPC. Un-defer when a real consumer appears.
  • Version bump included (platform-engineer call). Pairs the schema change with the version pin so downstream dep bumps are unambiguous.

Conditions filed as follow-ups (not in this PR):

  • NetworkPolicy on SeiNode pods restricting :9090 ingress — EC2 has SG-level gating; K8s parity requires explicit policy. Independently needed, more urgent after this propagates.
  • Remove cosmosExporterReadinessProbePort validator branch in sei-k8s-controller — becomes dead code after full fleet cycles.

Downstream sequencing (NOT part of this PR)

  1. This lands, tag v0.0.15.
  2. Bump sei-config dep in seictl, build new seictl image.
  3. Bump SEI_SIDECAR_IMAGE in sei-k8s-controller platform overlays (harbor + dev + prod).
  4. Cycle validator pods. config-apply re-runs on Init/NodeUpdate plans, not on env-var change — existing pods retain old app.toml until restart.

Test plan

  • go test ./... passes
  • TestDefaultForMode_ValidatorEnablesGRPC locks the new invariant
  • TestDefaultForMode_ValidatorDisablesServices still asserts the unchanged posture (REST/EVM/StateStore/GRPCWeb all disabled)
  • Downstream: seictl bump + sei-k8s-controller SEI_SIDECAR_IMAGE rollout
  • Manual verification: validator pod cycle → new app.toml → cosmos-exporter no longer Fatal-loops

🤖 Generated with Claude Code

`applyValidatorOverrides` previously disabled `API.GRPC.Enable`, diverging
from canonical sei-infra EC2 validators. Canonical evidence:

- `sei-chain/docker/localnode/config/app.toml` `[grpc] enable = true` —
  the seid binary's built-in default.
- `sei-infra/validators/deploy/scripts/init_configure.sh` sed-edits 10+
  fields (pruning, indexer, sc-enable, concurrency) but never touches
  the `[grpc]` section — default carries through.
- `sei-infra/validators/deploy/scripts/post_init.sh` starts the oracle
  price feeder, whose `price_feeder_config.toml:47` hard-codes
  `grpc_endpoint = "localhost:9090"`. A canonical validator without
  gRPC up cannot feed prices.

K8s validators (where seictl writes app.toml from these defaults) have
been diverging from this for the entire history of sei-config. The
divergence is also what makes the cosmos-exporter sidecar Fatal-loop
on K8s validators specifically — it dials :9090 at startup and seid
isn't listening there.

`GRPCWeb.Enable` stays disabled: no current consumer needs it and it
adds browser-reachable surface for no benefit (security-specialist
cross-review call). Un-defer when a real consumer appears.

`REST.Enable` / `EVM.HTTPEnabled` / `Storage.StateStore.Enable` stay
disabled — those are separate posture questions.

Cross-repo coordination after this lands + tags v0.0.15:
1. bump sei-config dep in seictl, build new seictl image
2. bump `SEI_SIDECAR_IMAGE` in sei-k8s-controller's platform overlays
3. cycle validator pods (config-apply re-runs on Init/NodeUpdate, not
   on env-var change — existing pods retain old app.toml until cycled)

Follow-up (filed separately as sei-k8s-controller issues):
- NetworkPolicy gating :9090 on SeiNode pods (EC2 has SG-level
  gating; K8s parity requires explicit policy).
- Remove `cosmosExporterReadinessProbePort` validator branch in
  sei-k8s-controller once full fleet cycles.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
@cursor
Copy link
Copy Markdown

cursor Bot commented May 20, 2026

You have used all Bugbot PR reviews included in your free trial for your GitHub account on this workspace.

To continue using Bugbot reviews, enable Bugbot for your team in the Cursor dashboard.

@github-actions
Copy link
Copy Markdown

Suggested version: v0.0.15

Comparing to: v0.0.14 (diff)

Changes in go.mod file(s):

(empty)

gorelease says:

panic: runtime error: invalid memory address or nil pointer dereference [recovered, repanicked]
[signal SIGSEGV: segmentation violation code=0x1 addr=0x0 pc=0x60b0d2]

goroutine 107 [running]:
go/types.(*Checker).handleBailout(0xbb7754c6000, 0xbb775193c30)
	/opt/hostedtoolcache/go/1.26.3/x64/src/go/types/check.go:473 +0x91
panic({0x6ea840?, 0x98eba0?})
	/opt/hostedtoolcache/go/1.26.3/x64/src/runtime/panic.go:860 +0x13a
go/types.(*StdSizes).Sizeof(0x0, {0x759c68, 0x992360})
	/opt/hostedtoolcache/go/1.26.3/x64/src/go/types/sizes.go:229 +0x312
go/types.(*Config).sizeof(...)
	/opt/hostedtoolcache/go/1.26.3/x64/src/go/types/sizes.go:334
go/types.representableConst.func1(...)
	/opt/hostedtoolcache/go/1.26.3/x64/src/go/types/const.go:77
go/types.representableConst({0x75ba60, 0x767900}, 0xbb7754c6000, 0x992360, 0xbb775190fa8)
	/opt/hostedtoolcache/go/1.26.3/x64/src/go/types/const.go:93 +0x1e9
go/types.(*Checker).representation(0xbb7754c6000, 0xbb775311280, 0x992360)
	/opt/hostedtoolcache/go/1.26.3/x64/src/go/types/const.go:257 +0x5f
go/types.(*Checker).implicitTypeAndValue(0xbb7754c6000, 0xbb775311280, {0x759c68?, 0x992360?})
	/opt/hostedtoolcache/go/1.26.3/x64/src/go/types/expr.go:404 +0x3ed
go/types.(*Checker).assignment(0xbb7754c6000, 0xbb775311280, {0x759c68, 0x992360}, {0x73fbc2, 0x10})
	/opt/hostedtoolcache/go/1.26.3/x64/src/go/types/assignments.go:70 +0x445
go/types.(*Checker).initVar(0xbb7754c6000?, 0x992360?, 0xbb775311280?, {0x73fbc2?, 0xbb77549e5a0?})
	/opt/hostedtoolcache/go/1.26.3/x64/src/go/types/assignments.go:181 +0x385
go/types.(*Checker).initVars(0xbb7754c6000, {0xbb7754a0270, 0x1, 0x0?}, {0xbb7754981e0, 0x6212cc?, 0x62f3dd?}, {0x75b128, 0xbb7754a48c0})
	/opt/hostedtoolcache/go/1.26.3/x64/src/go/types/assignments.go:413 +0x612
go/types.(*Checker).stmt(0xbb7754c6000, 0x0, {0x75b128, 0xbb7754a48c0})
	/opt/hostedtoolcache/go/1.26.3/x64/src/go/types/stmt.go:565 +0x6b7
go/types.(*Checker).stmtList(0xbb7754c6000, 0x0, {0xbb7754981f0?, 0x73bc80?, 0x5?})
	/opt/hostedtoolcache/go/1.26.3/x64/src/go/types/stmt.go:125 +0x85
go/types.(*Checker).stmt(0xbb7754c6000, 0x0, {0x75b188, 0xbb77549e5d0})
	/opt/hostedtoolcache/go/1.26.3/x64/src/go/types/stmt.go:603 +0x56e
go/types.(*Checker).stmt(0xbb7754c6000, 0x0, {0x75b1b8, 0xbb7754a84c0})
	/opt/hostedtoolcache/go/1.26.3/x64/src/go/types/stmt.go:615 +0x25fd
go/types.(*Checker).stmtList(0xbb7754c6000, 0x0, {0xbb7754a4920?, 0x73bc80?, 0x5?})
	/opt/hostedtoolcache/go/1.26.3/x64/src/go/types/stmt.go:125 +0x85
go/types.(*Checker).stmt(0xbb7754c6000, 0x0, {0x75b188, 0xbb77549e630})
	/opt/hostedtoolcache/go/1.26.3/x64/src/go/types/stmt.go:603 +0x56e
go/types.(*Checker).stmt(0xbb7754c6000, 0x0, {0x75b1b8, 0xbb7754a8500})
	/opt/hostedtoolcache/go/1.26.3/x64/src/go/types/stmt.go:615 +0x25fd
go/types.(*Checker).stmtList(0xbb7754c6000, 0x0, {0xbb7754b6080?, 0x0?, 0x10?})
	/opt/hostedtoolcache/go/1.26.3/x64/src/go/types/stmt.go:125 +0x85
go/types.(*Checker).funcBody(0xbb7754c6000, 0x75ac18?, {0xbb775482180?, 0xbb7754bda40?}, 0xbb775310580, 0xbb77549e810, {0x0?, 0x0?})
	/opt/hostedtoolcache/go/1.26.3/x64/src/go/types/stmt.go:42 +0x37b
go/types.(*Checker).funcDecl.func1()
	/opt/hostedtoolcache/go/1.26.3/x64/src/go/types/decl.go:838 +0x3a
go/types.(*Checker).processDelayed(0xbb7754c6000, 0x0)
	/opt/hostedtoolcache/go/1.26.3/x64/src/go/types/check.go:595 +0x1e2
go/types.(*Checker).checkFiles(0xbb7754c6000, {0xbb7754a0000?, 0x5c4d9b?, 0x993280?})
	/opt/hostedtoolcache/go/1.26.3/x64/src/go/types/check.go:537 +0x3f9
go/types.(*Checker).Files(0xbb7752300e0?, {0xbb7754a0000?, 0xbb77549c060?, 0x6?})
	/opt/hostedtoolcache/go/1.26.3/x64/src/go/types/check.go:491 +0x75
golang.org/x/tools/go/packages.(*loader).loadPackage(0xbb7752300e0, 0xbb7752074d0)
	/home/runner/go/pkg/mod/golang.org/x/tools@v0.2.0/go/packages/packages.go:1037 +0x8f2
golang.org/x/tools/go/packages.(*loader).loadRecursive.func1()
	/home/runner/go/pkg/mod/golang.org/x/tools@v0.2.0/go/packages/packages.go:847 +0x1a7
sync.(*Once).doSlow(0x0?, 0x0?)
	/opt/hostedtoolcache/go/1.26.3/x64/src/sync/once.go:78 +0xac
sync.(*Once).Do(...)
	/opt/hostedtoolcache/go/1.26.3/x64/src/sync/once.go:69
golang.org/x/tools/go/packages.(*loader).loadRecursive(0x0?, 0x0?)
	/home/runner/go/pkg/mod/golang.org/x/tools@v0.2.0/go/packages/packages.go:835 +0x3b
golang.org/x/tools/go/packages.(*loader).loadRecursive.func1.1(0x0?)
	/home/runner/go/pkg/mod/golang.org/x/tools@v0.2.0/go/packages/packages.go:842 +0x26
created by golang.org/x/tools/go/packages.(*loader).loadRecursive.func1 in goroutine 49
	/home/runner/go/pkg/mod/golang.org/x/tools@v0.2.0/go/packages/packages.go:841 +0x8c

gocompat says:

Your branch is up to date with 'origin/main'.

Cutting a Release (and modifying non-markdown files)

This PR is modifying both version.json and non-markdown files.
The Release Checker is not able to analyse files that are not checked in to main. This might cause the above analysis to be inaccurate.
Please consider performing all the code changes in a separate PR before cutting the release.

Automatically created GitHub Release

A draft GitHub Release has been created.
It is going to be published when this PR is merged.
You can modify its' body to include any release notes you wish to include with the release.

@bdchatham bdchatham merged commit 6b49a70 into main May 20, 2026
4 checks passed
bdchatham added a commit to sei-protocol/seictl that referenced this pull request May 20, 2026
## Summary

Picks up sei-protocol/sei-config#19, which removed the `API.GRPC.Enable
= false` override on `applyValidatorOverrides` to align with canonical
sei-infra EC2 validators.

## Behavioral effect for seictl

Validator-mode `app.toml` files generated by the sidecar's config-apply
path will now include `[grpc] enable = true` (was `false`). `gRPCWeb`
stays disabled (no current consumer). REST / EVM / StateStore overrides
unchanged.

## Downstream

After this merges (and the matching `chore: bump version to v0.0.52`
fast-follow lands), bumping seictl's image SHA in sei-k8s-controller's
platform overlays will, on next validator pod cycle, propagate the new
app.toml. That unblocks the cosmos-exporter sidecar, which dials
`localhost:9090` at startup and currently Fatal-loops on K8s validators
because gRPC isn't listening.

Note: config-apply only re-runs on Init/NodeUpdate plans, not on env-var
change. Existing validator pods will retain their old app.toml until
cycled.

## Cross-review

Substantive review happened on the underlying sei-config#19 PR
(security-specialist + platform-engineer + kubernetes-specialist all
returned proceed-with-conditions; conditions are tracked as
sei-k8s-controller#311 + #312). This PR is the mechanical dep bump only.

## Test plan

- [x] `go build ./...` clean
- [x] `go test ./...` passes
- [x] Fast-follow `chore: bump version to v0.0.52` PR after merge
- [x] Downstream: sei-k8s-controller `SEI_SIDECAR_IMAGE` overlay bump

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
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