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
- OS: Ubutu 16.04 server
- Software: Geth Version: 1.9.18-stable
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.
- Full Node - This node keeps a copy of the full 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
$ 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
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
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
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.
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.
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.
blockchain$ puppeth
Specify the chain id
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.
What would you like to do? (default = create)
1. Create new genesis from scratch
2. Import already existing genesis
> 1
Select proof-of-authority.
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.
How many seconds should blocks take? (default = 15)
> 1
Provide accounts created previously
Which accounts are allowed to seal? (mandatory at least one)
> 0x5D9DD2d7ea19D886F6D69c7E14e4F4Eeb922F8d4
> 0x80051706C32359A75389EA36dDEbA2159067C360
> 0xf189Ee2c9b61487Fe26C72b8a0ba52f453E71c25
> 0x
Provide accounts to get some free ethers
Which accounts should be pre-funded? (advisable at least one)
> 0x5D9DD2d7ea19D886F6D69c7E14e4F4Eeb922F8d4
> 0x80051706C32359A75389EA36dDEbA2159067C360
> 0xf189Ee2c9b61487Fe26C72b8a0ba52f453E71c25
> 0x
Should the precompile-addresses (0x1 .. 0xff) be pre-funded with 1 wei? (advisable yes)
> yes
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.
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
1. Modify existing configurations
2. Export genesis configurations
3. Remove genesis configuration
> 2
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
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.
"clique": {
"period": 0,
"epoch": 30000
}
Initialize the Nodes
Each node must initialize with the same genesis file.
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.
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
- --nousb Disables monitoring for and managing USB hardware wallets.
- --datadir=$pwd Data directory for the databases and keystore.
- --syncmode 'full' Enables full chain sync (default: "fast").
- --port 3030 assign port geth process.
- --miner.gasprice 0 On private network we don't want to pay anything, so make it zero.
- --miner.gastarget 470000000000 use same as the genesis file. However, actual gaslimit is dynamic for new block and depends on the previous block.
- --http Enable the HTTP-RPC server.
- --http.addr 'localhost' HTTP-RPC server listening interface (default: "localhost").
- --http.port 8545 HTTP-RPC server listening port (default: 8545).
- --http.api Buch of apis to be used over RPC calls.
- --mine Enable mining.
- --allow-insecure-unlock Allow insecure account unlocking when account-related RPCs are exposed by http.
- --unlock "0x251B7dC42D7472314fE4d6c3b9CAD2fb5927d7c8" Account to unlock, we'll use the address of node1.
- --password password.txt Password file to use for non-interactive password input
Additional Parameters
- --rpccorsdomain "*" Comma separated list of domains from which to accept cross origin requests (browser enforced).
- --rpcvhosts="*" Comma separated list of virtual hostnames from which to accept requests (server enforced). Accepts '*' wildcard.
- --miner.threads value Number of CPU threads to use for mining (default: 0).
When you run the node, you will find the enode in the log, copy that enode and keep it with you.
Node 1
enode://e832f6b25b2025ecb8a192439255557944a5e1c12175f72a7f1b79de811b94f3f11f930d9dcbf0389429ecba579856185f231930fbaf86a09d1b8c8071555f8e@127.0.0.1:30310
Node 2
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
enode://0142f6ce892526b3c3a99fa986e5f58770ddddec88a8a0752542469006cac9dcd364386f8ce31ac2fe3fb58e5583108df21df4dd20497ab2a25b7056a60ae964@127.0.0.1:30311
Node 3
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
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,
blockchain/node1$touch static-nodes.json
Add all three enodes into it.
[
"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.
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.
blockchain/node1$touch node1.sh
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.
blockchain/node1$sh node1.sh
blockchain/node2$sh node2.sh
blockchain/node3$sh node3.sh
Attach Geth with the following command
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.
> 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
$ 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
- https://github.com/ethereum/go-ethereum/wiki/Command-Line-Options