Set up the private chain – miners (3/6)

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

Part 2 described how to install Ethereum on your computer.

Our development environment requires the setup of a private Ethereum chain.

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 byHyperledgerEris/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 watchour Devoxx talk and read this article.

Our private chain needs miners in order to validate and propagate blocks of transactions within the blockchain. Miners will also be used to generate ether to pay for the gas required to process transactions on the Ethereum blockchain. Note that this ether will only be usable within our private blockchain.

Unfortunately, the Raspberry pi is not powerful enough to be used as a miner. The mining process is just too intense. This is why we will deploy at least two miners on our computer.

Why two miners and not only one?

At the time of writing this tutorial, Geth has an issue when it is deployed in a private chain. If you have only one miner, some transactions will not be processed and will remain pending. Having two miners solves this issue (check here for more information about the issue). By the way, two miners make sense to apply the notion of consensus within the blockchain.

Let’s start by describing how to create the first miner.

Introduction

Before we describe the steps to start the miners, it is important to understand the requirements for each node to join the same private blockchain:

  • Each node will use a distinct data directory to store the database and the wallet.
  • Each node must initialize a blockchain based on the same genesis file.
  • Each node must join the same network id different from the one reserved by Ethereum (0 to 3 are already reserved).
  • The port numbers must be different if different nodes are installed on the same computer.

All the operations must be performed from your computer.

Step 1 – Create the datadir folder

When running a private blockchain, it is highly recommended to use a specific folder to store the data (database and wallet) of the private blockchain without impacting the folders used to store the data coming from the public blockchain.

From your computer, create the folder that will host your first miner:

computer$ mkdir -p ~/ChainSkills/miner1

Repeat the operation for the second miner:

computer$ mkdir -p ~/ChainSkills/miner2

Step 2 – Create the Genesis file

Each blockchain starts with a genesis block that is used to initialize the blockchain and defines the terms and conditions to join the network.

Our genesis block is called “genesis.json” and is stored under “~/ChainSkills” folder.

Create a text file under ~/ChainSkills, called genesis.json, with the following content:

{
 "nonce": "0x0000000000000042",
 "mixhash": "0x0000000000000000000000000000000000000000000000000000000000000000",
 "difficulty": "0x400",
 "alloc": {}, 
 "coinbase": "0x0000000000000000000000000000000000000000",
 "timestamp": "0x00",
 "parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
 "extraData": "0x436861696e536b696c6c732047656e6573697320426c6f636b",
 "gasLimit": "0xffffffff",
 "config": {
    "chainId": 42,
    "homesteadBlock": 0,
    "eip155Block": 0,
    "eip158Block": 0
 }
}

Update (24-May-2017):  Since Geth 1.6, the genesis.json file has to provide a section “config” identifying the network id (chainId) of your private network. Based on our tutorial, we will use the network Id “42”.

Update (25-Sep-2017): A comma was missing after the gasLimit. We have also converted the extraData string with its hex value to avoid an error during the init phase.

Among the parameters, we have the following ones:

  • difficulty: if the value is low, the transactions will be quickly processed within our private blockchain.
  • gasLimit: define the limit of Gas expenditure per block. The gasLimit is set to the maximum to avoid being limited to our tests.

Step 3 – Initialize the private blockchain

It’s time to initialize the private blockchain with the genesis block.

This operation will create the initial database stored under the data directory dedicated to each miner.

Step 3.1 – Initialize miner #1

Type the following command to create the blockchain for the first miner:

computer$ cd ~/ChainSkills
computer$ geth --datadir ~/ChainSkills/miner1 init genesis.json

I1226 00:44:16.572007 cmd/utils/flags.go:615] WARNING: No etherbase set and no accounts found as default
...
I1226 00:44:16.604262 cmd/geth/chaincmd.go:131] successfully wrote genesis block and/or chain rule set: 6e92f8b23bcdfdf34dc813cfaf1d84b71beac80530506b5d63a2df10fe23a660

The logs provide the following information:

  • you need a default account
  • the blockchain has been successfully created

If you list the content of the miner1 folder, you will notice the following subfolders:

  • geth: contains the database of your private blockchain (chaindata).
  • keystore: location of your wallet used to store the accounts that you will create on this node.

