Updated 2019-10-24

Creating a Private Network using Ethash (Proof of Work) Consensus Protocol

A private network provides a configurable network for testing. By configuring a low difficulty and enabling mining, blocks are created quickly.

You can test multi-block and multi-user scenarios on a private network before moving to one of the public testnets.

Important

An Ethereum private network created as described here is isolated but not protected or secure. We recommend running the private network behind a properly configured firewall.

Prerequisites

Hyperledger Besu

Curl (or similar web service client)

Steps

The steps to create a private network using Ethash are displayed on the right.

1. Create Folders

Each node requires a data directory for the blockchain data. When the node is started, the node key is saved in this directory.

Create directories for your private network, each of the three nodes, and a data directory for each node:

Private-Network/
├── Node-1
│   ├── data
├── Node-2
│   ├── data
└── Node-3
    ├── data

2. Create Genesis File

The genesis file defines the genesis block of the blockchain (that is, the start of the blockchain). The genesis file includes entries for configuring the blockchain such as the mining difficulty and initial accounts and balances.

All nodes in a network must use the same genesis file. The network ID defaults to the chainID in the genesis file. The fixeddifficulty enables blocks to be mined quickly.

Copy the following genesis definition to a file called privateNetworkGenesis.json and save it in the Private-Network directory:

{
  "config": {
      "constantinoplefixblock": 0,
      "ethash": {
        "fixeddifficulty": 1000
      },
       "chainID": 1981
   },
  "nonce": "0x42",
  "gasLimit": "0x1000000",
  "difficulty": "0x10000",
  "alloc": {
    "fe3b557e8fb62b89f4916b721be55ceb828dbd73": {
      "privateKey": "8f2a55949038a9610f50fb23b5883af3b4ecb3c3bb792cbcefbd1542c692be63",
      "comment": "private key and this comment are ignored.  In a real chain, the private key should NOT be stored",
      "balance": "0xad78ebc5ac6200000"
    },
    "f17f52151EbEF6C7334FAD080c5704D77216b732": {
      "privateKey": "ae6ae8e5ccbfb04590405997ee2d52d2b330726137b875053c36d94e974d162f",
      "comment": "private key and this comment are ignored.  In a real chain, the private key should NOT be stored",
      "balance": "90000000000000000000000"
    }
  }
}

Warning

Do not use the accounts in the genesis file above on mainnet or any public network except for testing. The private keys are displayed so the accounts are not secure.

3. Start First Node as Bootnode

Start Node-1:

besu --data-path=data --genesis-file=../privateNetworkGenesis.json --miner-enabled --miner-coinbase fe3b557e8fb62b89f4916b721be55ceb828dbd73 --rpc-http-enabled --host-whitelist="*" --rpc-http-cors-origins="all"     
besu --data-path=data --genesis-file=..\privateNetworkGenesis.json --miner-enabled --miner-coinbase fe3b557e8fb62b89f4916b721be55ceb828dbd73 --rpc-http-enabled --host-whitelist="*" --rpc-http-cors-origins="all"    

The command line specifies:

Info

The miner coinbase account is one of the accounts defined in the genesis file.

When the node starts, the enode URL is displayed. Copy the enode URL to specify Node-1 as the bootnode in the following steps.

Node 1 Enode URL

4. Start Node-2

Start another terminal, change to the Node-2 directory and start Node-2 specifying the Node-1 enode URL copied when starting Node-1 as the bootnode:

besu --data-path=data --genesis-file=../privateNetworkGenesis.json --bootnodes=<Node-1 Enode URL> --p2p-port=30304      
besu --data-path=data --genesis-file=..\privateNetworkGenesis.json --bootnodes=<Node-1 Enode URL> --p2p-port=30304      

The command line specifies:

  • Different port to Node-1 for P2P peer discovery using the --p2p-port option.
  • Enode URL for Node-1 using the --bootnodes option.
  • Data directory for Node-2 using the --data-path option.
  • Genesis file as for Node-1.

5. Start Node-3

Start another terminal, change to the Node-3 directory and start Node-3 specifying the Node-1 enode URL copied when starting Node-1 as the bootnode:

besu --data-path=data --genesis-file=../privateNetworkGenesis.json --bootnodes=<Node-1 Enode URL> --p2p-port=30305      
besu --data-path=data --genesis-file=..\privateNetworkGenesis.json --bootnodes=<Node-1 Enode URL> --p2p-port=30305      

The command line specifies:

  • Different port to Node-1 and Node-2 for P2P peer discovery.
  • Data directory for Node-3 using the --data-path option.
  • Bootnode and genesis file as for Node-2.

6. Confirm Private Network is Working

Start another terminal, use curl to call the JSON-RPC API net_peerCount method and confirm the nodes are functioning as peers:

curl -X POST --data '{"jsonrpc":"2.0","method":"net_peerCount","params":[],"id":1}' localhost:8545

The result confirms Node-1 (the node running the JSON-RPC service) has two peers (Node-2 and Node-3):

{
  "jsonrpc" : "2.0",
  "id" : 1,
  "result" : "0x2"
}

Next Steps

Import accounts to MetaMask and send transactions as described in the Private Network Quickstart Tutorial

Info

Besu does not implement private key management.

Send transactions using eth_sendRawTransaction to send ether or, deploy or invoke contracts.

Use the JSON-RPC API.

Start a node with the --rpc-ws-enabled option and use the RPC Pub/Sub API.

Stop Nodes

When finished using the private network, stop all nodes using Ctrl+C in each terminal window.

Tip

To restart the private network in the future, start from 3. Start First Node as Bootnode.