Getting Started

System Requirements

Before setting up an ENI node, ensure your system meets the following minimum requirements:

Hardware Specifications

Component
Minimum Requirement
Recommended Configuration
Notes

CPU

8 cores

16 cores

Modern processor (Intel Xeon/Core i7/i9 or AMD Epyc/Ryzen)

Memory

32GB

64GB

DDR4 or higher

Storage

1TB NVMe SSD

2TB NVMe SSD

High IOPS required; SATA SSD not recommended

Network

1Gbps

2Gbps

Low-latency connection is critical

Basic System Setup

Start with a fresh installation of Debian 12, Ubuntu 20.04 LTS (or higher). Then, update the system and install the necessary packages:

sudo apt update && sudo apt upgrade -y
sudo apt install make gcc git jq chrony curl lz4 wget tar build-essential -y

Tip: Ensure your system clock is synchronized (via chrony or ntpd) and your timezone is set to UTC to avoid potential issues with block validation, IBC transfers, etc.


Rapid deployment

Eni has a default configuration of four nodes for single-machine deployment, which can be used for rapid deployment and startup of the eni chain. If implementing commercialized deployment, please skip rapid deployment and start with custom deployment or automated setup scripts below.

Download the source code

git clone

Clone the go-eni project code from the eni code repository using the git tool.

git clone https://github.com/eni-chain/go-eni.git

One-click deployment

After downloading the code, enter the project directory go-eni. Then execute the following command to deploy and start a four-node eni blockchain on one machine with one click.

cd go-eni
 
git checkout main

make start4-node

The make start-4-node command will automatically perform the following operations:

  • Compile the go-eni project code, create the go-eni/build directory, and place the generated eni executable file in the go-eni/build directory.

  • Read node1~ node4 in the default configuration directory of go-eni/eni-nodes, and start the four nodes node1~ node4 according to the default configuration.

After the command execution is completed, if the following information is printed, it indicates that the chain compile deployment has started successfully.

Starting 4 eni nodes...
nohup ./build/enid start --home=./eni-nodes/node1 &> ./build/node1.log &
nohup ./build/enid start --home=./eni-nodes/node2 &> ./build/node2.log &
nohup ./build/enid start --home=./eni-nodes/node3 &> ./build/node3.log &
nohup ./build/enid start --home=./eni-nodes/node4 &> ./build/node4.log &
Done starting 4 eni nodes.

After startup, the log files of the node will be printed in the go-eni/build directory in real time. You can enter go-eni/build to view the log files of node1~ node4 and observe the operation of the chain and node.

% cd build
% ls
enid        node1.log        node2.log        node3.log        node4.log
% tail -f node1.log 
6:27PM INF Time Commit end time=2025-04-17T18:27:48+08:00 module=server spend time=0
6:27PM INF Update fastMempool end block height=86 elapsedTime=0 module=mempool start time="Apr 17 18:27:48.572351" tx len=0
6:27PM INF committed state block_app_hash=FEADB503B8F5AA1D92C2E7D78DB10BD2F452ABD9E1EC1407E0937EC81C12A457 elapsed time=18826 height=86 module=state time now="Apr 17 18:27:48.572384"
6:27PM INF finalized block execute time elapsed=0.36 function elapsed =93.148 height=86 module=state time now="Apr 17 18:27:48.609816"
......

One-click close

Execute the following command to shut down the service with one click.

# return the upper directory "go-eni" from "build"
cd ..
# stop 4 node
make stop4-node

After the command is executed, if the following information is printed, it indicates that the service has been successfully shut down.

Stopping 4 eni nodes...
Done stopping 4 eni nodes.

After the service is shut down, it can be restarted by using the one-click deployment command make Start4-node. After startup, the chain still runs based on the last data. For example, if it was shut down when the block height was 88 last time, after this startup, the block height will start from 88.If you want to restart a chain from scratch, you need to clear the data from the last run and redeploy it with one click.

# clear the node data
make reset-multi-node

# build and start 4 node
make start4-node

Custom Deployment

