Node Setup

This section will guide you through how to setup a Story node. Story draws inspiration from ETH PoS in decoupling execution and consensus clients. The execution client story-geth relays EVM blocks into theΒ storyΒ consensus client via Engine ABI, using an ABCI++ adapter to make EVM state compatible with that of CometBFT. With this architecture, consensus efficiency is no longer bottlenecked by execution transaction throughput.

The story and geth binaries, which make up the clients required for running Story nodes, are available from our latest release pages:

Please download the binary matching your system architecture

System Specs

HardwareRequirement
CPU4 Cores
RAM16 GB
Disk200 GB
Bandwidth25 MBit/s

On AWS, we recommend using the M6i, R6i, or C6i series.

Ports

Ensure all ports needed for your node functionality are needed, described below

  • story-geth
    • 8545
      • Required if you want your node to interface via JSON-RPC API over HTTP
    • 8546
      • Required for websockets interaction
    • 30303 (TCP + API)
      • MUST be open for p2p communication
  • story
    • 26656
      • MUST be open for consensus p2p communication
    • 26657
      • Required if you want your node interfacing for Tendermint RPC
    • 26660
      • Needed if you want to expose prometheus metrics

Default Folder

By default, we setup the following default data folders for consensus and execution clients:

  • Mac OS X
    • story data root: ~/Library/Story/story
    • story-geth data root: ~/Library/Story/geth
  • Linux
    • story data root: ~/.story/story
    • story-geth data root: ~/.story/geth

For the remainder of this tutorial, we will refer to the story data root as ${STORY_DATA_ROOT} and the geth data root as ${GETH_DATA_ROOT}.

You are able to override these configs on the story client side by passing --home ${STORY_CONFIG_FOLDER}. Similarly, for geth, you may use --config ${GETH_CONFIG_FOLDER}. For information on how overrides work, view our readme on setting up a private network.

Execution Client Setup (story-geth)

  1. (Mac OS X only) The OS X binaries have yet to be signed by our build process, so you may need to unquarantine them manually:

    sudo xattr -rd com.apple.quarantine ./geth
    
  2. You may now run geth with the following command:

    ./geth --odyssey --syncmode full
    
    • Currently, snap sync mode, the default, is still undergoing development

Clear State

If you ever run into issues and would like to try joining the network from a cleared state, run the following:

rm -rf ${GETH_DATA_ROOT} && ./geth --odyssey --syncmode full
  • Mac OS X: rm -rf ~/Library/Story/geth/* && ./geth --odyssey --syncmode full
  • Linux: rm -rf ~/.story/geth/* && ./geth --odyssey --syncmode full

Debugging

If you would like to check the status of geth while it is running, it is helpful to communicate via its built-in IPC-RPC server by running the following:

geth attach ${GETH_DATA_ROOT}/geth.ipc
  • Mac OS X:
    • geth attach ~/Library/Story/geth/odyssey/geth.ipc
  • Linux:
    • geth attach ~/.story/geth/odyssey/geth.ipc

This will connect you to the IPC server from which you can run some helpful queries:

  • eth.blockNumber will print out the latest block geth is sync’d to - if this is undefined there is likely a peer connection or syncing issue
  • admin.peers will print out a list of other geth nodes your client is connected to - if this is blank there is a peer connectivity issue
  • eth.syncing will return true if geth is in the process of syncing, false otherwise

Consensus Client Setup (story)

  1. (Mac OS X Only) The OS X binaries have yet to be signed by our build process, so you may need to unquarantine them manually:

    sudo xattr -rd com.apple.quarantine ./story
    
  2. Initialize the story client with the following command:

    ./story init --network odyssey 
    
    • By default, this uses your username for the moniker (the human-readable identifier for your node), you may override this by passing in --moniker ${NODE_MONIKER}
    • If you would like to initialize the node using your own data directory, you can pass in --home ${STORY_DATA_DIR}
    • If you already have config and data files, and would like to re-initialize from scratch, you can add the --clean flag
  3. Now, you may run story with the following command:

    ./story run
    

Note: currently you might see a bunch of Stopping peer for error logs - this is a known issue around peer connection stability with our bootnodes that we are currently fixing - for now please ignore it and rest assured that it does not impact block progression.

If you ever run into issues and would like to try re-joining the network WHILE PRESERVING YOUR KEY, run the following:

rm -rf ${STORY_DATA_ROOT}/data/* && \
echo '{"height": "0", "round": 0, "step": 0}' > ${STORY_DATA_ROOT}/data/priv_validator_state.json && \
./story run
  • Mac OS X:
    rm -rf ~/Library/Story/story/data/* && \
    echo '{"height": "0", "round": 0, "step": 0}' > ~/Library/Story/story/data/priv_validator_state.json && \
    ./story run
    
  • Linux:
    rm -rf ~/.story/story/data/* && \
    echo '{"height": "0", "round": 0, "step": 0}' > ~/.story/story/data/priv_validator_state.json && \
    ./story run
    

*If you ever run into issues and would like to try joining the network from a COMPLETELY fresh state, run the following (*WARNING: THIS WILL DELETE YOUR priv_validator_key.json FILE )

rm -rf ${STORY_DATA_ROOT} && ./story init --network odyssey && ./story run
  • Mac OS X:
    • rm -rf ~/Library/Story/story/* && ./story init --network odyssey && ./story run
  • Linux:
    • rm -rf ~/.story/story/* && ./story init --network odyssey && ./story run

To quickly check if the node is syncing, you could

  • Check the geth RPC endpoint to see if blocks are increasing:
    curl -X POST -H "Content-Type: application/json" --data '{"jsonrpc":"2.0","method":"eth_blockNumber","params":[],"id":1}' [http://localhost:8545](http://localhost:8545/)
    
  • Attach to geth as explained above and see if the eth.blockNumber is increasing

Clear State

If you ever run into issues and would like to try joining the network from a fresh state, run the following:

rm -rf ${STORY_DATA_ROOT} && ./story init --network odyssey && ./story run
  • Mac OS X:
    • rm -rf ~/Library/Story/story/* && ./story init --network odyssey && ./story run
  • Linux:
    • rm -rf ~/.story/story/* && ./story init --network odyssey && ./story run

To quickly check if the node is syncing, you could

  • Check the geth RPC endpoint to see if blocks are increasing:
    curl -X POST -H "Content-Type: application/json" --data '{"jsonrpc":"2.0","method":"eth_blockNumber","params":[],"id":1}' [http://localhost:8545](http://localhost:8545/)
    
  • Attach to geth as explained above and see if the eth.blockNumber is increasing

Custom Configuration

To override your own node settings, you can do the following:

  • ${STORY_DATA_ROOT}/config/config.toml can be modified to change network and consensus settings
  • ${STORY_DATA_ROOT}/config/story.toml to update various client configs
  • ${STORY_DATA_ROOT}/priv_validator_key.json is a sensitive file containing your validator key, but may be replaced with your own

Custom Automation

Below we list a sample Systemd configuration you may use on Linux

# geth
[Unit]
Description=Node-Geth
After=network.target

[Service]
Type=simple
Restart=always
RestartSec=1
User=${USER_NAME}
WorkingDirectory=${YOUR_HOME_DIR}
ExecStart=geth --odyssey  --syncmode full
StandardOutput=journal
StandardError=journal
SyslogIdentifier=node-geth
StartLimitInterval=0
LimitNOFILE=65536
LimitNPROC=65536

[Install]
WantedBy=multi-user.target
# story
[Unit]
Description=Node-story
After=network.target node-geth.service

[Service]
Type=simple
Restart=always
RestartSec=1
User=ec2-user
WorkingDirectory=${YOUR_HOME_DIR}
ExecStart=story run
StandardOutput=journal
StandardError=journal
SyslogIdentifier=node-story
StartLimitInterval=0
LimitNOFILE=65536
LimitNPROC=65536

[Install]
WantedBy=multi-user.target

Debugging

If you would like to check the status of story while it is running, it is helpful to query its internal JSONRPC/HTTP endpoint. Here are a few helpful commands to run:

  • curl localhost:26657/net_info | jq '.result.peers[].node_info.moniker'
    • This will give you a list of consesus peers the node is sync’d with by moniker
  • curl localhost:26657/health
    • This will let you know if the node is healthy - {} indicates it is

Common Issues

  1. auth failure: secret conn failed: read tcp ${IP_A}:${PORT_A}->${IP_B}:{PORT_B}: i/o timeout
    • This issue occurs when the default external_address listed in config.toml (””) is not being introspected properly via the listener. To fix it, please remove addrbook.json in {STORY_DATA_ROOT}/config/addrbook.json and add exteral_address = {YOUR_NODE_PUBLIC_IP_ADDRESS} in config.toml

Automated Upgrades

To manage consensus client upgrades more easily, especially for hard forks, we recommend using Cosmovisor, which allows you to automate the process of upgrading client binaries without having to restart your client.

To get started, your client must be upgraded to at least version 0.9.13. Here is a guide to help you with the setup of automated upgrades with Cosmovisor.