diff --git a/.github/workflows/sync-default-configs.yml b/.github/workflows/sync-default-configs.yml new file mode 100644 index 00000000..62ecaec3 --- /dev/null +++ b/.github/workflows/sync-default-configs.yml @@ -0,0 +1,144 @@ +name: Sync default seid configs + +# Rebuilds the latest tagged seid release, runs `seid init`, and pipes the +# resulting app.toml / config.toml / client.toml into the inlined "Default +# Configurations" section of content/node/node-operators.mdx. If anything +# changed, opens a PR. +# +# Triggers: +# - workflow_dispatch (manual; can override the seid version) +# - schedule (weekly, Mondays 06:00 UTC) + +on: + workflow_dispatch: + inputs: + sei_version: + description: 'seid release tag to build (default: latest GitHub release)' + required: false + type: string + default: '' + schedule: + - cron: '0 6 * * 1' + +permissions: + contents: write + pull-requests: write + +defaults: + run: + shell: bash + +jobs: + sync: + runs-on: ubuntu-latest + timeout-minutes: 30 + steps: + - name: Checkout docs + uses: actions/checkout@v4 + + - name: Resolve seid version + id: version + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + INPUT_VERSION: ${{ inputs.sei_version }} + run: | + set -euo pipefail + requested="${INPUT_VERSION:-}" + if [[ -n "$requested" ]]; then + tag="$requested" + echo "Using requested seid tag: $tag" + else + tag=$(gh api repos/sei-protocol/sei-chain/releases/latest --jq .tag_name) + echo "Resolved latest seid tag: $tag" + fi + if [[ -z "$tag" ]]; then + echo "::error::Could not resolve a seid release tag" + exit 1 + fi + echo "tag=$tag" >> "$GITHUB_OUTPUT" + + - name: Checkout sei-chain + uses: actions/checkout@v4 + with: + repository: sei-protocol/sei-chain + ref: ${{ steps.version.outputs.tag }} + path: sei-chain + fetch-depth: 1 + + - name: Set up Go + uses: actions/setup-go@v5 + with: + go-version-file: sei-chain/go.mod + cache-dependency-path: sei-chain/go.sum + + - name: Install build helpers + run: sudo apt-get update && sudo apt-get install -y --no-install-recommends tree + + - name: Build seid + working-directory: sei-chain + run: | + set -euo pipefail + export PATH="$(go env GOPATH)/bin:$PATH" + make install + seid version --long || seid version + + - name: Capture commit SHA + id: commit + working-directory: sei-chain + run: echo "sha=$(git rev-parse --short HEAD)" >> "$GITHUB_OUTPUT" + + - name: Run seid init + env: + SEI_VERSION: ${{ steps.version.outputs.tag }} + run: | + set -euo pipefail + export PATH="$(go env GOPATH)/bin:$PATH" + rm -rf "$HOME/.sei" + seid init docs-example --chain-id pacific-1 + echo "---" + ls -la "$HOME/.sei/config" + + - name: Regenerate inlined default configs + env: + SEI_VERSION: ${{ steps.version.outputs.tag }} + SEI_COMMIT: ${{ steps.commit.outputs.sha }} + run: | + export SEI_HOME="$HOME/.sei" + node scripts/sync-default-configs.mjs + + - name: Show diff (for log visibility) + run: git --no-pager diff --stat -- content/node/node-operators.mdx || true + + - name: Open pull request if changed + uses: peter-evans/create-pull-request@v6 + with: + token: ${{ secrets.GITHUB_TOKEN }} + branch: bot/sync-default-configs + base: main + commit-message: 'docs(node): sync default configs from seid ${{ steps.version.outputs.tag }}' + title: 'docs(node): sync default configs from seid ${{ steps.version.outputs.tag }}' + body: | + Auto-generated by [`sync-default-configs.yml`](.github/workflows/sync-default-configs.yml). + + Refreshes the inlined "Default Configurations" tabs in + `content/node/node-operators.mdx` from a fresh `seid init` + against [`sei-chain@${{ steps.version.outputs.tag }}`](https://github.com/sei-protocol/sei-chain/releases/tag/${{ steps.version.outputs.tag }}) + (commit `${{ steps.commit.outputs.sha }}`). + + ## What is the purpose of the change? + Keep the documented default `app.toml`, `config.toml`, and + `client.toml` in sync with what node operators actually get when + they install the latest `seid`. + + ## Describe the changes to the documentation + Updates the marker-bounded TOML blocks inside + `content/node/node-operators.mdx`. No hand-written prose is touched. + + ## Notes + If this PR is empty, no defaults changed in the new release. + labels: | + documentation + automated + add-paths: | + content/node/node-operators.mdx + delete-branch: true diff --git a/content/node/_meta.js b/content/node/_meta.js index 0c56fb0c..3cddb20b 100644 --- a/content/node/_meta.js +++ b/content/node/_meta.js @@ -21,5 +21,6 @@ export default { }, 'advanced-config-monitoring': 'Advanced Configuration & Monitoring', 'rocksdb-backend': 'RocksDB Backend', + 'giga-storage-migration': 'Giga SS Store Migration', 'technical-reference': 'Technical Reference' }; diff --git a/content/node/giga-storage-migration.mdx b/content/node/giga-storage-migration.mdx new file mode 100644 index 00000000..6eb13aff --- /dev/null +++ b/content/node/giga-storage-migration.mdx @@ -0,0 +1,248 @@ +--- +title: 'Giga SS Store Migration Guide' +description: 'Migrate a Sei RPC node to Giga SS Store: split EVM state into a dedicated state-store backend so non-EVM modules stop paying EVM write amplification.' +keywords: ['sei node', 'giga storage', 'seidb', 'state sync', 'evm ss', 'flatkv', 'rpc node', 'pebbledb', 'rocksdb'] +--- + +# Giga SS Store Migration Guide + +Giga SS Store is the next step in Sei's storage evolution on top of [SeiDB](/node/node-operators#architecture). +It splits the hot EVM state into its own dedicated state-store (SS) database +so the node can scale toward the **~150k TPS** target throughput, and so +non-EVM modules stop paying write amplification for EVM state. + +After migration the SS layer is repartitioned into two cooperating stores: + +| Layer | Cosmos backend | EVM backend | +|---|---|---| +| **SC** (State Commit, app hash) | `memiavl` | FlatKV | +| **SS** (State Store, historical queries) | single MVCC DB (PebbleDB or RocksDB) | dedicated EVM SS MVCC DB(s) under `data/evm_ss/` | + +Only the **SS** layer changes for this migration. SC layer config is untouched +and `memiavl` remains the authoritative source for the app hash, so this is +invisible to the network. + +This guide tracks the canonical procedure in [`docs/migration/giga_store_migration.md`](https://github.com/sei-protocol/sei-chain/blob/main/docs/migration/giga_store_migration.md) inside `sei-chain`. Open an issue there if anything here drifts. + +## Prerequisites + +This migration is supported on **RPC nodes only**. Validator nodes and archive nodes are not supported by this flow yet — do not run it against either. + +- A `seid` build with the `evm-ss-split` flag wired in (Sei v6.5 or later). Older + releases used per-key `evm-ss-write-mode` / `evm-ss-read-mode` toggles; if your + `app.toml` still has those keys, upgrade `seid` before continuing. +- `sc-enable = true` and `ss-enable = true` in `app.toml`. Both must stay enabled. +- A trusted RPC endpoint to state-sync from (chain ID and trust-height source). +- Disk headroom for two SS databases. The EVM split does not duplicate data, but + during migration both the old and the new layouts may briefly coexist on disk. + +The migration **requires a full state sync**. There is no in-place migration +path and no live "dual-write then split" workflow — the state sync wipes the +local data directory and imports a fresh snapshot into the new layout. + +## Benefits + +- EVM reads are served exclusively from a dedicated EVM SS database. +- Non-EVM modules no longer pay write amplification for EVM state. +- A backend change (PebbleDB ↔ RocksDB) can be combined with the same state + sync, since `ss-backend` drives both the Cosmos SS MVCC DB and every EVM SS + sub-DB. + +## What's different about EVM SS + +EVM SS is **point-query only by design** (`Get` / `Has`). Iteration is +explicitly disabled on the EVM backend for performance: the hot EVM read path +is tuned for direct key lookups, and cross-bucket scans would defeat the +per-type sub-DB layout. Any EVM read that needs iteration must stay on the +Cosmos SS side. + +## Migration Steps + +### Step 1: Update `app.toml` + +Apply the following settings in `~/.sei/config/app.toml`: + +```toml copy +[state-commit] +# State commit is untouched by this migration. +sc-enable = true + +[state-store] +ss-enable = true + +# DBBackend for the Cosmos SS MVCC DB and for every EVM SS sub-DB. +# Supported: pebbledb, rocksdb. Default pebbledb. +ss-backend = "pebbledb" + +# Route EVM state to the dedicated EVM SS backend. +# When false (default), EVM state lives in the Cosmos SS backend alongside +# everything else. When true, EVM data is routed exclusively to the EVM SS +# backend; non-EVM data stays in Cosmos SS. No fallback between backends. +evm-ss-split = true +``` + +If you want to switch SS backend in the same step: + +- **PebbleDB → RocksDB**: set `ss-backend = "rocksdb"`, build `seid` with + `-tags rocksdbBackend`, and install RocksDB per the + [RocksDB Backend Guide](/node/rocksdb-backend). `ss-backend` drives both the + Cosmos SS MVCC DB and every EVM SS sub-DB, so a single setting flips both. +- No data migration tool is needed across backends — the state sync populates + the new layout. + +### Step 2: State sync into the new layout + +Giga SS Store is fully compatible with the existing state-snapshot format. On +import, the composite state store routes each snapshot node based on the +importing node's `evm-ss-split`: + +- With `evm-ss-split = true`, EVM snapshot nodes go only into EVM SS and + non-EVM nodes go only into Cosmos SS. +- The import path normalizes legacy `evm_flatkv` snapshot nodes to `evm`, so + snapshots produced by either the old or new FlatKV module are accepted. + +Both stores end up fully populated at the snapshot height, so the node can +start serving reads immediately. + +The full state-sync flow is documented in the +[Statesync guide](/node/statesync). The minimal shape for this migration: + +```bash copy +export TRUST_HEIGHT_DELTA=10000 +export MONIKER="" +export CHAIN_ID="" +export PRIMARY_ENDPOINT="" +export SEID_HOME="$HOME/.sei" + +# 1. Stop seid +sudo systemctl stop seid + +# 2. Back up files you need to preserve and wipe local state +cp $SEID_HOME/data/priv_validator_state.json /tmp/priv_validator_state.json +cp $SEID_HOME/config/priv_validator_key.json /tmp/priv_validator_key.json +cp $SEID_HOME/config/genesis.json /tmp/genesis.json +rm -rf $SEID_HOME/data/* +rm -rf $SEID_HOME/wasm +rm -rf $SEID_HOME/config/priv_validator_key.json +rm -rf $SEID_HOME/config/genesis.json +rm -rf $SEID_HOME/config/config.toml + +# 3. Re-init, re-apply config.toml and app.toml (set Step 1 values again) +seid init --chain-id "$CHAIN_ID" "$MONIKER" + +# 4. Resolve trust height/hash and persistent peers against PRIMARY_ENDPOINT, +# then update config.toml. See /node/statesync for the full snippet. + +# 5. Restore the backed-up files +cp /tmp/priv_validator_state.json $SEID_HOME/data/priv_validator_state.json +cp /tmp/priv_validator_key.json $SEID_HOME/config/priv_validator_key.json +cp /tmp/genesis.json $SEID_HOME/config/genesis.json + +# 6. Start seid +sudo systemctl restart seid +``` + +Make sure `priv_validator_key.json` is in safe storage before deleting it from the config directory. Loss of this key is unrecoverable for a validator and is not relevant to RPC-only nodes — but if you're following this from the wrong checklist you'll find out the hard way. + +### Step 3: Verify the new layout + +Once the state sync completes and the node starts producing blocks, confirm +Giga SS Store is active in two places. + +**Startup logs.** All three lines should appear: + +```text +"SeiDB SS is enabled" # with the configured `backend` +"SeiDB EVM StateStore optimization is enabled" # with the `separateDBs` label +"EVM state store enabled" # with `dir` and `separateDBs` labels +``` + +**EVM RPC.** `debug_traceBlockByNumber` is the cleanest end-to-end check — +it forces the node to read EVM state out of the new EVM SS backend: + +```bash copy +curl -s -X POST http://127.0.0.1:8545 \ + -H 'Content-Type: application/json' \ + --data '{"jsonrpc":"2.0","method":"debug_traceBlockByNumber","params":["latest",{}],"id":1}' +``` + +The response should contain a `"result"` field rather than an RPC error. + +## Safety checks + +`seid` runs three DB-state checks at startup and refuses to launch if the EVM +SS and Cosmos SS DBs are inconsistent. They specifically catch the footgun of +flipping `evm-ss-split` from `false` to `true` without state syncing. + +1. **EVM SS directory missing or empty** (before the EVM SS is opened). When + `evm-ss-split = true`, the composite state store refuses to proceed if + Cosmos SS already has committed history but the EVM SS directory + (`data/evm_ss/` by default) does not exist or is empty. Failing before + the sub-DBs are opened means a rejected config does not leave a confusing + empty `data/evm_ss/` behind. +2. **EVM SS DB empty post-open, pre-recovery.** Belt-and-suspenders for (1) + when the directory exists but its DBs are empty. The WAL only covers the + last `KeepRecent` blocks, so replay cannot rebuild a fresh EVM SS from + scratch. +3. **Mismatched earliest versions, post-recovery.** If the two DBs were + populated from different snapshots (or pruned independently), historical + reads would be inconsistent. A non-zero earliest-version divergence + aborts startup. + +If any check fires, the correct fix is either (a) complete the state sync +described above, or (b) set `evm-ss-split = false` and restart. If +`data/evm_ss/` is stale from a failed attempt, remove it before state syncing. + +## Rollback + +To roll back: + +1. Set `evm-ss-split = false` in `app.toml`. +2. Restart the node. The EVM SS DB under `data/evm_ss/` is no longer opened + but stays on disk until manually removed. + +To fully reclaim the disk used by EVM SS, stop the node and delete +`data/evm_ss/` after reverting the setting. + +Cleanly rolling back to `evm-ss-split = false` requires another state sync. Under `evm-ss-split = true`, EVM writes go only to the EVM SS DB, so Cosmos SS will not have those writes. Restarting with `evm-ss-split = false` stops opening the EVM SS DB, but EVM-state queries will miss anything written after the Giga state sync until you re-state-sync without the split. + +## FAQ + +### Where do the data files live after migrating? + +- Cosmos SS data lives under the same directory as before, typically + `data/pebbledb/` for the default `pebbledb` backend. +- EVM SS data lives under `data/evm_ss/`. +- SC data (`memiavl` + FlatKV) is untouched by this migration. + +### Does Giga SS Store change the app hash or consensus? + +No. The SC layer is unchanged, so `memiavl` remains the authoritative source +for the app hash. Giga SS Store is a per-node SS change that is invisible to +the network. + +### Can I migrate a validator node with this guide? + +Not yet. This migration guide is for RPC nodes only. + +### Can I migrate an archive node with this guide? + +Not yet. Archive-node migration is out of scope for this guide. + +### Can I toggle back to `evm-ss-split = false` after enabling it? + +Yes, but cleanly rolling back requires another state sync — see the +[Rollback](#rollback) section above. + +### Why can't I just flip `evm-ss-split = true` on a running node? + +Because `evm-ss-split = true` requires the EVM SS DB to already contain the +full history that Cosmos SS has. A live flip would leave the EVM SS DB empty +while the composite store refuses to fall back to Cosmos SS, which would +translate into missing EVM state at query time. The safety checks above +block this scenario at startup. + +### Does Giga SS Store support historical proofs? + +No, same as SeiDB. SS stores raw KVs and does not reconstruct IAVL-style +proofs. diff --git a/content/node/index.mdx b/content/node/index.mdx index 06ad283d..c451584e 100644 --- a/content/node/index.mdx +++ b/content/node/index.mdx @@ -543,6 +543,13 @@ seid query staking validator $(seid keys show --bech val -a)