If developers are not satisfied with rapid deployment based on default configuration and default Port Number, they can generate custom configurations and specify port deployment to start a chain.

Download the source code

git clone

Clone the go-eni project code from the eni code repository using the git tool.

git clone https://github.com/eni-chain/go-eni.git

Configuration generation

Enter the go-eni project directory and execute the following command to generate a custom configuration for the four nodes. The information such as the founder account and validator account in the configuration will be randomly generated. Because the default configuration already exists in the go-eni/eni-nodes directory, it is necessary to delete the default configuration directory before executing the custom configuration command.

cd go-eni

make build
 
#delete default config for 4 node
rm -rf eni-nodes  

# Generate custom configuration. The current script supports 3 parameters.
# -1. Number of consensus nodes created (default 4);
# -2. Number of Staking accounts (default 4), which requires that the number of staking accounts must be greater than the number of consensus nodes;
# -3. Whether it is a single-machine deployment script (default true).
# Generate the multi-machine deployment configuration. After the configuration is generated, the persistent_peers ip of config.yaml needs to be modified manually. For details, please refer to the configuration Settings below
./generate_nodefile.sh 4 4 false

# Node peer id query command. Different configuration directories need to be specified on different nodes. For example, node2 needs to specify --home=./eni-nodes/node2
./build/enid comet show-node-id --home=./eni-nodes/node1

After the command is executed, a new custom configuration will be generated in the go-eni/eni-nodes directory, as shown in the following figure.

