Quorum: first look

In this post we “unbox” the latest version of Quorum, setting up a network node in the process. According to the helpful Getting Started guide:

Quorum is an Ethereum-based distributed ledger protocol that has been developed to provide industries such as finance, supply chain, retail, real estate, etc. with a permissioned implementation of Ethereum that supports transaction and contract privacy.

So while Quorum is aimed at the needs for enterprise use (which typically prefer permissioned networks), it is nevertheless based on Ethereum at its core, so existing Ethereum users should find the transition familiar. That said, this post doesn’t assume any knowledge of either. We’ll approach Quorum as a completely new starter.

Installing

There are a number of options in terms of installing the Quorum suite of tools. Perhaps the simplest is to simply download the latest pre-compiled binary from the releases page. But while this give you the Quorum executable (actually, the binary has the same name as the well-known Ethereum client geth), we’ll also require bootnode for the bare-bones setup we’re going through here.

The “from scratch” setup that we’ll follow requires both the Quorum geth and bootnode binaries but the latter isn’t currently available to download!

Therefore the best way is to compile from source. Quorum requires Go, so follow the installation instructions if you do not have it already, before proceeding further. This guide was tested with the following version:

$ go version
go version go1.12.7 linux/amd64

Now clone the Quorum repo and make the binaries we need:

$ git clone https://github.com/jpmorganchase/quorum.git
$ cd quorum
$ make geth
$ make bootnode

It’s best to add these to your PATH (e.g. by copying them to /usr/local/bin).

Quorum node setup

We’ll now continue with the “from scratch” guide. Create a working directory which will be the base for the new node and change into it

$ mkdir fromscratch
$ cd fromscratch
$ mkdir new-node-1

Generate an account for this node (make up a passphrase when prompted):

$ geth --datadir new-node-1 account new
INFO [07-19|20:07:05.325] Maximum peer count                       ETH=25 LES=0 total=25                                                                                                                           
Your new account is locked with a password. Please give a password. Do not forget this password.
Passphrase:                                                                             
Repeat passphrase:                                                                 
Address: {e1bd06ace739b25a33d47909578a52b39777d4cb}

Note the account address e1bd06ace739b25a33d47909578a52b39777d4cb.

We pre-fund this account with some balance using the following genesis.json file (saved to the fromscratch directory)

{ "alloc": { "0xe1bd06ace739b25a33d47909578a52b39777d4cb": { "balance": "1000000000000000000000000000" } }, "coinbase": "0x0000000000000000000000000000000000000000", "config": { "homesteadBlock": 0, "byzantiumBlock": 0, "chainId": 10, "eip150Block": 0, "eip155Block": 0, "eip150Hash": "0x0000000000000000000000000000000000000000000000000000000000000000", "eip158Block": 0, "isQuorum": true }, "difficulty": "0x0", "extraData": "0x0000000000000000000000000000000000000000000000000000000000000000", "gasLimit": "0xE0000000", "mixhash": "0x00000000000000000000000000000000000000647572616c65787365646c6578", "nonce": "0x0", "parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000", "timestamp": "0x00" }

Using bootnode, generate a “node key” and copy it to the node’s directory

$ bootnode --genkey=nodekey
$ cp nodekey new-node-1/

The following determines the “enode” identifier of the new node

$ bootnode --nodekey=new-node-1/nodekey --writeaddress > new-node-1/enode
$ cat new-node-1/enode
58d5c91aad2d01ccfde50d3971436564a5a13393278d2c714279926f53b1fa8f2c217d18d9ac92ef1371fcbe5955b70397215ab5de826da19ba1c3d9c6ea4ed5

Now specify this enode id together with:

Raft is a consensus mechanism supported by Quorum, and used in this example. Others that can be configured are Istanbul BFT and Clique PoA (the latter already supported by geth). See the Consensus page for more details.

in a file static-nodes.json inside new-node-1:

[ "enode://58d5c91aad2d01ccfde50d3971436564a5a13393278d2c714279926f53b1fa8f2c217d18d9ac92ef1371fcbe5955b70397215ab5de826da19ba1c3d9c6ea4ed5@127.0.0.1:21000?discport=0&raftport=50000" ]

Starting the node

Now we can initialise the node with the following geth command

$ geth --datadir new-node-1 init genesis.json
INFO [07-19|20:31:42.129] Maximum peer count                       ETH=25 LES=0 total=25                                             
INFO [07-19|20:31:42.130] Allocated cache and file handles         database=/home/kk/Documents/blockchain/fromscratch/new-node-1/geth/chaindata cache=16 handles=16
INFO [07-19|20:31:42.143] Writing custom genesis block
INFO [07-19|20:31:42.147] Persisted trie from memory database      nodes=1 size=152.00B time=3.777502ms gcnodes=0 gcsize=0.00B gctime=0s livenodes=1 livesize=0.00B                              
INFO [07-19|20:31:42.148] Successfully wrote genesis state         database=chaindata                                                           hash=ad8c93…ab5509                                         
INFO [07-19|20:31:42.148] Allocated cache and file handles         database=/home/kk/Documents/blockchain/fromscratch/new-node-1/geth/lightchaindata cache=16 handles=16
INFO [07-19|20:31:42.157] Writing custom genesis block
INFO [07-19|20:31:42.157] Persisted trie from memory database      nodes=1 size=152.00B time=82.946µs   gcnodes=0 gcsize=0.00B gctime=0s livenodes=1 livesize=0.00B
INFO [07-19|20:31:42.158] Successfully wrote genesis state         database=lightchaindata                                                           hash=ad8c93…ab5509

Now create the following script startnode1.sh which will start the node in the background

#!/bin/bash PRIVATE_CONFIG=ignore nohup geth --datadir new-node-1 --nodiscover --verbosity 5 --networkid 31337 --raft --raftport 50000 --rpc --rpcaddr 0.0.0.0 --rpcport 22000 --rpcapi admin,db,eth,debug,miner,net,shh,txpool,personal,web3,quorum,raft --emitcheckpoints --port 21000 >> node.log 2>&1 &

Set permissions and execute the script

$ chmod +x startnode1.sh 
$ ./startnode1.sh

Now that the node is running, we may attach and interact with it via geth

$ geth attach new-node-1/geth.ipc
Welcome to the Geth JavaScript console!                                                                  

instance: Geth/v1.8.18-stable-f2055c06(quorum-v2.2.4)/linux-amd64/go1.12.7                                                           
coinbase: 0xe1bd06ace739b25a33d47909578a52b39777d4cb                                                                                 
at block: 0 (Thu, 01 Jan 1970 01:00:00 BST)         
 datadir: /home/kk/Documents/blockchain/fromscratch/new-node-1
 modules: admin:1.0 debug:1.0 eth:1.0 ethash:1.0 miner:1.0 net:1.0 personal:1.0 raft:1.0 rpc:1.0 txpool:1.0 web3:1.0

> raft.cluster                                      
[{
    ip: "127.0.0.1",
    nodeId: "58d5c91aad2d01ccfde50d3971436564a5a13393278d2c714279926f53b1fa8f2c217d18d9ac92ef1371fcbe5955b70397215ab5de826da19ba1c3d9c6ea4ed5",
    p2pPort: 21000,                                 
    raftId: 1,                                      
    raftPort: 50000                                 
}]
> raft.leader                                       
"58d5c91aad2d01ccfde50d3971436564a5a13393278d2c714279926f53b1fa8f2c217d18d9ac92ef1371fcbe5955b70397215ab5de826da19ba1c3d9c6ea4ed5"
> raft.role                                         
"minter"                                            
>                                                   
> exit

This completes the setup of the node. The next post in the series will continue by adding an additional node to the network, and demonstrate how they transact with each other.