Raspberry Pi and Ethereum: The Epilogue

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

In part 6, we finalized the configuration of the private blockchain. We sent ether between our nodes and verified that the database 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.

So far, we only worked with pure software. In this final part, we will connect our blockchain with the physical world and connect some wires.

The goal of this tutorial is to check whether you are allowed to use a service. By using a button and two LEDs (green and red), we will be able to check the Smart Contract (SmartToken) to retrieve the number of tokens assigned to the user account (identified by its address).

To complete this tutorial, we will use the following solutions:

  • Hardware: A breadboard, 2 LEDs (green and red), a button, 4 resistors (2 x 220Ω, 1kΩ, 10kΩ), some wires
  • Software: Node.js and two packages (Web3 and OnOff)

The sample was inspired by the post available here.

It’s time to build some electronics.

Step 1 – Start with some electronics

Before you proceed, ensure your RPi is turned off.

The goal is to connect a LED to the GPIO17 port of the RPi.

The schematic is the following:

Here below you can see the breadboard that shows how to physically connect the electronic parts:

The GPIO17 port (port 11) is linked to the anode pin (positive) of the led.

The cathode pin (negative) of the led is connected to the resistor which is linked to the GND port (port 6) of the RPi.

Ensure to respect the polarity of the LED (check here).

When you have finished, you can power on the RPi.

Step 2 – Connect to your RPi

Use the SSH command to connect to your RPi as illustrated here below:

computer$ ssh pi@192.168.1.31

Step 3 – Start nodes

Before deploying the Smart Contract, let’s start our nodes.

Start the miner #1:

computer$ cd ~/ChainSkills/miner1
computer$ ./startminer1.sh

Start the miner #2:

computer$ cd ~/ChainSkills/miner2
computer$ ./startminer2.sh

Start the RPi node:

pi$ cd ~/ChainSkills/node
pi$ ./starnode.sh

Step 4 – Prepare the RPi

This step describes all the operations to perform on your RPi in order to set up all the pieces of software.

Step 4.1 – Install Node.js

We will use Node.js to run the script that interacts with the Smart Contract.

To install Node.js 7.x on your RPi, please follow the instructions illustrated here below:

pi$ curl -sL https://deb.nodesource.com/setup_7.x | sudo -E bash -
pi$ sudo apt-get install nodejs

pi$ node -v
v7.4.0

pi$ npm -v
4.0.5

Step 4.2 – Install Git

Git will be required for the installation of Web3:

pi$ sudo apt-get install git

Step 4.3 – Prepare the project folder

Let’s create the folder for our project:
pi$ mkdir -p ~/Projects/ChainSkills/SmartToken

Step 4.4 – Install Web3 module

The Ethereum Web3 package is a node module that provides a JavaScript API to interact with the Ethereum blockchain.
This module will be required to allow the JS script to fetch the status of the Smart Contract.
Install the Web3 module:
pi$ cd ~/Projects/ChainSkills/SmartToken
pi$ npm install web3

Step 4.5 – Install OnOff module

The OnOff module is used to easily interact with GPIO pins of the RPi and set them On or Off.

Install the OnOff module:
pi$ cd ~/Projects/ChainSkills/SmartToken
pi$ npm install onoff

Step 5 – Create the client application

Let’s create a JS script the called “smart_token.js“.

This script will be used to:

  1. Interact with the Smart Contract
  2. Interact with RPi

Create the file “smart_token.js”:

pi$ cd ~/Projects/ChainSkills/SmartToken
pi$ nano smart_token.js

Copy and paste the following code:

// Interaction with GPIO
var Gpio = require('onoff').Gpio

// Interaction with Ethereum
var Web3 = require('web3')
var web3 = new Web3()

// connect to the local node
web3.setProvider(new web3.providers.HttpProvider('http://localhost:8042'))

// The contract that we are going to interact with
var contractAddress = '0xe1d76d2bffc600333248343f7a1d144edaef29a2'

