Telos Technical How To #4

Ross Dold
EOSphere Blog

--

If you have been following our Telos Technical How To Series you should now be comfortable with building and running EOSIO software in the safety of the Telos Testnet environment. Freely available tokens and relatively low system requirements make the Telos Testnet an ideal place to learn, however after running successfully for 2 weeks it’s now time to graduate to the Telos Mainnet.

This 4th Telos Technical How To Edition will give you the insight to build solid Telos Mainnet nodes that will handle the network and infrastructure demands that are required to be met by successful Telos Block Producers.

How to Set Up a Solid Telos Mainnet Node

The Telos Mainnet as far as EOSIO chains go can be quite busy at times and with the success of Telos EVM it is set to start being quite demanding on infrastructure. There are numerous ways to fulfill these demands depending on the specific services requirement and the network is continuously growing, meaning what works today may have to be reassessed in the future.

This article will walk through an example that is currently valid (August 2022) and in use by EOSphere who are serving multiple peers and millions of API requests per day.

Mainnet Requirements

Hardware

  • 4 Core CPU / 4Ghz+ recommended if you would like to produce blocks
  • (1) 128GB+ Disk / Enterprise Grade SSD or NVMe (High Endurance Req.)
  • (2) 2TB+ Disk / SAS or SATA are OK however SSD or NVMe preferred
  • 8GB+ RAM

Operating System

  • Amazon Linux 2
  • CentOS 7
  • CentOS 7.x
  • CentOS 8
  • Ubuntu 16.04
  • Ubuntu 18.04 (Recommended)
  • Ubuntu 20.04 (Recommended)
  • MacOS 10.14 (Mojave)
  • MacOS 10.15 (Catalina)

Internet

  • Modern Broadband / Fibre Connection (100Mb/s synchronous and above)
  • Static Public IP Address (Either terminating on this node or forwarded with NAT)

Prepare the Operating System Environment

Before the EOSIO software is built and configured, the operating system environment Ubuntu 18.04 in this case needs to be configured for performance and the load that is will take on.

Zettabyte File System (ZFS)

This node build uses 2 Discrete Disks in order to balance disk IO and provide a more affordable storage option for the blocks.log file, which is currently 225GB and growing.

Disk 1 is the high speed enterprise grade SSD or NVMe and will be the OS disk used for the EOSIO software, all config and the state files. The state files are extremely IO intensive, a consumer based SSD’s life span will be short lived due to the high number of writes, hence the need to use a high endurance enterprise SSD or NVMe.

Note: It needs to be mentioned that there are mechanisms to run these state files in memory if you have enough available, this topic will be covered in a future article.

In this example, Disk 1 will run the default OS Ext4 File System that will already be implemented during the Ubuntu 18.04 installation.

Disk 2 is the large capacity SATA or SAS disk that will host the blocks.log file. The IO demands on the blocks directory are far lower than the state files and slower larger capacity spindle based disks are still suitable.

In this example Disk 2 will run the ZFS File System which will give us two main benefits. ZFS will enable us to use LZ4 compression (which currently is a gain of 1.3x) and it will improve disk IO with Adaptive Replacement Cache (ARC)

Implement ZFS on Disk 2 with the below configuration:

#Install ZFS
> sudo apt-get install zfsutils-linux
#Locate the Disk 2 device name
> lsblk
#Create ZFS Pool called "datavolume" on device "sdb"
> sudo zpool create datavolume /dev/sdb
#Enable LZ4 compression
> sudo zfs set compression=lz4 datavolume
#Disable ZFS access time Updates
> sudo zfs set atime=off datavolume
#Set ARC to only cache metadata
> sudo zfs set primarycache=all datavolume
#Set the mountpoint location to your preferred location
> sudo zfs set mountpoint=/home/eosphere/datavolume datavolume
#Verify ZFS Settings
> zfs get all

Network Time Protocol (NTP)

It is crucial for a globally meshed blockchain to have synchronised time across all nodes.

Chrony is an excellent NTP client and is quite suitable for the needs of the Telos Mainnet.

Install, configure and verify as below:

#Install Chrony
> sudo apt install chrony
#If necessary manually add local peers, these are AU servers
> sudo nano /etc/chrony/chrony.conf
server 0.pool.ntp.org
server 1.pool.ntp.org
server 2.pool.ntp.org
server 3.pool.ntp.org
#Restart Chrony
> sudo /etc/init.d/chrony restart
#Verify
> chronyc sources -v
> chronyc tracking
#Set your local timezone if neccesary
> sudo timedatectl set-timezone Australia/Perth

