This tutorial is part of a series of articles introduced here.

In part 4, we paired the miners and ensured that the private blockchain is properly synchronised.

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.

In this part, we are going to move forward with the setup of the Rapsberry PI and pair it with the miners.

All the commands ran from the computer are prefixed by “computer$“. Those ran from the RPi are identified with the prefix “pi$“.

Step 1 – Create the datadir folder

As already done for the miners, we have to use a specific folder that will host the data of the private blockchain.

Create this folder with the following command:

pi$ mkdir -p ~/ChainSkills/node

Step 2 – Transfer the genesis file

From your computer, upload the genesis.json file to the RPi:

computer$ cd ~/ChainSkills

computer$ sftp pi@
pi@'s password: 
Connected to

sftp> cd ChainSkills

sftp> put genesis.json
Uploading genesis.json to /home/pi/ChainSkills/genesis.json
genesis.json 100% 420 83.8KB/s 00:00 

sftp> exit

Step 3 – Initialize the node

It’s time to initialize the private blockchain on the RPi with the genesis block.
The private blochain data will reside in the folder “node”.
pi$ cd ~/ChainSkills
pi$ geth --datadir ~/ChainSkills/node init ../genesis.json

I0105 00:13:28.961585 cmd/utils/flags.go:615] WARNING: No etherbase set and no accounts found as default
I0105 00:13:29.441262 cmd/geth/chaincmd.go:131] successfully wrote genesis block and/or chain rule set: 6e92f8b23bcdfdf34dc813cfaf1d84b71beac80530506b5d63a2df10fe23a660
The log provides the following information:
  • you need a default account
  • the blockchain has been successfully created

Step 4 – Create accounts

Create an initial account that will be used to run the node.

To create the default account, type the following command. Keep the password in a safe place:

pi$ geth --datadir ~/ChainSkills/node account new
Your new account is locked with a password. Please give a password. Do not forget this password.
Repeat passphrase: 
Address: {b312d49ee143e803e07814ce0213e6327ab19250}
The account creation might take a few seconds, don’t worry.
Add an additional account for testing purposes:
pi$ geth --datadir ~/ChainSkills/node account new 
Your new account is locked with a password. Please give a password. Do not forget this password. 
Repeat passphrase: 
Address: {6af547b83493fd59bf5a2e67546b65191392f45a}
The wallet for these accounts is located right here:
pi$ ls -l ~/ChainSkills/node/keystore 
-rw------- 1 pi pi 491 Jan 5 00:16 UTC--2017-01-04T23-15-54.907864384Z--b312d49ee143e803e07814ce0213e6327ab19250
-rw------- 1 pi pi 491 Jan 5 00:16 UTC--2017-01-04T23-16-32.920742236Z--6af547b83493fd59bf5a2e67546b65191392f45a
To list all accounts available on your node, use the following command:
pi$ geth --datadir ~/ChainSkills/node account list 

Account #0: {b312d49ee143e803e07814ce0213e6327ab19250} /home/pi/ChainSkills/node/keystore/UTC--2017-01-04T23-15-54.907864384Z--b312d49ee143e803e07814ce0213e6327ab19250

Account #1: {6af547b83493fd59bf5a2e67546b65191392f45a} /home/pi/ChainSkills/node/keystore/UTC--2017-01-04T23-16-32.920742236Z--6af547b83493fd59bf5a2e67546b65191392f45a

Step 5 – Prepare the node

We are ready to start the node from our RPi.

To start the node, we will require to run the following command:
geth --identity "node1" --fast --networkid 42 --datadir /home/pi/ChainSkills/node --nodiscover --rpc --rpcport "8042" --port "30303" --unlock 0 --password "/home/pi/ChainSkills/node/password.sec" --ipcpath /home/pi/.ethereum/geth.ipc

The meaning of the main parameters is the following:

  • identity: name of our node
  • fast: fast syncing of the database (more details here)
  • networkid: this network contains an arbitrary value that will be used to identify all nodes of the network. This value must be different from 0 to 3 (used by the live chains)
  • datadir: folder where is stored in our private blockchain
  • rpc and rpcport: enabling HTTP-RPC server and giving its listening port number
  • port: network listening port number
  • nodiscover: disable the discovery mechanism (we will pair our nodes later)
  • unlock: id of the default account
  • password: path to the file containing the password of the default account
  • ipcpath: path where to store the filename for IPC socket/pipe
You can find more information about Geth parameters right here.
We recommend you to store the Geth command into a runnable script. In our example, this script is called “” and is located here: ~/ChainSkills/node

geth --identity "node1" --fast --networkid 42 --datadir /home/pi/ChainSkills/node --nodiscover --rpc --rpcport "8042" --port "30303" --unlock 0 --password "/home/pi/ChainSkills/node/password.sec" --ipcpath /home/pi/.ethereum/geth.ipc
You should then create the password file in the datadir folder of your node, and this file should just contain the password of the default account. In our example, this file is called “password.sec” and is located here: ~/ChainSkills/node

Step 6 – Start the node

Make the script runnable:

pi$ cd ~/ChainSkills/node 

pi$ chmod +x

Let’s start the node:

pi$ ./
You will notice that the server starts.

Step 7 – JavaScript console

You can manage your node using the Geth Javascript console.
To use this console from your RPi, open a second SSH session attached to your running instance of Geth.
Open a new terminal session and type “geth attach“.
pi$ geth attach

Step 8 – Stop the mining nodes

If your miners are still running on your computer, go to their console window and press CTRL-C.