// Define the ABI (Application Binary Interface)
var ABI = JSON.parse('[{"constant":false,"inputs":[{"name":"recipient","type":"address"},{"name":"value","type":"uint256"}],"name":"depositToken","outputs":[{"name":"success","type":"bool"}],"payable":false,"type":"function"},{"constant":true,"inputs":[{"name":"recipient","type":"address"}],"name":"getTokens","outputs":[{"name":"value","type":"uint256"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"recipient","type":"address"},{"name":"value","type":"uint256"}],"name":"withdrawToken","outputs":[{"name":"success","type":"bool"}],"payable":false,"type":"function"},{"anonymous":false,"inputs":[{"indexed":false,"name":"status","type":"uint256"}],"name":"OnStatusChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"_from","type":"address"},{"indexed":false,"name":"_value","type":"uint256"}],"name":"OnValueChanged","type":"event"}]')

// contract object
var contract = web3.eth.contract(ABI).at(contractAddress)

// components connected to the RPi
var greenLed = new Gpio(14, 'out')
var redLed = new Gpio(15, 'out')
var button = new Gpio(18, 'in', 'rising')


// display initial state
showStatus()


// watch event on the button
button.watch(function (err, value) {
 if (err) {
 throw err
 }

 showStatus()
})


// wait for an event triggered on the Smart Contract
var onValueChanged = contract.OnValueChanged({_from: web3.eth.coinbase});

onValueChanged.watch(function(error, result) {
 if (!error) {
 showStatus()
 }
})


// power the LED according the value of the token
function showStatus() {
 
 // retrieve the value of the token
 var token = contract.getTokens(web3.eth.coinbase)

 // display the LED according the value of the token
 if (token > 0) {
 // Green: you have enough token
 redLed.writeSync(0)
 greenLed.writeSync(1)
 } else {
 // Red: not enough token
 greenLed.writeSync(0)
 redLed.writeSync(1)
 }

}


// release process
process.on('SIGINT', function () {
 greenLed.unexport()
 redLed.unexport()
 button.unexport()
})

This script has to be changed according to your environment.

First, change the value of the variable “contractAddress” with the address of the contract deployed on your private blockchain (see part 6).

Then, provide the ABI of your SmartContract (see part 6) by replacing the content of the variable “ABI“.

Step 6 – Run the client application

Run the client application:

pi$ node smart_token.js

The client application will wait for a change to occur on the Smart Contract.

Step 7 – Test the application

Test your application using Mist by depositing tokens to the coinbase address of the Pi node.

You should see the appropriate LED displayed according the remaining amount of token.

You can also press the button to get the number of tokens.

Summary

Congratulations!

You have successfully completed this series of tutorials.

Of course, this is just a glimpse of what you can do with Ethereum but you had the opportunity to experiment some part of this technology.

Now, it’s up to you to move forward with the journey and to imagine other kinds of Smart Contracts and how to link them with IoT devices.

Shameless plug

Now that you are done with 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.

Synchronize the Raspberry PI with the Private Blockchain (5/6)

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@192.168.1.31
pi@192.168.1.31's password: 
Connected to 192.168.1.31.

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.
Passphrase: 
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. 
Passphrase: 
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 “startnode.sh” and is located here: ~/ChainSkills/node
#!/bin/bash

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 startnode.sh

Let’s start the node:

pi$ ./startnode.sh
...
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$ ./startnode.sh
...
 From your second terminal session, start the Geth console:
pi$ geth attach
...
>

Retrieve the node information:

> admin.nodeInfo.enode

"enode://c52b3349d899e1f8ea67c2d01df35c3a40532dec41174460b777bab020079e1a546313552b91d5f61adb86ed4e74dd80c0ced70c91d658ef0e4f05969a1cf78e@[::]:30303?discport=0"

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):

[
"enode://b8863bf7c8bb13c3afc459d5bf6e664ed4200f50b86aebf5c70d205d32dd77cf2a888b8adf4a8e55ab13e8ab5ad7ec93b7027e73ca70f87af5b425197712d272@192.168.1.39:30303",
"enode://41be9d79ebe23b59f21cbaf5b584bec5760d448ff6f57ca65ada89c36e7a05f20d9cfdd091b81464b9c2f0601555c29c3d2d88c9b8ab39b05c0e505dc297ebb7@192.168.1.39:30304",
"enode://c52b3349d899e1f8ea67c2d01df35c3a40532dec41174460b777bab020079e1a546313552b91d5f61adb86ed4e74dd80c0ced70c91d658ef0e4f05969a1cf78e@192.168.1.31:30303"
]

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@192.168.1.31
pi@192.168.1.31's password: 
Connected to 192.168.1.31.

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: "192.168.1.39:30303",
remoteAddress: "192.168.1.39:63533"
 },
 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: "192.168.1.39:30303",