Here we need to focus on three documents:

  • node_key is the private key we use for network communication.

  • priv_validator_key is the private key used during the consensus period.

  • Keyring-test/validator1.info is the key file for collecting gas fee and block reward (there is no key by default, you can export the private key by the following command:

echo y | ./enid keys export validator1 --unarmored-hex --unsafe --home ../eni-nodes/node1
897c2fc636602de4e1ca89409ebd006edb927ec8bfa5aabd26ec94e51c0bd4d1

Configuration settings

After the custom configuration is generated, some configuration fields can be modified according to one's own needs.

app.toml configuration

The automatically generated app.toml file is missing EniDB Configuration and evm Configuration, so we need to manually append its content to the end of the app.toml file.

cat >> eni-nodes/node1/config/app.toml <<EOF
#############################################################################
###                             EniDB Configuration                       ###
#############################################################################

[state-commit]
# Enable defines if the state-commit (memiavl) should be enabled to override existing IAVL db backend.
sc-enable = true

# ZeroCopy defines if memiavl should return slices pointing to mmap-ed buffers directly (zero-copy),
# the zero-copied slices must not be retained beyond current block's execution.
# the sdk address cache will be disabled if zero-copy is enabled.
sc-zero-copy = false

# AsyncCommitBuffer defines the size of asynchronous commit queue, this greatly improve block catching-up
# performance, <=0 means synchronous commit.
sc-async-commit-buffer = 100

# SnapshotKeepRecent defines how many state-commit snapshots (besides the latest one) to keep
# defaults to 1 to make sure ibc relayers work.
sc-keep-recent = 1

# SnapshotInterval defines the block interval the snapshot is taken, default to 10000 blocks.
sc-snapshot-interval = 1000

# SnapshotWriterLimit defines the max concurrency for taking commit store snapshot
sc-snapshot-writer-limit = 2

# CacheSize defines the size of the LRU cache for each store on top of the tree, default to 100000.
sc-cache-size = 1000

[state-store]

# Enable defines if the state-store should be enabled for historical queries.
# In order to use state-store, you need to make sure to enable state-commit at the same time
ss-enable = true

# DBBackend defines the backend database used for state-store.
# Supported backends: pebbledb, rocksdb, sqlite
# defaults to pebbledb (recommended)
ss-backend = "leveldb"

# 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
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 0
ss-keep-recent = 10000

# PruneIntervalSeconds defines the minimum interval in seconds + some random delay to trigger pruning.
# It is more efficient to trigger pruning less frequently with large interval.
# default to 600 seconds
ss-prune-interval = 60

# ImportNumWorkers defines the concurrency for state sync import
# defaults to 1
ss-import-num-workers = 1

[evm]
http_enabled = true
http_port = 8545
ws_enabled = true
ws_port = 8546
EOF

In the configuration of app.toml, the commonly used configuration item modifications are mainly the various fields under the state-store module and the evm module. Other fields generally use default values.

  • State-store module:

    • The ss-backend field specifies the database type. The optional database types can be found in the configuration comments. However, in daily life, the main choice is between leveldb and pebbledb. It is recommended that consensus nodes choose leveldb, which does not store historical data and can ensure higher consensus efficiency. It is recommended to choose pebbledb for synchronization nodes. For details, please refer to the appendix

  • EVM module:

    • http_enabled: whether the http service is enabled;

    • http_port: http Port Number, if it is a single deployment of multiple nodes, to avoid port conflicts, each node must be configured to different values.

    • ws_enabled: whether the websocket service is enabled;

    • ws_port: websocket Port Number, if it is a single machine deployment of multiple nodes, to avoid port conflicts, each node must be configured to different values.

[state-store]
# Enable defines if the state-store should be enabled for historical queries.
# In order to use state-store, you need to make sure to enable state-commit at the same time
ss-enable = true

# DBBackend defines the backend database used for state-store.
# Supported backends: pebbledb, rocksdb, sqlite
# defaults to pebbledb (recommended)
ss-backend = "leveldb"

[evm]
http_enabled = true
http_port = 8545
ws_enabled = true
ws_port = 8546

Note: The configuration fields of the above common modification items can be configured to different values for each node according to its own situation, which will not affect the consensus consistency.

Contract administrator configuration

If the chain does not start the dpos mechanism, the consensus node set is the initial value configured by the genutil.gen_txs configuration item in the genesis.json configuration file (see the genesis.json configuration section for details). In the current version, we use the consensus mechanism that does not start the dpos, which has met the needs during the x play period.

However, for chain security, we still need to pay attention to the setting of the dpos administrator address to ensure that the key pair corresponding to the administrator address is managed by the official.Administrator privileges are crucial for the DPOS mechanism and consensus system. Therefore, if it is a custom-deployed chain, the default administrator address needs to be modified. The system contract of the DPOS series has a default administrator who is used to do some chain management work, including:

  • Set the initialization random value seed: In the DPOS mechanism, multiple block generation intervals can be set to one epoch period. Within each epoch period, the validator needs to send random values to the VRF contract of the DPOS for participation in consensus elections. The random values sent in each round are signed by the validator using their own private key for the previous random seed. The initial random value seed is passed in by the system admin, and subsequent random value seeds are generated by adding the random values of this round.

  • Verifier application review: If a user applies to become a verifier, the system admin needs to review the applicant's qualifications. If approved, it can be called a formal verifier participating in consensus election and block generation.

  • Verifier withdrawal: If a verifier requests to withdraw, the system admin also needs to pass the review to avoid a large number of verifiers suddenly withdrawing, exceeding the maximum consensus fault tolerance rate and causing the chain to fail to reach consensus.

  • System Contract Upgrade: The system contract uses a delegated call mechanism, where the proxy contract calls the logical contract to perform specific system functions. Administrators can deploy new logical contracts, pass in the address of the logical contract to replace the old one, and upgrade the system contract.

  • System admin change: system admin can transfer administrative permissions to other users, and will lose administrative permissions after transfer.

Modify the value of the update.contract_admin_addr field in the go-eni/app.toml configuration file to modify the default contract administrator address. Note that the default contract administrator address must be the same for all nodes on the chain.

[update]
contract_admin_addr = "0x110b6FB6675Fb2a310394ac3a43b23Fc23aB9BC6"

Gas administrator configuration

The gas administrator has the authority to adjust the gas fee coefficients of the chain to adjust the transaction pressure and frequency of the chain, including:

  • base_fee_per_gas

  • maximum_fee_per_gas

  • max_dynamic_base_fee_upward_adjustment

  • max_dynamic_base_fee_downward_adjustment

  • target_gas_used_per_block

Modify the value of the update.gas_admin_addr field in the go-eni/app.toml configuration file to modify the default gas administrator address. Note that the default gas administrator address must be the same for all nodes on the chain, and the address must be of the eni address type.

[update]
gas_admin_addr = "eni1wklu5t7ctecdlfr465lm6ms709xneg0rf45ajt"

Upgrade effective block high configuration

Each time the chain is upgraded, in order to ensure the consistency of the consensus across the network, a unified effective block height must be set for each node to be upgraded before the upgrade. When the block height reaches the effective block height, the upgraded logic will be executed concurrently.

When ENI fixed a bug caused by the consensus node slash mechanism, it had already undergone a mainnet upgrade. If other nodes want to join the ENI mainnet, they must also modify the effective block height to the same value as the mainnet before joining: 1982800. If the blockchain is deployed independently instead of joining the ENI mainnet, this value can be freely set.

Modify the value of the update.slashing_skip_height field in the go-eni/app.toml configuration file to modify the effective block height. Note that all nodes on the value chain must be the same.

[update]
slashing_skip_height = 1982800

config.toml configuration

note: the default configuration is already supported for commercial teams.

In the config.toml configuration file, commonly used configurations include the following fields:

  • Moniker: Node name, each node can be customized according to its own situation.

  • log_level: Log level, logs below the specified value will not be printed, for example, when it is info level, logs of debug and trace levels below info will not be printed.

  • genesis_file: Genesis file directory name.

  • p2p:

    • Laddr: The P2P port of this node, used for P2P communication between nodes. If deploying multiple nodes on a single machine, to avoid port conflicts, each node must be configured with different values.

    • persistent_peers: This node continues to link to the end node address and p2p port, similar to the seed node. If you create a configuration file to select multiple machines, you need to manually modify the IP here.

  • Mempool (default configuration already meets commercial requirements):

    • Size: The maximum number of transactions that can be stored in the transaction pool. It is recommended to configure the same value between nodes.

    • max_txs_bytes: the maximum total number of bytes of transactions that can be stored in the transaction pool;

    • cache_size: The maximum number of transactions that can be cached in the transaction pool. Cache is generally used for transaction plagiarism detection. The larger the cache, the larger the range of plagiarism detection, but it also consumes more memory.

    • Pending-size: Ethereum-type transactions with discontinuous nonce values will be placed in the pending transaction queue. Pending-size records the maximum value of the pending transaction queue.

    • max-pending-txs-bytes: records the total maximum number of bytes of pending transaction queue cache transactions.

  • Consensus (Consensus Configuration)

    • timeout_commit: Block interval, default is 5s, 1 s is recommended for commercial scenarios

# A custom human readable name for this node
moniker = "node1"

# Output level for logging, including package level options
log_level = "info"

[p2p]

# Address to listen for incoming connections
laddr = "tcp://0.0.0.0:26656"

# Comma separated list of nodes to keep persistent connections to
persistent_peers = "aeae7d4753419b11c958248de72fc8ba26460701@localhost:26656,c816663066d786f89e61c23076a37e0c0c81be7d@localhost:26666,9b6526775a0b81e72b2e1ed9a1ad7c58601618ff@localhost:26676,66594928af8120b4af318125b5d23f5545cf03a7@localhost:26686,"
# Note that for multi-machine deployment, each localhost in each persistent_peers needs to be modified to the ip of the machine where each node is located, for example:
# persistent_peers = "[email protected]:26656,[email protected]:26656,[email protected]:26656,[email protected]:26656,"

[mempool]
# 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

pending-size = 5000

max-pending-txs-bytes = 1073741824

[consensus]
# How long we wait after committing a block, before starting on the new
# height (this gives us a chance to receive some more precommits, even
# though we already have +2/3).
timeout_commit = "5s"

genesis .json configuration

note: the default configuration is already supported for commercial teams

The configuration in genesis .json is a genesis configuration. Each node must be completely consistent, otherwise the chain will not be able to reach consensus at genesis. Generally, an error will be reported after startup, and the block cannot be grown.In the Genesis configuration, focus on whether the following fields need to be modified according to your own situation. It is recommended to use the default configuration values for configurations not mentioned.

  • app_state various configuration items under evm.params:

    • base_fee_per_gas: the base fee in the dynamic gas rate calculation;

    • minimum_fee_per_gas: the minimum value of gas price;

    • maximum_fee_per_gas: the maximum value of gas price;

    • max_dynamic_base_fee_upward_adjustment: the upper limit of the adjustment parameters in the dynamic rate;

    • max_dynamic_base_fee_downward_adjustment: the lower limit of the adjustment parameters in the dynamic rate;

    • init_eni_address: A list of account addresses generated by default at creation;

    • init_eni_amount: When creating, set the initial chain native token value for the default account address, that is, the ueni initial balance of the default account. Note that the assignment order must be the same as the init_eni_address, otherwise it will cause the problem of incorrect initial account balance.

  • Genesis transactions under Genutil.gen_txs body messages (these genesis transactions are transactions where staked tokens become consensus nodes):

    • pubkey.@type: Node public key type of the initial validator at chain startup;

    • Pubkey.key: The public key of the initial validator's node at chain startup. The public key is base64-encoded data used for message signing and verification during the consensus process.

Note: how many body configuration items are under genutil.gen_txs, how many initial validators will there be when the chain starts, and everything in the genesis .json configuration file must be exactly the same for each node in the chain.

{
    ......
    "app_state": {
        ......
        "evm": {
            "params": {
              ......
              "base_fee_per_gas": "0.000000000000000000",
              "minimum_fee_per_gas": "100.000000000000000000",
              "max_dynamic_base_fee_upward_adjustment": "0.018900000000000000",
              "max_dynamic_base_fee_downward_adjustment": "0.003900000000000000",
              "target_gas_used_per_block": "250000",
              "maximum_fee_per_gas": "1000000000000.000000000000000000",
              "init_eni_amount": "100000000000000000000000000,100000000000000000000000000,100000000000000000000000000,100000000000000000000000000",
              "init_eni_address": "3140aedbf686A3150060Cb946893b0598b266f5C,B680152a597c937164941e77cbF4a6b2F866675c,5746036C781851B9eF234219e770E1591104561f,7B6ba0Fe2610BF3c69Fc571C37aeC7bB87A281D2"
            },
        }
    }
    ......
    "genutil": {
        "gen_txs": [
            "body": {
                "messages": [
                    ......
                    "pubkey": {
                        "@type": "/cosmos.crypto.ed25519.PubKey",
                        "key": "oRBlTVa0kOY9+6Wk3tx/8ImsJPjwGkffUzpkREEmAmg="
                    },
                    ....
                ]
            }
            "body": {
                ......
            }
            "body": {
                ......
            }
            "body": {
                ......
            }
        ]
    }
    ......
}

Multi-machine deployment

After the configuration settings are completed, the eni needs to be deployed to different machines, and the machines must be able to communicate normally. Before deployment, package and send the compiled go-eni project to different designated machines.

# exit to the upper directory of go-eni
cd ../

# the path of go-eni needs to be replaced with its your own path
tar -jcv -f eni.tar.bz2 ./go-eni

# send the eni.tar.bz2 package to the designated directory of each machine. The directory needs to be specified as its own directory
scp ./eni.tar.bz2  [email protected]:/path/to/your/dir

# Log in to the directory of each machine and extract the compressed package
tar -jxv -f eni.tar.bz2 -C ./

Start eni on each node. Note that different nodes specify different configuration paths. For example, on node 1, specify./eni-nodes/node1, and on node 2, specify./eni-nodes/node2.

# log in to the go-eni directory of node 1 and execute the following command
% nohup ./build/enid start --home=./eni-nodes/node1  &> ./build/node1.log &

# log in to the go-eni directory of node 2 and execute the following command
% nohup ./build/enid start --home=./eni-nodes/node2  &> ./build/node2.log &

# log in to the go-eni directory of node 3 and execute the following command
% nohup ./build/enid start --home=./eni-nodes/node3  &> ./build/node3.log &

# log in to the go-eni directory of node 4 and execute the following command
% nohup ./build/enid start --home=./eni-nodes/node4  &> ./build/node4.log &

Full Node Deployment

Full nodes are asynchronous nodes that do not participate in the consensus of the chain and only synchronize blocks. If full nodes are not deployed, this chapter process can be skipped.

Copy configuration

Copy a configuration from any consensus node.

cp rf eni-nodes/node4 eni-nodes/node5

Modify config.toml

Modify the identity nickname moniker of the full node to avoid having the same name as other nodes.

moniker = "node5"

Modify app.toml (optional modification, can be skipped)

Modify the database type in app.toml and enable historical data storage.

[state-store]
# DBBackend defines the backend database used for state-store.
# Supported backends: pebbledb, rocksdb, sqlite
# defaults to pebbledb (recommended)
ss-backend = "pebbledb"

ss-keep-last-version = true 

Delete nodes and validator key files

Non-consensus nodes must delete node_key and priv_validator_key files, otherwise they will interfere with consensus. After deletion, full nodes will regenerate their own node_key and priv_validator_key files.

rm -rf eni-nodes/node5/config/node_key.json

rm -rf eni-nodes/node5/config/priv_validator_key.json

Start the full node

After the configuration file is set up, compile the go-eni project and start the full node.

make build

nohup ./build/enid start --home=./eni-nodes/node5 &> ./build/node.log &

Automated setup scripts (development/testing)

In addition to one-click quick deployment and custom deployment, we also provide script automation deployment. This option is ideal when you want to quickly start a node without delving into manual configuration.


git clone https://github.com/eni-chain/go-eni.git
cd go-eni
make build
python3 scripts/run-node.py

This script will guide you to choose:

  • Network: (mainnet, testnet or local)

  • Database backend: (recommended to use eni-db )

  • Basic configuration options


Advanced Synchronization Options

Choose one of the following synchronization methods based on your operational needs:

State Sync Configuration (Non-Archive Nodes)

State sync allows your node to catch up quickly by retrieving a recent snapshot from trusted peers instead of replaying all historical blocks.

Steps

Edit the [statesync] section: In ~/.eni/config/config.toml, update or add the following persistent peers:

p2p.state-sync-0.eniac-1.eniac.network:26656,

Automate Trust Parameter Configuration:

Use the following script to dynamically set the trust height and hash based on the provided RPC endpoint:

Click to expand
```bash
#!/bin/bash

# Check if an RPC URL or IP:PORT is provided
if [ -z "$1" ]; then
echo "Usage: $0 <rpc_url_or_ip:port>"
exit 1
fi

RPCADDR=$1
CONFIG_FILE="$HOME/.eni/config/config.toml"

# Fetch the current height and latest block hash from /status
STATUS_DATA=$(curl -s "$RPCADDR/status" | jq -r '.sync_info.latest_block_height + " " + .sync_info.latest_block_hash')
CURRENT_HEIGHT=$(echo "$STATUS_DATA" | cut -d' ' -f1)
LATEST_HASH=$(echo "$STATUS_DATA" | cut -d' ' -f2)

if [ -z "$CURRENT_HEIGHT" ] || [ -z "$LATEST_HASH" ]; then
echo "Error: Could not fetch current height or latest block hash from $RPCADDR"
exit 1
fi

# Adjust the current height for safety
ADJUSTED_HEIGHT=$((CURRENT_HEIGHT - 9000))
ROUNDED_HEIGHT=$(( (ADJUSTED_HEIGHT / 10000) * 10000 + 1 ))
TRUST_HEIGHT=$ROUNDED_HEIGHT

# Fetch the trust hash for the calculated trust height
BLOCK_DATA=$(curl -s "$RPCADDR/block?height=$TRUST_HEIGHT" | jq -r '.block_id.hash')
TRUST_HASH=$BLOCK_DATA

if [ -z "$TRUST_HASH" ]; then
echo "Error: Could not fetch trust hash for height $TRUST_HEIGHT from $RPCADDR"
exit 1
fi

# Update the config.toml file
if [ -f "$CONFIG_FILE" ]; then
sed -i "s/^enable = .*/enable = true/" "$CONFIG_FILE"
sed -i "s/^use-p2p = .*/use-p2p = true/" "$CONFIG_FILE"
sed -i "s/^trust-height = .*/trust-height = $TRUST_HEIGHT/" "$CONFIG_FILE"
sed -i "s/^trust-hash = .*/trust-hash = \"$TRUST_HASH\"/" "$CONFIG_FILE"

echo "Updated $CONFIG_FILE with the following values:"
echo "  trust-height = $TRUST_HEIGHT"
echo "  trust-hash = $TRUST_HASH"
else
echo "Error: Config file $CONFIG_FILE not found."
exit 1
fi
```

Usage:

chmod +x script.sh
./script.sh <rpc_url>

Ensure the [statesync] section already includes the persistent peers listed above.


Mempool Configuration Tuning

To optimize transaction processing and resource management, it’s recommended to update the mempool settings in the config.toml file as follows:

#######################################################
###          Mempool Configuration Options           ###
#######################################################
[mempool]

# Broadcast transactions to other nodes
broadcast = true

# Maximum number of transactions in the mempool
size = 5000

# Limit the total size of all transactions in the mempool
max-txs-bytes = 10737418240

# Cache size (for filtering duplicate transactions)
cache-size = 10000

# Do not remove invalid transactions from the cache
keep-invalid-txs-in-cache = false

# Maximum size of a single transaction
max-tx-bytes = 2048576

# Maximum size of transaction batches sent to peers
max-batch-bytes = 0

# Time-to-live duration for transactions in the mempool
ttl-duration = "3s"

# Maximum number of blocks a transaction can remain in the mempool
ttl-num-blocks = 5

tx-notify-threshold = 0

check-tx-error-blacklist-enabled = false

check-tx-error-threshold = 0

pending-size = 5000

max-pending-txs-bytes = 1073741824

pending-ttl-duration = "3s"

pending-ttl-num-blocks = 5

Suggestion: Adjust these parameters if you encounter performance or resource issues.


Set Up Service with systemd

Setting up a systemd service ensures your node starts automatically on boot and restarts if it crashes.

sudo tee /etc/systemd/system/enid.service > /dev/null << EOF
[Unit]
Description=ENI Node
After=network-online.target

[Service]
User=$USER
ExecStart=$(which enid) start
Restart=always
RestartSec=3
LimitNOFILE=65535

[Install]
WantedBy=multi-user.target
EOF

sudo systemctl daemon-reload
sudo systemctl enable enid
sudo systemctl start enid

Note: Confirm that the User field suits your environment. Update it accordingly if running under a different user.


Validation and Troubleshooting

Validate Your Setup

Run the following commands to confirm the node’s status:

# Check sync status
enid status | jq .SyncInfo

# View live logs
journalctl -u enid -f -o cat

Your node is correctly set up when:

  • Sync status shows "catching_up": false

  • Logs indicate blocks are being processed

Common Troubleshooting Tips

Sync Issues

  • Verify sufficient disk space.

  • Ensure a stable network connection.

  • Confirm the system time is correctly synchronized.

  • Use state sync for rapid initial sync (note: not applicable for archive nodes).

Performance Issues

  • Monitor system resources (CPU, memory, I/O).

  • Evaluate disk performance and network bandwidth.

  • Adjust mempool and persistent peer settings if necessary.

Network Connectivity

  • Confirm firewall rules allow required ports (e.g., 26656, 26657, 9090).

  • Check that DNS resolution is functioning.

  • View system logs and node info via RPC [localhost:26657/net_info] to verify peer connections.


Next Steps

Once your node is up and running, consider the following:

  1. Monitoring and Alerts: Set up tools to monitor node health and performance.

  2. Security Best Practices: Harden your server (firewall, SSH keys, etc.).

  3. Backup Procedures: Regularly back up your configuration and data directories.

Additional documentation can be found at:

  • Advanced Configuration and Monitoring Guide

  • Node Operators Guide

  • Validators Guide

Last updated