Pair the miners (4/6)
This tutorial is part of a series of articles introduced here.
In part 3, we configured the miners of our private blockchain.
NB: It is important that what we mean by “private Ethereum blockchain” in this context has absolutely nothing to do with the “private blockchain” championed by
We saw that transactions are not propagated from miner #1 to miner #2.
Remember that a blockchain is a peer-to-peer network. This means that our miners need to see each other in order to propagate transactions.
In addition, the discovery protocol is not working on a private blockchain. This means that we have to configure each node to specify the identity and the location of its peers.
This part describes how to pair our miners.
Let’s start by retrieving the node information that uniquely identify each node deployed in the blockchain.
Step 1 Clean your miners
We noticed some issues when we tried to synchronise our miners having several thousand blocks. Sometimes, miners were not able to pair or the synchronization process became too slow.
The easiest way is to reset the chaindata of the private blockchain installed on each miner.
Step 1.1 – Stop miners
First ensure that your miners are stopped.
As a reminder, you can either press ^C on the miner’s console, or search and kill the “geth” process:
computer$ ps aux | grep geth eloudsa 43872 0.0 2.2 556717632 363492 s001 S+ 3:49PM 1:58.01 geth --identity miner1 --dev computer$ kill -INT 43872
Step 1.2 – Delete the chaindata
Delete chain data for miners:
computer$ rm -rf ~/ChainSkills/miner1/geth computer$ rm -rf ~/ChainSkills/miner2/geth
Step 1.3 – Initialize miners
We initialize our miners with the genesis block.
Start with the miner #1:
computer$ cd ~/ChainSkills computer$ geth --datadir ~/ChainSkills/miner1 init genesis.json
Then the miner #2:
computer$ cd ~/ChainSkills computer$ geth --datadir ~/ChainSkills/miner2 init genesis.json
Step 2 Get IP address
Get the IP address of your computer running miners.
computer$ ipconfig getifaddr en0 192.168.1.39
Replace the interface according to your network settings:
- en0: wired/ethernet
- en1: wireless
Step 3 Get Node info from miner #1
Step 3.1 Node info for miner #1
Let’s start the miner #1:
computer$ cd ~/ChainSkills/miner1 computer$ ./startminer1.sh ...
Open a second terminal and start the Geth console:
computer$ geth attach ... >
Stop the mining to avoid generating too much blocks before the synchronisation process:
> miner.stop() true
Retrieve the node information:
> admin.nodeInfo.enode "enode://b8863bf7c8bb13c3afc459d5bf6e664ed4200f50b86aebf5c70d205d32dd77cf2[email protected][::]:30303?discport=0"
Step 3.2 Get Node info from miner #2
Repeat the process to retrieve the node information from the second miner.
Start the miner #2:
computer$ cd ~/ChainSkills/miner2 computer$ ./startminer2.sh ...
Open a second terminal and start the Geth console:
computer$ geth attach ipc:./miner2/geth.ipc ... >
Stop the mining to avoid generating too much blocks before the synchronisation process:
> miner.stop() true
Retrieve the node information:
> admin.nodeInfo.enode "enode://41be9d79ebe23b59f21cbaf5b584bec5760d448ff6f57ca65ada89c36e7a05f20[email protected][::]:30304?discport=0"
Step 4 – Pair the nodes
There are different ways to pair nodes.
Here, we illustrate how to define permanent static nodes stored in a file called “static-nodes.json“. This file will contain the node information of our miners.
Based on our environment, we will have the following content:
[ "enode://b8863bf7c8bb13c3afc459d5bf6e664ed4200f50b86aebf5c70d205d32dd77cf2[email protected]192.168.1.39:30303", "enode://41be9d79ebe23b59f21cbaf5b584bec5760d448ff6f57ca65ada89c36e7a05f20[email protected]192.168.1.39:30304" ]
You will notice that we have replaced the placeholder [::] with the IP address of our computer. The last part (?discport=0) has been removed.
Each node information is separated by a comma character.
Based on our example, the file “static-nodes.json” must be stored under the following location:
- ~/ChainSkills/miner1
- ~/ChainSkills/miner2
When the miner starts, the Geth process will process the file automatically.
Step 5 – Restart your miners
Stop and start the miners to ensure that they will properly reload the “static-nodes.json” file.
If you check the console of your miners, you should see a line mentioning the synchronisation process (“Block synchronisation started”):
... I1219 01:12:03.223537 eth/downloader/downloader.go:326] Block synchronisation started ...
Step 6 – Check the synchronisation process
We check if the miners are properly paired.
Step 6.1 – Check from miner #1
Open the Geth console linked to the miner #1:
computer$ geth attach ... >
Check which nodes are paired to miner #1:
> admin.peers [{ caps: ["eth/62", "eth/63"], id: "41be9d79ebe23b59f21cbaf5b584bec5760d448ff6f57ca65ada89c36e7a05f20d9cfdd091b81464b9c2f0601555c29c3d2d88c9b8ab39b05c0e505dc297ebb7", name: "Geth/miner2/v1.5.5-stable-ff07d548/darwin/go1.7.4", network: { localAddress: "192.168.1.39:59153", remoteAddress: "192.168.1.39:30304" }, protocols: { eth: { difficulty: 96831214, head: "0x0f8a3318a47429aee7a442cd1c3258eab7427b7fa1cb3c2a3e4bdf70ed6d8cf8", version: 63 } } }]
We can see that our node is paired to miner #2 identified by its IP address and its port number (30304).
Step 6.2 – Check from miner #2
Open the Geth console linked to the miner #2:
computer$ geth attach ipc:./miner2/geth.ipc ... >
Check which nodes are paired to miner #2:
> admin.peers [{ caps: ["eth/62", "eth/63"], id: "b8863bf7c8bb13c3afc459d5bf6e664ed4200f50b86aebf5c70d205d32dd77cf2a888b8adf4a8e55ab13e8ab5ad7ec93b7027e73ca70f87af5b425197712d272", name: "Geth/miner1/v1.5.5-stable-ff07d548/darwin/go1.7.4", network: { localAddress: "192.168.1.39:30304", remoteAddress: "192.168.1.39:59153" }, protocols: { eth: { difficulty: 88045328, head: "0xa084d0c7f1a18120780c44bd4ba6c3ec237eb3feb0912bffd74ac1030246a723", version: 63 } } }]
We can see that our node is paired to miner #1 identified by its IP address and its port number (59153).
Step 7 -Validate the synchronisation
Let’s validate the synchronisation process by sending some ethers between accounts defined on each miner.
We are going to send 10 ethers between the following accounts:
- miner #1(eth.coinbase) -> miner #2(eth.accounts[1])
eth.coinbase is the default account that receive the rewards for the mining process. In the miner #1, eth.coinbase is the same as eth.accounts[0].
First, make sure that the mining process is running on both miners.
Step 7.1 – Send ethers from Miner #1 to Miner #2
Start a Geth console linked to the miner #2, retrieve the address of the account[1] and check its initial balance:
computer$ geth attach ipc:./miner2/geth.ipc ... > eth.accounts[1] "0xfa919b49ef34a821fb4cadfdfa5cc6593cb46fe1" > web3.fromWei(eth.getBalance(eth.accounts[1])) 0
The account #1 has no ether.
From the Geth console linked to the miner #1, send 10 ethers from the default account to the address of the account[1]:
computer$ geth attach ... > eth.sendTransaction({from: eth.coinbase, to: "0xfa919b49ef34a821fb4cadfdfa5cc6593cb46fe1", value: web3.toWei(10, "ether")})
From the miner #1, check if the recipient has received the ethers:
> web3.fromWei( eth.getBalance("0xfa919b49ef34a821fb4cadfdfa5cc6593cb46fe1")) 10
From the miner #2, check that you have the same balance:
> web3.fromWei( eth.getBalance(eth.accounts[1])) 10
Step 7.2 – Send ethers from Miner #2 to Miner #1
We are going to send 2 ethers between the following accounts:
- miner #2(eth.accounts[1]) -> miner #1(eth.accounts[1])
From the Geth console linked to the miner #1, check the initial balance of the account that will receive ethers:
computer$ geth attach ... > eth.accounts[1] "0xae3ab39b3ebc425289dad620aece197a4a3f8940" > web3.fromWei(eth.getBalance(eth.accounts[1])) 0
The account #1 has 0 ether.
From the Geth console linked to the miner #2, send 2 ethers from the account #1:
computer$ geth attach ipc:./miner2/geth.ipc ... > eth.sendTransaction({from: eth.accounts[1], to: "0xae3ab39b3ebc425289dad620aece197a4a3f8940", value: web3.toWei(2, "ether")}) Error: account is locked at web3.js:3119:20 at web3.js:6023:15 at web3.js:4995:36 at <anonymous>:1:1
Oops! We cannot send the transaction because the account #1 is locked.
To send transactions from an account, Ethereum requires that you unlock this account. The coinbase account is unlocked by our startminer.sh script thanks to the password file. But all other accounts are locked.
From the miner #2, unlock the account #1 with its password:
> personal.unlockAccount(eth.accounts[1], 'type your password') true
From the miner #2, we are ready to send our transaction:
> eth.sendTransaction({from: eth.accounts[1], to: "0xae3ab39b3ebc425289dad620aece197a4a3f8940", value: web3.toWei(2, "ether")}) "0x02b1c360e3b094e8c7faac3d3f8def8eec6350a3d68a1b7e071827d1026221f0"
From the miner #2, check that our balance has changed (2 ethers plus some transaction fees):
> web3.fromWei( eth.getBalance(eth.accounts[1])) 7.99958
From the miner #1, check that the recipient has received the ethers:
> web3.fromWei( eth.getBalance(eth.accounts[1])) 2
Summary
Congratulations! You have synchronised your miners.
In part 5, we will synchronise the RPi node with these miners.