Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
45 changes: 45 additions & 0 deletions docker/localnode/config/app.toml
Original file line number Diff line number Diff line change
Expand Up @@ -277,6 +277,51 @@ enable_test_api = true
# Set to 0 to disable request limiter, otherwise this limits the number of concurrent simulation calls.
max_concurrent_simulation_calls = 0

# Legacy sei_* / sei2_* JSON-RPC (EVM HTTP only).
# DEPRECATION: All sei_* and sei2_* methods are deprecated and scheduled for removal - no new integrations.
# HTTP 200; gate errors: JSON-RPC error (data legacy_sei_deprecated). Success: unchanged body; optional header Sei-Legacy-RPC-Deprecation.
# Docker localnet enables every gated method except sei_sign (integration tests assert the
# disabled-method path; sei_sign is not in partner telemetry and has no rpc_io_test fixtures).
# Production defaults from seid init remain the three-method sei_* allowlist - see evmrpc/config.
enabled_legacy_sei_apis = [
# "sei_sign",
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

nit - remove?

"sei_associate",
"sei_getBlockByHash",
"sei_getBlockByHashExcludeTraceFail",
"sei_getBlockByNumber",
"sei_getBlockByNumberExcludeTraceFail",
"sei_getBlockReceipts",
"sei_getBlockTransactionCountByHash",
"sei_getBlockTransactionCountByNumber",
"sei_getCosmosTx",
"sei_getEVMAddress",
"sei_getEvmTx",
"sei_getFilterChanges",
"sei_getFilterLogs",
"sei_getLogs",
"sei_getSeiAddress",
"sei_getTransactionByBlockHashAndIndex",
"sei_getTransactionByBlockNumberAndIndex",
"sei_getTransactionByHash",
"sei_getTransactionCount",
"sei_getTransactionErrorByHash",
"sei_getTransactionReceipt",
"sei_getTransactionReceiptExcludeTraceFail",
"sei_getVMError",
"sei_newBlockFilter",
"sei_newFilter",
"sei_traceBlockByHashExcludeTraceFail",
"sei_traceBlockByNumberExcludeTraceFail",
"sei_uninstallFilter",
"sei2_getBlockByHash",
"sei2_getBlockByHashExcludeTraceFail",
"sei2_getBlockByNumber",
"sei2_getBlockByNumberExcludeTraceFail",
"sei2_getBlockReceipts",
"sei2_getBlockTransactionCountByHash",
"sei2_getBlockTransactionCountByNumber",
]

###############################################################################
### Admin Configuration (Auto-managed) ###
###############################################################################
Expand Down
43 changes: 43 additions & 0 deletions docker/rpcnode/config/app.toml
Original file line number Diff line number Diff line change
Expand Up @@ -264,3 +264,46 @@ enable_test_api = true

# Set to 0 to disable request limiter, otherwise this limits the number of concurrent simulation calls.
max_concurrent_simulation_calls = 0