Another option is to kill the Geth running process as illustrated here below:

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 9 – Synchronise the blockhain

In this step, we are going to link the RPi to the private blockchain already synchronised on our miners.

Step 9.1 – Get Node info

Let’s start the node:
pi$ cd ~/ChainSkills/node

pi$ ./
 From your second terminal session, start the Geth console:
pi$ geth attach

Retrieve the node information:

> admin.nodeInfo.enode


Step 9.2 – Update the file “static-nodes.json”

The file “static-nodes.json” created in part 4 has to be updated by adding the information of the node deployed on the RPi.

This file is on your computer under one of the following locations:

  • ~/ChainSkills/miner1
  • ~/ChainSkills/miner2

Based on our environment, we will have the following content (adjust the values according to your environment):


The first two entries are related to miner #1 and miner #2. The last row identified the node deployed on the RPi (with its IP address and port number).

Make sure your IP addresses are still up-to-date as they tend to change on a local network.

This new version of “static-nodes.json” must be stored under the following locations:

  • [miner #1] ~/ChainSkills/miner1
  • [miner #2] ~/ChainSkills/miner2
  • [RPi] ~/ChainSkills/node

You can transfer this file to the RPi using the SFTP command:

computer$ cd ~/ChainSkills/miner1

computer$ sftp pi@
pi@'s password: 
Connected to

sftp> cd ChainSkills/node

sftp> put static-nodes.json
Uploading static-nodes.json to /home/pi/ChainSkills/node/static-nodes.json
static-nodes.json 100% 480 44.8KB/s 00:00 

sftp> exit

Step 9.3 – Restart your blockchain

Stop and start each node of your blockchain:

  • miner #1
  • miner #2
  • RPi

Step 10 – Check the synchronisation process

Open the Geth console linked to the miner #1:

computer$ geth attach

Check which nodes is paired to the 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: "",
remoteAddress: ""
 protocols: {
 eth: {
 difficulty: 892873381,
 head: "0x263550838a2c63ffe70f91a5bf1851dce951d28d90e7863d19805711bac578e3",
 version: 63
}, {
 caps: ["eth/63"],
 id: "c52b3349d899e1f8ea67c2d01df35c3a40532dec41174460b777bab020079e1a546313552b91d5f61adb86ed4e74dd80c0ced70c91d658ef0e4f05969a1cf78e",
 name: "Geth/node1/v1.5.5-stable-ff07d548/linux/go1.7.4",
 network: {
 localAddress: "",
remoteAddress: ""
 protocols: {
 eth: {
 difficulty: 891744952,
 head: "0x6ae07a4c2636835445a68d68219e1bb41c04a9519559a9cc899687218c00253d",
 version: 63

We can see that two nodes are paired with the miner #1: miner #2 and the RPi.

You can repeat this process on each node to ensure that they are paired with each other.

Step 11 -Validate the synchronisation

Let’s validate the synchronisation process by sending some ethers between accounts defined on each node (miners and RPi).

Before you proceed, ensure that the mining process is running on both miners.

Step 11.1 – Send ethers from Miner #1 to RPI

We are going to send 10 ethers between the following accounts:

  • miner #1(eth.coinbase) -> RPI(eth.accounts[1])

From the Geth console linked to the RPi, check the initial balance of the account[1] that will receive ethers:

pi$ geth attach 
> eth.accounts[1]

>  web3.fromWei(eth.getBalance(eth.accounts[1]))

The account #1 has 0 ether.

From the Geth console linked to the miner #1, send 10 ethers from the default account to the address of the account[1] created in the RPi:

computer$ geth attach
> eth.sendTransaction({from: eth.coinbase, to: "0x6af547b83493fd59bf5a2e67546b65191392f45a", value: web3.toWei(10, "ether")})

From the miner #1 (or the miner #2), check if the recipient has received the ethers:

> web3.fromWei( eth.getBalance("0x6af547b83493fd59bf5a2e67546b65191392f45a"))

From the RPI, check that you have the same balance:

> web3.fromWei( eth.getBalance(eth.accounts[1]))

Of course, the transaction will be processed ONLY if the mining process is started from at least one miner. 

Step 7.1 – Send ethers from RPI to Miner #2

We are going to send 2 ethers between the following accounts:

  • RPI(eth.accounts[1]) -> miner #2(eth.accounts[1])

From the Geth console linked to the miner #2, check the initial balance of the account that will receive ethers:

computer$ geth attach ipc:/Users/eloudsa/ChainSkills/miner2/geth.ipc
> eth.accounts[1]

>  web3.fromWei(eth.getBalance(eth.accounts[1]))

From the Geth console linked to the RPI, send 2 ethers from the account #1 to the address of the account[1] created on the miner #2:

pi$ geth attach 
> eth.sendTransaction({from: eth.accounts[1], to: "0xfa919b49ef34a821fb4cadfdfa5cc6593cb46fe1", 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
From the RPi, unlock the account #1 with its password:
> personal.unlockAccount(eth.accounts[1], 'type your password')

From the RPi, we are ready to send our transaction:

> eth.sendTransaction({from: eth.accounts[1], to: "0xfa919b49ef34a821fb4cadfdfa5cc6593cb46fe1", value: web3.toWei(2, "ether")})

From the RPi, check the balance:

> web3.fromWei( eth.getBalance(eth.accounts[1]))

From the miner #2, check that the recipient has received the ethers:

> web3.fromWei( eth.getBalance(eth.accounts[1]))


Congratulations! You have synchronised your miners and the RPi.

In part 6, we create and deploy a Smart Contract.

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

Said Eloudrhiri