How freeze mode works
An upgrade can remove modules and stores that earlier heights depend on. After the upgrade, queries for those heights can fail on the new release or give different results. A node that still runs the outgoing release answers them the way the chain did at the time. Freeze mode runs such a node. You setfreeze-height to the upgrade height. The node executes every block below that height and stops before the upgrade block. It does not halt or exit at the boundary. It keeps serving queries from the state at freeze-height - 1, which is also its latest block.
From startup, freeze mode changes the node like this:
- Query endpoints stay up: the Tendermint RPC, the REST API, gRPC, and the EVM JSON-RPC.
- Transaction and evidence submission fail with
RPC writes are disabled in freeze mode. This includeseth_sendRawTransaction. - Mempool gossip is off.
- State sync is off. If it is enabled in
config.toml, the node logs a notice and uses block sync. - Block sync and consensus stop before
freeze-heightand do not advance.
Freeze heights
Setfreeze-height to the upgrade height. Run the latest patch of the release that the upgrade replaced.
Your live node serves the heights from the freeze height on.
To read upgrade heights from the chain, query the upgrade module. The first command returns the height at which
v6.7 was applied on Sei Mainnet. For Sei Testnet, use https://rest-testnet.sei-apis.com. The second command returns the name and height of the next scheduled upgrade, or no upgrade scheduled.
Before you begin
You need:- A full node. Freeze mode does not run in validator or seed mode.
- A copy of a node’s data directory that is below the freeze height. The node refuses to start if its application, block store, or state store has reached
freeze-height. - The history that you want to serve. A frozen node serves only what its data directory holds. To serve the full history, copy an archive node.
- Disk space for a full copy of that data. The copy stops growing when it reaches the freeze height.
- Peers that store the blocks from the copy’s height up to the freeze height. The node fetches these blocks with block sync before it freezes. Pruned nodes delete old blocks, so for a copy far below the freeze height, list archive nodes in
persistent-peersinconfig.toml.
Take the copy before the chain reaches the upgrade height. A node saves each block before it executes it, so a node that halted at the upgrade height already holds the upgrade block. With that block in its block store, the node refuses to start with that
freeze-height. After the chain has passed the upgrade height, you can build a frozen node only from data below that height, such as a backup.Set up a frozen node
These steps use the Sei Mainnet values for the v6.7 upgrade. For Sei Testnet, use the values in Freeze heights.1
Copy the data directory
Stop The
seid on a node that holds the history you want to serve. Take a volume snapshot of its data disk, or copy its whole home directory, including data/ and wasm/, to the new host. Then start the source node again.--exclude flag keeps the validator signing key on the source host. A frozen node never signs blocks, so it does not need that key. The remote path .sei/ is relative to the home directory of <user>, so connect as the user that runs seid on the new host.On the new host, delete the node key. If you took a volume snapshot, also delete the validator key. seid generates new keys when it starts. Two nodes must not share a node key.To start from a provider’s archive snapshot instead, take these steps on the new host:
- Install the outgoing release, as described in the next step.
- Run
seid init <moniker> --chain-id pacific-1 --mode archive. It writes the genesis file and a configuration that keeps all history. - In
config.toml, setpersistent-peersto archive nodes that store the blocks from the snapshot height up to the freeze height. Each entry has the form<node-id>@<host>:26656, andseid tendermint show-node-idprints the node ID on an archive node that you run. - Restore the snapshot with the snapshot guide, but stop before its restart step.
2
Install the outgoing release
Install v6.6.4 on the new host. Do not start The v6.6.4 release has a prebuilt binary for Linux x86_64 only.Check the version:Keep this binary on the frozen node. Exclude the node from any process that upgrades the binaries of your other nodes.
seid yet.- Prebuilt binary
- Build from source
3
Set the freeze height
In In An
$HOME/.sei/config/config.toml, make sure that the node runs in full mode. mode is a top-level key:$HOME/.sei/config/app.toml, set freeze-height to the upgrade height, and set halt-height and halt-time to 0. The three keys sit together in the base configuration at the top of the file, before the first [section] header:app.toml
app.toml from a release before v6.6.3 has no freeze-height line. In that case, add the line after halt-height.If you copied an archive node, keep its pruning settings, so that the node keeps every version up to the freeze height. Do not start the node with --grpc-only. The node refuses to start when freeze-height is combined with --grpc-only, halt-height, or halt-time. It also refuses to start with Autobahn enabled, that is, with a non-empty autobahn-config-file in config.toml.4
Start the node
A new host has no The log shows
seid service yet. Create one that runs the v6.6.4 binary directly. Do not run a frozen node through Cosmovisor, which exists to switch binaries at upgrade heights. Run these commands as the user that runs seid:$(which seid) writes the full path of the binary that you checked in step 2 into ExecStart. If the host already has a seid service, run systemctl cat seid and check that its ExecStart runs that binary.Start seid and follow the log:Freeze mode enabled at startup. The node then syncs to height 236449999. When it reaches that height, it logs Block sync stopped before configured freeze height or Consensus frozen before configured height, and it keeps serving queries.If the node exits with <source> height <n> has already reached freeze height <h>, its data is at or above the freeze height. Start again from a copy that is below it.5
Verify the frozen node
Check that the Tendermint RPC and the EVM RPC both report a latest block one below the freeze height:Restart the node once, and run the EVM check again. This confirms that the EVM RPC comes back after a restart.If you scrape the node’s Prometheus metrics,
sei_chain_app_build_info shows the running release in its seid_version and commit labels. Alert when either label changes.6
Back up the frozen node
After the node reaches the freeze height boundary, back up its data directory, for example with a volume snapshot. The node executes no more blocks, so the backup stays valid. Keep it, because after the chain has passed the freeze height, you can rebuild this node only from data below that height.
Route queries by block height
Clients usually connect to one endpoint. Thefrozen-rpc-router binary gives them one for EVM JSON-RPC over HTTP. It reads the block height in each request and sends the request to the matching frozen node or to the live node.
The router is a separate binary in the sei-chain repository, and make install does not install it. Build it from v6.6.3 or a later release tag:
--live-node, and pass each frozen node with a --frozen-node <freeze-height>=<address> flag. In this Sei Mainnet example, the router runs on the live node’s host. Move the live node’s EVM HTTP port to 9545 with http_port under [evm] in app.toml, so that the router can listen on 8545. The frozen node runs on its own host.
236449999 to the frozen node, and it sends 236450000 and later to the live node. When you add a frozen node for a later upgrade, add one more --frozen-node flag. Each frozen node then serves the heights from the previous freeze height up to its own.
The Sei-RPC-Route response header shows which backend answered:
latest returns live. A batch that the router splits across backends returns mixed.
Plan around these limits:
- The router handles only EVM JSON-RPC over HTTP. For the Tendermint RPC, the REST API, or gRPC at old heights, query the frozen node directly.
- Requests without a block number go to the live node. This includes lookups by block or transaction hash, such as
eth_getTransactionReceipt. - WebSocket clients must connect to the live node directly.
- An
eth_getLogsoreth_feeHistoryrange must stay within one interval. A range that crosses a freeze height fails with JSON-RPC error-32000. - The router has no authentication. Bind it to
127.0.0.1, or put it behind a firewall or reverse proxy.
Prepare for each upgrade
Each upgrade adds one frozen node:- When an upgrade proposal passes, read its height with
seid query upgrade plan. - Before the chain reaches that height, set up a frozen node on the latest patch of the current release, with
freeze-heightset to the upgrade height. - After the new frozen node reaches its boundary, back it up and add it to the router with one more
--frozen-nodeflag.
freeze-height. You can install a later patch of the same release line, for example v6.6.4 over v6.6.3. Keep each frozen node for as long as you serve queries for its heights.