The enterprise blockchain market is huge, and there are different solutions available to implement blockchain for enterprise -- Hyperledger, Corda, and Ethereum are the well-known providers. You can set up enterprise blockchain in different ways, on a cloud, or on-premise. Here in this post, we'll learn how you can setup a private ethereum blockchain on your server.

OS and Software

Validator nodes

We will use proof of authority (PoA) consensus to setup the private network. In PoA-based networks, transactions and blocks are validated by approved accounts, known as validators or sealer. The process is automated and does not require validators to be constantly monitoring their computers.

PoA algorithms rely on a set of N trusted nodes called the authorities. We'll create three sealer nodes to validate the transactions.

Types of Nodes in PoA NetworkValidator/Authority - Validate, confirm transactions, and add new blocks into blockchain.

Here is the structure we'll build in this tutorial. A full template can be found from the attachment of this article.

blockchain
├── accounts.txt
├── genesis.json
├── node1
│ ├── geth
│ ├── keystore
│ ├── node1.sh
│ ├── password.txt
│ └── static-nodes.json
├── node2
│ ├── geth
│ ├── keystore
│ ├── node2.sh
│ ├── password.txt
│ └── static-nodes.json
└── node3
├── geth
├── keystore
├── node3.sh
├── password.txt
└── static-nodes.json

Create a main directory

Markdown
$ mkdir blockchain    
$ cd blockchain    
    
blockchain$ mkdir node1 node2 node3

Create validator accounts

The account required public-private keys to interact with the blockchain. Hence we need to create new accounts for validators.

Node 1

Markdown
blockchain$ geth --datadir node1/ account new    
    
Your new account is locked with a password. Please give a password. Do not forget this password.    
Password:    
Repeat password:    
    
Your new key was generated    
    
Public address of the key:   0x5D9DD2d7ea19D886F6D69c7E14e4F4Eeb922F8d4    
Path of the secret key file: node1/keystore/UTC--2020-07-29T15-48-00.687512615Z--5d9dd2d7ea19d886f6d69c7e14e4f4eeb922f8d4

Node 2

Markdown
blockchain$ geth --datadir node2/ account new    
  
Your new account is locked with a password. Please give a password. Do not forget this password.    
Password:    
Repeat password:    
    
Your new key was generated    
    
Public address of the key:   0x80051706C32359A75389EA36dDEbA2159067C360    
Path of the secret key file: node2/keystore/UTC--2020-07-29T15-54-17.548848773Z--80051706c32359a75389ea36ddeba2159067c360

Node 3

Markdown
blockchain$ geth --datadir node3/ account new    
  
Your new account is locked with a password. Please give a password. Do not forget this password.    
Password:    
Repeat password:    
    
Your new key was generated    
    
Public address of the key:   0xf189Ee2c9b61487Fe26C72b8a0ba52f453E71c25    
Path of the secret key file: node3/keystore/UTC--2020-07-29T15-56-15.523088698Z--f189ee2c9b61487fe26c72b8a0ba52f453e71c25

Note that keystore files automatically generated inside node folders, and keystore files can be found inside the keystore directory.

Save Credentials

For future use, we'll copy these three wallet address to a text file.

Markdown
blockchain$ echo '0x5D9DD2d7ea19D886F6D69c7E14e4F4Eeb922F8d4' >> accounts.txt
blockchain$ echo '0x80051706C32359A75389EA36dDEbA2159067C360' >> accounts.txt
blockchain$ echo '0xf189Ee2c9b61487Fe26C72b8a0ba52f453E71c25' >> accounts.txt

To make the process easier, save the password of each node to the respective folder.

Markdown
blockchain$ echo 'pwd@node1' > node1/password.txt
blockchain$ echo 'pwd@node2' > node2/password.txt
blockchain$ echo 'pwd@node3' > node2/password.txt

Create your Genesis file

Geth comes with different tools included; if you're using tar file, you need to install it separately. Puppeth is a tool to create a new genesis file by selecting different options.

Markdown
blockchain$ puppeth

Specify the chain id

Markdown
Please specify a network name to administer (no spaces, hyphens or capital letters please)
> 1515

As we want to generate a new genesis file, choose the first option.

Markdown
What would you like to do? (default = create)    
 1. Create new genesis from scratch    
 2. Import already existing genesis    
> 1

Select proof-of-authority.