Stack Limits and Openfiles

EOSIO software memory addressing and the number of API requests a Production Mainnet Node will receive require that the Ubuntu 18.04 default Stack Limit and Number of Open Files be increased.

Configure and verify the raised limits as below:

> sudo nano /etc/systemd/system.conf#Append the following configuration
DefaultLimitNOFILE=64000
DefaultLimitSTACK=65536000
#Restart server and verify
> ulimit -a

Build the Software

The Telos Network utilises opensource EOSIO software, Telos specific smart contracts and chain configuration have customised EOSIO to suit the needs of the Telos Network.

EOSIO software has been forked from the original code, this code fork is currently still in testing so won’t be built in this guide. However to prepare for a frictionless upgrade path EOSIO v2.0.13 will be used.

The latest eosio build tag is still available on the EOSIO GitHub.

Building Process

This example uses Ubuntu Linux to build the software from source following the process below:

> cd ~> git clone https://github.com/EOSIO/eos.git> cd eos> git checkout v2.0.13> git submodule update --init --recursive> cd scripts > ./eosio_build.sh -P#Binaries are in ~/eos/build/programs#If you want to install
> ./eosio_install.sh

As the -P option is used on the build script this may take some time to compile as it will build with pinned clang and libcxx

Configuration

Now that a clean build of the EOSIO software has been compiled lets get into configuring for Telos Mainnet operation.

To configure and start the node nodeos will be used, nodeosis the core service daemon that runs on every Telos Network node.

nodeos can be configured to process smart contracts, validate transactions, produce blocks containing valid transactions, and confirm blocks to record them on the blockchain. You can read more about it here.

The primary operational functions of nodeos are; running it as a Block Producer, Network API Endpoint, P2P Seed Node or State-History Node. Typically on a busy network you would separate these functions across physically discrete servers.

In this Telos Mainnet example you will make your node connect to other network peers, offer a P2P Seed Node service and make the node available as a Network API Endpoint. This node won’t be providing historical data query support.

nodeos requires two files to connect to peers and run on the Telos Mainnet:

config.ini

Create a default config.ini by running nodeos without config as per the command below:

> mkdir ~/telosdata> nodeos --data-dir ~/telosdata --config-dir ~/telosdata

You will then be able to edit the newly created config.ini and see all the available parameters:

> cd ~/telosdata> nano config.ini

Now edit the config.iniand add the following configuration settings:

# the location of the blocks directory on Disk 2
blocks-dir = /home/eosphere/datavolume/blocks
wasm-runtime = eos-vm-jit
chain-state-db-size-mb = 16384
chain-state-db-guard-size-mb = 1024
enable-account-queries = true
http-server-address = 0.0.0.0:8888
access-control-allow-origin = *
access-control-allow-headers = Origin, X-Requested-With, Content-Type, Accept
http-max-response-time-ms = 100
verbose-http-errors = true
http-validate-host = false
p2p-listen-endpoint = 0.0.0.0:9876
# actifittelos: FI, Helsinki, FI
p2p-peer-address = telosp2p.actifit.io:9876

# amsterdam: NL, Amsterdam
p2p-peer-address = telos.eu.eosamsterdam.net:9120

# argentinatls: AR, Argentina
p2p-peer-address = p2p.telos.eosargentina.io:9879

# bp.boid: ES, Tenerife, Canary Islands, Spain
p2p-peer-address = telos.p2p.boid.animus.is:5151

# bp.boid: ES, Tenerife, Canary Islands, Spain
p2p-peer-address = telos.p2p.boid.animus.is:5252

# cryptobloksx: US, Portland, OR
p2p-peer-address = p2p.telos.cryptobloks.io:9876

# cryptolions1: DE, Germany-Finland
p2p-peer-address = telos.cryptolions.io:9871

# eosauthority: DE, Falkenstein
p2p-peer-address = node-telos.eosauthority.com:10311

# eosbarcelona: DE, Germany
p2p-peer-address = telosp2p.eos.barcelona:2095

# eosphereiobp: AU, Sydney
p2p-peer-address = peer1-telos.eosphere.io:9876

# eosphereiobp: AU, Sydney
p2p-peer-address = peer2-telos.eosphere.io:9876

# goodblocktls: US, Seattle, WA
p2p-peer-address = mainnet.telos.goodblock.io:9879

# katalyotelos: FI, Finland
p2p-peer-address = tlos-p2p.katalyo.com:11877

# nation.tlos: CA, Canada
p2p-peer-address = telos.seed.eosnation.io:9876