Specialized instructions for validators, including staking, commission settings, and security best practices.

+ + +
+

Default Configurations

+

Full reference for app.toml, config.toml, and client.toml shipped by the latest seid release.

+
+
diff --git a/content/node/node-operators.mdx b/content/node/node-operators.mdx index ce4959a7..2fd2efc8 100644 --- a/content/node/node-operators.mdx +++ b/content/node/node-operators.mdx @@ -26,92 +26,1493 @@ $HOME/.sei/config/ └── priv_validator_key.json # Validator private signing key (if running as a validator) ``` +The snippets below are opinionated tuning recommendations layered on top of +the defaults. For the *full* unmodified `app.toml`, `config.toml`, and +`client.toml` shipped by the latest tagged `seid` release, jump to +[Default Configurations](#default-configurations) at the bottom of this +section. + ### Essential Configuration Parameters #### Network Settings (config.toml) ```toml copy [p2p] -# Public IP for other nodes to reach you +# Public address other nodes use to dial in (host:port) external-address = "your-public-ip:26656" # Local address to listen for incoming P2P connections laddr = "tcp://0.0.0.0:26656" -# Number of peers allowed -max-num-inbound-peers = 40 -max-num-outbound-peers = 20 -# Network bandwidth limits to prevent congestion -send-rate = 204800000 # 200MB/s -recv-rate = 204800000 # 200MB/s +# Combined inbound + outbound peer limit. Default is 100; raise it for +# well-connected RPC nodes. (`max-num-inbound-peers` / `max-num-outbound-peers` +# from older Tendermint configs no longer apply.) +max-connections = 200 +# Per-connection bandwidth caps in bytes/sec. Defaults are 20 MiB/s; raise +# only if your link can sustain it. +send-rate = 20971520 +recv-rate = 20971520 [rpc] # RPC listen address laddr = "tcp://0.0.0.0:26657" -# Maximum number of simultaneous connections +# Maximum number of simultaneous connections (HTTP + WS) max-open-connections = 900 -# Transaction confirmation timeout +# Transaction confirmation timeout for /broadcast_tx_commit timeout-broadcast-tx-commit = "10s" ``` #### Application Settings (app.toml) ```toml copy -# Minimum gas prices [to prevent spam transactions] +# Minimum gas prices to prevent spam transactions minimum-gas-prices = "0.01usei" +# Block retention for /block, /block_results, etc., and the floor used by +# the receipt store's pruner. 0 disables block pruning. +min-retain-blocks = 100000 + +# Concurrent transaction execution workers. The default is set dynamically +# (2× CPU cores, capped at 128, minimum 10). +concurrency-workers = 10 + +# Optimistic Concurrency Control for parallel tx execution +occ-enabled = true + [api] -# Enable the API server +# Enable the REST/Cosmos API server (port 1317) enable = true max-open-connections = 1000 [state-commit] -# Use SeiDB for improved performance +# SeiDB state-commit (memiavl + FlatKV). Recommended on every node. +sc-enable = true + +[state-store] +# Historical SS layer for queries. Required for any node serving RPC. +ss-enable = true +# 0 = keep everything; 100,000 is roughly 28 hours of pacific-1 history. +ss-keep-recent = 100000 + +[receipt-store] +# Storage backend for EVM transaction receipts (pebbledb or parquet). +rs-backend = "pebbledb" +``` + +### Default Configurations + +The full unmodified `app.toml`, `config.toml`, and `client.toml` produced by +`seid init` against the latest tagged `seid` release. Use these as the +canonical reference for every available knob and its default value. + + + + +Application-layer configuration: gas, API, gRPC, pruning, SeiDB, EVM, etc. + +{/* AUTO-GENERATED:APP_TOML:START */} + +```toml +# 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 = "0.01usei" + +# MinRetainBlocks defines the minimum block height offset from the current block +# for pruning Tendermint blocks. Set to 0 to disable pruning. This only affects +# Tendermint block pruning, not application state (see "pruning-*" configs). +min-retain-blocks = 100000 + +# ConcurrencyWorkers defines how many workers to run for concurrent transaction execution. +# Default is dynamically set to 2x CPU cores, capped at 128, with a minimum of 10. +concurrency-workers = 10 + +# occ-enabled defines whether OCC is enabled or not for transaction execution +occ-enabled = true + +# 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 + +# InterBlockCache enables inter-block caching. +inter-block-cache = true + +# IndexEvents defines the set of events in the form {eventType}.{attributeKey}, +# which informs Tendermint what to index. If empty, all events will be indexed. +# +# Example: +# ["message.sender", "message.recipient"] +index-events = [] + +# IAVLDisableFastNode enables or disables the fast node feature of IAVL. +# Default is true. +iavl-disable-fastnode = true + +# CompactionInterval sets (in seconds) the interval between forced levelDB +# compaction. A value of 0 means no forced levelDB. +# Default is 0. +compaction-interval = 0 + +# deprecated +no-versioning = false + +# Whether to store orphan data (to-be-deleted data pointers) outside the main +# application LevelDB +separate-orphan-storage = false + +# if separate-orphan-storage is true, how many versions of orphan data to keep +separate-orphan-versions-to-keep = 0 + +# if separate-orphan-storage is true, how many orphans to store in each file +num-orphan-per-file = 0 + +# if separate-orphan-storage is true, where to store orphan data +orphan-dir = "" + +############################################################################### +### 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). Must be a multiple of pruning-keep-every. +snapshot-interval = 0 + +# snapshot-keep-recent specifies the number of recent snapshots to keep and serve (0 to keep all). +snapshot-keep-recent = 2 + +# snapshot-directory sets the directory for where state sync snapshots are persisted. +# default is empty which will then store under the app home directory same as before. +snapshot-directory = "" + +############################################################################### +### State Commit Configuration ### +############################################################################### + +[state-commit] +# Enable defines if the SeiDB should be enabled to override existing IAVL db backend. sc-enable = true +# Defines the SC store directory, if not explicitly set, default to application home directory +sc-directory = "" + +# WriteMode defines how EVM data writes are routed between backends. +# Valid values: cosmos_only, dual_write, split_write, evm_only +# defaults to cosmos_only +sc-write-mode = "cosmos_only" + +# ReadMode defines how EVM data reads are routed between backends. +# Valid values: cosmos_only, evm_first, split_read +# defaults to cosmos_only +sc-read-mode = "cosmos_only" + +# EnableLatticeHash controls whether the FlatKV lattice hash participates +# in the final app hash. Default: false. +sc-enable-lattice-hash = false + +# Max concurrent historical proof queries (RPC /store path) +sc-historical-proof-max-inflight = 1 + +# Historical proof query rate limit in req/sec (<=0 disables rate limiting) +sc-historical-proof-rate-limit = 1 + +# Historical proof query burst size +sc-historical-proof-burst = 1 + +# AsyncCommitBuffer defines the size of asynchronous commit queue, this greatly improve block catching-up +# performance, setting to 0 means synchronous commit. +sc-async-commit-buffer = 100 + +# KeepRecent defines how many state-commit snapshots (besides the latest one) to keep +# defaults to 0 to only keep one current snapshot +sc-keep-recent = 0 + +# SnapshotInterval defines the block interval the snapshot is taken, default to 10000 blocks. +sc-snapshot-interval = 10000 + +# SnapshotMinTimeInterval defines the minimum time interval (in seconds) between snapshots. +# This prevents excessive snapshot creation during catch-up and ensures snapshots don't overlap +# (current snapshot creation takes 3+ hours). Default to 3600 seconds (1 hour). +# Note: If you set a small sc-snapshot-interval (e.g., < 5000), you may want to reduce this value +# to allow more frequent snapshots during normal operation. +sc-snapshot-min-time-interval = 3600 + +# SnapshotPrefetchThreshold defines the page cache residency threshold (0.0-1.0) to trigger snapshot prefetch. +# Prefetch sequentially reads nodes/leaves files into page cache for faster cold-start replay. +# Only active trees (evm/bank/acc/wasm) are prefetched, skipping sparse kv files to save memory. +# Skips prefetch if more than threshold of pages already resident (e.g., 0.8 = 80%). +# Defaults to 0.8 +sc-snapshot-prefetch-threshold = 0.8 + +# Maximum snapshot write rate in MB/s (global across all trees). 0 = unlimited. Default 100. +sc-snapshot-write-rate-mbps = 100 + +############################################################################### +### FlatKV (EVM) Configuration ### +############################################################################### + +[state-commit.flatkv] +# Fsync controls whether PebbleDB writes (data DBs + metadataDB) use fsync. +# WAL always uses NoSync (matching memiavl); crash recovery relies on +# WAL catchup, which is idempotent. Default: false. +fsync = false + +# AsyncWriteBuffer defines the size of the async write buffer for data DBs. +# Set <= 0 for synchronous writes. +async-write-buffer = 0 + +# SnapshotInterval defines how often (in blocks) a PebbleDB checkpoint is taken. +# 0 disables auto-snapshots. Default: 10000. +snapshot-interval = 10000 + +# SnapshotKeepRecent defines how many old snapshots to keep besides the latest one. +# 0 = keep only the current snapshot. Default: 2. +snapshot-keep-recent = 2 + +############################################################################### +### State Store Configuration ### +############################################################################### + [state-store] -# Enable state store for historical queries +# Enable defines whether the state-store should be enabled for storing historical data. +# Supporting historical queries or exporting state snapshot requires setting this to true +# This config only take effect when SeiDB is enabled (sc-enable = true) ss-enable = true -# Retain 100,000 blocks for queryability -# 0 = "keep all" + +# Defines the directory to store the state store db files +# If not explicitly set, default to application home directory +ss-db-directory = "" + +# DBBackend defines the backend database used for state-store. +# Supported backends: pebbledb, rocksdb +# defaults to pebbledb (recommended) +ss-backend = "pebbledb" + +# AsyncWriteBuffer defines the async queue length for commits to be applied to State Store +# Set <= 0 for synchronous writes, which means commits also need to wait for data to be persisted in State Store. +# defaults to 100 for asynchronous writes +ss-async-write-buffer = 100 + +# KeepRecent defines the number of versions to keep in state store +# Setting it to 0 means keep everything +# Default to keep the last 100,000 blocks ss-keep-recent = 100000 + +# PruneInterval defines the minimum interval in seconds + some random delay to trigger SS pruning. +# It is recommended to trigger pruning less frequently with a large interval. +# default to 600 seconds +ss-prune-interval = 600 + +# ImportNumWorkers defines the concurrency for state sync import +# defaults to 1 +ss-import-num-workers = 1 + +# EVMDBDirectory defines the directory for the optional EVM state-store DB(s). +# If unset, defaults to /data/evm_ss when EVM SS is enabled. +evm-ss-db-directory = "" + +# WriteMode controls how EVM data writes are routed. +# Supported values: "cosmos_only", "dual_write", "split_write" +evm-ss-write-mode = "cosmos_only" + +# ReadMode controls how EVM data reads are routed. +# Supported values: "cosmos_only", "evm_first", "split_read" +evm-ss-read-mode = "cosmos_only" + +# SeparateEVMSubDBs controls whether EVM data is split across per-type DBs. +# When false, all EVM data stays in one DB using the current unified layout. +# When true, data is routed to separate DBs while preserving the same evm key prefix format. +evm-ss-separate-dbs = false + +############################################################################### +### Receipt Store Configuration ### +############################################################################### + +[receipt-store] +# Backend defines the receipt store backend. +# Supported backends: pebble (aka pebbledb), parquet +# defaults to pebbledb +rs-backend = "pebbledb" + +# Defines the receipt store directory. If unset, defaults to /data/receipt.db +db-directory = "" + +# AsyncWriteBuffer defines the async queue length for commits to be applied to receipt store. +# Applies only when rs-backend = "pebbledb"; parquet ignores this setting. +# Set <= 0 for synchronous writes. +# defaults to 100 +async-write-buffer = 100 + +# PruneIntervalSeconds defines the interval in seconds to trigger pruning. +# Receipt retention is controlled by the global min-retain-blocks flag. +# defaults to 600 seconds +prune-interval-seconds = 600 + +############################################################################### +### EVM Configuration ### +############################################################################### + +[evm] +# controls whether an HTTP EVM server is enabled +http_enabled = true +http_port = 8545 + +# controls whether a websocket server is enabled +ws_enabled = true +ws_port = 8546 + +# ReadTimeout is the maximum duration for reading the entire +# request, including the body. +# Because ReadTimeout does not let Handlers make per-request +# decisions on each request body's acceptable deadline or +# upload rate, most users will prefer to use +# ReadHeaderTimeout. It is valid to use them both. +read_timeout = "30s" + +# ReadHeaderTimeout is the amount of time allowed to read +# request headers. The connection's read deadline is reset +# after reading the headers and the Handler can decide what +# is considered too slow for the body. If ReadHeaderTimeout +# is zero, the value of ReadTimeout is used. If both are +# zero, there is no timeout. +read_header_timeout = "30s" + +# WriteTimeout is the maximum duration before timing out +# writes of the response. It is reset whenever a new +# request's header is read. Like ReadTimeout, it does not +# let Handlers make decisions on a per-request basis. +write_timeout = "30s" + +# IdleTimeout is the maximum amount of time to wait for the +# next request when keep-alives are enabled. If IdleTimeout +# is zero, the value of ReadTimeout is used. If both are +# zero, ReadHeaderTimeout is used. +idle_timeout = "2m0s" + +# Maximum gas limit for simulation +simulation_gas_limit = 10000000 + +# Timeout for EVM call in simulation +simulation_evm_timeout = "1m0s" + +# list of CORS allowed origins, separated by comma +cors_origins = "*" + +# list of WS origins, separated by comma +ws_origins = "*" + +# timeout for filters +filter_timeout = "2m0s" + +# checkTx timeout for sig verify +checktx_timeout = "5s" + +# controls whether to have txns go through one by one +slow = false + +# Deny list defines list of methods that EVM RPC should fail fast, e.g ["debug_traceBlockByNumber"] +deny_list = [] + +# 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 = [ + "sei_getSeiAddress", + "sei_getEVMAddress", + "sei_getCosmosTx", + + # 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 = 10000 + +# max number of blocks to query logs for +max_blocks_for_log = 2000 + +# max number of concurrent NewHead subscriptions +max_subscriptions_new_head = 10000 + +# MaxConcurrentTraceCalls defines the maximum number of concurrent debug_trace calls. +# Set to 0 for unlimited. +max_concurrent_trace_calls = 10 + +# Max number of blocks allowed to look back for tracing +# Set to -1 for unlimited lookback, which is useful for archive nodes. +max_trace_lookback_blocks = 10000 + +# Timeout for each trace call +trace_timeout = "30s" + +# Enable the parallelized default debug_traceBlock* path. +enable_parallelized_block_trace = false + +# WorkerPoolSize defines the number of workers in the worker pool. +# Default: min(64, CPU cores × 2). Capped at 64 to prevent excessive goroutines on high-core machines. +# Set to 0 to use the default. +worker_pool_size = 8 + +# WorkerQueueSize defines the size of the task queue in the worker pool. +# Default: 1000 tasks. Set to 0 to use the default. +worker_queue_size = 1000 + +############################################################################### +### Giga Executor Configuration ### +############################################################################### + +[giga_executor] +# enabled controls whether to use the Giga executor (evmone-based) instead of geth's interpreter. +# This is an experimental feature for improved EVM throughput. +# Default: false +enabled = false + +# occ_enabled controls whether to use OCC (Optimistic Concurrency Control) with the Giga executor. +# When true, transactions are executed in parallel with conflict detection and retry. +# Default: false +occ_enabled = false + +############################################################################### +### Admin Configuration (Auto-managed) ### +############################################################################### + +[admin_server] + +# Enable the admin gRPC server for runtime log level control. +admin_enabled = false + +# Listen address for the admin gRPC server. Must be a loopback address. +admin_address = "127.0.0.1:9095" + +############################################################################### +### Telemetry Configuration (Auto-managed) ### +############################################################################### + +[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 = 7200 + +# When both 'api.enable' and 'telemetry.enabled' are true, this node will expose +# application metrics (custom Cosmos SDK metrics) on the API server endpoint along with the +# Tendermint metrics (port 26660) which are always enabled. + +# 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 = [] + +############################################################################### +### API Configuration (Auto-managed) ### +############################################################################### + +[api] + +# Enable defines if the API server should be enabled. +enable = true + +# Swagger defines if swagger documentation should automatically be registered. +swagger = true + +# Address defines the API server to listen on. +address = "tcp://0.0.0.0:1317" + +# MaxOpenConnections defines the number of maximum open connections. +max-open-connections = 1000 + +# RPCReadTimeout defines the Tendermint RPC read timeout (in seconds). +rpc-read-timeout = 10 + +# RPCWriteTimeout defines the Tendermint RPC write timeout (in seconds). +rpc-write-timeout = 0 + +# RPCMaxBodyBytes defines the Tendermint maximum response 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 + +############################################################################### +### Rosetta Configuration (Auto-managed) ### +############################################################################### + +[rosetta] + +# Enable defines if the Rosetta API server should be enabled. +enable = false + +# Address defines the Rosetta API server to listen on. +address = ":8080" + +# Network defines the name of the blockchain that will be returned by Rosetta. +blockchain = "app" + +# Network defines the name of the network that will be returned by Rosetta. +network = "network" + +# Retries defines the number of retries when connecting to the node before failing. +retries = 3 + +# Offline defines if Rosetta server should run in offline mode. +offline = false + +############################################################################### +### gRPC Configuration (Auto-managed) ### +############################################################################### + +[grpc] + +# Enable defines if the gRPC server should be enabled. +enable = true + +# Address defines the gRPC server address to bind to. +address = "0.0.0.0:9090" + +############################################################################### +### gRPC Web Configuration (Auto-managed) ### +############################################################################### + +[grpc-web] + +# GRPCWebEnable defines if the gRPC-web should be enabled. +# NOTE: gRPC must also be enabled, otherwise, this configuration is a no-op. +enable = true + +# Address defines the gRPC-web server address to bind to. +address = "0.0.0.0:9091" + +# EnableUnsafeCORS defines if CORS should be enabled (unsafe - use it at your own risk). +enable-unsafe-cors = false + +############################################################################### +### Genesis Configuration (Auto-managed) ### +############################################################################### + +# Genesis config allows configuring whether to stream from an genesis json file in streamed form +[genesis] + +# stream-import specifies whether to the stream the import from the genesis json file. The genesis +# file must be in stream form and exported in a streaming fashion. +stream-import = false + +# genesis-stream-file specifies the path of the genesis json file to stream from. +genesis-stream-file = "" + +############################################################################### +### Legacy IAVL Settings (Auto-managed) ### +############################################################################### + +[iavl] +# Pruning Strategies: +# - default: Keep the recent 362880 blocks and prune is triggered every 10 blocks +# - nothing: all historic states will be saved, nothing will be deleted (i.e. archiving node) +# - everything: all saved states will be deleted, storing only the recent 2 blocks; pruning at every block +# - custom: allow pruning options to be manually specified through 'pruning-keep-recent' and 'pruning-interval' +# Pruning strategy is completely ignored when seidb is enabled +pruning = "nothing" + +# These are applied if and only if the pruning strategy is custom, and seidb is not enabled +pruning-keep-recent = "0" +pruning-keep-every = "0" +pruning-interval = "0" + +############################################################################### +### WASM Configuration (Auto-managed) ### +############################################################################### + +[wasm] +# This is the maximum sdk gas (wasm and storage) that we allow for any x/wasm "smart" queries +query_gas_limit = 300000 +# This is the number of wasm vm instances we keep cached in memory for speed-up +# Warning: this is currently unstable and may lead to crashes, best to keep for 0 unless testing locally +lru_size = 0 + +############################################################################### +### ETH Replay Configuration (Auto-managed) ### +############################################################################### + +[eth_replay] +eth_replay_enabled = false +eth_rpc = "http://44.234.105.54:18545" +eth_data_dir = "/root/.ethereum/chaindata" +eth_replay_contract_state_checks = false + +############################################################################### +### ETH Block Test Configuration (Auto-managed) ### +############################################################################### + +[eth_blocktest] +eth_blocktest_enabled = false +eth_blocktest_test_data_path = "~/testdata/" + +############################################################################### +### EVM Query Configuration (Auto-managed) ### +############################################################################### + +[evm_query] +evm_query_gas_limit = 300000 + +############################################################################### +### Light Invariance Configuration (Auto-managed) ### +############################################################################### + +[light_invariance] +supply_enabled = true +``` + +{/* AUTO-GENERATED:APP_TOML:END */} + + + + + +Tendermint / consensus-layer configuration: P2P, RPC, mempool, consensus, +state-sync, etc. + +{/* AUTO-GENERATED:CONFIG_TOML:START */} + +```toml +# This is a TOML config file. +# For more information, see https://github.com/toml-lang/toml + +# NOTE: Any path below can be absolute (e.g. "/var/myawesomeapp/data") or +# relative to the home directory (e.g. "data"). The home directory is +# "$HOME/.tendermint" by default, but could be changed via $TMHOME env variable +# or --home cmd flag. + +####################################################################### +### Main Base Config Options ### +####################################################################### + +# TCP or UNIX socket address of the ABCI application, +# or the name of an ABCI application compiled in with the Tendermint binary +proxy-app = "tcp://127.0.0.1:26658" + +# A custom human readable name for this node +moniker = "docs-example" + +# Mode of Node: full | validator | seed +# * validator node +# - all reactors +# - with priv_validator_key.json, priv_validator_state.json +# * full node +# - all reactors +# - No priv_validator_key.json, priv_validator_state.json +# * seed node +# - only P2P, PEX Reactor +# - No priv_validator_key.json, priv_validator_state.json +mode = "full" + +# Database backend: goleveldb | cleveldb | boltdb | rocksdb | badgerdb +# * goleveldb (github.com/syndtr/goleveldb - most popular implementation) +# - pure go +# - stable +# * cleveldb (uses levigo wrapper) +# - fast +# - requires gcc +# - use cleveldb build tag (go build -tags cleveldb) +# * boltdb (uses etcd's fork of bolt - github.com/etcd-io/bbolt) +# - EXPERIMENTAL +# - may be faster is some use-cases (random reads - indexer) +# - use boltdb build tag (go build -tags boltdb) +# * rocksdb (uses github.com/tecbot/gorocksdb) +# - EXPERIMENTAL +# - requires gcc +# - use rocksdb build tag (go build -tags rocksdb) +# * badgerdb (uses github.com/dgraph-io/badger) +# - EXPERIMENTAL +# - use badgerdb build tag (go build -tags badgerdb) +db-backend = "goleveldb" + +# Database directory +db-dir = "data" + +# Output level for logging, including package level options +log-level = "info" + +# Output format: 'plain' (colored text) or 'json' +log-format = "text" + +##### additional base config options ##### + +# Path to the JSON file containing the initial validator set and other meta data +genesis-file = "config/genesis.json" + +# Path to the JSON file containing the private key to use for node authentication in the p2p protocol +node-key-file = "config/node_key.json" + +# Mechanism to connect to the ABCI application: socket | grpc +abci = "socket" + +# If true, query the ABCI app on connecting to a new peer +# so the app can decide if we should keep the connection or not +filter-peers = false + +####################################################################### +### Advanced Configuration Options ### +####################################################################### + +####################################################### +### RPC Server Configuration Options ### +####################################################### +[rpc] + +# TCP or UNIX socket address for the RPC server to listen on +laddr = "tcp://0.0.0.0:26657" + +# A list of origins a cross-domain request can be executed from +# Default value '[]' disables cors support +# Use '["*"]' to allow any origin +cors-allowed-origins = [] + +# A list of methods the client is allowed to use with cross-domain requests +cors-allowed-methods = ["HEAD", "GET", "POST", ] + +# A list of non simple headers the client is allowed to use with cross-domain requests +cors-allowed-headers = ["Origin", "Accept", "Content-Type", "X-Requested-With", "X-Server-Time", ] + +# Activate unsafe RPC commands like /dial-seeds and /unsafe-flush-mempool +unsafe = false + +# Maximum number of simultaneous connections (including WebSocket). +# If you want to accept a larger number than the default, make sure +# you increase your OS limits. +# 0 - unlimited. +# Should be < {ulimit -Sn} - {MaxNumInboundPeers} - {MaxNumOutboundPeers} - {N of wal, db and other open files} +# 1024 - 40 - 10 - 50 = 924 = ~900 +max-open-connections = 900 + +# Maximum number of unique clientIDs that can /subscribe +# If you're using /broadcast_tx_commit, set to the estimated maximum number +# of broadcast_tx_commit calls per block. +max-subscription-clients = 100 + +# Maximum number of unique queries a given client can /subscribe to +# If you're using a Local RPC client and /broadcast_tx_commit, set this +# to the estimated maximum number of broadcast_tx_commit calls per block. +max-subscriptions-per-client = 5 + +# If true, disable the websocket interface to the RPC service. This has +# the effect of disabling the /subscribe, /unsubscribe, and /unsubscribe_all +# methods for event subscription. +# +# EXPERIMENTAL: This setting will be removed in Tendermint v0.37. +experimental-disable-websocket = false + +# The time window size for the event log. All events up to this long before +# the latest (up to EventLogMaxItems) will be available for subscribers to +# fetch via the /events method. If 0 (the default) the event log and the +# /events RPC method are disabled. +event-log-window-size = "30s" + +# The maxiumum number of events that may be retained by the event log. If +# this value is 0, no upper limit is set. Otherwise, items in excess of +# this number will be discarded from the event log. +# +# Warning: This setting is a safety valve. Setting it too low may cause +# subscribers to miss events. Try to choose a value higher than the +# maximum worst-case expected event load within the chosen window size in +# ordinary operation. +# +# For example, if the window size is 10 minutes and the node typically +# averages 1000 events per ten minutes, but with occasional known spikes of +# up to 2000, choose a value > 2000. +event-log-max-items = 0 + +# How long to wait for a tx to be committed during /broadcast_tx_commit. +# WARNING: Using a value larger than 10s will result in increasing the +# global HTTP write timeout, which applies to all connections and endpoints. +# See https://github.com/tendermint/tendermint/issues/3435 +timeout-broadcast-tx-commit = "10s" + +# Maximum size of request body, in bytes +max-body-bytes = 1000000 + +# Maximum size of request header, in bytes +max-header-bytes = 1048576 + +# The path to a file containing certificate that is used to create the HTTPS server. +# Might be either absolute path or path related to Tendermint's config directory. +# If the certificate is signed by a certificate authority, +# the certFile should be the concatenation of the server's certificate, any intermediates, +# and the CA's certificate. +# NOTE: both tls-cert-file and tls-key-file must be present for Tendermint to create HTTPS server. +# Otherwise, HTTP server is run. +tls-cert-file = "" + +# The path to a file containing matching private key that is used to create the HTTPS server. +# Might be either absolute path or path related to Tendermint's config directory. +# NOTE: both tls-cert-file and tls-key-file must be present for Tendermint to create HTTPS server. +# Otherwise, HTTP server is run. +tls-key-file = "" + +# pprof listen address (https://golang.org/pkg/net/http/pprof) +pprof-laddr = "" + +# timeout for any read request +timeout-read = "10s" + +####################################################################### +### P2P Configuration Options ### +####################################################################### +[p2p] + +# Select the p2p internal queue +queue-type = "simple-priority" + +# Address to listen for incoming connections +laddr = "tcp://0.0.0.0:26656" + +# Address to advertise to peers for them to dial +# If empty, will use the same port as the laddr, +# and will introspect on the listener or use UPnP +# to figure out the address. ip and port are required +# example: 159.89.10.97:26656 +external-address = "" + +# Comma separated list of peers to be added to the peer store +# on startup. Either BootstrapPeers or PersistentPeers are +# needed for peer discovery +bootstrap-peers = "" + +# Comma separated list of nodes to keep persistent connections to +persistent-peers = "" + +# Comma separated list of nodes for block sync only +blocksync-peers = "" + +# UPNP port forwarding +upnp = false + +# Maximum number of connections (inbound and outbound). +max-connections = 100 + +# Rate limits the number of incoming connection attempts per IP address. +max-incoming-connection-attempts = 100 + +# Set true to enable the peer-exchange reactor +pex = true + +# Comma separated list of peer IDs to keep private (will not be gossiped to other peers) +# Warning: IPs will be exposed at /net_info, for more information https://github.com/tendermint/tendermint/issues/3055 +private-peer-ids = "" + +# Toggle to disable guard against peers connecting from the same ip. +allow-duplicate-ip = false + +# Peer connection configuration. +handshake-timeout = "10s" +dial-timeout = "3s" + +# Time to wait before flushing messages out on the connection +# TODO: Remove once MConnConnection is removed. +flush-throttle-timeout = "100ms" + +# Maximum size of a message packet payload, in bytes +# TODO: Remove once MConnConnection is removed. +# WARNING: coordinate before changing this default; impacts network interoperability +max-packet-msg-payload-size = 1000000 + +# Rate at which packets can be sent, in bytes/second +# TODO: Remove once MConnConnection is removed. +send-rate = 20971520 + +# Rate at which packets can be received, in bytes/second +# TODO: Remove once MConnConnection is removed. +recv-rate = 20971520 + +# List of node IDs, to which a connection will be (re)established, dropping an existing peer if any existing limit has been reached +unconditional-peer-ids = "" + +####################################################################### +### Mempool Configuration Options ### +####################################################################### +[mempool] + +# recheck has been moved from a config option to a global +# consensus param in v0.36 +# See https://github.com/tendermint/tendermint/issues/8244 for more information. + +# Set true to broadcast transactions in the mempool to other nodes +broadcast = true + +# Maximum number of transactions in the mempool +size = 5000 + +# Limit the total size of all txs in the mempool. +# This only accounts for raw transactions (e.g. given 1MB transactions and +# max-txs-bytes=5MB, mempool will only accept 5 transactions). +max-txs-bytes = 1073741824 + +# Size of the cache (used to filter transactions we saw earlier) in transactions +cache-size = 10000 + +# Size of the cache duplicate tx keys for tracking metrics +duplicate-txs-cache-size = "100000" + +# Do not remove invalid transactions from the cache (default: false) +# Set to true if it's not possible for any invalid transaction to become valid +# again in the future. +keep-invalid-txs-in-cache = false + +# Maximum size of a single transaction. +# NOTE: the max size of a tx transmitted over the network is {max-tx-bytes}. +max-tx-bytes = 1048576 + +# Maximum size of a batch of transactions to send to a peer +# Including space needed by encoding (one varint per transaction). +# XXX: Unused due to https://github.com/tendermint/tendermint/issues/5796 +max-batch-bytes = 0 + +# ttl-duration, if non-zero, defines the maximum amount of time a transaction +# can exist for in the mempool. +# +# Note, if ttl-num-blocks is also defined, a transaction will be removed if it +# has existed in the mempool at least ttl-num-blocks number of blocks or if it's +# insertion time into the mempool is beyond ttl-duration. +ttl-duration = "5s" + +# ttl-num-blocks, if non-zero, defines the maximum number of blocks a transaction +# can exist for in the mempool. +# +# Note, if ttl-duration is also defined, a transaction will be removed if it +# has existed in the mempool at least ttl-num-blocks number of blocks or if +# it's insertion time into the mempool is beyond ttl-duration. +ttl-num-blocks = 10 + +tx-notify-threshold = 0 + +check-tx-error-blacklist-enabled = true + +check-tx-error-threshold = 50 + +pending-size = 5000 + +max-pending-txs-bytes = 1073741824 + +pending-ttl-duration = "0s" + +pending-ttl-num-blocks = 0 + +# Defines the percentage of transactions with the lowest priority hint +# (expressed as a percentage in the range [0.0, 1.0]) that will be +# dropped from the mempool once the configured utilisation threshold +# is reached. +drop-priority-threshold = 0.1 + +# Defines the mempool utilisation level (expressed as a percentage in +# the range [0.0, 1.0]) above which transactions will be selectively +# dropped based on their priority hint. +# +# For example, if this parameter is set to 0.8, then once the mempool reaches +# 80% capacity, transactions with priority hints below drop-priority-threshold +# percentile will be dropped to make room for new transactions. +drop-utilisation-threshold = 1 + +# Defines the size of the reservoir for keeping track +# of the distribution of transaction priorities in the mempool. +# +# This is used to determine the priority threshold below which transactions will +# be dropped when the mempool utilisation exceeds drop-priority-threshold. +# +# The reservoir is a statistically representative sample of transaction +# priorities in the mempool, and is used to estimate the priority distribution +# without needing to store all transaction priorities. +# +# A larger reservoir size will yield a more accurate estimate of the priority +# distribution, but will consume more memory. +# +# The default value of 10,240 is a reasonable compromise between accuracy and +# memory usage for most use cases. It takes approximately 80KB of memory storing +# int64 transaction priorities. +# +# See DropUtilisationThreshold and DropPriorityThreshold. +drop-priority-reservoir-size = 10240 + +####################################################################### +### State Sync Configuration Options ### +####################################################################### +[statesync] +# State sync rapidly bootstraps a new node by discovering, fetching, and restoring a state machine +# snapshot from peers instead of fetching and replaying historical blocks. Requires some peers in +# the network to take and serve state machine snapshots. State sync is not attempted if the node +# has any local state (LastBlockHeight > 0). The node will have a truncated block history, +# starting from the height of the snapshot. +enable = false + +# State sync uses light client verification to verify state. This can be done either through the +# P2P layer or RPC layer. Set this to true to use the P2P layer. If false (default), RPC layer +# will be used. +use-p2p = false + +# If using RPC, at least two addresses need to be provided. They should be compatible with net.Dial, +# for example: "host.example.com:2125" +rpc-servers = "" + +# The hash and height of a trusted block. Must be within the trust-period. +trust-height = 0 +trust-hash = "" + +# The trust period should be set so that Tendermint can detect and gossip misbehavior before +# it is considered expired. For chains based on the Cosmos SDK, one day less than the unbonding +# period should suffice. +trust-period = "168h0m0s" + +# Backfill sequentially fetches after state sync completes, verifies and stores light blocks in reverse order. +# backfill-blocks means it will keep reverse fetching up to backfill-blocks number of blocks behind state sync position +# backfill-duration means it will keep fetching up to backfill-duration old time +# The actual backfill process will take at backfill-blocks as priority: +# - If backfill-blocks is set, use backfill-blocks to backfill +# - If backfill-blocks is not set to be greater than 0, use backfill-duration to backfill +backfill-blocks = "0" +backfill-duration = "0s" + +# Time to spend discovering snapshots before initiating a restore. +discovery-time = "15s" + +# Temporary directory for state sync snapshot chunks, defaults to os.TempDir(). +# The synchronizer will create a new, randomly named directory within this directory +# and remove it when the sync is complete. +temp-dir = "" + +# Whether to use local snapshot only for state sync or not. +# If this is true, then state sync will look for existing snapshots +# which are located in the snapshot-dir configured in app.toml (default to [home-dir]/data/snapshots) +use-local-snapshot = false + +# The timeout duration before re-requesting a chunk, possibly from a different +# peer (default: 15 seconds). +chunk-request-timeout = "15s" + +# The number of concurrent chunk and block fetchers to run (default: 4). +fetchers = "2" + +verify-light-block-timeout = "1m0s" + +blacklist-ttl = "5m0s" + +####################################################################### +### Consensus Configuration Options ### +####################################################################### +[consensus] + +wal-file = "data/cs.wal/wal" + +# How many blocks to look back to check existence of the node's consensus votes before joining consensus +# When non-zero, the node will panic upon restart +# if the same consensus key was used to sign {double-sign-check-height} last blocks. +# So, validators should stop the state machine, wait for some blocks, and then restart the state machine to avoid panic. +double-sign-check-height = 0 + +# EmptyBlocks mode and possible interval between empty blocks +create-empty-blocks = true +create-empty-blocks-interval = "0s" + +# Only gossip hashes, not the actual data +gossip-tx-key-only = "true" + +# Reactor sleep duration parameters +peer-gossip-sleep-duration = "100ms" +peer-query-maj23-sleep-duration = "2s" + +### Unsafe Timeout Overrides ### + +# These fields provide temporary overrides for the Timeout consensus parameters. +# Use of these parameters is strongly discouraged. Using these parameters may have serious +# liveness implications for the validator and for the chain. +# +# These fields will be removed from the configuration file in the v0.37 release of Tendermint. +# For additional information, see ADR-74: +# https://github.com/tendermint/tendermint/blob/master/docs/architecture/adr-074-timeout-params.md + +# This field provides an unsafe override of the Propose timeout consensus parameter. +# This field configures how long the consensus engine will wait for a proposal block before prevoting nil. +# If this field is set to a value greater than 0, it will take effect. +unsafe-propose-timeout-override = "0s" + +# This field provides an unsafe override of the ProposeDelta timeout consensus parameter. +# This field configures how much the propose timeout increases with each round. +# If this field is set to a value greater than 0, it will take effect. +unsafe-propose-timeout-delta-override = "0s" + +# This field provides an unsafe override of the Vote timeout consensus parameter. +# This field configures how long the consensus engine will wait after +# receiving +2/3 votes in a round. +# If this field is set to a value greater than 0, it will take effect. +unsafe-vote-timeout-override = "0s" + +# This field provides an unsafe override of the VoteDelta timeout consensus parameter. +# This field configures how much the vote timeout increases with each round. +# If this field is set to a value greater than 0, it will take effect. +unsafe-vote-timeout-delta-override = "0s" + +# This field provides an unsafe override of the Commit timeout consensus parameter. +# This field configures how long the consensus engine will wait after receiving +# +2/3 precommits before beginning the next height. +# If this field is set to a value greater than 0, it will take effect. +unsafe-commit-timeout-override = "0s" + +# This field provides an unsafe override of the BypassCommitTimeout consensus parameter. +# This field configures if the consensus engine will wait for the full Commit timeout +# before proceeding to the next height. +# If this field is set to true, the consensus engine will proceed to the next height +# as soon as the node has gathered votes from all of the validators on the network. +# unsafe-bypass-commit-timeout-override = + +####################################################################### +### Transaction Indexer Configuration (Auto-managed) ### +####################################################################### +[tx-index] + +# The backend database list to back the indexer. +# If list contains "null" or "", meaning no indexer service will be used. +# +# The application will set which txs to index. In some cases a node operator will be able +# to decide which txs to index based on configuration set in the application. +# +# Options: +# 1) "null" (default) - no indexer services. +# 2) "kv" - a simple indexer backed by key-value storage (see DBBackend) +# 3) "psql" - the indexer services backed by PostgreSQL. +# When "kv" or "psql" is chosen "tx.height" and "tx.hash" will always be indexed. +indexer = ["kv"] + +# The PostgreSQL connection configuration, the connection format: +# postgresql://:@:/? +psql-conn = "" + +####################################################################### +### Instrumentation Configuration (Auto-managed) ### +####################################################################### +[instrumentation] + +# When true, Prometheus metrics are served under /metrics on +# PrometheusListenAddr. +# Check out the documentation for the list of available metrics. +prometheus = false + +# Address to listen for Prometheus collector(s) connections +prometheus-listen-addr = ":26660" + +# Maximum number of simultaneous connections. +# If you want to accept a larger number than the default, make sure +# you increase your OS limits. +# 0 - unlimited. +max-open-connections = 3 + +# Instrumentation namespace +namespace = "tendermint" + +####################################################################### +### Priv Validator Configuration (Auto-managed) ### +####################################################################### +[priv-validator] + +# Path to the JSON file containing the private key to use as a validator in the consensus protocol +key-file = "config/priv_validator_key.json" + +# Path to the JSON file containing the last sign state of a validator +state-file = "data/priv_validator_state.json" + +# TCP or UNIX socket address for Tendermint to listen on for +# connections from an external PrivValidator process +# when the listenAddr is prefixed with grpc instead of tcp it will use the gRPC Client +laddr = "" + +# Path to the client certificate generated while creating needed files for secure connection. +# If a remote validator address is provided but no certificate, the connection will be insecure +client-certificate-file = "" + +# Client key generated while creating certificates for secure connection +client-key-file = "" + +# Path to the Root Certificate Authority used to sign both client and server certificates +root-ca-file = "" + +####################################################################### +### SelfRemediation Configuration (Auto-managed) ### +####################################################################### +[self-remediation] + +# If the node has no p2p peers available then trigger a restart +# Set to 0 to disable +p2p-no-peers-available-window-seconds = 0 + +# If node has no peers for statesync after a period of time then restart +# Set to 0 to disable +statesync-no-peers-available-window-seconds = 0 + +# Threshold for how far back the node can be behind the current block height before triggering a restart +# Set to 0 to disable +blocks-behind-threshold = 0 + +# How often to check if node is behind +blocks-behind-check-interval = 60 + +# Cooldown between each restart +restart-cooldown-seconds = 600 ``` +{/* AUTO-GENERATED:CONFIG_TOML:END */} + + + + + +CLI and client defaults used by `seid` itself (chain id, keyring backend, +output format, node endpoint). + +{/* AUTO-GENERATED:CLIENT_TOML:START */} + +```toml +# This is a TOML config file. +# For more information, see https://github.com/toml-lang/toml + +############################################################################### +### Client Configuration ### +############################################################################### + +# The network chain ID +chain-id = "pacific-1" +# The keyring's backend, where the keys are stored (os|file|kwallet|pass|test|memory) +keyring-backend = "os" +# CLI output format (text|json) +output = "text" +# : to Tendermint RPC interface for this chain +node = "tcp://localhost:26657" +# Transaction broadcasting mode (sync|async|block) +broadcast-mode = "sync" +``` + +{/* AUTO-GENERATED:CLIENT_TOML:END */} + + + + ## Database Management -### Database Types +### Architecture -Sei supports two database backends: +Sei stores chain data through **SeiDB**, a two-layer design that replaces the +legacy single-database IAVL store with separate hot- and historical-data tiers: -1. **SeiDB (Recommended)** +1. **State Commit (SC)** — the active chain state used for transaction + execution and to compute the per-block app hash. Cosmos modules sit on a + memory-mapped Merkle tree (`memiavl`) ported from Cronos. EVM state can + additionally be routed through **FlatKV**, an EVM-tuned PebbleDB store + with per-type sub-databases (`account`, `code`, `storage`, `legacy`, + `metadata`). Routing is controlled by `sc-write-mode` / `sc-read-mode` + and defaults to memiavl-only — FlatKV is only opened when one of those + modes is set to a non-default value. +2. **State Store (SS)** — versioned raw key/value pairs used for historical + queries. Required for any node that serves RPC. The default backend is + **PebbleDB**; **RocksDB** is available for iteration-heavy workloads such + as archive nodes or RPC nodes that run a lot of `debug_trace*` (see the + [RocksDB Backend Guide](/node/rocksdb-backend) for build instructions). - - Optimized for performance and sync times - - Reduces resource usage - - Best for all nodes +The legacy IAVL backend is still selectable via `sc-enable = false` but is +deprecated and slated for removal — new deployments and existing nodes +should run on SeiDB. -2. **Legacy IAVL DB** - - Standard Cosmos SDK database - - More widely tested +### SeiDB Configuration -### Sei-DB Configuration +The full set of knobs is in the auto-generated +[Default Configurations](#default-configurations) above. The block below +covers the values most node operators tune in practice. ```toml copy [state-commit] +# Enable SeiDB. Disable to fall back to legacy IAVL. sc-enable = true + +# Async commit queue. Larger values improve catch-up; 0 = synchronous. sc-async-commit-buffer = 100 -sc-keep-recent = 1 # Keep only the most recent state for performance -sc-snapshot-interval = 10000 # Take state snapshots every 10,000 blocks + +# How many memiavl snapshots to keep besides the latest one. +# 0 = current snapshot only. Set to 1 if you serve IBC light-client queries +# so relayers can verify against an older snapshot height. +sc-keep-recent = 1 + +# Take a state-commit snapshot every N blocks. +sc-snapshot-interval = 10000 + +# Minimum wall-clock interval (seconds) between snapshots; prevents overlap +# during catch-up. Lower this if you set sc-snapshot-interval below ~5000. +sc-snapshot-min-time-interval = 3600 + +# Cap on snapshot write throughput across all trees (MB/s). 0 = unlimited. +sc-snapshot-write-rate-mbps = 100 + +# EVM data routing between the Cosmos memiavl tree and FlatKV. +# Default: cosmos_only / cosmos_only — all EVM state lives in memiavl. See +# the Giga Storage section below for the dual_write + split_read setup. +sc-write-mode = "cosmos_only" +sc-read-mode = "cosmos_only" +sc-enable-lattice-hash = false + +[state-commit.flatkv] +# FlatKV is the EVM-optimized commit store (PebbleDB). It is only opened +# when sc-write-mode is dual_write or split_write — otherwise these +# settings have no effect. WAL crash recovery is idempotent, so fsync +# stays off by default. +fsync = false +async-write-buffer = 0 +snapshot-interval = 10000 +snapshot-keep-recent = 2 [state-store] +# Historical SS layer. Validators can disable this to save disk; any node +# serving RPC must keep it on. ss-enable = true -ss-backend = "pebbledb" # Default, required + +# pebbledb (default) or rocksdb (faster iteration, archive-friendly). +ss-backend = "pebbledb" + ss-async-write-buffer = 100 -ss-keep-recent = 100000 # Keep last 100,000 blocks -ss-prune-interval = 600 # Cleanup interval for pruning +# Versions to retain. 0 = keep everything (archive-style). 100,000 ≈ 28h. +ss-keep-recent = 100000 +# Pruning interval, plus a small random jitter, to avoid colliding with +# snapshot creation. +ss-prune-interval = 600 + +# Optional EVM SS routing — same semantics as the SC modes above. Leave on +# cosmos_only unless you have completed the Giga SS Store migration. +evm-ss-write-mode = "cosmos_only" +evm-ss-read-mode = "cosmos_only" +evm-ss-separate-dbs = false + +[receipt-store] +# pebbledb (default) or parquet. Receipts are pruned together with blocks +# according to min-retain-blocks above. +rs-backend = "pebbledb" +async-write-buffer = 100 +prune-interval-seconds = 600 ``` -Setting very small [more frequent] pruning intervals may cause issues with automated -snapshotting in the event those events collide. Too large [less frequent] -pruning intervals means it will take a longer overall time to prune which may -cause missed blocks and excessive resync time. +Setting very small (more frequent) pruning intervals may collide with +snapshot creation. Too-large (less frequent) intervals mean pruning takes +longer overall, which can cause missed blocks and excessive resync time. + +### Giga Storage and Giga Executor + +These are two **separate** opt-in features that ship in newer `seid` +releases. Both default to off; only enable them deliberately and after +following the relevant migration guide. + +**Giga Storage** repartitions SeiDB so EVM state lives in its own +databases at both the SC and SS layers, freeing non-EVM modules from EVM +write amplification. + +For step-by-step instructions — including the full state-sync flow, startup verification, safety checks, and rollback — see the [Giga SS Store Migration Guide](/node/giga-storage-migration). The snippet below is just the resulting `app.toml` shape. + + +```toml copy +[state-commit] +sc-write-mode = "dual_write" # write EVM data to memiavl AND FlatKV +sc-read-mode = "split_read" # read EVM data from FlatKV +sc-enable-lattice-hash = true # required for split-mode app-hash equality + +[state-store] +evm-ss-write-mode = "split_write" +evm-ss-read-mode = "split_read" +``` + +Enabling Giga Storage requires a fresh state sync — flipping the EVM SS +modes on a node with existing data fails the startup safety checks because +the new EVM SS DB starts empty while Cosmos SS already has history. The +full procedure is in the +[Giga SS Store Migration Guide](/node/giga-storage-migration) and is +currently supported on **RPC nodes only**; validators and archive nodes are +not yet covered. + +**Giga Executor** is independent of Giga Storage. It swaps the EVM +interpreter from go-ethereum's geth to an evmone-based executor for +higher throughput, with optional OCC parallelism on top: + +```toml copy +[giga_executor] +# Use the evmone-based executor instead of geth's interpreter. Experimental. +enabled = false +# Run Giga-executed txs in parallel with Optimistic Concurrency Control. +occ_enabled = false +``` ### Database Maintenance @@ -218,8 +1619,10 @@ make install sudo systemctl restart seid ``` -_Tip - build the upgrade before the halt-height so you can quickly replace it -with minimal downtime_ + + Build the upgrade before the halt-height so you can quickly replace it + with minimal downtime. + ## Performance Optimization diff --git a/mdx-components.js b/mdx-components.js index 1db2933f..34ef78de 100644 --- a/mdx-components.js +++ b/mdx-components.js @@ -1,5 +1,5 @@ import { useMDXComponents as getThemeComponents } from 'nextra-theme-docs'; -import { Check, Danger, Info, Note, Tip, Warning } from './src/components/MintlifyShims'; +import { Check, Danger, Info, Note, Tab, Tabs, Tip, Warning } from './src/components/MintlifyShims'; const themeComponents = getThemeComponents(); @@ -12,6 +12,8 @@ export function useMDXComponents(components) { Tip, Check, Danger, + Tabs, + Tab, ...components }; } diff --git a/scripts/sync-default-configs.mjs b/scripts/sync-default-configs.mjs new file mode 100755 index 00000000..de69ef37 --- /dev/null +++ b/scripts/sync-default-configs.mjs @@ -0,0 +1,89 @@ +#!/usr/bin/env node +/** + * Refreshes the inlined default `app.toml`, `config.toml`, and `client.toml` + * blocks inside `content/node/node-operators.mdx` with the unmodified output + * of `seid init` against a freshly built seid binary. + * + * Inputs (env): + * SEI_HOME Directory `seid init` wrote to (default: $HOME/.sei) + * SEI_VERSION Tag of the seid release that was built (e.g. v6.4.4) [required] + * SEI_COMMIT Short commit SHA the binary was built from [optional, unused but kept for compatibility] + * OUTPUT_FILE MDX file to update (default: content/node/node-operators.mdx) + * + * The MDX file uses paired marker comments such as + * {/* AUTO-GENERATED:APP_TOML:START *\/} + * ...replaced content... + * {/* AUTO-GENERATED:APP_TOML:END *\/} + * Everything between START/END (inclusive of newlines) is replaced; everything + * outside is preserved so docs writers can edit prose without touching the + * sync script. + * + * NOTE: MDX comments ({/* ... *\/}) are required instead of HTML comments + * () because Nextra/MDX does not accept HTML comments at the + * top level and will fail to parse the page. + */ + +import { execSync } from 'node:child_process'; +import { existsSync, readFileSync, writeFileSync } from 'node:fs'; +import { homedir } from 'node:os'; +import { dirname, join, resolve } from 'node:path'; +import process from 'node:process'; +import { fileURLToPath } from 'node:url'; + +const __dirname = dirname(fileURLToPath(import.meta.url)); +const REPO_ROOT = resolve(__dirname, '..'); + +const SEI_HOME = process.env.SEI_HOME || join(homedir(), '.sei'); +const SEI_VERSION = process.env.SEI_VERSION; +const OUTPUT_FILE = resolve(REPO_ROOT, process.env.OUTPUT_FILE || 'content/node/node-operators.mdx'); + +if (!SEI_VERSION) { + console.error('error: SEI_VERSION env var is required (e.g. v6.4.4)'); + process.exit(2); +} +if (!existsSync(SEI_HOME)) { + console.error(`error: SEI_HOME does not exist: ${SEI_HOME}`); + process.exit(2); +} +if (!existsSync(OUTPUT_FILE)) { + console.error(`error: OUTPUT_FILE does not exist: ${OUTPUT_FILE}`); + process.exit(2); +} + +function readToml(name) { + const p = join(SEI_HOME, 'config', name); + if (!existsSync(p)) { + console.error(`error: expected file not found: ${p}`); + process.exit(2); + } + return readFileSync(p, 'utf8').replace(/\s+$/u, '') + '\n'; +} + +function escapeRe(s) { + return s.replace(/[.*+?^${}()|[\]\\]/gu, '\\$&'); +} + +function replaceBlock(source, marker, replacement) { + const start = `{/* AUTO-GENERATED:${marker}:START */}`; + const end = `{/* AUTO-GENERATED:${marker}:END */}`; + const pattern = new RegExp(`${escapeRe(start)}[\\s\\S]*?${escapeRe(end)}`, 'u'); + if (!pattern.test(source)) { + console.error(`error: missing marker block ${marker} in ${OUTPUT_FILE}`); + process.exit(2); + } + return source.replace(pattern, `${start}\n\n${replacement}\n\n${end}`); +} + +const blocks = { + APP_TOML: '```toml\n' + readToml('app.toml') + '```', + CONFIG_TOML: '```toml\n' + readToml('config.toml') + '```', + CLIENT_TOML: '```toml\n' + readToml('client.toml') + '```' +}; + +let source = readFileSync(OUTPUT_FILE, 'utf8'); +for (const [marker, content] of Object.entries(blocks)) { + source = replaceBlock(source, marker, content); +} + +writeFileSync(OUTPUT_FILE, source); +console.log(`wrote ${OUTPUT_FILE} from seid ${SEI_VERSION}`); diff --git a/src/components/MintlifyShims.tsx b/src/components/MintlifyShims.tsx index 60217d68..614fdca3 100644 --- a/src/components/MintlifyShims.tsx +++ b/src/components/MintlifyShims.tsx @@ -1,5 +1,6 @@ import { Callout } from 'nextra/components'; -import type { ReactNode } from 'react'; +import { Children, isValidElement, type ReactElement, type ReactNode } from 'react'; +import { Tabs as RadixTabs, TabsContent, TabsList, TabsTrigger } from './Tabs'; interface CalloutProps { children: ReactNode; @@ -16,3 +17,49 @@ export const Tip = ({ children }: CalloutProps) => {childre export const Check = ({ children }: CalloutProps) => {children}; export const Danger = ({ children }: CalloutProps) => {children}; + +interface TabProps { + title: string; + children: ReactNode; +} + +// Mintlify is just a labeled container; the parent reads its +// `title` prop and renders the tab list/panel UI itself. +export const Tab = ({ children }: TabProps) => <>{children}; +Tab.displayName = 'MintlifyTab'; + +interface TabsProps { + children: ReactNode; +} + +// Mintlify wrapping children. We render through the +// existing Radix-based Tabs primitives so the visual style matches the rest +// of the site, while keeping the source MDX portable to Mintlify. +export const Tabs = ({ children }: TabsProps) => { + const tabs = Children.toArray(children).filter((child): child is ReactElement => { + if (!isValidElement(child)) return false; + const type = child.type as { displayName?: string } | string; + return typeof type !== 'string' && type.displayName === 'MintlifyTab'; + }); + + if (tabs.length === 0) return null; + + const defaultValue = tabs[0].props.title; + + return ( + + + {tabs.map((tab) => ( + + {tab.props.title} + + ))} + + {tabs.map((tab) => ( + + {tab.props.children} + + ))} + + ); +};