Markdown
Which consensus engine to use? (default = clique)    
 1. Ethash - proof-of-work    
 2. Clique - proof-of-authority    
> 2

For the fast transaction, hence provide 1 second.

Markdown
How many seconds should blocks take? (default = 15)    
> 1

Provide accounts created previously

Markdown
Which accounts are allowed to seal? (mandatory at least one)    
> 0x5D9DD2d7ea19D886F6D69c7E14e4F4Eeb922F8d4    
> 0x80051706C32359A75389EA36dDEbA2159067C360    
> 0xf189Ee2c9b61487Fe26C72b8a0ba52f453E71c25    
> 0x

Provide accounts to get some free ethers

Markdown
Which accounts should be pre-funded? (advisable at least one)    
> 0x5D9DD2d7ea19D886F6D69c7E14e4F4Eeb922F8d4    
> 0x80051706C32359A75389EA36dDEbA2159067C360    
> 0xf189Ee2c9b61487Fe26C72b8a0ba52f453E71c25    
> 0x
Markdown
Should the precompile-addresses (0x1 .. 0xff) be pre-funded with 1 wei? (advisable yes)    
> yes
Markdown
Specify your chain/network ID if you want an explicit one (default = random)    
> 1515 
Configured new genesis block

The genesis block is configured, now we need to export the configuration into a file.

Markdown
What would you like to do? (default = stats)    
 1. Show network stats    
 2. Manage existing genesis    
 3. Track new remote server    
 4. Deploy network components    
> 2
Markdown
1. Modify existing configurations    
2. Export genesis configurations    
3. Remove genesis configuration    
> 2
Markdown
Which folder to save the genesis specs into? (default = current)    
  Will create 1515.json, 1515-aleth.json, 1515-harmony.json, 1515-parity.json    
> // enter to create in existing folder   
  
INFO [07-29|16:33:29.147] Saved native genesis chain spec path=1515.json  
ERROR[07-29|16:33:29.147] Failed to create Aleth chain spec err="unsupported consensus engine"  
ERROR[07-29|16:33:29.147] Failed to create Parity chain spec err="unsupported consensus engine"  
INFO [07-29|16:33:29.149] Saved genesis chain spec client=harmony path=1515-harmony.json
Markdown
What would you like to do? (default = stats)    
 1. Show network stats    
 2. Manage existing genesis    
 3. Track new remote server    
 4. Deploy network components    
     
> ^C //ctrl+C to quit puppeth

You should see the 1515.json created inside blockchain folder, rename it to genesis.json and delete the generated file that ends in -harmony.json.

Modify the Genesis file

Set block sealing period to 0, this will automatically force geth to only create a new block whenever there is a transaction in the network.

Markdown
"clique": {    
      "period": 0,    
      "epoch": 30000    
    }

Initialize the Nodes

Each node must initialize with the same genesis file.

Markdown
blockchain$ geth --datadir node1/ init genesis.json  
blockchain$ geth --datadir node2/ init genesis.json  
blockchain$ geth --datadir node3/ init genesis.json

Run the Nodes

We'll run node using geth with different available options. For reusable purposes, you can create a shell script. Put all the options you want to enable in one huge command.

Go inside the node1 directory and run the command.

Markdown
blockchain/node1$geth --nousb --datadir=$pwd --syncmode 'full' --port 30310 --miner.gasprice 0 --miner.gastarget 470000000000 --http --http.addr 'localhost' --http.port 8545 --http.api admin,eth,miner,net,txpool,personal,web3 --mine --allow-insecure-unlock --unlock "0x5D9DD2d7ea19D886F6D69c7E14e4F4Eeb922F8d4" --password password.txt

Additional Parameters

When you run the node, you will find the enode in the log, copy that enode and keep it with you.

Node 1

Markdown
enode://e832f6b25b2025ecb8a192439255557944a5e1c12175f72a7f1b79de811b94f3f11f930d9dcbf0389429ecba579856185f231930fbaf86a09d1b8c8071555f8e@127.0.0.1:30310

Node 2

Markdown
blockchain/node2$geth --nousb --datadir=$pwd --syncmode 'full' --port 30311 --miner.gasprice 0 --miner.gastarget 470000000000 --http --http.addr 'localhost' --http.port 8546 --http.api admin,eth,miner,net,txpool,personal,web3 --mine --allow-insecure-unlock --unlock "0x80051706C32359A75389EA36dDEbA2159067C360" --password password.txt