remoteAddress: "192.168.1.31:50142"
 },
 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]
"0x6af547b83493fd59bf5a2e67546b65191392f45a"

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

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"))
10

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

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

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]
"0xfa919b49ef34a821fb4cadfdfa5cc6593cb46fe1"

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

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')
true

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

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

From the RPi, check the balance:

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

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

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

Summary

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 beta.chainskills.com.

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.

Create a private Ethereum blockchain with IoT devices (1/6)

Introduction

This series of tutorials will describe how to set up a private Ethereum blockchain that will be composed of a computer (miner) and one or several Raspberry PI 3 devices (nodes).

The objective is to build a development environment to learn about blockchain principles, to develop and test your own smart contracts before releasing them to the live chain (mainnet).

To make this project fun, we will integrate a RPi with a Smart Contract deployed on a private chain. The Smart Contract will be used to check if a user has enough tokens to use a service. The RPi will be used to visualize the status of the contract.

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.

Conventions

We will use the following naming conventions to identify the devices on which the commands are entered:

computer$ A computer requires to perform initial configuration

pi$ Shell of the node running on the Raspberry PI device

Disclaimer

This series of tutorials doesn’t pretend to be comprehensive neither to give you a full introduction to Ethereum.

There are many ways to set up a private Ethereum blockchain from the most simplistic to the most complicated.

Here are some other examples:

  • Microsoft Azure and RPi  (here)
  • Docker image (here)
  • Pre-defined images such with EthRaspian (here)

Part 1: Install an Ethereum node on a Raspberry PI (RPi)

In this first part, we will describe the steps to transform your Raspberry PI 3 (RPi) into an Ethereum node.

The RPi is intended to act as a node connected to our private Ethereum blockchain. This means that it’s not required to install a full flesh operating system. A minimal image of Raspbian is good enough.

For information, there are pre-bundled RPi images that make it possible for you to transform your RPi into an Ethereum node.

One of these images is provided by the project EthRaspbian.

Here, we chose to build our Ethereum node without these prepared images. The objective is to show you all the required steps to do it from scratch.

Due to hardware limitations (CPU, memory), your RPi will not be able to mine ethers or to build new blocks of transactions.

Step 1 – Check your configuration

We will use a Raspberry PI 3 with a microSD of 16 Gb and a computer to prepare the microSD card.

The setup of the RPi will require the following hardware:

  • A Raspberry Pi
  • An SD Card with at least 16Gb
  • A LAN cable
  • A keyboard
  • A display

Step 2 – Format your SD Card

Insert your SD card on your computer and format it as FAT32.

On macOS, use the format ExFat in Disk Utility:

Step 3 – Write the Raspbian image

From your computer, download the Raspbian Jessie Lite image (minimal image) available here.

Unzip the file.

Write the image on the SD card by following instructions there. The process varies slightly depending on whether you are on a MacOS, Linux or Windows machine.

Here is an example for macOS (be very careful with the commands, every character matters):

computer$ diskutil list
...
/dev/disk5 (external, physical):
...

computer$ diskutil unmountDisk /dev/disk5

computer$ sudo dd bs=1m if=2016-11-25-raspbian-jessie-lite.img of=/dev/rdisk5

computer$ diskutil eject /dev/disk5

Ensure that your RPi is powered off.

Insert the SD card on you RPi and power on the device. Your RPi will boot the image.

Step 4 – Configure your RPi

Log in the RPi with the default credential is:

  • username: pi
  • password: raspberry

The RPi needs to be configured:

  • Change the keyboard layout (if required)
  • Set the timezone: required to allow a blockchain synchronisation between nodes
  • Enable SSH: securely access your RPi from your computer
  • Change your hostname: easily identified your RPi within your network (example: node1, node2, etc.)

We use raspi-config to setup all these settings:

pi$ sudo raspi-config

