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 Hyperledger, Eris/Monax, or the recently announced Enterprise Ethereum Alliance. These are different codebases with different client applications, so they correspond to different implementations of a different set of concepts. They are private in the sense that they limit who has access to their chain. They are also called permissioned blockchains, and to be perfectly transparent, we wish they were not even called blockchains at all. In this series of articles, what we call “private blockchain” is a private instance of the Ethereum implementation. Same code base, same client application, different network identifier and genesis block. In other words, what we will come to create in this series is a chain with the same rules as the main chain, the same consensus algorithm too, but a different root block. This will become clearer in part 3. For more information about the 3-layer model and differences between concepts, implementations and instances, you can also watch our Devoxx talk and read this article.

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://b8863bf7c8bb13c3afc459d5bf6e664ed4200f50b86aebf5c70d205d32dd77cf2a888b8adf4a8e55ab13e8ab5ad7ec93b7027e73ca70f87af5b425197712d272@[::]: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://41be9d79ebe23b59f21cbaf5b584bec5760d448ff6f57ca65ada89c36e7a05f20d9cfdd091b81464b9c2f0601555c29c3d2d88c9b8ab39b05c0e505dc297ebb7@[::]: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://b8863bf7c8bb13c3afc459d5bf6e664ed4200f50b86aebf5c70d205d32dd77cf2a888b8adf4a8e55ab13e8ab5ad7ec93b7027e73ca70f87af5b425197712d272@192.168.1.39:30303",
"enode://41be9d79ebe23b59f21cbaf5b584bec5760d448ff6f57ca65ada89c36e7a05f20d9cfdd091b81464b9c2f0601555c29c3d2d88c9b8ab39b05c0e505dc297ebb7@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.

Shameless plug

While you are waiting for the next part of this series, we just wanted to let you know that we are currently preparing a full-blown online training about the development of distributed applications on Ethereum and we are looking for your feedback to figure out what you would like to see in this training. If you want to help us, you can take a few minutes to answer a survey here.

And if you just want us to keep you informed when the full online training program will be available, you can register to our mailing list on beta.chainskills.com.

2 thoughts on “Pair the miners (4/6)”

Leave a Reply

Your email address will not be published. Required fields are marked *