Run a node · How-to guide
Build, run, and configure a node
Start by choosing the role and execution capability you need. A CPU-only build is useful for development and offline configuration checks. A sequencer or validating executor requires the CUDA SBF engine and its startup self-tests. A read-only replica applies state diffs and can skip that engine.
This guide describes the maintained Rust svm-vm node. The public singularity CLI and the Rust eto-cli helper are separate programs; use the CLI reference for their command contracts.
Before starting, choose CPU inspection or a GPU execution role, and identify the configuration bundle you intend to validate. The build steps require the pinned Rust toolchain; GPU execution additionally requires the native libraries described below. The configuration task is complete when the intended binary accepts the intended allowlisted settings and you have retained its effective configuration. Running a healthy executor requires the separate startup checks at the end.
For why the roles initialize different services, see node runtime architecture.
Choose an artifact deliberately
The repository pins Rust 1.93.0 with rustfmt and Clippy. Run Cargo from runtime/. The tree includes its dependencies; it does not require Git submodule initialization.
| Build feature | Operational meaning |
|---|---|
cuda | CUDA execution/acceleration, including the SBF production path and one-book dependency |
cuevm | Canonical CuEVM integration; native library must also be present |
mimalloc | Allocator choice |
qmdb-cuda | Separate experimental state-root path with recovery compatibility concerns |
rbpf-oracle | Offline reference/testing engine, not a production validator fallback |
bench-skip-verify, bench-preload | Benchmark-only bypasses; exclude from operational artifacts |
gpu-evm, gevm-only | Legacy/placeholder paths, not the canonical EVM deployment configuration |
The default features are cuda,mimalloc,cuevm. Specify the intended set explicitly for a release candidate so a changed default cannot silently alter the artifact. Enabling the one-book CUDA dependency does not establish installed Bombil dispatch; see Bombil. Cargo features, toolchain.
A CPU development build is:
cd runtime
../scripts/eto-build cargo build --no-default-features --bin svm-vmThe shared-host build wrapper serializes heavy work with a lock and defaults to 12 jobs. ETO_BUILD_JOBS adjusts its cap. The interactive and immutable classes control incremental compilation and cache behavior; use the class appropriate to the existing build workflow. A successful CPU build does not produce a CPU sequencer capable of production SBF execution. Build wrapper, role-specific GPU startup.
No Cargo build was run for this documentation generation.
Provision CuEVM before building an EVM-capable candidate
The native target is libcuevm_state.so, built from runtime/deps/gevm/CuEVM with BUILD_STATE_LIBRARY. A deployment build needs the appropriate CUDA toolchain, driver, device architecture, and native dependencies. Set CUEVM_LIB_DIR to the actual output directory.
The Rust FFI build script does not fail when that library is absent: it compiles an unavailable-engine stub. This is why a successful Cargo exit alone cannot establish EVM capability. Its defaults include the machine-specific historical library path /home/naman/CuEVM/build_state and CUDA library directory /usr/local/cuda/lib64; explicitly set the library path on other machines. Native link behavior.
With the native library provisioned, the source release build is:
cd runtime
../scripts/eto-build cargo build --release --no-default-features \
--features cuda,mimalloc,cuevm --bin svm-vmThe testnet launcher additionally checks the CuEVM-only artifact marker, dynamic linkage to libcuevm_state.so, and unresolved dependencies before starting nodes. Its LD_LIBRARY_PATH and shared-device settings make the native library visible to launched processes. Those are artifact checks; an execution acceptance case is still needed to prove the engine can commit a transaction. Launcher checks.
The production node runs hardware/JIT and chain-owned BPFCC adapter self-tests before installing its SBF executor. A read-only role explicitly skips these tests because it applies diffs rather than re-executing SBF. Startup self-tests.
Supply a persistent identity and explicit paths
The node accepts:
| Option | Meaning and default |
|---|---|
--config, -c | Consensus TOML path; absent means ephemeral single-node defaults |
--genesis, -g | Genesis JSON path; default genesis.json |
--data-dir, -d | State directory; default /tmp/svm-node-<listen-port> |
--check-config | Validate the allowlisted startup configuration and exit |
--print-effective-config | Print nonsecret startup JSON and exit |
--help, -h | Usage |
--version, -V | Build identity |
Unknown options and missing option values fail with exit 2. A TOML load failure exits 1; snapshot validation failure exits 2. Argument parser, configuration entry.
Persistent configurations use private_key_path. The former private_key_seed field is rejected. The file is operator-supplied identity material, not a public numeric seed from which peers derive keys. Use the repository key-generation workflow in a protected deployment directory and keep key files out of version control.
TOML roles are exactly sequencer, validator, and readonly. Without a config file, a new identity is generated for the process; restarting that convenience mode does not preserve membership identity. Consensus configuration loader.
For an already provisioned deployment, the command shape is:
runtime/target/release/svm-vm \
--config /etc/eto/consensus.toml \
--genesis /etc/eto/genesis.json \
--data-dir /var/lib/etoThese paths are an operator template, not files created by this documentation run. Provision the matching genesis, identity, membership, bridge policy, native libraries, and writable state directory before launching.
Check configuration without starting services
Run the same binary, config, genesis path, data path, and environment intended for the service, adding --check-config or --print-effective-config. These modes return before opening chain state, contacting peers, or initializing GPU services.
For an already provisioned configuration, from the repository root:
runtime/target/release/svm-vm --config /etc/eto/consensus.toml \
--genesis /etc/eto/genesis.json --data-dir /var/lib/eto --check-config
runtime/target/release/svm-vm --config /etc/eto/consensus.toml \
--genesis /etc/eto/genesis.json --data-dir /var/lib/eto --print-effective-configUse your actual artifact and paths. Require exit 0 and retain the JSON from the second command. If validation fails, correct the reported configuration error before starting the service; the exit codes above distinguish argument and configuration failures.
The output is an allowlist with a schema version, optional revision label, consensusSha256, nodeSha256, and typed effective fields. It intentionally excludes secret keys, secret hashes, credential-bearing oracle/bridge URLs, and recovered membership/epoch. A revision label is descriptive; compare digests with an independently approved configuration bundle.
A valid result does not check genesis contents, disk recovery, secret-provider availability, or GPU readiness. A TOML-backed run still needs to read its configured identity. Snapshot contract, early exit.
This run executed all four safe inspection modes against the existing debug binary: help, version, config check, and effective-config print. Each exited 0. That binary identified itself as runtime 1.0.0, debug, no Cargo features, Git 57e7c8631db8aba656b7a797c44180dc4d864814. It is a different artifact from the inspected checkout and the public node. The config check used ephemeral defaults and explicitly excluded state/genesis/GPU readiness. A fresh-directory repeat at 01:59 UTC on 8 September 2026 confirmed version, config check and effective-config print all exit 0 for the same debug artifact; it did not validate a provisioned deployment bundle.
Understand precedence and the validation boundary
Configuration is not one universal flat environment map. CLI chooses file and state paths. TOML supplies consensus identity, role, participants, and base settings. The startup snapshot then resolves an explicit set of environment overrides once.
| Override | Default or rule in the snapshot |
|---|---|
ETO_CONSENSUS | TOML engine unless explicitly overridden; supported engine parser applies |
SIMPLEX_LEADER_TIMEOUT_MS | TOML timeout; must exceed batch fill |
SIMPLEX_NOTARIZATION_TIMEOUT_MS | TOML timeout; must be positive |
SVM_BATCH_FILL_MS | 200 ms |
ETO_RPC_PORT | 8899 |
ETO_RPC_BIND | 127.0.0.1; malformed snapshot input is rejected |
ETO_METRICS_PORT | 9090 |
TURBO_BASE_PORT | 19000 for RPC forwarding; listener setup is a separate subsystem |
SVM_MEMPOOL_SIZE | 8,000,000; must be positive |
SVM_MEMPOOL_GPU_VERIFY | Zero/off by default; nonzero forces the policy |
SVM_MEMPOOL_GPU_DEVICE | Requested index defaults to 1; the current verifier backend has a device-zero implementation gap |
ETO_CONFIG_REVISION | Optional 1–128-character restricted label |
The snapshot validates port ranges and selected timing constraints, then installs one immutable object. It does not claim to cover every environment variable read by every subsystem. Separate bridge, HILSA, oracle, ingest, storage, and WebSocket controls require their own inspection. Resolution and validation.
Treat settings that change accepted transactions, execution results, genesis, protocol format, or membership as coordinated changes. Timing and networking changes may preserve state semantics but still break quorum progress. Ports and local capacity can often change per node after checking resource and routing dependencies. Benchmark bypasses are not operational tuning.
The standard-library fleet inventory checker compares independently approved configuration/binary digests with observed installed and running identities. Its focused test_eto_config.py suite passed 17 tests in this run. That verifies fixture behavior of the audit logic, not the actual fleet's configuration. Audit implementation, behavior tests.
Start a disposable three-node testnet
On a suitable CUDA host with the native library available:
./testnet/run.sh buildThis script builds the exact CUDA/CuEVM feature set, checks the artifact, generates local identities/configurations, and starts one sequencer plus two validators. If the binary is already built and validated, ./testnet/run.sh uses it.
The script removes /tmp/svm-node-1, /tmp/svm-node-2, and /tmp/svm-node-3 and generates fresh testnet keys. It is a disposable-network launcher, not a restart command for state you intend to preserve. On a shared build host, prebuild through scripts/eto-build rather than launching a second unqueued Cargo build. Testnet lifecycle.
The launcher derives local bridge validator/guardian configuration and signing seeds. Those bootstrap values do not prove external vaults, deposit gossip, HILSA feeds, or withdrawal delivery are active. Asset bridging owns those integration conditions.
After startup, verify the intended role, build identity, effective configuration, progressing height, healthy persistence drain, and a small transaction's actual receipt. An HTTP listener or successful version call alone is insufficient. Continue with deployment and upgrades for replacing a persistent node and observability and recovery for diagnosing startup or durability failures.