Step 3.2 – Initialize miner #2

Repeat the same operation to initialize the second miner by specifying its own target folder (~/ChainSkills/miner2):

computer$ cd ~/ChainSkills
computer$ geth --datadir ~/ChainSkills/miner2 init genesis.json

I1226 00:47:14.867704 cmd/utils/flags.go:615] WARNING: No etherbase set and no accounts found as default
...
I1226 00:47:14.890635 cmd/geth/chaincmd.go:131] successfully wrote genesis block and/or chain rule set: 6e92f8b23bcdfdf34dc813cfaf1d84b71beac80530506b5d63a2df10fe23a660

Step 4 – Create accounts

Let’s create some accounts for our miners.

Step 4.1 – Accounts for miner #1

Create the default account that will be used to run the node.

This account will receive all ethers created by the miner in the private blockchain. These ethers will serve to test our solutions by paying the gas required to process each transaction.

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

computer$ geth --datadir ~/ChainSkills/miner1 account new
Your new account is locked with a password. Please give a password. Do not forget this password.
Passphrase: 
Repeat passphrase: 
Address: {3e3753727dd6d965c0c696ea5619b8050ca89a49}

Add an additional account for testing purpose:

computer$ geth --datadir ~/ChainSkills/miner1 account new 
Your new account is locked with a password. Please give a password. Do not forget this password. 
Passphrase: 
Repeat passphrase: 
Address: {ae3ab39b3ebc425289dad620aece197a4a3f8940}

The wallet for these accounts is located right here:

computer$ ls -al ~/ChainSkills/miner1/keystore 
-rw------- 1 eloudsa staff 491 Dec 26 00:55 UTC--2016-12-25T23-55-58.526082355Z--3e3753727dd6d965c0c696ea5619b8050ca89a49
-rw------- 1 eloudsa staff 491 Dec 29 17:53 UTC--2016-12-29T16-53-48.822735465Z--ae3ab39b3ebc425289dad620aece197a4a3f8940

To list all accounts of your node, use the following command:

computer$ geth --datadir ~/ChainSkills/miner1 account list

Account #0: {3e3753727dd6d965c0c696ea5619b8050ca89a49} /Users/eloudsa/ChainSkills/miner1/keystore/UTC--2016-12-25T23-55-58.526082355Z--3e3753727dd6d965c0c696ea5619b8050ca89a49

Account #1: {ae3ab39b3ebc425289dad620aece197a4a3f8940} /Users/eloudsa/ChainSkills/miner1/keystore/UTC--2016-12-29T16-53-48.822735465Z--ae3ab39b3ebc425289dad620aece197a4a3f8940

Step 4.2 – Accounts for miner #2

Repeat the same operation to create the default account for the second miner. The difference lies in the target folder (~/ChainSkills/miner2).

The default account of miner #2:

computer$ geth --datadir ~/ChainSkills/miner2 account new 
Your new account is locked with a password. Please give a password. Do not forget this password. 
Passphrase: 
Repeat passphrase: 
Address: {22b2f81b46146aa3e1036fd3dc5cbcf12551b2db}

An additional account of miner #2:

computer$ geth --datadir ~/ChainSkills/miner2 account new 
Your new account is locked with a password. Please give a password. Do not forget this password. 
Passphrase: 
Repeat passphrase: 
Address: {fa919b49ef34a821fb4cadfdfa5cc6593cb46fe1}

To list all accounts of your node, use the following command:

computer$ geth --datadir ~/ChainSkills/miner2 account list

Account #0: {22b2f81b46146aa3e1036fd3dc5cbcf12551b2db} /Users/eloudsa/ChainSkills/miner2/keystore/UTC--2016-12-26T00-00-12.726226915Z--22b2f81b46146aa3e1036fd3dc5cbcf12551b2db

Account #1: {fa919b49ef34a821fb4cadfdfa5cc6593cb46fe1} /Users/eloudsa/ChainSkills/miner2/keystore/UTC--2016-12-29T16-59-28.053461367Z--fa919b49ef34a821fb4cadfdfa5cc6593cb46fe1

Step 5 – Prepare the miners

We are ready to start the miners from our computer and to mine some ethers that will reward our default accounts.

Step 5.1 – Miner #1: setup

