SingularityDocs
Run a node

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 featureOperational meaning
cudaCUDA execution/acceleration, including the SBF production path and one-book dependency
cuevmCanonical CuEVM integration; native library must also be present
mimallocAllocator choice
qmdb-cudaSeparate experimental state-root path with recovery compatibility concerns
rbpf-oracleOffline reference/testing engine, not a production validator fallback
bench-skip-verify, bench-preloadBenchmark-only bypasses; exclude from operational artifacts
gpu-evm, gevm-onlyLegacy/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-vm

The 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-vm

The 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:

OptionMeaning and default
--config, -cConsensus TOML path; absent means ephemeral single-node defaults
--genesis, -gGenesis JSON path; default genesis.json
--data-dir, -dState directory; default /tmp/svm-node-<listen-port>
--check-configValidate the allowlisted startup configuration and exit
--print-effective-configPrint nonsecret startup JSON and exit
--help, -hUsage
--version, -VBuild 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/eto

These 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-config

Use 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.

OverrideDefault or rule in the snapshot
ETO_CONSENSUSTOML engine unless explicitly overridden; supported engine parser applies
SIMPLEX_LEADER_TIMEOUT_MSTOML timeout; must exceed batch fill
SIMPLEX_NOTARIZATION_TIMEOUT_MSTOML timeout; must be positive
SVM_BATCH_FILL_MS200 ms
ETO_RPC_PORT8899
ETO_RPC_BIND127.0.0.1; malformed snapshot input is rejected
ETO_METRICS_PORT9090
TURBO_BASE_PORT19000 for RPC forwarding; listener setup is a separate subsystem
SVM_MEMPOOL_SIZE8,000,000; must be positive
SVM_MEMPOOL_GPU_VERIFYZero/off by default; nonzero forces the policy
SVM_MEMPOOL_GPU_DEVICERequested index defaults to 1; the current verifier backend has a device-zero implementation gap
ETO_CONFIG_REVISIONOptional 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 build

This 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.

Updated Sep 8, 2026View source

On this page