How to setup a Nethermind only Clique based chain
Set of validators sealing blocks on private clique network

TL;DR

Download a script that will do all the steps described below for you. It will prompt you 2 things:
    Confirm installation of required packages
    The number of Validators you wish to run in your private network
Script can be found here:
nethermind/clique-validators.sh at master · NethermindEth/nethermind
GitHub
or use this command to download it:
1
wget https://raw.githubusercontent.com/NethermindEth/nethermind/master/scripts/private-networking/clique-validators.sh
Copied!
Finally give the script permissions and run it (script requires sudo privileges):
1
chmod +x clique-validators.sh
2
./clique-validators.sh
Copied!

Prerequisites

    Linux bash shell
    Docker-compose
    Docker
    jq
    pwgen
1
sudo apt-get install -y docker-compose docker.io jq pwgen
Copied!

Manual setup

All these steps are automated and written in the above clique-validators.sh script.
In this setup we will create a private network of 3 Nethermind nodes running Clique consensus algorithm.
    create separate directory where we will store all files
1
mkdir private-networking
2
cd private-networking
Copied!
    create folders for each node and genesis
1
mkdir node_1 node_2 node_3 genesis
Copied!
    download chainspec file with clique engine and place it in genesis folder (we will be using goerli chainspec in this example)
1
wget https://raw.githubusercontent.com/NethermindEth/nethermind/09389fc28b37605acc5eaed764d3e973969fe319/src/Nethermind/Chains/goerli.json
2
cp goerli.json genesis/goerli.json
Copied!
    create subfolders in each node folder
1
mkdir node_1/configs node_2/configs node_3/configs
Copied!
    create a static-nodes.json file and place it in working directory
1
cat <<EOF > static-nodes.json
2
[
3
4
]
5
EOF
Copied!
    create config.cfg file and place it in node_1/configs subfolders (do this for node_2 and node_3 as well)
1
cat <<EOF > node_1/configs/config.cfg
2
{
3
"Init": {
4
"WebSocketsEnabled": false,
5
"StoreReceipts" : true,
6
"EnableUnsecuredDevWallet": true,
7
"IsMining": true,
8
"ChainSpecPath": "/config/genesis/goerli.json",
9
"BaseDbPath": "nethermind_db/clique",
10
"LogFileName": "clique.logs.txt",
11
"StaticNodesPath": "Data/static-nodes.json"
12
},
13
"Network": {
14
"DiscoveryPort": 30300,
15
"P2PPort": 30300,
16
"LocalIp": "10.5.0.2",
17
"ExternalIp": "10.5.0.2"
18
},
19
"JsonRpc": {
20
"Enabled": true,
21
"Host": "10.5.0.2",
22
"Port": 8545
23
},
24
"KeyStoreConfig": {
25
"TestNodeKey": "8687A55019CCA647F6C063F530D47E9A90725D62D853F4B973E589DB24CA9305"
26
}
27
}
28
EOF
Copied!
For each node you will need to change following items in configuration:
    TestNodeKey should be a 64 character length alphanumeric string. Can be generated with pwgen tool for example.
    LocalIp, ExternalIp and Host should have the same value and be incremented for each node e.g. 10.5.0.3, 10.5.0.4 and so on and so forth.