Let’s start by creating a file that will contain the password for our default account, which is the first account we created for each miner. Create a password.sec file under ~/ChainSkills/miner1/ that contains the password you configured for the first account on miner1, in plain text.

To start the miner #1, we will require to run the following command:

computer$ geth --identity "miner1" --networkid 42 --datadir "~/ChainSkills/miner1" --nodiscover --mine --rpc --rpcport "8042" --port "30303" --unlock 0 --password ~/ChainSkills/miner1/password.sec --ipcpath "~/Library/Ethereum/geth.ipc"

The meaning of the main parameters is the following:

  • identity: name of our node
  • networkid: this network identifier is an arbitrary value that will be used to pair all nodes of the same network. This value must be different from 0 to 3 (already used by the live chains)
  • datadir: folder where our private blockchain stores its data
  • rpc and rpcport: enabling HTTP-RPC server and giving its listening port number
  • port: network listening port number, on which nodes connect to one another to spread new transactions and blocks
  • nodiscover: disable the discovery mechanism (we will pair our nodes later)
  • mine: mine ethers and transactions
  • 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 that you store the Geth command into a runnable script. In our example, this script is called “startminer1.sh” and is located here: ~/ChainSkills/miner1

#!/bin/bash

geth --identity "miner1" --networkid 42 --datadir "~/ChainSkills/miner1" --nodiscover --mine --rpc --rpcport "8042" --port "30303" --unlock 0 --password ~/ChainSkills/miner1/password.sec --ipcpath "~/Library/Ethereum/geth.ipc"

What’s the meaning of the parameter “ipcpath“?

If you want to manage your private blockchain via the Mist browser, you will need to create the “geth.ipc” file in the default Ethereum folder. Mist will detect that your private network is running and will connect to it rather than starting its own instance of Geth.

 Step 5.2 – Miner #1: start

Make the script runnable:

computer$ cd ~/ChainSkills/miner1 

computer$ chmod +x startminer1.sh

Let’s start the miner #1:

computer$ ./startminer1.sh
...

You will notice that the server and the mining process start.

You default account will receive ethers mined by the node.

If you start Mist, you will see that the default account is rewarded by ethers.

Remember that these ethers are fake money only available in your private blockchain and not on the live main chain. So, you are not (yet) rich ?

Step 5.3 – Miner #1: JavaScript console

You can manage your miner using the Geth Javascript console.

For example, you can start and stop mining from the console or send transactions.

This console needs to be attached to a running instance of Geth.

Open a new terminal session and type “geth attach“.

If you want to start or stop the mining process, proceed as below:

computer$ geth attach
...
> miner.start()
...
> miner.stop()
...

You will notice that “geth attach” didn’t need any additional parameters. The reason is that the “geth.ipc” file is generated into the Ethereum default directory.

More commands for the JavaScript console are described right there.

To quit the attached console, simply use the exit command.

Step 5.4 – Miner #1: stop

To stop your miner, go to its 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

Thanks to the identity parameter, we are able to easily identify the miner instance we want to stop.

Now let’s continue with the second miner.

Step 5.5 – Miner #2: setup

To prepare the second miner, the instructions are similar to those described for the miner #1 with some minor changes.

First, create the “password.sec” file under ~/ChainSkills/miner2 that will contain the password of the default account of your miner #2:

Create the script “startminer2.sh“that will be stored at the following location: ~/ChainSkills/miner2

#!/bin/bash

geth --identity "miner2" --networkid 42 --datadir "~/ChainSkills/miner2" --nodiscover --mine --rpc --rpcport "8043" --port "30304" --unlock 0 --password ~/ChainSkills/miner2/password.sec

The difference from the first miner is about the following parameters:

  • identity: a specific name used to identify our miner
  • datadir: the folder related to the second miner
  • rpcport: a specific HTTP-RPC port number used to reach the miner #2
  • port: a specific network port number used to reach the miner #2
  • password: path of the file containing the password of the default account on the miner #2

You will notice that we have the same networkid (42). This will be useful later.

We are not providing the “ipcpath” parameter. This means that the “geth.ipc” will be created in the data directory of the miner.

Let’s start the miner #2:

computer$ cd ~/ChainSkills/miner2

computer$ chmod +x startminer2.sh

