Ethereum Private Network
Create your own Ethereum Blockchain!

To develop a complex ethereum application, you will want to run it on a private network to see how it works before deploying it. So, in this Ethereum Private Network tutorial, you will learn how to create a Private Ethereum Network and how to make a transaction between two accounts.

Installing Ethereum on Ubuntu

To create an Ethereum Private Network, we first need to have Ethereum installed in our system. In this section of Ethereum Private Network Tutorial, you will learn how to install Ethereum on Ubuntu.

To install Ethereum, run the following commands in a terminal:

$ sudo apt-get install software-properties-common
$ sudo add-apt-repository -y ppa:ethereum/ethereum
$ sudo apt-get update
$ sudo apt-get install ethereum

Done! This will install Ethereum on your system.

Let’s start with the Private Network creation.

In this Ethereum Private Network Tutorial, we will send ethers from one account to another and so, we need accounts. Let’s now see how to create accounts for our Blockchain.

Creating Accounts For Ethereum Private Network

This section will run through the commands for setting up a simple private network of two nodes. Both nodes will run on the local machine using the same genesis block and network ID. The data directories for each node will be named node1 and node2.

Before creating new accounts, let us create a new directory for our workplace. Refer to the below commands to do this:

$ mkdir private-ethereum
$ cd private-ethereum
$ mkdir node1 node2

Each node will have an associated account that will receive some ether at launch. The following command creates an account for Node 1:

$ geth --datadir node1 account new

This command returns a request for a password. Enter the passphrase for each account when asked. Do not forget this passphrase!

Once a password has been provided the following information is returned to the terminal:

Your new account is locked with a password. Please give a password. Do not foget this password.
Repeat password:
Your new key was generated
Public address of the key: 0xC1B2c0dFD381e6aC08f34816172d6343Decbb12b
Path of the secret key file: node1/keystore/UTC--2022-05-13T14-25-49.229126160Z--c1b2c0dfd381e6ac08f34816172d6343decbb12b
- You can share your public address with anyone. Others need it to interact with you.
- You must NEVER share the secret key with anyone! The key controls access to your funds!
- You must BACKUP your key file! Without the key, it's impossible to access account funds!
- You must remember your password! Without the password, it's impossible to decrypt the key!

The keyfile and account password should be backed up securely.

These steps can then be repeated for Node 2.

$ geth --datadir node2 account new

These commands create keyfiles that are stored in the keystore directory in node1 and node2 data directories. In order to unlock the accounts later the passwords for each account should be saved to a text file in each node's data directory. 

$ echo 'your password' >> password.txt
$ cp password.txt node1
$ cp password.txt node2

Creating Genesis File

A Genesis file contains the properties that define the Blockchain. A Genesis file is the start-point of the Blockchain and so, it is mandatory to create the Genesis file to create a Blockchain.  Now, let’s create the Genesis file.

In each data directory save a copy of the following genesis.json to the top level project directory. The account addresses in the alloc field should be replaced with those created for each node in the previous step (without the leading 0x).

First, create a file named genesis.json

$ nano genesis.json

