Comment on page
THIS GUIDE IS FOR TESTING PURPOSES ONLY
The below guide will instruct you on how to set up a Credit Smart Chain network on your local machine for testing and development purposes.
In this guide, our goal is to establish a working
polygon-edgeblockchain network working with IBFT consensus protocol. The blockchain network will consist of 4 nodes of whom all 4 are validator nodes, and as such are eligible for both proposing block, and validating blocks that came from other proposers. All 4 nodes will run on the same machine, as the idea of this guide is to give you a fully functional IBFT cluster in the least amount of time.
To achieve that, we will guide you through 4 easy steps:
- 1.Initializing data directories will generate both the validator keys for each of the 4 nodes, and initialize empty blockchain data directories. The validator keys are important as we need to bootstrap the genesis block with the initial set of validators using these keys.
- 2.Preparing the connection string for the bootnode will be the vital information for every node we will run as to which node to connect to when starting for the first time.
- 3.Generating the
genesis.jsonfile will require as input both the validator keys generated in step 1 used for setting the initial validators of the network in the genesis block and the bootnode connection string from step 2.
- 4.Running all the nodes is the end goal of this guide and will be the last step we do, we will instruct the nodes which data directory to use and where to find the
genesis.jsonwhich bootstraps the initial network state.
As all four nodes will be running on localhost, during the setup process it is expected that all the data directories for each of the nodes are in the same parent directory.
NUMBER OF VALIDATORS
There is no minimum to the number of nodes in a cluster, which means clusters with only 1 validator node are possible. Keep in mind that with a single node cluster, there is no crash tolerance and no BFT guarantee.
The minimum recommended number of nodes for achieving a BFT guarantee is 4 - since in a 4 node cluster, the failure of 1 node can be tolerated, with the remaining 3 functioning normally.
In order to get up and running with IBFT, you need to initialize the data folders, one for each node:
polygon-edge secrets init --data-dir test-chain-1
polygon-edge secrets init --data-dir test-chain-2
polygon-edge secrets init --data-dir test-chain-3
polygon-edge secrets init --data-dir test-chain-4
For a node to successfully establish connectivity, it must know which
bootnodeserver to connect to in order to gain information about all the remaining nodes on the network. The
bootnodeis sometimes also known as the
rendezvousserver in p2p jargon.
bootnodeis not a special instance of the credit-smart-chain node. Every credit-smart-chain node can serve as a
bootnode, but every credit-smart-chain node needs to have a set of bootnodes specified which will be contacted to provide information on how to connect with all remaining nodes in the network.
In this guide, we will treat the first and second nodes as the bootnodes for all other nodes. What will happen in this scenario is that nodes that connect to the
node 2will get information on how to connect to one another through the mutually contacted bootnode.
YOU NEED TO SPECIFY AT LEAST ONE BOOTNODE TO START A NODE
At least one bootnode is required, so other nodes in the network can discover each other. More bootnodes are recommended, as they provide resilience to the network in case of outages. In this guide we will list two nodes, but this can be changed on the fly, with no impact on the validity of the
Since we are running on localhost, it is safe to assume that the
<port>we will use
10001since we will configure the libp2p server for
node 1to listen on this port later.
And lastly, we need the
<node_id>which we can get from the output of the previously ran command
polygon-edge secrets init --data-dir test-chain-1command (which was used to generate keys and data directories for the
After the assembly, the multiaddr connection string to the
node 1which we will use as the bootnode will look something like this (only the
<node_id>which is at the end should be different):
Similarly, we construct the multiaddr for second bootnode as shown below
polygon-edge genesis --consensus ibft --ibft-validators-prefix-path test-chain- --bootnode /ip4/127.0.0.1/tcp/10001/p2p/16Uiu2HAmJxxH1tScDX2rLGSU9exnuvZKNM9SoK3v315azp68DLPW --bootnode /ip4/127.0.0.1/tcp/20001/p2p/16Uiu2HAmS9Nq4QAaEiogE4ieJFUYsoH28magT7wSvJPpfUGBj3Hq
What this command does:
--ibft-validators-prefix-pathsets the prefix folder path to the one specified which IBFT in Credit Smart Chain can use. This directory is used to house the
consensus/folder, where the validator's private key is kept. The validator's public key is needed in order to build the genesis file - the initial list of bootstrap nodes. This flag only makes sense when setting up the network on localhost, as in a real-world scenario we cannot expect all the nodes' data directories to be on the same filesystem from where we can easily read their public keys.
--bootnodesets the address of the bootnode that will enable the nodes to find each other. We will use the multiaddr string of the
node 1, as mentioned in step 2.
The result of this command is the
genesis.jsonfile which contains the genesis block of our new blockchain, with the predefined validator set and the configuration for which node to contact first in order to establish connectivity.
PREMINING ACCOUNT BALANCES
You will probably want to set up your blockchain network with some addresses having "premined" balances.
To achieve this, pass as many
--premineflags as you want per address that you want to be initialized with a certain balance on the blockchain.
For example, if we would like to premine 1000 ETH to address
0x3956E90e632AEbBF34DEB49b71c28A83Bc029862in our genesis block, then we would need to supply the following argument:
Note that the premined amount is in WEI, not ETH.
SET THE BLOCK GAS LIMIT
The default gas limit for each block is
5242880. This value is written in the genesis file, but you may want to increase / decrease it.
GenesisFileName = "./genesis.json"
DefaultChainName = "example"
DefaultChainID = 100
DefaultPremineBalance = "0x3635C9ADC5DEA00000"
DefaultConsensus = "pow"
GenesisGasUsed = 458752
GenesisGasLimit = 5242880 // The default block gas limit
To do so, you can use the flag
--block-gas-limitfollowed by the desired value as shown below :
SET SYSTEM FILE DESCRIPTOR LIMIT
The default file descriptor limit ( maximum number of open files ) on some operating systems is pretty small. If the nodes are expected to have high throughput, you might consider increasing this limit on the OS level.
For Ubuntu distro the procedure is as follows ( if you're not using Ubuntu/Debian distro, check the official docs for your OS ) :
- Check current os limits ( open files )
ubuntu@ubuntu:~$ ulimit -a
core file size (blocks, -c) 0
data seg size (kbytes, -d) unlimited
scheduling priority (-e) 0
file size (blocks, -f) unlimited
pending signals (-i) 15391
max locked memory (kbytes, -l) 65536
max memory size (kbytes, -m) unlimited
open files (-n) 1024
pipe size (512 bytes, -p) 8
POSIX message queues (bytes, -q) 819200
real-time priority (-r) 0
stack size (kbytes, -s) 8192
cpu time (seconds, -t) unlimited
max user processes (-u) 15391
virtual memory (kbytes, -v) unlimited
file locks (-x) unlimited
- Increase open files limit
ulimit -u 65535
- Localy - affects only current session:
sudo vi /etc/security/limits.conf # we use vi, but you can use your favorite text editorCopy/etc/security/limits.conf# /etc/security/limits.conf##Each line describes a limit for a user in the form:##<domain> <type> <item> <value>##Where:#<domain> can be:# - a user name# - a group name, with @group syntax# - the wildcard *, for default entry# - the wildcard %, can be also used with %group syntax,# for maxlogin limit# - NOTE: group and wildcard limits are not applied to root.# To apply a limit to the root user, <domain> must be# the literal username root.##<type> can have the two values:# - "soft" for enforcing the soft limits# - "hard" for enforcing hard limits##<item> can be one of the following:# - core - limits the core file size (KB)# - data - max data size (KB)# - fsize - maximum filesize (KB)# - memlock - max locked-in-memory address space (KB)# - nofile - max number of open file descriptors# - rss - max resident set size (KB)# - stack - max stack size (KB)# - cpu - max CPU time (MIN)# - nproc - max number of processes# - as - address space limit (KB)# - maxlogins - max number of logins for this user# - maxsyslogins - max number of logins on the system# - priority - the priority to run user process with# - locks - max number of file locks the user can hold# - sigpending - max number of pending signals# - msgqueue - max memory used by POSIX message queues (bytes)# - nice - max nice priority allowed to raise to values: [-20, 19]# - rtprio - max realtime priority# - chroot - change root to directory (Debian-specific)##<domain> <type> <item> <value>##* soft core 0#root hard core 100000#* hard rss 10000#@student hard nproc 20#@faculty soft nproc 20#@faculty hard nproc 50#ftp hard nproc 0#ftp - chroot /ftp#@student - maxlogins 4* soft nofile 65535* hard nofile 65535# End of fileOptionaly, modify additional parameters, save the file and restart the system. After restart check file descriptor limit again. It should be set to the value you defined in limits.conf file.
- Globaly or per user ( add limits at the end of /etc/security/limits.conf file ) :
Because we are attempting to run a Credit Smart Chain network consisting of 4 nodes all on the same machine, we need to take care to avoid port conflicts. This is why we will use the following reasoning for determining the listening ports of each server of a node:
10000for the gRPC server of
20000for the GRPC server of
node 2, etc.
10001for the libp2p server of
20001for the libp2p server of
node 2, etc.
10002for the JSON-RPC server of
20002for the JSON-RPC server of
node 2, etc.
To run the first client (note the port
10001since it was used as a part of the libp2p multiaddr in step 2 alongside node 1's Node ID):
polygon-edge server --data-dir ./test-chain-1 --chain genesis.json --grpc-address :10000 --libp2p :10001 --jsonrpc :10002 --seal
To run the second client:
polygon-edge server --data-dir ./test-chain-2 --chain genesis.json --grpc-address :20000 --libp2p :20001 --jsonrpc :20002 --seal
To run the third client:
polygon-edge server --data-dir ./test-chain-3 --chain genesis.json --grpc-address :30000 --libp2p :30001 --jsonrpc :30002 --seal
To run the fourth client:
polygon-edge server --data-dir ./test-chain-4 --chain genesis.json --grpc-address :40000 --libp2p :40001 --jsonrpc :40002 --seal
To briefly go over what has been done so far:
- The directory for the client data has been specified to be ./test-chain-*
- The GRPC servers have been started on ports 10000, 20000, 30000 and 40000, for each node respectively
- The libp2p servers have been started on ports 10001, 20001, 30001 and 40001, for each node respectively
- The JSON-RPC servers have been started on ports 10002, 20002, 30002 and 40002, for each node respectively
- The seal flag means that the node which is being started is going to participate in block sealing
- The chain flag specifies which genesis file should be used for chain configuration
After running the previous commands, you have set up a 4 node Credit Smart Chain network, capable of sealing blocks and recovering from node failure.
START THE CLIENT USING CONFIG FILE
Instead of specifying all configuration parameters as CLI arguments, the Client can also be started using a config file by executing the following command:
polygon-edge server --config <config_file_path>
polygon-edge server --config ./test/config-node1.json
STEPS TO RUN A NON-VALIDATOR NODE
A Non-validator will always sync the latest blocks received from the validator node, you can start a non-validator node by running the following command.
polygon-edge server --data-dir <directory_path> --chain <genesis_filename> --grpc-address <portNo> --libp2p <portNo> --jsonrpc <portNo>
For example, you can add fifth Non-validator client by executing the following command :
polygon-edge server --data-dir ./test-chain --chain genesis.json --grpc-address :50000 --libp2p :50001 --jsonrpc :50002
SPECIFY THE PRICE LIMIT
A Credit Smart Chain node can be started with a set price limit for incoming transactions.
The unit for the price limit is
Setting a price limit means that any transaction processed by the current node will need to have a gas price higher then the set price limit, otherwise it will not be included in a block.
Having the majority of nodes respect a certain price limit enforces the rule that transactions in the network cannot be below a certain price threshold.
The default value for the price limit is
0, meaning it is not enforced at all by default.
Example of using the
polygon-edge server --price-limit 100000 ...
It is worth noting that price limits are enforced only on non-local transactions, meaning that the price limit does not apply to transactions added locally on the node.
Now that you've set up at least 1 running client, you can go ahead and interact with the blockchain using the account you premined above and by specifying the JSON-RPC URL to any of the 4 nodes:
- Node 1:
- Node 2:
- Node 3:
- Node 4:
Follow this guide to issue operator commands to the newly built cluster: How to query operator information (the GRPC ports for the cluster we have built are
40000for each node respectively)