# Legacy sei_* / sei2_* JSON-RPC (EVM HTTP only).
# DEPRECATION: All sei_* and sei2_* methods are deprecated and scheduled for removal - no new integrations.
# HTTP 200; gate errors: JSON-RPC error (data legacy_sei_deprecated). Success: unchanged body; optional header Sei-Legacy-RPC-Deprecation.
# Same allowlist as docker/localnode (all gated methods except sei_sign for integration coverage).
enabled_legacy_sei_apis = [
# "sei_sign"
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

nit - remove?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I left it here intentionally commented to show explicitly that this one is not enabled. we can remove it as well. no worries.

"sei_associate",
"sei_getBlockByHash",
"sei_getBlockByHashExcludeTraceFail",
"sei_getBlockByNumber",
"sei_getBlockByNumberExcludeTraceFail",
"sei_getBlockReceipts",
"sei_getBlockTransactionCountByHash",
"sei_getBlockTransactionCountByNumber",
"sei_getCosmosTx",
"sei_getEVMAddress",
"sei_getEvmTx",
"sei_getFilterChanges",
"sei_getFilterLogs",
"sei_getLogs",
"sei_getSeiAddress",
"sei_getTransactionByBlockHashAndIndex",
"sei_getTransactionByBlockNumberAndIndex",
"sei_getTransactionByHash",
"sei_getTransactionCount",
"sei_getTransactionErrorByHash",
"sei_getTransactionReceipt",
"sei_getTransactionReceiptExcludeTraceFail",
"sei_getVMError",
"sei_newBlockFilter",
"sei_newFilter",
"sei_traceBlockByHashExcludeTraceFail",
"sei_traceBlockByNumberExcludeTraceFail",
"sei_uninstallFilter",
"sei2_getBlockByHash",
"sei2_getBlockByHashExcludeTraceFail",
"sei2_getBlockByNumber",
"sei2_getBlockByNumberExcludeTraceFail",
"sei2_getBlockReceipts",
"sei2_getBlockTransactionCountByHash",
"sei2_getBlockTransactionCountByNumber",
]
6 changes: 5 additions & 1 deletion evmrpc/AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,13 @@ EVM RPCs prefixed by `eth_` and `debug_` on Sei generally follows [Ethereum's sp
- `eth_newPendingTransactionFilter`
- `eth_syncing`

## `sei_` prefixed endpoints
## `sei_` and `sei2_` prefixed endpoints
Several `eth_` prefixed endpoints have a `sei_` prefixed counterpart. `eth_` endpoints only have visibility into EVM transactions, whereas `sei_` endpoints have visibility into EVM transactions plus Cosmos transactions that have synthetic EVM receipts.

The **`sei2`** namespace exposes the same **block** JSON-RPC shape as `sei` blocks, with **bank transfers** included in block payloads (HTTP only). There are seven `sei2_*` methods (block + block receipts + tx counts + `*ExcludeTraceFail` variants); there is no `sei2` transaction or filter API.

Legacy **`sei_*` and `sei2_*`** JSON-RPC (EVM HTTP only) are **gated** by the same `[evm].enabled_legacy_sei_apis` list in `app.toml` (after `deny_list`). Enforcement is **centralized** in `wrapSeiLegacyHTTP` (see `sei_legacy_http.go`): it inspects the JSON-RPC `method` field only. Wired from `HTTPServer.EnableRPC` via `HTTPConfig.SeiLegacyAllowlist` — handlers do not duplicate gate logic. Both surfaces are **deprecated** and scheduled for removal; **only methods named in that array** are allowed. `seid init` / `DefaultConfig` pre-fill the three `sei_*` address/Cosmos helpers; other gated methods (including `sei2_*`) appear **commented** in the generated template. **Docker localnet** (`docker/localnode/config/app.toml`) enables **all** gated methods except **`sei_sign`**. **HTTP 200** for all responses. **Disabled** methods return JSON-RPC `error` code `-32601`, `message` explains not enabled + deprecated, `data` `"legacy_sei_deprecated"`. **Allowed** responses pass through **unchanged**; optional deprecation signal: HTTP header `Sei-Legacy-RPC-Deprecation` (`SeiLegacyDeprecationHTTPHeader` in `sei_legacy.go`). Coverage: `evmrpc/sei_legacy_test.go` and `integration_test/evm_module/rpc_io_test/testdata/sei_legacy_deprecation/*.iox`.

## `debug_` prefixed endpoints
`debug_trace*` endpoints should faithfully replay historical execution. If a transaction encountered an error during its actual execution, a `debug_trace*` call for it should reflect so. If a transction consumed X amount of gas during its actual execution, a `debug_trace*` call should show that exact amount as well.

Expand Down
68 changes: 68 additions & 0 deletions evmrpc/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,10 @@ type Config struct {
// WorkerQueueSize defines the size of the task queue in the worker pool.
// Set to 0 to use default: 1000
WorkerQueueSize int `mapstructure:"worker_queue_size"`

// EnabledLegacySeiApis lists which gated sei_* and sei2_* JSON-RPC methods are allowed on the EVM HTTP endpoint.
// Set in app.toml [evm] as enabled_legacy_sei_apis (see ReadConfig and ConfigTemplate defaults).
EnabledLegacySeiApis []string `mapstructure:"enabled_legacy_sei_apis"`
}

var DefaultConfig = Config{
Expand Down Expand Up @@ -165,6 +169,11 @@ var DefaultConfig = Config{
RPCStatsInterval: 10 * time.Second,
WorkerPoolSize: min(MaxWorkerPoolSize, runtime.NumCPU()*2), // Default: min(64, CPU cores × 2)
WorkerQueueSize: DefaultWorkerQueueSize, // Default: 1000 tasks
EnabledLegacySeiApis: []string{
"sei_getSeiAddress",
"sei_getEVMAddress",
"sei_getCosmosTx",
},
}

const (
Expand Down Expand Up @@ -196,6 +205,7 @@ const (
flagRPCStatsInterval = "evm.rpc_stats_interval"
flagWorkerPoolSize = "evm.worker_pool_size"
flagWorkerQueueSize = "evm.worker_queue_size"
flagEVMLegacySeiApis = "evm.enabled_legacy_sei_apis"
)

func ReadConfig(opts servertypes.AppOptions) (Config, error) {
Expand Down Expand Up @@ -341,6 +351,11 @@ func ReadConfig(opts servertypes.AppOptions) (Config, error) {
return cfg, err
}
}
if v := opts.Get(flagEVMLegacySeiApis); v != nil {
if cfg.EnabledLegacySeiApis, err = cast.ToStringSliceE(v); err != nil {
return cfg, err
}
}

return cfg, nil
}
Expand Down Expand Up @@ -412,6 +427,59 @@ slow = {{ .EVM.Slow }}
# Deny list defines list of methods that EVM RPC should fail fast, e.g ["debug_traceBlockByNumber"]
deny_list = {{ .EVM.DenyList }}

# Legacy sei_* / sei2_* JSON-RPC (EVM HTTP only - not Cosmos REST on 1317).
#
# DEPRECATION: The sei_* and sei2_* JSON-RPC surfaces are deprecated and scheduled for removal. Do not
# build new integrations on them; use eth_* / debug_* and documented replacements. HTTP 200;
# gate errors use standard JSON-RPC error encoding (see evmrpc/AGENTS.md). Successful allowlisted
# responses are unchanged; nodes may set HTTP header Sei-Legacy-RPC-Deprecation (see AGENTS.md).
#
# Only methods listed in enabled_legacy_sei_apis are allowed. Init defaults enable the three
# address/Cosmos helpers; uncomment optional lines below to enable more legacy methods (include
# sei2_* block methods at the end of the list if you need them).
enabled_legacy_sei_apis = [
{{- range .EVM.EnabledLegacySeiApis }}
"{{ . }}",
{{- end }}

# Optional legacy methods - uncomment to enable (same deprecation applies):
# "sei_associate",
# "sei_getBlockByHash",
# "sei_getBlockByHashExcludeTraceFail",
# "sei_getBlockByNumber",
# "sei_getBlockByNumberExcludeTraceFail",
# "sei_getBlockReceipts",
# "sei_getBlockTransactionCountByHash",
# "sei_getBlockTransactionCountByNumber",
# "sei_getEvmTx",
# "sei_getFilterChanges",
# "sei_getFilterLogs",
# "sei_getLogs",
# "sei_getTransactionByBlockHashAndIndex",
# "sei_getTransactionByBlockNumberAndIndex",
# "sei_getTransactionByHash",
# "sei_getTransactionCount",
# "sei_getTransactionErrorByHash",
# "sei_getTransactionReceipt",
# "sei_getTransactionReceiptExcludeTraceFail",
# "sei_getVMError",
# "sei_newBlockFilter",
# "sei_newFilter",
# "sei_sign",
# "sei_traceBlockByHashExcludeTraceFail",
# "sei_traceBlockByNumberExcludeTraceFail",
# "sei_uninstallFilter",
#
# Optional sei2_* block namespace (bank transfers in blocks; HTTP only):
# "sei2_getBlockByHash",
# "sei2_getBlockByHashExcludeTraceFail",
# "sei2_getBlockByNumber",
# "sei2_getBlockByNumberExcludeTraceFail",
# "sei2_getBlockReceipts",
# "sei2_getBlockTransactionCountByHash",
# "sei2_getBlockTransactionCountByNumber",
]

# max number of logs returned if block range is open-ended
max_log_no_block = {{ .EVM.MaxLogNoBlock }}

Expand Down
3 changes: 3 additions & 0 deletions evmrpc/config/config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,9 @@ func (o *opts) Get(k string) interface{} {
if k == "evm.worker_queue_size" {
return o.workerQueueSize
}
if k == "evm.enabled_legacy_sei_apis" {
return nil
}
panic("unknown key")
}

Expand Down
6 changes: 5 additions & 1 deletion evmrpc/rpcstack.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,9 @@ type HTTPConfig struct {
CorsAllowedOrigins []string
Vhosts []string
DenyList []string
// SeiLegacyAllowlist is BuildSeiLegacyEnabledSet(app.toml enabled_legacy_sei_apis); nil skips the HTTP gate
// for gated sei_* and sei2_* methods.
SeiLegacyAllowlist map[string]struct{}
prefix string // path prefix on which to mount http handler
RPCEndpointConfig
}
Expand Down Expand Up @@ -312,8 +315,9 @@ func (h *HTTPServer) EnableRPC(apis []rpc.API, config HTTPConfig) error {
srv.RegisterDenyList(method)
}
h.HTTPConfig = config
base := NewHTTPHandlerStack(srv, config.CorsAllowedOrigins, config.Vhosts, config.JwtSecret)
h.httpHandler.Store(&rpcHandler{
Handler: NewHTTPHandlerStack(srv, config.CorsAllowedOrigins, config.Vhosts, config.JwtSecret),
Handler: wrapSeiLegacyHTTP(base, config.SeiLegacyAllowlist),
server: srv,
})
return nil
Expand Down
Loading
Loading