And now copy and paste the following code in that file:

  "config": {
    "chainId": 12345,
    "homesteadBlock": 0,
    "eip150Block": 0,
    "eip155Block": 0,
    "eip158Block": 0,
    "byzantiumBlock": 0,
    "constantinopleBlock": 0,
    "petersburgBlock": 0,
    "istanbulBlock": 0,
    "muirGlacierBlock": 0,
    "berlinBlock": 0,
    "londonBlock": 0,
    "arrowGlacierBlock": 0,
    "grayGlacierBlock": 0,
    "clique": {
      "period": 5,
      "epoch": 30000
  "difficulty": "1",
  "gasLimit": "800000000",
  "extradata": "0x00000000000000000000000000000000000000000000000000000000000000007df9a875a174b3bc565e6424a0050ebc1b2d1d820000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
  "alloc": {
    "C1B2c0dFD381e6aC08f34816172d6343Decbb12b": { "balance": "500000" },
    "c94d95a5106270775351eecfe43f97e8e75e59e8": { "balance": "500000" }

Note: In the above code, replace the address under alloc section with the address of the accounts that you created in the previous step. 

Save it and exit. 

Let me explain the contents of the Genesis file in brief:

  • chainId – This is the chain identification number that is used to distinguish between Blockchains

  • homesteadBlock, eip155Block, eip158Block, byzantiumBlock – these properties are related to chain forking and versioning. We don’t need these for our tutorial, so let’s set them to 0.

  • difficulty – This number decides how difficult the blocks will be to mine. For Private networks, it’s good to set a lower number as it lets you mine blocks quickly, which results in fast transactions.

  • gasLimit – This number is the total amount of gas that can be used in each block. We don’t want our network to hit the limit, so we have set this high.

  • alloc – This part is used to allocate ethers to already created accounts.

The Genesis file is ready. Now, it’s time to start the Blockchain.

Instantiating Data Directory

Before starting the Blockchain, we have to instantiate the data directory. The Data Directory is the directory where the data related to the Blockchain is stored. To instantiate the data directory, run the following command:

$ geth init --datadir node1 genesis.json

This should be repeated for both nodes:

$ geth init --datadir node2 genesis.json

The following will be returned to the terminal: 

INFO [05-13|15:41:47.520] Maximum peer count                       ETH=50 LES=0 total=50
INFO [05-13|15:41:47.520] Smartcard socket not found, disabling    err="stat /run/pcscd/pcscd.comm: no such file or directory"
INFO [05-13|15:41:47.520] Set global gas cap                       cap=50,000,000
INFO [05-13|15:41:47.520] Allocated cache and file handles         database=/home/go-ethereum/node2/geth/chaindata cache=16.00MiB handles=16
INFO [05-13|15:41:47.542] Writing custom genesis block
INFO [05-13|15:41:47.542] Persisted trie from memory database      nodes=3 size=397.00B time="41.246µs" gcnodes=0 gcsize=0.00B gctime=0s livenodes=1 livesize=0.00B
INFO [05-13|15:41:47.543] Successfully wrote genesis state         database=chaindata hash=c9a158..d415a0
INFO [05-13|15:41:47.543] Allocated cache and file handles         database=/home/go-ethereum/node2/geth/chaindata cache=16.00MiB handles=16
INFO [05-13|15:41:47.556] Writing custom genesis block
INFO [05-13|15:41:47.557] Persisted trie from memory database      nodes=3 size=397.00B time="81.801µs" gcnodes=0 gcsize=0.00B gctime=0s livenodes=1 livesize=0.00B
INFO [05-13|15:41:47.558] Successfully wrote genesis state         database=chaindata hash=c9a158..d415a0

With the Data Directory instantiated, we can now go to the next step to start the Blockchain.

Configure Bootnode

The next step is to configure a bootnode. This can be any node, but for this tutorial the developer tool bootnode will be used to quickly and easily configure a dedicated bootnode. First the bootnode requires a key, which can be created with the following command, which will save a key to boot.key:

$ bootnode -genkey boot.key

This key can then be used to generate a bootnode as follows:

$ bootnode -nodekey boot.key -addr :30305

The choice of port passed to -addr is arbitrary, but public Ethereum networks use 30303, so this is best avoided. The bootnode command returns the following logs to the terminal, confirming that it is running:

Note: you're using cmd/bootnode, a developer tool.
We recommend using a regular node as bootstrap node for production deployments.
INFO [05-13|15:50:03.645] New local node record                    seq=1,652,453,403,645 id=a2d37f4a7d515b3a ip=nil udp=0 tcp=0

Starting Ethereum Private Blockchain

The two nodes can now be started.

Open separate terminals for each node, leaving the bootnode running in the original terminal.

In each terminal, run the following command (replacing node1 with node2 where appropriate, and giving each node different --port and authrpc.port IDs.

The account address and password file for node 1 must also be provided, and we set it as the miner node as well, by specifying the --mine, --miner.thread, and --miner.etherbase parameters.

$ geth --datadir node1 --port 30306 --bootnodes enode://f7aba85ba369923bffd3438b4c8fde6b1f02b1c23ea0aac825ed7eac38e6230e5cadcf868e73b0e28710f4c9f685ca71a86a4911461637ae9ab2bd852939b77f@  --networkid 123454321 --unlock 0xC1B2c0dFD381e6aC08f34816172d6343Decbb12b --password node1/password.txt --authrpc.port 8551 --mine --miner.threads=1 --miner.etherbase 0xce34508A9a26AdCA55fFDAe834625A18B4DFbe8C

Open new terminal for running node 2:

$ geth --datadir node2 --port 30307 --bootnodes enode://f7aba85ba369923bffd3438b4c8fde6b1f02b1c23ea0aac825ed7eac38e6230e5cadcf868e73b0e28710f4c9f685ca71a86a4911461637ae9ab2bd852939b77f@  --networkid 123454321 --unlock 0xC1B2c0dFD381e6aC08f34816172d6343Decbb12b --password node2/password.txt --authrpc.port 8552 

Done! Your private Ethereum Blockchain is up and running.

The output of this code should look something like this:

INFO [05-13|16:17:40.061] Maximum peer count                       ETH=50 LES=0 total=50
INFO [05-13|16:17:40.061] Smartcard socket not found, disabling    err="stat /run/pcscd/pcscd.comm: no such file or directory"
INFO [05-13|16:17:40.061] Set global gas cap                       cap=50,000,000
INFO [05-13|16:17:40.061] Allocated trie memory caches             clean=154.00MiB dirty=256.00MiB
INFO [05-13|16:17:40.061] Allocated cache and file handles         database=/home/go-ethereum/node1/geth/chaindata cache=512.00MiB handles=524,288
INFO [05-13|16:17:40.094] Opened ancient database                  database=/home/go-ethereum/node1/geth/chaindata/ancient readonly=false
INFO [05-13|16:17:40.095] Initialised chain configuration          config="{ChainID: 123454321 Homestead: 0 DAO: nil DAOSupport: false EIP150: 0 EIP155: 0 EIP158: 0 Byzantium: 0 Constantinople: 0 Petersburg: 0 Istanbul: nil, Muir Glacier: nil, Berlin: nil, London: nil, Arrow Glacier: nil, MergeFork: nil, Terminal TD: nil, Engine: clique}"
INFO [05-13|16:17:40.096] Initialising Ethereum protocol           network=123,454,321 dbversion=8
INFO [05-13|16:17:40.098] Loaded most recent local header          number=0 hash=c9a158..d415a0 td=1 age=53y1mo2w
INFO [05-13|16:17:40.098] Loaded most recent local full block      number=0 hash=c9a158..d415a0 td=1 age=53y1mo2w
INFO [05-13|16:17:40.098] Loaded most recent local fast block      number=0 hash=c9a158..d415a0 td=1 age=53y1mo2w
INFO [05-13|16:17:40.099] Loaded local transaction journal         transactions=0 dropped=0
INFO [05-13|16:17:40.100] Regenerated local transaction journal    transactions=0 accounts=0
INFO [05-13|16:17:40.100] Gasprice oracle is ignoring threshold set threshold=2
WARN [05-13|16:17:40.100] Unclean shutdown detected                booted=2022-05-13T16:16:46+0100 age=54s
INFO [05-13|16:17:40.100] Starting peer-to-peer node               instance=Geth/v1.10.18-unstable-8d84a701-20220503/linux-amd64/go1.18.1
INFO [05-13|16:17:40.130] New local node record                    seq=1,652,454,949,228 id=f1364e6d060c4625 ip= udp=30306 tcp=30306
INFO [05-13|16:17:40.130] Started P2P networking                   self=enode://87606cd0b27c9c47ca33541d4b68cf553ae6765e22800f0df340e9788912b1e3d2759b3d1933b6f739c720701a56ce26f672823084420746d04c25fc7b8c6824@
INFO [05-13|16:17:40.133] IPC endpoint opened                      url=/home/go-ethereum/node1/geth.ipc
INFO [05-13|16:17:40.785] Unlocked account                         address=0xC1B2c0dFD381e6aC08f34816172d6343Decbb12b
INFO [05-13|16:17:42.636] New local node record                    seq=1,652,454,949,229 id=f1364e6d060c4625 ip= udp=30306 tcp=30306
INFO [05-13|16:17:43.309] Mapped network port                      proto=tcp extport=30306 intport=30306 interface="UPNP IGDv1-IP1"
INFO [05-13|16:17:43.822] Mapped network port                      proto=udp extport=30306 intport=30306 interface="UPNP IGDv1-IP1"
[05-13|16:17:50.150] Looking for peers                        peercount=0 tried=0 static=0
INFO [05-13|16:18:00.164] Looking for peers                        peercount=0 tried=0 static=0


The bootnode Logs

In the first terminal that is currently running the logs resembling the following will be displayed, showing the discovery process in action:

INFO [05-13|15:50:03.645] New local node record                    seq=1,652,453,403,645 id=a2d37f4a7d515b3a ip=nil udp=0 tcp=0
TRACE[05-13|16:15:49.228]  PING/v4                               id=f1364e6d060c4625 addr= err=nil
TRACE[05-13|16:15:49.229]  PONG/v4                               id=f1364e6d060c4625 addr= err=nil
TRACE[05-13|16:15:49.229]  PING/v4                               id=f1364e6d060c4625 addr= err=nil
TRACE[05-13|16:15:49.230]  PONG/v4                               id=f1364e6d060c4625 addr= err=nil
TRACE[05-13|16:15:49.730]  FINDNODE/v4                           id=f1364e6d060c4625 addr= err=nil
TRACE[05-13|16:15:49.731]  NEIGHBORS/v4                          id=f1364e6d060c4625 addr= err=nil
TRACE[05-13|16:15:50.231]  FINDNODE/v4                           id=f1364e6d060c4625 addr= err=nil
TRACE[05-13|16:15:50.231]  NEIGHBORS/v4                          id=f1364e6d060c4625 addr= err=nil
TRACE[05-13|16:15:50.561]  FINDNODE/v4                           id=f1364e6d060c4625 addr= err=nil
TRACE[05-13|16:15:50.561]  NEIGHBORS/v4                          id=f1364e6d060c4625 addr= err=nil
TRACE[05-13|16:15:50.731]  FINDNODE/v4                           id=f1364e6d060c4625 addr= err=nil
TRACE[05-13|16:15:50.731]  NEIGHBORS/v4                          id=f1364e6d060c4625 addr= err=nil
TRACE[05-13|16:15:51.231]  FINDNODE/v4                           id=f1364e6d060c4625 addr= err=nil
TRACE[05-13|16:15:51.232]  NEIGHBORS/v4                          id=f1364e6d060c4625 addr= err=nil
TRACE[05-13|16:15:52.591]  FINDNODE/v4                           id=f1364e6d060c4625 addr= err=nil
TRACE[05-13|16:15:52.591]  NEIGHBORS/v4                          id=f1364e6d060c4625 addr= err=nil
TRACE[05-13|16:15:57.767]  PING/v4                               id=f1364e6d060c4625 addr= err=nil

Attaching Geth Console

It is now possible to attach a Javascript console to either node to query the network properties:

$ geth attach node1/geth.ipc

Once the Javascript console is running, check that the node is connected to one other peer (node 2):

> net.peerCount

The details of this peer can also be queried and used to check that the peer really is Node 2:

> admin.peers

This should return the following:

    caps: ["eth/66", "snap/1"],
    enode: "enode://f7aba85ba369923bffd3438b4c8fde6b1f02b1c23ea0aac825ed7eac38e6230e5cadcf868e73b0e28710f4c9f685ca71a86a4911461637ae9ab2bd852939b77f@",
    id: "d300c59ba301abcb5f4a3866aab6f833857c3ddf2f0febb583410b1dc466f175",
    name: "Geth/v1.10.18-unstable-8d84a701-20220503/linux-amd64/go1.18.1",
    network: {
      inbound: false,
      localAddress: "",
      remoteAddress: "",
      static: false,
      trusted: false
    protocols: {
      eth: {
        difficulty: 1,
        head: "0xc9a158a687eff8a46128bd5b9aaf6b2f04f10f0683acbd7f031514db9ad415a0",
        version: 66
      snap: {
        version: 1

Verifying Accounts

To verify the accounts created on genesis block, we will run the following command in the geth console.

> eth.accounts

This will show a list of all accounts available.

The account associated with Node 1 and Node 2 was supposed to be funded with some ether at the chain genesis. This can be checked easily using eth.getBalance():

> eth.getBalance()

or to show the balance in Ether:

> web3.fromWei(eth.getBalance(eth.accounts[0]), "ether")

We are ready with everything required to make a transaction. Why wait? Let’s do it!

Making A Transaction

In this Ethereum Private Network tutorial, we will send some ethers from one account to another.

This account on Node 1 can then be unlocked and some ether sent to Node 2, using the following commands: 

> eth.sendTransaction({
value: web3.toWei(amount, "ether")

We will send 1 ether from account 1 to account 2 using the following command:

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

This should return a Transaction ID.

The same steps can then be repeated to attach a console to Node 2.

Done! You have successfully made a transaction!

Verify Transactions

To verify the transaction, let’s check the balance in both the accounts.

> web3.fromWei(eth.getBalance("0x82c440bba462220c9b54600e584373014706c177"), "ether")
> web3.fromWei(eth.getBalance("0x9db5b590fdecc10cdb04b85a3503e94e61b207ca"), "ether")

Verify Transaction - Ethereum Private Network tutorial - Edureka

Yay! We can see that 1 ether were sent from one account to another!

Congratulations! You have created an Ethereum Private Network and made a transaction. I hope this Ethereum Private Network tutorial was informative and helped you understand about Ethereum Private Network. Now, go ahead and try experimenting with the newly created Private network.

Connecting from Metamask or Remix

Let's now try to connect our private network from Remix or Metmask. The point it, it should provide HTTP port opened to be connected by client applications.

Let's modify Node2 and add http access.

Note: If you are running the network on VirtualBox on NAT network, you must do port forwarding on port 8545.

Next, setup your Remix to connect directly to HTTP provider provided by our private network.

The same applies to Metamask, Just add a new network connecting to our Private Network address at localhost:8545.




How To Install Hyperledger Fabric v2.4
on Ubuntu 20.04