computer$ ./startminer2.sh
...

Step 5.6 – Miner #2: JavaScript console

As for miner #1, we can manage our node through the JavaScript console.

Unlike miner #1, we will have to attach the console to the running instance of Geth because its “geth.ipc” file has been generated in the “datadir” folder and not in the default Ethereum folder.

To attach the console, you can attach it by mentioning the path to the IPC-RPC interface (geth.ipc):

computer$ cd ~/ChainSkills

computer$ geth attach ipc:./miner2/geth.ipc

Another option is to attach the console to the HTTP-RPC interface:

computer$ geth attach http://127.0.0.1:8043
...

Be aware that these commands may have some limitations such as starting or stopping the mining process:

computer $ geth attach http://127.0.0.1:8043
Welcome to the Geth JavaScript console!

instance: Geth/miner2/v1.5.5-stable-ff07d548/darwin/go1.7.4
coinbase: 0x22b2f81b46146aa3e1036fd3dc5cbcf12551b2db
at block: 1294 (Sat, 31 Dec 2016 16:08:22 CET)
 modules: eth:1.0 net:1.0 rpc:1.0 web3:1.0

> miner.stop()
ReferenceError: 'miner' is not defined
 at <anonymous>:1:1

First, you can see that the “miner” module is not specified in the list of modules: eth:1.0 net:1.0 rpc:1.0 web3:1.0

This is the reason why we have an error when we try to stop the mining process.

The following command is more useful:

computer $ geth attach ipc:./miner2/geth.ipc
Welcome to the Geth JavaScript console!

instance: Geth/miner2/v1.5.5-stable-ff07d548/darwin/go1.7.4
coinbase: 0x22b2f81b46146aa3e1036fd3dc5cbcf12551b2db
at block: 1417 (Sat, 31 Dec 2016 16:12:25 CET)
 datadir: /Users/eloudsa/ChainSkills/miner2
 modules: admin:1.0 debug:1.0 eth:1.0 miner:1.0 net:1.0 personal:1.0 rpc:1.0 shh:1.0 txpool:1.0 web3:1.0

> miner.stop()
true

Here the miner can be managed through the console because the miner module is available from the IPC interface.

Keep this in mind if you have any trouble running a command from the Geth console.

Of course, you can define the modules available for the Geth console by mentioning them from the command line (ipcapi and rpcapi parameters).

For example, let’s change the Geth command by mentioning the “miner” module:

#!/bin/bash

geth --identity "miner2" --dev --networkid 42 --datadir "~/ChainSkills/miner2" --nodiscover --mine --rpc --rpcport "8043" --rpcapi "db,eth,net,web3,miner" --port "30304" --unlock 0 --password ~/ChainSkills/miner2/password.sec

Start the miner and open the console with the following command:

computer $ geth attach http://127.0.0.1:8043
Welcome to the Geth JavaScript console!

instance: Geth/miner2/v1.5.5-stable-ff07d548/darwin/go1.7.4
coinbase: 0x22b2f81b46146aa3e1036fd3dc5cbcf12551b2db
at block: 1473 (Sat, 31 Dec 2016 16:21:22 CET)
 modules: eth:1.0 miner:1.0 net:1.0 rpc:1.0 web3:1.0

Now the miner module is available from the Geth console!

You can manage the mining process:

> miner.stop()

true

This shows that by changing the Geth command, you can allow or restrict the usage of some APIs available from the HTTP-RPC or IPC-RPC interfaces.

Step 5.7 – Miner #2: stop

The principle is the same as described for the miner #1.

Step 6 – Send ethers within miner #1

To ensure that our mining node is properly installed, let’s try to send some ethers between accounts created on each miner.

Step 6.1 – Start the miner and its console

Let’s begin to start the miner #1:

computer$ cd ~/ChainSkills/miner1

computer$ ./startminer1.sh
...

 Open a second terminal and start the Geth console:

computer$ geth attach
...
>

Step 6.2 – Check balances

Get the default account with “eth.coinbase”:

> eth.coinbase
"0x3e3753727dd6d965c0c696ea5619b8050ca89a49"

List the accounts with “eth.accounts”:

> eth.accounts
["0x3e3753727dd6d965c0c696ea5619b8050ca89a49", "0xae3ab39b3ebc425289dad620aece197a4a3f8940"]

