~/.evmd/config/app.toml. This guide covers parameters unique to the EVM implementation.
- EVM
- Mempool
- JSON-RPC
- Runtime Flags
- Application Config
- Genesis Config
- Validator Nodes
EVM execution environment configuration.
string
default:""
Controls VM execution tracing for debugging.Valid Options:
""- Disabled (default)"json"- Full execution trace in JSON format, used by debug_traceTransaction RPC"struct"- Go struct format for programmatic processing"access_list"- Generates EIP-2930 access lists for gas optimization"markdown"- Human-readable format for manual analysis
server/config/config.go:139
Implementation: x/vm/keeper/state_transition.go:150-157number
default:"0"
Limits gas for transactions in CheckTx mode to prevent DoS attacks.When set to 0, any gas amount is accepted which can lead to mempool spam.Source:
server/config/config.go:141
Testnet Default: Set by evmd/cmd/evmd/cmd/testnet.go:303boolean
default:"false"
Enables SHA3 preimage recording in the VM for debugging tools to reverse hash lookups.Increases memory usage when enabled.Source:
server/config/config.go:143number
default:"262144"
EIP-155 replay protection chain ID.Must match the expected network chain ID. Used for transaction signing validation.Source:
server/config/config.go:145
Used in: x/vm/genesis.go:22number
default:"0"
Minimum priority fee (tip) required for transaction inclusion in mempool.Transactions with tips below this value may be rejected. Set to 0 to disable filtering.Flag:
EVMMinTip
Source: server/config/config.go:150
Type: Converted to uint256.Int internallystring
default:"127.0.0.1:8100"
Address for go-ethereum metrics server.Emits EVM-specific metrics in Prometheus format on a separate server from Cosmos SDK metrics.Source:
server/config/config.go:152
New in: v0.5.0EVM mempool configuration for transaction pool management.Low-Resource Node:Strict Spam Protection:
New in v0.5.0: Mempool configuration is now fully exposed in
app.toml and can be adjusted without code changes. Previously, these settings were hardcoded.number
default:"1"
Minimum gas price to enforce for acceptance into the pool (in wei).Transactions with gas prices below this value are rejected from the mempool.Source:
server/config/config.go:160
Validation: Must be at least 1number
default:"10"
Minimum price bump percentage to replace an already existing transaction (nonce).When replacing a transaction with the same nonce, the new transaction must have a gas price at least this percentage higher.Source:
server/config/config.go:162
Example: 10 = require 10% higher gas price
Validation: Must be at least 1number
default:"16"
Number of executable transaction slots guaranteed per account.Each account is guaranteed to have this many pending transactions in the executable queue.Source:
server/config/config.go:164
Validation: Must be at least 1number
default:"5120"
Maximum number of executable transaction slots for all accounts.Total capacity for all pending executable transactions across all accounts (4096 + 1024 = 5120).Source:
server/config/config.go:166
Validation: Must be at least 1number
default:"64"
Maximum number of non-executable transaction slots permitted per account.For transactions with gaps in nonce sequence (future transactions).Source:
server/config/config.go:168
Validation: Must be at least 1number
default:"1024"
Maximum number of non-executable transaction slots for all accounts.Total capacity for queued (non-executable) transactions across all accounts.Source:
server/config/config.go:170
Validation: Must be at least 1string
default:"3h0m0s"
Maximum amount of time non-executable transactions are queued.Transactions that remain non-executable longer than this duration are removed from the mempool.Source:
server/config/config.go:172
Format: Go duration string (e.g., "1h30m", "30m0s", "24h0m0s")
Validation: Must be at least 1nsConfiguration Examples
High-Throughput Chain:[evm.mempool]
global-slots = 10240
global-queue = 2048
price-limit = 100000000 # 0.1 gwei minimum
lifetime = "6h0m0s"
[evm.mempool]
global-slots = 2048
global-queue = 512
lifetime = "1h0m0s"
account-slots = 8
[evm.mempool]
price-limit = 1000000000 # 1 gwei minimum
price-bump = 25 # 25% replacement cost
lifetime = "30m0s"
account-slots = 4
Ethereum JSON-RPC server configuration.
Core Settings
boolean
default:"false"
Enable the JSON-RPC server.Must be
true for Ethereum compatibility.Source: server/config/config.go:169
Testnet configuration: evmd/cmd/evmd/cmd/testnet.go:303string
default:"127.0.0.1:8545"
HTTP server bind address using standard Ethereum RPC port.Source:
server/config/config.go:153string
default:"127.0.0.1:8546"
WebSocket server address for eth_subscribe methods.Source:
server/config/config.go:155
Implementation: rpc/stream/rpc.gostring
default:"eth,net,web3"
JSON-RPC namespaces to enable.Available namespaces:
web3, eth, personal, net, txpool, debug, minerSource: server/config/config.go:151
Namespace implementations: rpc/namespaces/string[]
default:"['127.0.0.1', 'localhost']"
Allowed CORS origins for WebSocket connections.Source:
server/config/config.go:195Resource Limits
number
default:"25000000"
Gas limit for eth_call/estimateGas operations (25M gas).Set to 0 for unlimited.Source:
server/config/config.go:157
Enforced: rpc/namespaces/ethereum/eth/api.go:1039number
default:"1"
Maximum transaction fee cap in ether for eth_sendTransaction.Source:
server/config/config.go:163
Enforced: rpc/namespaces/ethereum/eth/api.go:1586number
default:"200"
Maximum concurrent filters per connection.Source:
server/config/config.go:165
Implementation: rpc/namespaces/ethereum/eth/filters/number
default:"100"
Maximum blocks that can be fetched for eth_feeHistory.Source:
server/config/config.go:167number
default:"10000"
Maximum logs returned from a single eth_getLogs query.Source:
server/config/config.go:171
Enforced: rpc/namespaces/ethereum/eth/filters/api.go:442number
default:"10000"
Maximum block range allowed for eth_getLogs queries.Source:
server/config/config.go:173
Enforced: rpc/namespaces/ethereum/eth/filters/filter.go:268Connection Settings
number
default:"1000"
Maximum number of requests in a batch (go-ethereum standard).Source:
server/config/config.go:182number
default:"25000000"
Maximum bytes returned from a batched call (25MB).Source:
server/config/config.go:184string
default:"30s"
Read/write timeout for HTTP JSON-RPC server.Source:
server/config/config.go:175string
default:"120s"
Idle timeout for HTTP connections.Source:
server/config/config.go:177number
default:"0"
Maximum simultaneous connections for the server listener.Set to 0 for unlimited.Source:
server/config/config.go:187string
default:"5s"
Global timeout for eth_call operations.Source:
server/config/config.go:161Features
boolean
default:"false"
Enable custom transaction indexer for EVM transactions.Required for:
eth_getLogs, eth_getTransactionReceiptSource: server/config/config.go:189
Testnet default: evmd/cmd/evmd/cmd/testnet.go:303boolean
default:"false"
Enable pprof endpoints in debug namespace.Source:
server/config/config.go:197string
default:"127.0.0.1:6065"
Prometheus metrics server address.Metrics path:
/debug/metrics/prometheusSource: server/config/config.go:191Security
boolean
default:"false"
Allow non-EIP155 signed transactions to be submitted.Source:
server/config/config.go:180boolean
default:"true"
Allow insecure account unlocking when personal namespace is enabled.Source:
server/config/config.go:159CLI flags and environment variables for runtime configuration. These parameters can be set via command line or environment variables to override configuration file settings.
Context: These are EVM-specific runtime parameters that complement the standard Cosmos SDK flags. They control chain initialization and runtime behavior specific to EVM functionality.
string
default:"local-1"
Cosmos SDK chain identifier for transaction signing and network identification.CLI Flag:
--chain-id
Environment: EVMD_CHAIN_ID
Usage: evmd start --chain-id mychain-1number
default:"262144"
EIP-155 replay protection chain ID for Ethereum compatibility. Must be unique across all EVM networks.CLI Flag:
--evm.evm-chain-id
Environment: EVMD_EVM_CHAIN_ID
Usage: evmd start --evm.evm-chain-id 9000
Config Alternative: Set in app.toml under [evm] evm-chain-idstring
default:"atest"
Base denomination for native token transactions and staking.CLI Flag:
--denom
Environment: EVMD_DENOM
Usage: evmd init mynode --denom mytokennumber
default:"0"
Minimum priority fee (in wei) required for mempool inclusion.CLI Flag:
--evm.min-tip
Environment: EVMD_EVM_MIN_TIP
Usage: evmd start --evm.min-tip 1000000000
Config Alternative: Set in app.toml under [evm] min-tipnumber
default:"0"
Maximum gas limit for transactions in CheckTx validation mode.CLI Flag:
--evm.max-tx-gas-wanted
Environment: EVMD_MAX_TX_GAS_WANTED
Usage: evmd start --evm.max-tx-gas-wanted 50000000
Config Alternative: Set in app.toml under [evm] max-tx-gas-wantedComplete
app.toml with EVM-specific sections highlighted.Complete Application Configuration
# This is a TOML config file.
# For more information, see https://github.com/toml-lang/toml
###############################################################################
### Base Configuration ###
###############################################################################
# The minimum gas prices a validator is willing to accept for processing a
# transaction. A transaction's fees must meet the minimum of any denomination
# specified in this config (e.g. 0.25token1,0.0001token2).
minimum-gas-prices = "0atest"
# The maximum gas a query coming over rest/grpc may consume.
# If this is set to zero, the query can consume an unbounded amount of gas.
query-gas-limit = "0"
# default: the last 362880 states are kept, pruning at 10 block intervals
# nothing: all historic states will be saved, nothing will be deleted (i.e. archiving node)
# everything: 2 latest states will be kept; pruning at 10 block intervals.
# custom: allow pruning options to be manually specified through 'pruning-keep-recent', and 'pruning-interval'
pruning = "default"
# These are applied if and only if the pruning strategy is custom.
pruning-keep-recent = "0"
pruning-interval = "0"
# HaltHeight contains a non-zero block height at which a node will gracefully
# halt and shutdown that can be used to assist upgrades and testing.
#
# Note: Commitment of state will be attempted on the corresponding block.
halt-height = 0
# HaltTime contains a non-zero minimum block time (in Unix seconds) at which
# a node will gracefully halt and shutdown that can be used to assist upgrades
# and testing.
#
# Note: Commitment of state will be attempted on the corresponding block.
halt-time = 0
# MinRetainBlocks defines the minimum block height offset from the current
# block being committed, such that all blocks past this offset are pruned
# from CometBFT. It is used as part of the process of determining the
# ResponseCommit.RetainHeight value during ABCI Commit. A value of 0 indicates
# that no blocks should be pruned.
#
# This configuration value is only responsible for pruning CometBFT blocks.
# It has no bearing on application state pruning which is determined by the
# "pruning-*" configurations.
#
# Note: CometBFT block pruning is dependant on this parameter in conjunction
# with the unbonding (safety threshold) period, state pruning and state sync
# snapshot parameters to determine the correct minimum value of
# ResponseCommit.RetainHeight.
min-retain-blocks = 0
# InterBlockCache enables inter-block caching.
inter-block-cache = true
# IndexEvents defines the set of events in the form {eventType}.{attributeKey},
# which informs CometBFT what to index. If empty, all events will be indexed.
#
# Example:
# ["message.sender", "message.recipient"]
index-events = []
# IavlCacheSize set the size of the iavl tree cache (in number of nodes).
iavl-cache-size = 781250
# IAVLDisableFastNode enables or disables the fast node feature of IAVL.
# Default is false.
iavl-disable-fastnode = false
# AppDBBackend defines the database backend type to use for the application and snapshots DBs.
# An empty string indicates that a fallback will be used.
# The fallback is the db_backend value set in CometBFT's config.toml.
app-db-backend = ""
###############################################################################
### Telemetry Configuration ###
###############################################################################
[telemetry]
# Prefixed with keys to separate services.
service-name = ""
# Enabled enables the application telemetry functionality. When enabled,
# an in-memory sink is also enabled by default. Operators may also enabled
# other sinks such as Prometheus.
enabled = true
# Enable prefixing gauge values with hostname.
enable-hostname = false
# Enable adding hostname to labels.
enable-hostname-label = false
# Enable adding service to labels.
enable-service-label = false
# PrometheusRetentionTime, when positive, enables a Prometheus metrics sink.
prometheus-retention-time = 1000000000000
# GlobalLabels defines a global set of name/value label tuples applied to all
# metrics emitted using the wrapper functions defined in telemetry package.
#
# Example:
# [["chain_id", "cosmoshub-1"]]
global-labels = [
]
# MetricsSink defines the type of metrics sink to use.
metrics-sink = ""
# StatsdAddr defines the address of a statsd server to send metrics to.
# Only utilized if MetricsSink is set to "statsd" or "dogstatsd".
statsd-addr = ""
# DatadogHostname defines the hostname to use when emitting metrics to
# Datadog. Only utilized if MetricsSink is set to "dogstatsd".
datadog-hostname = ""
###############################################################################
### API Configuration ###
###############################################################################
[api]
# Enable defines if the API server should be enabled.
enable = true
# Swagger defines if swagger documentation should automatically be registered.
swagger = false
# Address defines the API server to listen on.
address = "tcp://localhost:1317"
# MaxOpenConnections defines the number of maximum open connections.
max-open-connections = 1000
# RPCReadTimeout defines the CometBFT RPC read timeout (in seconds).
rpc-read-timeout = 10
# RPCWriteTimeout defines the CometBFT RPC write timeout (in seconds).
rpc-write-timeout = 0
# RPCMaxBodyBytes defines the CometBFT maximum request body (in bytes).
rpc-max-body-bytes = 1000000
# EnableUnsafeCORS defines if CORS should be enabled (unsafe - use it at your own risk).
enabled-unsafe-cors = false
###############################################################################
### gRPC Configuration ###
###############################################################################
[grpc]
# Enable defines if the gRPC server should be enabled.
enable = true
# Address defines the gRPC server address to bind to.
address = "localhost:9090"
# MaxRecvMsgSize defines the max message size in bytes the server can receive.
# The default value is 10MB.
max-recv-msg-size = "10485760"
# MaxSendMsgSize defines the max message size in bytes the server can send.
# The default value is math.MaxInt32.
max-send-msg-size = "2147483647"
###############################################################################
### gRPC Web Configuration ###
###############################################################################
[grpc-web]
# GRPCWebEnable defines if the gRPC-web should be enabled.
# NOTE: gRPC must also be enabled, otherwise, this configuration is a no-op.
# NOTE: gRPC-Web uses the same address as the API server.
enable = true
###############################################################################
### State Sync Configuration ###
###############################################################################
# State sync snapshots allow other nodes to rapidly join the network without replaying historical
# blocks, instead downloading and applying a snapshot of the application state at a given height.
[state-sync]
# snapshot-interval specifies the block interval at which local state sync snapshots are
# taken (0 to disable).
snapshot-interval = 0
# snapshot-keep-recent specifies the number of recent snapshots to keep and serve (0 to keep all).
snapshot-keep-recent = 2
###############################################################################
### State Streaming ###
###############################################################################
# Streaming allows nodes to stream state to external systems.
[streaming]
# streaming.abci specifies the configuration for the ABCI Listener streaming service.
[streaming.abci]
# List of kv store keys to stream out via gRPC.
# The store key names MUST match the module's StoreKey name.
#
# Example:
# ["acc", "bank", "gov", "staking", "mint"[,...]]
# ["*"] to expose all keys.
keys = []
# The plugin name used for streaming via gRPC.
# Streaming is only enabled if this is set.
# Supported plugins: abci
plugin = ""
# stop-node-on-err specifies whether to stop the node on message delivery error.
stop-node-on-err = true
###############################################################################
### Mempool ###
###############################################################################
[mempool]
# Setting max-txs to 0 will allow for a unbounded amount of transactions in the mempool.
# Setting max_txs to negative 1 (-1) will disable transactions from being inserted into the mempool (no-op mempool).
# Setting max_txs to a positive number (> 0) will limit the number of transactions in the mempool, by the specified amount.
#
# Note, this configuration only applies to SDK built-in app-side mempool
# implementations.
max-txs = -1
###############################################################################
### EVM Configuration ###
###############################################################################
[evm]
# Tracer defines the 'vm.Tracer' type that the EVM will use when the node is run in
# debug mode. To enable tracing use the '--evm.tracer' flag when starting your node.
# Valid types are: json|struct|access_list|markdown
tracer = ""
# MaxTxGasWanted defines the gas wanted for each eth tx returned in ante handler in check tx mode.
max-tx-gas-wanted = 0
# EnablePreimageRecording enables tracking of SHA3 preimages in the VM
cache-preimage = false
# EVMChainID is the EIP-155 compatible replay protection chain ID. This is separate from the Cosmos chain ID.
evm-chain-id = 262144
# MinTip defines the minimum priority fee for the mempool.
min-tip = 0
# Geth metrics server address
geth-metrics-address = "127.0.0.1:8100"
# Mempool configuration for EVM transactions
[evm.mempool]
# PriceLimit is the minimum gas price to enforce for acceptance into the pool (in wei)
price-limit = 1
# PriceBump is the minimum price bump percentage to replace an already existing transaction (nonce)
price-bump = 10
# AccountSlots is the number of executable transaction slots guaranteed per account
account-slots = 16
# GlobalSlots is the maximum number of executable transaction slots for all accounts
global-slots = 5120
# AccountQueue is the maximum number of non-executable transaction slots permitted per account
account-queue = 64
# GlobalQueue is the maximum number of non-executable transaction slots for all accounts
global-queue = 1024
# Lifetime is the maximum amount of time non-executable transaction are queued
lifetime = "3h0m0s"
###############################################################################
### JSON RPC Configuration ###
###############################################################################
[json-rpc]
# Enable defines if the JSONRPC server should be enabled.
enable = true
# Address defines the EVM RPC HTTP server address to bind to.
address = "127.0.0.1:8545"
# Address defines the EVM WebSocket server address to bind to.
ws-address = "127.0.0.1:8546"
# WSOrigins defines the allowed origins for WebSocket connections.
# Example: ["localhost", "127.0.0.1", "myapp.example.com"]
ws-origins = ["127.0.0.1", "localhost"]
# API defines a list of JSON-RPC namespaces that should be enabled
# Example: "eth,txpool,personal,net,debug,web3"
api = "eth,net,web3"
# GasCap sets a cap on gas that can be used in eth_call/estimateGas (0=infinite). Default: 25,000,000.
gas-cap = 25000000
# Allow insecure account unlocking when account-related RPCs are exposed by http
allow-insecure-unlock = true
# EVMTimeout is the global timeout for eth_call. Default: 5s.
evm-timeout = "5s"
# TxFeeCap is the global tx-fee cap for send transaction. Default: 1eth.
txfee-cap = 1
# FilterCap sets the global cap for total number of filters that can be created
filter-cap = 200
# FeeHistoryCap sets the global cap for total number of blocks that can be fetched
feehistory-cap = 100
# LogsCap defines the max number of results can be returned from single 'eth_getLogs' query.
logs-cap = 10000
# BlockRangeCap defines the max block range allowed for 'eth_getLogs' query.
block-range-cap = 10000
# HTTPTimeout is the read/write timeout of http json-rpc server.
http-timeout = "30s"
# HTTPIdleTimeout is the idle timeout of http json-rpc server.
http-idle-timeout = "2m0s"
# AllowUnprotectedTxs restricts unprotected (non EIP155 signed) transactions to be submitted via
# the node's RPC when the global parameter is disabled.
allow-unprotected-txs = false
# MaxOpenConnections sets the maximum number of simultaneous connections
# for the server listener.
max-open-connections = 0
# EnableIndexer enables the custom transaction indexer for the EVM (ethereum transactions).
enable-indexer = false
# MetricsAddress defines the EVM Metrics server address to bind to. Pass --metrics in CLI to enable
# Prometheus metrics path: /debug/metrics/prometheus
metrics-address = "127.0.0.1:6065"
# Maximum number of requests in a batch.
batch-request-limit = 1000
# Maximum number of bytes returned from a batched call.
batch-response-max-size = 25000000
# Enabled profiling in the debug namespace
enable-profiling = false
###############################################################################
### TLS Configuration ###
###############################################################################
[tls]
# Certificate path defines the cert.pem file path for the TLS configuration.
certificate-path = ""
# Key path defines the key.pem file path for the TLS configuration.
key-path = ""
Lines (130-260): are EVM-specific configuration sections added by Cosmos EVMLines (1-129): are Base Cosmos SDK parametersKey EVM sections:
[evm]: EVM runtime settings (lines 645-670)[evm.mempool]: Mempool configuration (lines 672-694, new in v0.5.0)[json-rpc]: Ethereum JSON-RPC server (lines 700-747)[tls]: TLS configuration (lines 753-760)
- SDK config:
cosmos-sdk/server/config/toml.go - EVM config:
evm/server/config/toml.go
Blockchain initialization parameters set during chain genesis. These EVM-specific parameters configure the initial state and behavior of the EVM module.EVM-Specific Parameters:
Context: These parameters are set once during chain initialization and typically cannot be changed without governance proposals or network upgrades. They control fundamental EVM behavior and compatibility.
Genesis Configuration Example
{
"chain_id": "mychain-1",
"app_state": {
"evm": {
"params": {
"evm_denom": "atest",
"history_serve_window": 8192,
"active_static_precompiles": [
"0x0000000000000000000000000000000000000100",
"0x0000000000000000000000000000000000000400",
"0x0000000000000000000000000000000000000800",
"0x0000000000000000000000000000000000000801",
"0x0000000000000000000000000000000000000802",
"0x0000000000000000000000000000000000000804",
"0x0000000000000000000000000000000000000805"
],
"access_control": {
"create": {"access_type": "ACCESS_TYPE_PERMISSIONLESS"},
"call": {"access_type": "ACCESS_TYPE_PERMISSIONLESS"}
}
}
},
"feemarket": {
"params": {
"no_base_fee": false,
"base_fee_change_denominator": 8,
"elasticity_multiplier": 2,
"base_fee": "1000000000",
"min_gas_price": "0",
"min_gas_multiplier": "0.5"
}
}
},
"consensus": {
"params": {
"block": {
"max_bytes": "22020096",
"max_gas": "100000000"
}
}
}
}
evm_denom: Base denomination for EVM operations and gas paymentshistory_serve_window: Number of historical block hashes to store (EIP-2935)active_static_precompiles: Enabled precompile contract addressesaccess_control: Permissions for contract creation and execution
base_fee: Initial EIP-1559 base fee valuebase_fee_change_denominator: Rate of base fee adjustmentelasticity_multiplier: Block utilization threshold for fee changes
max_gas: Maximum gas per block (critical for mempool configuration)
Production validator node configuration and security considerations.Why this matters:
Critical Security Notice: Validator nodes should NEVER expose RPC/API ports publicly. Only dedicated RPC nodes (non-validators) should serve public traffic.
Validator vs RPC Node Architecture
Production networks should use a two-tier architecture:Validator Nodes (Private)
Purpose: Block production and consensus participation onlyConfiguration Requirements:- Disable all public-facing services
- Restrict network access to other validators via persistent peers
- Do NOT enable JSON-RPC server
- Do NOT expose API/gRPC ports publicly
- Use firewall rules to block external access
app.toml settings:[api]
enable = false # Disable REST API
[grpc]
enable = false # Disable gRPC or bind to localhost only
address = "localhost:9090"
[json-rpc]
enable = false # CRITICAL: Keep JSON-RPC disabled on validators
[evm]
max-tx-gas-wanted = 50000000 # Set reasonable gas limits
- DDoS Protection: Public RPC access can overwhelm validator resources
- Resource Exhaustion: Heavy query load impacts block production
- Uptime: Validators must prioritize consensus participation over serving requests
- Security: Reduced attack surface for exploits
- Slashing Risk: Downtime from overload can lead to slashing penalties
RPC Nodes (Public)
Purpose: Serve public API/RPC requests without participating in consensusConfiguration Requirements:- Enable JSON-RPC, API, and WebSocket endpoints
- Use load balancers for distribution
- Set appropriate rate limits and caps
- Can run multiple RPC nodes for redundancy
- No validator keys stored
app.toml settings:[api]
enable = true
address = "tcp://0.0.0.0:1317" # Bind to all interfaces
max-open-connections = 1000
[grpc]
enable = true
address = "0.0.0.0:9090"
[json-rpc]
enable = true
address = "0.0.0.0:8545"
ws-address = "0.0.0.0:8546"
api = "eth,net,web3,txpool"
# Set resource limits
gas-cap = 50000000
filter-cap = 200
logs-cap = 10000
block-range-cap = 10000
max-open-connections = 500
batch-request-limit = 100
Validator Security Checklist
- JSON-RPC is disabled on validator nodes
- API/gRPC endpoints not exposed publicly on validators
- Firewall rules restrict validator access to known peers only
- Separate RPC nodes deployed for public access
- Load balancers configured for RPC node redundancy
- Monitoring alerts for validator downtime
- Regular security audits of network architecture
- Validator keys stored securely (preferably HSM)
- SSH access restricted and key-based only
Network Topology Example
Public Internet
│
├─── Load Balancer
│ │
│ ┌────┴────┬────────┐
│ │ │ │
│ RPC Node RPC Node RPC Node
│ │ │ │
└────┴─────────┴────────┘
│
═══════════════════════════
Private Validator Network
═══════════════════════════
│
┌──────────┼──────────┐
│ │ │
Validator 1 Validator 2 Validator 3
(RPC disabled) (RPC disabled) (RPC disabled)
State Sync Consideration: If validators need to quickly sync using state sync, they may temporarily enable RPC on a private network segment to serve snapshots to each other. This should be done on a separate internal interface, never exposed publicly.