Enode for node2

Markdown
enode://0142f6ce892526b3c3a99fa986e5f58770ddddec88a8a0752542469006cac9dcd364386f8ce31ac2fe3fb58e5583108df21df4dd20497ab2a25b7056a60ae964@127.0.0.1:30311

Node 3

Markdown
blockchain/node3$geth --nousb --datadir=$pwd --syncmode 'full' --port 30312 --miner.gasprice 0 --miner.gastarget 470000000000 --http --http.addr 'localhost' --http.port 8547 --http.api admin,eth,miner,net,txpool,personal,web3 --mine --allow-insecure-unlock --unlock "0xf189Ee2c9b61487Fe26C72b8a0ba52f453E71c25" --password password.txt

Enode for node3

Markdown
enode://6948ac526196e3b0e71bf6718a83924d5471aaae1e763a66a0a615eb92b3ee62c1fbb896553e1187f1012cb11b0d154d431c77d3fe2489c6452b47cb113c98ce@127.0.0.1:30312

Now you have all three enodes, we'll use this to connect all the nodes.

Prepare static-nodes.json file

Geth has a different feature to connect to the network, we'll use static nodes. It generally used when you know the peers and we always want to connect with them.\

Crate static-nodes.json in node1 and add values of enodes as follows,

Markdown
blockchain/node1$touch static-nodes.json

Add all three enodes into it.

Markdown
[       
  "enode://e832f6b25b2025ecb8a192439255557944a5e1c12175f72a7f1b79de811b94f3f11f930d9dcbf0389429ecba579856185f231930fbaf86a09d1b8c8071555f8e@127.0.0.1:30310",    
      
  "enode://0142f6ce892526b3c3a99fa986e5f58770ddddec88a8a0752542469006cac9dcd364386f8ce31ac2fe3fb58e5583108df21df4dd20497ab2a25b7056a60ae964@127.0.0.1:30311",    
      
  "enode://6948ac526196e3b0e71bf6718a83924d5471aaae1e763a66a0a615eb92b3ee62c1fbb896553e1187f1012cb11b0d154d431c77d3fe2489c6452b47cb113c98ce@127.0.0.1:30312"    
]

Copy that json file to other nodes.

Markdown
blockchain/node1$cp static-nodes.json /home/dmdesai/blockchain/node2/    
blockchain/node1$cp static-nodes.json /home/dmdesai/blockchain/node3/

Start all the nodes

To make the process simpler, create a shall script file and paste a huge command into it.

Markdown
blockchain/node1$touch node1.sh
Markdown
nohup geth --nousb --datadir=$pwd --syncmode 'full' --port 30310 --miner.gasprice 0 --miner.gastarget 470000000000 --http --http.addr 'localhost' --http.port 8545 --http.api admin,eth,miner,net,txpool,personal,web3 --mine --allow-insecure-unlock --unlock "0x5D9DD2d7ea19D886F6D69c7E14e4F4Eeb922F8d4" --password password.txt &    
      
echo "Geth started on node 1"

Repeat this process for node2 and node3, then run the script file for each.

Markdown
blockchain/node1$sh node1.sh    
blockchain/node2$sh node2.sh     
blockchain/node3$sh node3.sh

Attach Geth with the following command

Markdown
blockchain/node1$ geth attach geth.ipc  
  
Welcome to the Geth JavaScript console!  
instance: Geth/v1.9.18-stable-f5382591/linux-amd64/go1.14.2  
coinbase: 0x5d9dd2d7ea19d886f6d69c7e14e4f4eeb922f8d4  
at block: 0 (Wed Jul 29 2020 16:30:59 GMT+0000 (UTC))  
datadir: /home/rsa-key-20200717/blockchain/node1  
modules: admin:1.0 clique:1.0 debug:1.0 eth:1.0 miner:1.0 net:1.0 personal:1.0 rpc:1.0 txpool:1.0 web3:1.0  
>

Check if the other two nodes are connected or not. It should show the peer count 2.

Markdown
> net.peerCount    
2

Your private blockchain is ready! You can make a transaction on one node, and it will be synced with the connected peers.

Stop the nodes

Markdown
$ ps ax | grep geth
  
$ kill <process id>  

$ kill -9 <process id> //kill the process forcefully

What’s next ?

We will see how you can connect nodes of different servers, so even if one server is down, the second one can process transactions.

Reference