Skip to main content

Purpose and Scope

This document explains the procedure for deploying a private StableNet network from scratch.
It covers the initial network setup phase, including genesis file generation, nodekey management, and bootnode configuration.
Deployment is performed by building from source in the StableNet repository. Required binaries such as gstable, bootnode, and genesis_generator are built via the Makefile or build/ci.go. For detailed instructions, refer to Installation and Building. The following topics are out of scope for this document and are covered elsewhere:

Generating a Genesis File with genesis_generator

genesis_generator is a dedicated CLI tool for genesis creation provided to initialize a StableNet network.
It generates a genesis file and a base configuration file tailored to the selected consensus engine, validator setup, and network topology.

Tool Overview

genesis_generator automatically performs the following tasks:
  • Extracts validator information from nodekeys
  • Generates a genesis structure compatible with the consensus engine
  • Computes the initial validator set and quorum
  • Generates genesis.json and config.toml

Single-Node Network Configuration

For development and testing purposes, a single-node network configuration can be generated.
This setup is intended only for network initialization and functional validation and is not suitable for real deployments or production environments.
Process Flow:
  1. Load nodekey
    • Input the nodekey file path
    • Default path: ./nodekey
  2. Derive validator keys
    • Derive the following from the nodekey (ECDSA private key):
      • Validator account address
      • BLS public key for QBFT consensus
  3. Automatically configure validator set
    • Number of validators: 1
    • Quorum: 1
  4. Generate genesis.json
    • Register the single validator in the validator set
    • Allocate an initial balance to the validator account
    • Apply the selected consensus engine configuration
  5. Generate config.toml
    • StaticNodes is generated as an empty list
    • Includes only the minimum settings required to run a single node

Generated Artifacts

  • genesis.json
    Contains network ID, consensus configuration, validator information, and initial state
  • config.toml
    Base configuration file for node execution (StaticNodes is an empty array in single-node mode)

Multi-Node Network Configuration

For development, testing, or production networks, a multi-node network configuration can be generated.
This setup supports validator sets with governance quorum and collects validator, quorum, and static node information interactively.
Process Flow:
  1. Input validators
    • Enter validator addresses and their corresponding BLS public keys (empty input terminates)
    • For each validator, a BLS public key is requested (0x-prefixed, 96 hex characters)
  2. Configure quorum
    • Enter the governance quorum value
    • Minimum: 2, Maximum: number of validators
  3. Static nodes
    • Optionally input enode URLs to populate config.toml
    • If skipped, static nodes must be managed manually
  4. Generate genesis.json
    • Apply Anzeon configuration using the provided validators, BLS keys, and quorum
    • System contract parameters are set via setAnzeonConfig()
  5. Save
    • Specify output paths and generate the genesis and configuration files

Generated Artifacts

  • genesis.json
    Includes network ID, consensus configuration, validator list, BLS public keys, quorum, and system contract parameters (e.g., GovValidator)
  • config.toml
    Base configuration file for node execution
    (StaticNodes populated with provided enode URLs if selected, otherwise an empty array)

Nodekey Generation and Management

Before deploying validators, each node requires a unique nodekey used for multiple purposes.

Data Derived from a Nodekey

Each node’s nodekey (ECDSA private key) is used to derive the validator address (block signing / coinbase) and the BLS key pair (consensus signing).
This derivation is used by genesis_generator (deriveAccount()), bootnode, and node networking configuration (static nodes, enode URLs, etc.).

Generating a Nodekey

The bootnode utility can be used to generate a nodekey and inspect its public key (for enode URLs). Common flags include:
FlagDescription
-genkeyGenerate a nodekey and store it in the specified file
-nodekeySpecify the private key file path
-writeaddressPrint the node public key and exit (used for enode URL construction)
# Generate a nodekey (stored in the specified file)
bootnode -genkey nodekey

# Print the public key from an existing key (used in enode URLs)
bootnode -nodekey nodekey -writeaddress

Network Initialization Workflow

Genesis Initialization Process

  1. Generate genesis and config: Use genesis_generator to create genesis.json (and optionally config.toml)
  2. Distribute files: Copy the same genesis.json to the intended data directory location on every node
  3. Initialize data directories: Run gstable init on each node to write the genesis block, then start the node using that directory
init overwrites existing data, so the target directory must not contain an active chain.
For Anzeon genesis files, consensus and system contract settings are validated during initialization.

Initialization Command

gstable init accepts a single argument: the path to the genesis file.
The data directory is specified with --datadir.
gstable --datadir /path/to/datadir init /path/to/genesis.json
  • --datadir: Data directory to initialize (defaults if omitted)
  • <genesisPath>: Path to the genesis.json file
