# 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
[Pantheon ](../Installation/Install-Binaries.md )
[Curl (or similar web service client) ](https://curl.haxx.se/download.html )
## Steps
To create a private network:
1. [Create Folders ](#1-create-folders )
1. [Create Genesis File ](#2-create-genesis-file )
1. [Get Public Key of First Node ](#3-get-public-key-of-first-node )
1. [Start First Node as Bootnode ](#4-restart-first-node-as-bootnode )
1. [Start Node-2 ](#5-start-node-2 )
1. [Start Node-3 ](#6-start-node-3 )
1. [Confirm Private Network is Working ](#7-confirm-private-network-is-working )
### 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:
```bash
Private-Network/
├── Node-1
│ ├── Node-1-data-path
├── Node-2
│ ├── Node-2-data-path
└── Node-3
├── Node-3-data-path
```
### 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 ](../Configuring-Pantheon/NetworkID-And-ChainID.md )
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:
```json
{
"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. Get Public Key of First Node
To enable nodes to discover each other, a network requires one or more nodes to be bootnodes.
For this private network, we will use Node-1 as the bootnode. This requires obtaining the public key for the [enode URL ](../Configuring-Pantheon/Node-Keys.md#enode-url ).
In the `Node-1` directory, use the [`public-key` subcommand ](../Reference/Pantheon-CLI-Syntax.md#public-key ) to write
the [node public key ](../Configuring-Pantheon/Node-Keys.md#node-public-key ) to the specified file (`publicKeyNode1` in this example):
```bash tab="MacOS"
pantheon --data-path=Node-1-data-path --genesis-file=../privateNetworkGenesis.json public-key export --to=Node-1-data-path/publicKeyNode1
```
```bash tab="Windows"
pantheon --data-path=Node-1-data-path --genesis-file=..\privateNetworkGenesis.json public-key export --to=Node-1-data-path\publicKeyNode1
```
!!!note
The [`--data-path` ](../Reference/Pantheon-CLI-Syntax.md#data-path ) and [`--genesis-file` ](../Reference/Pantheon-CLI-Syntax.md#genesis-file )
options are not used when running Pantheon from the [Docker image ](../Getting-Started/Run-Docker-Image.md ).
Use a bind mount to [specify a configuration file with Docker ](../Getting-Started/Run-Docker-Image.md#custom-genesis-file )
and volume to [specify the data directory ](../Getting-Started/Run-Docker-Image.md#data-directory ).
Your node 1 directory now contains:
```bash
├── Node-1
├── Node-1-data-path
├── database
├── key
├── publicKeyNode1
```
The `database` directory contains the blockchain data.
### 4. Start First Node as Bootnode
Start Node-1:
```bash tab="MacOS"
pantheon --data-path=Node-1-data-path --genesis-file=../privateNetworkGenesis.json --bootnodes --miner-enabled --miner-coinbase fe3b557e8fb62b89f4916b721be55ceb828dbd73 --rpc-http-enabled --host-whitelist=* --rpc-http-cors-origins="all"
```
```bash tab="Windows"
pantheon --data-path=Node-1-data-path --genesis-file=..\privateNetworkGenesis.json --bootnodes --miner-enabled --miner-coinbase fe3b557e8fb62b89f4916b721be55ceb828dbd73 --rpc-http-enabled --host-whitelist=* --rpc-http-cors-origins="all"
```
The command line specifies:
* No arguments for the [`--bootnodes` ](../Reference/Pantheon-CLI-Syntax.md#bootnodes ) option because this is your bootnode.
* Mining is enabled and the account to which mining rewards are paid using the [`--miner-enabled` ](../Reference/Pantheon-CLI-Syntax.md#miner-enabled )
and [`--miner-coinbase` ](../Reference/Pantheon-CLI-Syntax.md#miner-coinbase ) options.
* JSON-RPC API is enabled using the [`--rpc-http-enabled` ](../Reference/Pantheon-CLI-Syntax.md#rpc-http-enabled ) option.
* All hosts can access the HTTP JSON-RPC API using the [`--host-whitelist` ](../Reference/Pantheon-CLI-Syntax.md#host-whitelist ) option.
* All domains can access the node using the HTTP JSON-RPC API using the [`--rpc-http-cors-origins` ](../Reference/Pantheon-CLI-Syntax.md#rpc-http-cors-origins ) option.
!!! info
The miner coinbase account is one of the accounts defined in the genesis file.
### 5. Start Node-2
You need the [enode URL ](../Configuring-Pantheon/Node-Keys.md#enode-url ) for Node-1 to specify Node-1 as the bootnode for Node-2 and Node-3.
Start another terminal, change to the `Node-2` directory and start Node-2 replacing the enode URL with your bootnode:
```bash tab="MacOS"
pantheon --data-path=Node-2-data-path --genesis-file=../privateNetworkGenesis.json --bootnodes="enode://< node public key ex 0x > @127.0.0.1:30303" --p2p-port=30304
```
```bash tab="Windows"
pantheon --data-path=Node-2-data-path --genesis-file=..\privateNetworkGenesis.json --bootnodes="enode://< node public key ex 0x > @127.0.0.1:30303" --p2p-port=30304
```
The command line specifies:
* Different port to Node-1 for P2P peer discovery using the [`--p2p-port` ](../Reference/Pantheon-CLI-Syntax.md#p2p-port ) option.
* Enode URL for Node-1 using the [`--bootnodes` ](../Reference/Pantheon-CLI-Syntax.md#bootnodes ) option.
* Data directory for Node-2 using the [`--data-path` ](../Reference/Pantheon-CLI-Syntax.md#data-path ) option.
* Genesis file as for Node-1.
### 6. Start Node-3
Start another terminal, change to the `Node-3` directory and start Node-3 replacing the enode URL with your bootnode:
```bash tab="MacOS"
pantheon --data-path=Node-3-data-path --genesis-file=../privateNetworkGenesis.json --bootnodes="enode://< node public key ex 0x > @127.0.0.1:30303" --p2p-port30305
```
```bash tab="Windows"
pantheon --data-path=Node-3-data-path --genesis-file=..\privateNetworkGenesis.json --bootnodes="enode://< node public key ex 0x > @127.0.0.1:30303" --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` ](../Reference/Pantheon-CLI-Syntax.md#data-path ) option.
* Bootnode and genesis file as for Node-2.
### 7. Confirm Private Network is Working
Start another terminal, use curl to call the JSON-RPC API [`net_peerCount` ](../Reference/JSON-RPC-API-Methods.md#net_peercount ) method and confirm the nodes are functioning as peers:
```bash
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):
```json
{
"jsonrpc" : "2.0",
"id" : 1,
"result" : "0x2"
}
```
## Next Steps
Import accounts to MetaMask and send transactions as described in the [Private Network Quickstart Tutorial ](Private-Network-Quickstart.md#creating-a-transaction-using-metamask )
!!! info
Pantheon does not implement [private key management ](../Using-Pantheon/Account-Management.md ).
Send transactions using `eth_sendRawTransaction` to [send ether or, deploy or invoke contracts ](../Using-Pantheon/Transactions/Transactions.md ).
Use the [JSON-RPC API ](../JSON-RPC-API/Using-JSON-RPC-API.md ).
Start a node with the [`--rpc-ws-enabled` ](../Reference/Pantheon-CLI-Syntax.md#rpc-ws-enabled ) option and use the [RPC Pub/Sub API ](../Using-Pantheon/RPC-PubSub.md ).
## 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 [4. Restart First Node as Bootnode ](#4-restart-first-node-as-bootnode ).