# pandabloks: PT, Porto
p2p-peer-address = p2p.telos.pandabloks.com:9876

# swedencornet: FI, Helsinki
p2p-peer-address = telos.eossweden.eu:8012

# teleologytls: HK, Hong Kong
p2p-peer-address = telos.teleology.one:9876

# telosarabia1: DE, Munich
p2p-peer-address = p2p.telosarabia.net:9876

# teloscentral: DE, Germany
p2p-peer-address = sslapi.teloscentral.com:9876

# telosculture: CA, Montreal
p2p-peer-address = testnet.telosculture.com:9874

# telosgermany: DE, Frankfurt
p2p-peer-address = p2p.telosgermany.genereos.io:9876

# telosglobal1: US, Sacramento,CA
p2p-peer-address = node1.us-west.telosglobal.io:9876

# telosglobal1: US, Herndon,VA
p2p-peer-address = node1.us-east.telosglobal.io:9876

# telosgreenbp: DE, Germany
p2p-peer-address = p2p2.telos.telosgreen.com:9877

# telosmadrid1: DE, SEED
p2p-peer-address = seed.telosmadrid.io:9876

# telosunlimit: US, St.Louis
p2p-peer-address = p2p.telosunlimited.io:9876

# theteloscrew: DE, Frankfurt
p2p-peer-address = mainnet.teloscrew.com:18876

# tlosimperabp: IT, Italy
p2p-peer-address = 136.243.90.53:9876

# votedutcheos: CA, Full (backup), Beauharnois
p2p-peer-address = p2p.telos.dutcheos.io:9876
# PeerList - https://validate.eosnation.io/telos/reports/config.htmlagent-name = "<yourname> Telos Mainnet"
max-clients = 100
sync-fetch-span = 500
plugin = eosio::http_plugin
plugin = eosio::history_api_plugin
plugin = eosio::history_plugin
plugin = eosio::chain_plugin
plugin = eosio::chain_api_plugin

genesis.json

These are the initial state parameters required by every new starting node on the Telos Mainnet. Create the file as below:

> cd ~/telosdata> nano genesis.json

Add the following parameters to the genesis.json file for the Telos Public Mainnet:

{
"initial_key": "EOS52vfcN43YHHU8Akh7VyfBdnDiMg15dPTELosWG9SR86ssBoU1T",
"initial_configuration": {
"max_transaction_delay": 3888000,
"min_transaction_cpu_usage": 100,
"net_usage_leeway": 500,
"context_free_discount_net_usage_den": 100,
"max_transaction_net_usage": 524288,
"context_free_discount_net_usage_num": 20,
"max_transaction_lifetime": 3600,
"deferred_trx_expiration_window": 600,
"max_authority_depth": 6,
"max_transaction_cpu_usage": 5000000,
"max_block_net_usage": 1048576,
"target_block_net_usage_pct": 1000,
"max_generated_transaction_count": 16,
"max_inline_action_size": 4096,
"target_block_cpu_usage_pct": 1000,
"base_per_transaction_net_usage": 12,
"max_block_cpu_usage": 50000000,
"max_inline_action_depth": 4
},
"initial_timestamp": "2018-12-12T10:29:00.000"
}

Running Nodeos

Now that the config.ini has been configured and the initial Telos Mainnet chain parameters genesis.json have been created, you can now join the network and sync up the node.

Use screen to keep your session live even when you disconnect, usage below:

#Create a new screen session
> screen -US telos
#Disconnect screen session
> ctrl-a+d
#Reconnect screen session
> screen -r telos

Run nodeos with pointers to the config, data directory and genesis file:

> nodeos --data-dir ~/telosdata --config-dir ~/telosdata --genesis-json ~/telosdata/genesis.json

Your Telos Mainnet node will now start syncing with the configured peers until it catches up and is current with the Telos Mainnet chain.

It is possible to speed up the sync process by starting with a snapshot and valid blocks.log the process is explained in Telos Technical How To #2

The Next Edition of Telos Technical How To .. will look into fronting your API service with a Proxy that will terminate client SSL requests and provide limits to these requests.

Be sure to ask any questions in the EOSphere Telegram

EOSphere is a Block Producer on the Telos Mainnet and Testnet Blockchains as well as many other EOSIO based networks.

If you find our work helpful, please vote us on the Telos Mainnet: eosphereiobp

Connect with EOSphere via these channels:

TELEGRAM | MEDIUM |YOUTUBE | FACEBOOK | TWITTER | INSTAGRAM

--

--