1) Timezone can be changed from the option "Internationalisation Options" and "Change Timezone".

2) Keyboard layout can be changed from the option "Internationalisation Options" and "Change Keyboard Layout". 

3) SSH can be enabled from the option "Advanced Options" then "SSH". 

4) The hostname can be changed from the option "Advanced Options" and then "Hostname. In our tutorial, we use the hostname "ethpinode1"

Press Finish and reboot your RPi:

p$> sudo reboot

Finally, you should really change the default password of the pi account:

pi$ passwd

Step 5 – Setup Wi-Fi

To setup your Wi-Fi interface, proceed as described below:

pi$ sudo nano /etc/wpa_supplicant/wpa_supplicant.conf
  1. Change the country code to set yours
  2. Add the following lines at the end of the file and replace the ssid with the name of your WiFi and psk with your WiFi’s password:
network={
 ssid="enter the SSID of your Wi-Fi network"
 psk="enter the password of your Wi-Fi network"
}

To apply your changes, restart your RPi or your Wi-Fi interface:

pi$ sudo ifdown wlan0
pi$ sudo ifup wlan0

You can now unplug  your LAN cable.

Step 6 – Connect to your RPI

To connect remotely to your RPi through SSH, you have to know the IP address of your RPi device.

You can find it by typing the following command from your RPi:

pi$ ifconfig

Or you can search it from your LAN by filtering IP adresses from a MAC  prefix address (b8:27:eb is the MAC prefix address of RPi devices):

computer$ arp -na | grep -i b8:27:eb
? (192.168.1.31) at b8:27:eb:1c:aa:94 on en0 ifscope [ethernet]


If you have several RPi, you can locate them using the “host” command:

computer$ host 192.168.1.31
31.1.168.192.in-addr.arpa domain name pointer ethpinode1.

At this stage, you can continue the setup of your RPI remotely from your computer using the “ssh” (“pi” is the username defined on your RPi):

computer$ ssh pi@192.168.1.31

It’s time to install Ethereum.

Step 7 – Install Geth

In this step, we are going to install the Go implementation of Ethereum client called Geth.

Connect to your RPi and retrieve the type of your CPU:

pi$ cat /proc/cpuinfo
...
model name : ARMv7 Processor rev 4 (v7l)
...

Go to the download page of Go-Ethereum by clicking here.

Select the tab Linux from the stable releases page.

Locate the row related to your CPU model and copy the link address . It’s recommended to retrieve the latest version of Geth.

In our example, we use Geth 1.5.7.

Back to your RPi, retrieve the bundle and extract the archive:

pi$ wget https://gethstore.blob.core.windows.net/builds/geth-linux-arm7-1.5.7-da2a22c3.tar.gz

pi$ tar zxvf geth-linux-arm7-1.5.7-da2a22c3.tar.gz 

Copy the Geth application to the /usr/local/bin folder:

pi$ cd geth-linux-arm7-1.5.7-da2a22c3

pi$ sudo cp geth /usr/local/bin

You can remove the archive and the uncompressed folder.

Check the version of Geth:

pi$ geth version
Geth
Version: 1.5.7-stable
Git Commit: da2a22c384a9b621ec853fe4b1aa651d606cf42b
Protocol Versions: [63 62]
Network Id: 1
Go Version: go1.7.4
OS: linux
GOPATH=
GOROOT=/usr/local/go

The same process can be applied to update an existing version of Geth.

Now, Ethereum is installed.

Let’s start it!

Step 8 – Run Geth

Start Geth using the following command:

pi$ geth
...
I1217 19:11:27.420830 p2p/server.go:342] Starting Server
...
I1217 19:11:39.816110 eth/downloader/downloader.go:326] Block synchronisation started

Press CTRL-C to stop the Ethereum server.

Summary

At this stage, Ethereum is installed on your RPi and able to synchronise with the live chain (mainnet).

The blockchain data (chaindata) is located right here: ~/.ethereum/chaindata

Your accounts will be stored in a wallet located in this folder: ~/.ethereum/keystore

Congratulations! Your RPi is an Ethereum node.

You can repeat these steps to setup additional RPi.

Part 2 describes how to set up Ethereum on a computer.

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.