The goal of this project is to start the primary-validator of a new blockchain network in a cluster with its corresponding seed and sentry nodes.
The number of machines must be equal to the number of nodes, because each node runs on a standalone machine.
The machines must be connected in a private network with an internet connection.
The PC, where the script will run, must be able to connect to each of nodes' machines via SSH using keys. The account used for SSH must be able to execute "sudo" without asking for password, e.g. it must be part of "sudoers". More information can be found here
At least 500GB free space
Docker must be installed
Docker-compose must be installed
It is recommended to increase the max number of open file descriptors of the OS. There is a known bug in Tendermint, where a logger opens many files. Rarely it reaches the open files limit of the OS and crashes the node. The limit increase can be done by changing the nofile
flag in /etc/security/limits.conf
in case of linux OS. We recommend a value of 4,096.
Place all of the validators' genesises, obtained by successful execution of the constructor script, in ./launcher/genesises folder.
All of the config files are in ./launcher/config folder.
Important: Do not leave any comments in any .env file
Prepare the .env based on .env.example. It contains the following variables:
-
PARAM_ETH_RPC: a RPC endpoint of an Ethereum node. This is used for orchestrators. Example: PARAM_ETH_RPC="http://1.2.3.4:8545"
-
PARAM_CONTRACT_DEPLOYER_ETH_PRIV_KEY: a private key of an address with some ETH for gravity bridge contract deployment. Example: PARAM_CONTRACT_DEPLOYER_ETH_PRIV_KEY="ae1341352513513a7f9a9a7a9a9a08a6a4a5f6ea9204135f1f3e1a3b1dae413e"
-
PARAM_CONTRACT_DEPLOYER_ETH_ADDRESS: the eth address of the PARAM_CONTRACT_DEPLOYER_ETH_PRIV_KEY. Example: PARAM_CONTRACT_DEPLOYER_ETH_ADDRESS="0x582436824932f3b313e3a3b3d3e31413be6d6a"
-
PARAM_GRAVITY_DEFAULT_NETWORK: the network where gravity contract will be verified at. Possible options are rinkeby | mainnet Example: PARAM_GRAVITY_DEFAULT_NETWORK="rinkeby"
-
PARAM_ETHERSCAN_API_KEY: Etherscan API key used to verify the contract. Example: PARAM_ETHERSCAN_API_KEY="HFSFKGBKESYHFGGFEIGFHUEISWGHFIYGHA"
-
PARAM_SOURCE_DIR: this is the dir on which the nodes home dir will be, usually we use something like "/usr/cudos" Example: PARAM_SOURCE_DIR="/usr/cudos"
-
PARAM_STATIC_VAL_COSMOS_ADDRS: this is a list of wallets of validators that MUST run orchestrators. This value CAN be empty if only the primary-validator will have an orchestrator. Example: PARAM_STATIC_VAL_COSMOS_ADDRS="cudos1yveg0eu5rfak5dl5z72d5h143rfna2cp0jew0a,cudos193jq2nalg24vrew5adbdycuk8cz6n9h6ya9g77t"
Prepare the .env files for each of the nodes.
Validator:
Clone validator.env.example to validator.mainnet.env (The actual name could be arbitrary because the absolute filename to this file is specified below in the configuration). It contains the following variables:
- MONIKER: The name of the node. You could safely use the default value provided in the .example file. Example: MONIKER="cudos-root-node-mainnet"
- CHAIN_ID: The id of the chain. DO NOT MODIFY THIS VALUE. Leave it "cudos-1" as it is in the example.
- ORCH_ETH_ADDRESS: The ETH address of the the wallet that will be used by the orchestrator. Example: ORCH_ETH_ADDRESS="0x582436824932f3b313e3a3b3d3e31413be6d6a"
- MONITORING_ENABLED: This variable defined whether the code will export data to port 26660 for prometheus. If the monitoring is disabled the port 26660 will be closed, otherwise it will be opened to the internal private interface. Example: MONITORING_ENABLED="false"
- ADDR_BOOK_STRICT: This defines the behaviour of the internal address book. DO NOT MODIFY THIS VALUE. Leave it "true" as it is in the example.
- GRAVITY_MODULE_BALANCE: DO NOT MODIFY THIS VALUE. Leave it "0" as it is in the example.
- CUDOS_TOKEN_CONTRACT_ADDRESS: The address of the CUDOS token contract. Example: CUDOS_TOKEN_CONTRACT_ADDRESS="0x12d474723cb8c02bcbf46cd335a3bb4c75e9de44"
- ROOT_VALIDATOR_MNEMONIC: The address of the CUDOS token contract. Example: ROOT_VALIDATOR_MNEMONIC="word1...word24"
- NUMBER_OF_VALIDATORS: The number of validator accounts that will be initialized with the primary-validator. DO NOT MODIFY THIS VALUE. Leave it "1" as it is in the example.
- NUMBER_OF_ORCHESTRATORS: The number of orchestrator accounts that will initialized with the primary-validator. The default value is 3 Example: NUMBER_OF_ORCHESTRATORS="3"
- VALIDATOR_BALANCE: The amount of staked tokens that each genesis validator will have. Example: VALIDATOR_BALANCE="2000000000000000000000000"
- ORCHESTRATOR_BALANCE: This is the balance that each orchestrator will have. Example: ORCHESTRATOR_BALANCE="1000000000000000000"
- FAUCET_BALANCE: The balance of the faucet. If set to 0 then no faucet will be created. Example: FAUCET_BALANCE="8000000000000000000000000000"
- KEYRING_OS_PASS: The password of your keyring. It must be at least 8 characters. Example: KEYRING_OS_PASS="11111111"
Seed:
Clone seed.env.example to seed.mainnet.env (The actual name could be arbitrary because the absolute filename to this file is specified below in the configuration). It contains the following variables:
- MONIKER: The name of the node. You could safely use the default value provided in the .example file. Example: MONIKER="cudos-seed-node-mainnet-01"
- PERSISTENT_PEERS: DO NOT MODIFY THIS VALUE. Leave it empty as it is in the example.
- PRIVATE_PEERS: DO NOT MODIFY THIS VALUE. Leave it empty as it is in the example.
- SEEDS: DO NOT MODIFY THIS VALUE. Leave it empty as it is in the example.
- SHOULD_USE_GLOBAL_PEERS: DO NOT MODIFY THIS VALUE. Leave it "false" as it is in the example.
- SHOULD_USE_STATE_SYNC: DO NOT MODIFY THIS VALUE. Leave it "false" as it is in the example.
- MONITORING_ENABLED: This variable defined whether the code will export data to port 26660 for prometheus. If the monitoring is disabled the port 26660 will be closed, otherwise it will be opened to the internal private interface. Example: MONITORING_ENABLED="false"
- EXTERNAL_ADDRESS: This variable defines the address to advertise to peers for them to dial. It must be the public address of the node plus the 26656 (or any other external number that could be redirected to internal port 26656) port. Example: EXTERNAL_ADDRESS="43.14.14.12:26656"
- ADDR_BOOK_STRICT: This defines the behaviour of the internal address book. DO NOT MODIFY THIS VALUE. Leave it "true" as it is in the example.
Sentry:
Clone sentry.env.example to sentry.mainnet.env (The actual name could be arbitrary because the absolute filename to this file is specified below in the configuration). It contains the following variables:
- MONIKER: The name of the node. You could safely use the default value provided in the .example file. Example: MONIKER="cudos-sentry-node-mainnet-01"
- PERSISTENT_PEERS: DO NOT MODIFY THIS VALUE. Leave it empty as it is in the example.
- PRIVATE_PEERS: DO NOT MODIFY THIS VALUE. Leave it empty as it is in the example.
- SEEDS: DO NOT MODIFY THIS VALUE. Leave it empty as it is in the example.
- SHOULD_USE_GLOBAL_PEERS: DO NOT MODIFY THIS VALUE. Leave it "false" as it is in the example.
- SHOULD_USE_STATE_SYNC: DO NOT MODIFY THIS VALUE. Leave it "false" as it is in the example.
- TLS_ENABLED: DO NOT MODIFY THIS VALUE. Leave it "false" as it is in the example.
- MONITORING_ENABLED: This variable defined whether the code will export data to port 26660 for prometheus. If the monitoring is disabled the port 26660 will be closed, otherwise it will be opened to the internal private interface. Example: MONITORING_ENABLED="false"
- EXTERNAL_ADDRESS: This variable defines the address to advertise to peers for them to dial. It must be the public address of the node plus the 26656 (or any other external number that could be redirected to internal port 26656) port. Example: EXTERNAL_ADDRESS="43.14.14.12:26656"
- ADDR_BOOK_STRICT: This defines the behaviour of the internal address book. DO NOT MODIFY THIS VALUE. Leave it "true" as it is in the example.
Orchestrator:
Clone orchestrator.env.example to orchestrator.mainnet.env (The actual name could be arbitrary because the absolute filename to this file is specified below in the configuration). It contains the following variables:
- ADDRESS_PREFIX: DO NOT MODIFY THIS VALUE. Leave it "cudos" as it is in the example.
- FEES: The gas price, with acudos suffix, that are paid by the orchestrator when he iteracts with the blockchain. The value must be >= than minimum gas price which is 5*1E12 Example: FEES="5000000000000acudos"
- GRPC: DO NOT MODIFY THIS VALUE. Leave it empty as it is in the example.
- ETHRPC: Address to the ethereum full node. Example: ETHRPC="http://43.14.14.12:8545"
- CONTRACT_ADDR: DO NOT MODIFY THIS VALUE. Leave it empty as it is in the example.
- COSMOS_ORCH_MNEMONIC: DO NOT MODIFY THIS VALUE. Leave it empty as it is in the example.
- ETH_PRIV_KEY_HEX: The private key of the address defined in ORCH_ETH_ADDRESS of validator.mainnet.env. Example: ETH_PRIV_KEY_HEX="ae1341352513513a7f9a9a7a9a9a08a6a4a5f6ea9204135f1f3e1a3b1dae413e"
Prepare the topology of the cluster based on the example. Clone topology.json.example to topology.json
topology.json
is a json file has the following structure:
{
"computers": Computer[], // Defines each computer where a node will be deployed.
"nodes": Node[], // Defines the topology of the network.
}
Computer object:
Each computer defined in the topology.json
is accessed by a private key, username and private key's pass.
{
"id": string, // The id of the computer. It is used as a unique identifier of the machine.
"ip": string, // The IP of the computer.
"internalIp": string, // The internal IP of the computer. It will be used for communication betweek the computers themselves.
"port": number, // The SSH service port. Usually it is 22.
"user": string, // The SSH service user.
"sshKeyPath": string, // Absolute filename of the sshKey.
"pass": string // The password of the sshKey.
}
Node object:
{
"primary-validator": Validator, // Defines the root validator, e.g. the one that starts the network.
"seeds": Seed[], // Defines the seed nodes and how they are attached to validators.
"sentries": Sentry[], // Defines the sentry nodes and how they are attached to validators.
}
Validator object:
{
"computerId": string, // The id of the computer where this node will run.
"envPath": string, // Absolute filename to the validator.mainnet.env created in step 2 of the config section above
"orchEnvPath": string, // Absolute filename to the orchestrator.mainnet.env craeted in step 2 of the config section above
}
Seed object:
{
"computerId": string, // The id of the computer where this node will run.
"envPath": string, // Absolute filename to the seed.mainnet.env created in step 2 of the config section above
}
Sentry object:
{
"computerId": string, // The id of the computer where this node will run.
"envPath": string, // Absolute filename to the seed.mainnet.env created in step 2 of the config section above
}
Remarks:
- Each computer instance can be used only by a single node.
- Each validator must have at least one seed and one sentry.
There are 3 scripts.
Important: The side effect of executing any of these scripts will be a folder, defined in PARAM_SOURCE_DIR at .env, on each machine defined in topology.json
Launch sequence: Execute these scripts only when all config files are ready. Follow the order below.
- First execute validate to ensure that the connection to peers is fine
- Second execute launcher to start the network
- [This script must be executed when the network has started producing blocks, in other words - when 2/3 of genesis validator are online.] Third Execute gravity to deploy the smart contract and start the first orchestrator. The result of this execution will be a gravity smart contract address in the console. As mentioned this step starts only the first orchestrator. If you have more orchestrators you must use the constructor script (the one that was used to start the rest of the validators) to start them. You can find its readme here. You will need the contract address and orchestrator mnemonics from ./exports/orchs.mnemonics in the constructor script.
Validate: It validates the connection from current machine to other machines defined in the topology and also checks for available space, software, etc.
Ensure that it has execute permission and then start the script from ./launcher folder
./src/validate.sh
Launcher: It starts the cluster.
Ensure that it has execute permission and then start the script from ./launcher folder
./src/launch.sh
Gravity: It starts the gravity.
Ensure that it has execute permission and then start the script from ./launcher folder
./src/gravity.sh