Copy docker-compose file and place it in working directory.
1
version: "3.5"
2
services:
3
4
node_1:
5
image: nethermind/nethermind:1.10.17
6
command: --config config
7
container_name: node_1
8
volumes:
9
- ./genesis:/config/genesis
10
- ./node_1/configs/config.cfg:/nethermind/configs/config.cfg
11
- ./static-nodes.json:/nethermind/Data/static-nodes.json
12
- ./node_1/db/clique:/nethermind/nethermind_db/clique
13
- ./node_1/keystore:/nethermind/keystore
14
ports:
15
- 0.0.0.0:8547:8545
16
networks:
17
vpcbr:
18
ipv4_address: 10.5.0.2
19
20
node_2:
21
image: nethermind/nethermind:1.10.17
22
command: --config config
23
container_name: node_2
24
volumes:
25
- ./genesis:/config/genesis
26
- ./node_2/configs/config.cfg:/nethermind/configs/config.cfg
27
- ./static-nodes.json:/nethermind/Data/static-nodes.json
28
- ./node_2/db/clique:/nethermind/nethermind_db/clique
29
- ./node_2/keystore:/nethermind/keystore
30
ports:
31
- 0.0.0.0:8548:8545
32
networks:
33
vpcbr:
34
ipv4_address: 10.5.0.3
35
36
node_3:
37
image: nethermind/nethermind:1.10.17
38
command: --config config
39
container_name: node_3
40
volumes:
41
- ./genesis:/config/genesis
42
- ./node_3/configs/config.cfg:/nethermind/configs/config.cfg
43
- ./static-nodes.json:/nethermind/Data/static-nodes.json
44
- ./node_3/db/clique:/nethermind/nethermind_db/clique
45
- ./node_3/keystore:/nethermind/keystore
46
ports:
47
- 0.0.0.0:8549:8545
48
networks:
49
vpcbr:
50
ipv4_address: 10.5.0.4
51
52
networks:
53
vpcbr:
54
driver: bridge
55
ipam:
56
config:
57
- subnet: 10.5.0.0/16
Copied!
    run each node separately so that we can copy Enode and Node address for each node, we will use them later
1
docker-compose run node_1
Copied!
Stop the node when Nethermind initialization completes Ctrl +C. Copy This node and Node address (without 0x prefixes) values to a text file. Continue with node_2 and node_3.
You can use Nethermind.Cli to fetch these values from nodes by executing the following. Nethermind.Cli can be found in packages on Github Releases or Download Page.
1
node.switch("http://localhost:8547")
2
node.enode
3
node.address
Copied!
    the file should look similar to this:
1
SIGNER_1="b5bc4d9e63eb1cb16aeeb0fd08e8344283b45b0d"
2
STATIC_NODE_1="enode://2281549869465d98e90cebc45e1d6834a01465a990add7bcf07a49287e7e66b50[email protected]10.5.0.2:30300"
3
SIGNER_2="c4e3a14d33f765faaca31672bd90d0c325bfa0cf"
4
STATIC_NODE_2="enode://37878ec16a5ed87c9c80b4648e5428f5c768eddd79483be118319c49d11c4e535[email protected]10.5.0.3:30300"
5
SIGNER_3="0076873eb11c627057834fdbdc7b391a33eb9f81"
6
STATIC_NODE_3="enode://6067f06d84c207e6233dacf1f3ef961bd7231f71d5425cbaf843cf19cfd5f7e13[email protected]10.5.0.4:30300"
Copied!
    copy & paste above variables into your terminal and create EXTRA_VANITY and EXTRA_SEAL variables
1
EXTRA_VANITY="0x22466c6578692069732061207468696e6722202d204166726900000000000000"
2
EXTRA_SEAL="0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
Copied!
1
EXTRA_DATA=${EXTRA_VANITY}${SIGNER_1}${SIGNER_2}${SIGNER_3}${EXTRA_SEAL}
Copied!
    in goerli.json chainspec file, modify extraData property in genesis field
You can do this either manually or using below command
1
cat goerli.json | jq '.genesis.extraData = '\"$EXTRA_DATA\"'' > genesis/goerli.json
Copied!
    Modify the content of static-nodes.json files by appending Enodes to it
1
cat <<EOF > static-nodes.json
2
[
3
"$STATIC_NODE_1",
4
"$STATIC_NODE_2",
5
"$STATIC_NODE_3"
6
]
7
EOF
Copied!
    remove databases for each node
1
sudo rm -rf node_1/db/clique node_2/db/clique node_3/db/clique
Copied!
    finally run docker-compose file
1
docker-compose up
Copied!
You should see the private network working and nodes sealing blocks in Clique consensus algorithm
🎉
Clique validators sealing blocks in private network
Last modified 8mo ago