When running the node, use the same --datadir, and specify --networkid to match config.chainId in the genesis file.

Network Presets (—mainnet, —testnet)

When joining an already configured public StableNet network, network preset flags can be used.
These presets include built-in genesis and bootnodes, allowing nodes to run without a custom genesis.json.
FlagDescriptionNetwork IDUse Case
--mainnetStableNet mainnet8282Connect to StableNet mainnet
--testnetStableNet testnet8283Connect to the preconfigured StableNet test network
  • These flags are mutually exclusive.
  • When using --mainnet or --testnet, the corresponding genesis and bootnode list are applied automatically, and the default network ID is used unless overridden.
Example: running a StableNet testnet node
gstable --testnet --datadir /path/to/datadir

Bootnode Configuration and Peer Connectivity

Static Node Configuration

Static nodes are peers that a node attempts to connect to on startup.
They are defined in the [Node.P2P] section of config.toml generated by genesis_generator.
  • Single-node: StaticNodes is generated as an empty array ([])
  • Multi-node: When enode URLs are provided interactively, StaticNodes is populated accordingly, simplifying peer connectivity among validator nodes
Example config.toml for a multi-node setup:
[Node.P2P]
StaticNodes = [
  "enode://<128_hex_public_key>@<IP>:<port>",
  "enode://<128_hex_public_key>@<IP>:<port>"
]

Enode URL Structure

An enode URL uniquely identifies a node in the P2P network and is used for static nodes and bootnodes. Format: enode://<public_key_128_hex>@<host>:<port>
  • Public key: 64-byte ECDSA public key encoded as 128 hex characters
  • Host and port: IP address (or hostname) and listening port
genesis_generator.validateEnodeURL() verifies that each enode URL satisfies:
  1. Starts with the enode:// prefix
  2. Public key is exactly 128 hexadecimal characters
  3. Host is a valid IPv4 or IPv6 address
  4. Port is an integer in the range 1–65535

Deploying a Bootnode for Peer Discovery

For production networks, it is recommended to deploy a dedicated bootnode to facilitate peer discovery.
A bootnode provides discovery services only and does not maintain the full chain.
1. Key generation and execution
# Generate a bootnode key
bootnode -genkey boot.key

# Run the bootnode (configure listen address, network restriction, log level)
bootnode \
    -nodekey boot.key \
    -addr :30303 \
    -netrestrict 0.0.0.0/0 \
    -verbosity 3

# Print the public key (for constructing the enode URL)
bootnode -nodekey boot.key -writeaddress
2. Client usage When running each node, include the bootnode enode URL via -bootnodes to enable peer discovery.
gstable -bootnodes enode://<public_key>@<bootnode-IP>:30303 -datadir /path/to/datadir

Production Network Deployment Checklist

Pre-Deployment Preparation

TaskDetailsVerification
Generate nodekeysUse bootnode -genkey, one per validatorVerify derived addresses and BLS keys
Create genesis fileUse genesis_generator with all validator addresses and BLS keysValidate JSON structure and quorum
Configure static nodesBuild config.toml with all validator enode URLsTest enode connectivity
Set chain parametersChoose a unique chainId, gas limits, system contractsReview gas tip policy, mint/burn quorum
Pre-fund accountsAllocate initial balances in genesis allocVerify total supply matches expectations

Initialization Sequence

  1. Copy the same genesis.json to all nodes
  2. Run gstable -datadir <path> init <genesis.json path> on each node
  3. Start each node with
    gstable -datadir <path> -networkid <chainId> (and -bootnodes, -config if needed)
Common runtime flags:
FlagDescription
-datadirData directory (must match initialization)
-networkidMust match the genesis chainId
-bootnodesBootnode enode URLs (comma-separated)
-configPath to config.toml (static nodes, etc.)

Post-Deployment Verification

After nodes are running, verify the following:
  1. Peer count: Attach via gstable attach and check admin.peers.length
  2. Consensus: Monitor block production and finalization
  3. Transactions: Send test transactions and verify propagation and execution
  4. Gas tip: Confirm that the governance-defined gas tip is enforced
  5. System contracts: Call GovValidator.getValidators() and verify the validator set matches genesis

System Contract Deployment Verification

After network initialization, you can verify that system contracts defined in the genesis file were deployed correctly.
During genesis application, GetSystemContractsTransition() is invoked to install contract code and initialize storage using genesis parameters.
By querying code and storage at system contract addresses via RPC, you can confirm successful deployment.