Of course, you will find addresses related to your environment.

Check balances with “eth.getBalance(<account id>)”:

> eth.getBalance(eth.coinbase)
2.48859375e+21

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

The default account has plenty of ethers obtained during the mining process. We will use them to test our solutions.

Use the following command to get the balance in ether:

> web3.fromWei(eth.getBalance(eth.coinbase))
3008.125

By default, the balance is expressed in Wei that is the base unit of ether.

Step 6.3 – Stop mining

We stop the mining process to let us review the content of a transaction:

> miner.stop()
true

Step 6.4 – Send ethers

Through the Geth console, we send 10 ethers from account #0 to account #1:

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

The command returns a transaction hash.

As the mining process has been stopped, we can review the list of pending transactions:

> eth.pendingTransactions
[{
 blockHash: null,
 blockNumber: null,
 from: "0x3e3753727dd6d965c0c696ea5619b8050ca89a49",
 gas: 90000,
 gasPrice: 20000000000,
 hash: "0x4ed5ef14cb5df5069059ac201a7294d810b89dcc05c0f60f970b87bff7faa5b6",
 input: "0x",
 nonce: 0,
 r: "0xdfd5465e315207e41d10a01189c41a1e9b42e7577cd256a100b3fa2157e9b0",
 s: "0x39b10c973c1e9764e9b3cfd98339164d65e78971c917ae24fe880a2a7c775cf6",
 to: "0xae3ab39b3ebc425289dad620aece197a4a3f8940",
 transactionIndex: null,
 v: "0x1c",
 value: 10000000000000000000
}]

We can easily identify the following information:

  • The sender address
  • The recipient address
  • The value to transfer (expressed in Wei)
  • The hash of the transaction
  • The cost of the transaction (gas x gasPrice) in Wei

Let the miner process the transaction:

> miner.start()
true

The transaction is processed:

> eth.pendingTransactions
[]

Check the balance of the recipient:

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

10

The recipient address has received 10 ethers.

Congratulations your miner # 1 is properly installed!

Let’s do the same for miner #2.

Step 7 – Send ethers within miner #2

Test your miner #2 by following the steps described for miner #1.

Keep in mind that the Geth console will have to be started using one of the following commands (change the port id according to your settings):

computer$ geth attach ipc:/Users/eloudsa/ChainSkills/miner2/geth.ipc

OR

computer$ geth attach http://127.0.0.1:8043

Step 8 – Send ethers between nodes of the private blockchain

Now, let’s try to send ethers between accounts of our miners.

We will send 5 ethers from the default account of the miner #1 to the account #1 of the miner #2.

Step 8.1 – Start miners

First, start both miners (miner #1 and miner #2).

Step 8.2 – Check balance from miner #2

From the Geth console attached to the miner 2, check the initial balance of the account 1:

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

Step 8.3 – Send Ethers from miner #1

From the console of the first miner, send 5 ethers from the default account (eth.coinbase) to the address of the account 1 in miner #2:

> eth.sendTransaction({from: eth.coinbase, to: '[REPLACE WITH ADDRESS OF ACCOUNT 1 IN MINER #2]', value: web3.toWei(5, "ether")})
"0x866db90bade948dbec0679b0a673807a74d6b3d94b3a7616dd86d72eb8a72e9b"

Step 8.4 – Check balance from miner #1

Check the balance from the Geth console attached to the miner #1:

> web3.fromWei( eth.getBalance("[REPLACE WITH ADDRESS OF ACCOUNT 1 IN MINER #2]"))
5

We have 5 ethers while we should expect 15 ethers.

Step 8.5 – Check balance from miner #2

Check the balance from the Geth console attached to the miner #2:

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

We have 10 ethers while we should expect 15 ethers.

Why?

Because our miners are not connected to the same blockchain.

Each miner is running its own version of the private blockchain. The transactions are not distributed within the same private blockchain.

To synchronise the blockchain, we have to pair the nodes with each other.

Summary

We have installed our miners but they are not synchronised with each other.

We will do that in Part 4 (what a teaser, man!).

posted @ 2018-11-29 14:09  Mr.zzz  阅读(21)  评论(0编辑  收藏  举报