Create your own Blockchain using Python and Ethereum

Shivam Oswal
Posted by Shivam Oswal on October 24, 2018

Blockchain, as the name suggests, is a collection of blocks or data records chained together in a cryptographic fashion. Each block in the chain contains a hash of the previous block, timestamp, and the transaction data, securing it from intruders/attackers and modifications in the future. This immutability is one of the most interesting features of the Blockchain. Transactions, once written, are very difficult to modify (it is possible to modify the chain from a particular block but that means splitting the chain in two and to do that 51% of the miners have to agree to use the new chain.)

The best thing about Blockchain that makes it secure is the way it is decentralized, meaning you cannot access it from any centralized location or modify certain blocks in a Blockchain to hack the transactions. Any attempt to modify the chain needs consensus from more than 50% of the miners for the chain. Very difficult to achieve.

In this blog, I will be talking about some basic Blockchain concepts and I will try to illustrate them with an example of creating a simple Blockchain using Ethereum and Python on a Linux/Ubuntu box.


  • Any Ubuntu VM (desktop/server) with minimum 2 GB RAM and 10 GB disk space
  • Python 3.5 or 3.5+
  • Ethereum basics
  • Basic understanding of Blockchain
sudo add-apt-repository ppa:jonathonf/python-3.6
sudo apt-get update
sudo apt-get install python3.6
sudo apt-get install ethereum
sudo apt-get install software-properties-common
sudo add-apt-repository -y ppa:ethereum/ethereum
sudo apt-get update
sudo apt-get install ethereum

So, let’s start with your very own Blockchain:

1. The first step in creating Blockchain is to create an initial block of the chain using the config file. This initial block will basically define the properties of your whole Blockchain.

2. Under your working directory create a JSON file that holds the configuration for the initial block.

sudo vi firstblock.json and paste the below content in it.

"config": {
"chainId": 1,
"homesteadBlock": 0,
"eip155Block": 0,
"eip158Block": 0,
"byzantiumBlock": 0
"difficulty": "100",
"gasLimit": "4000000",
"alloc": {
"8c684d22367d208c46584dcf7f09d8bc8f56ffff": {
"balance": "500000000000000000000000"
"ge14d41d66af28385c7af6d825ab102eb271ffff": {
"balance": "10000000000000000000000"

Let's have a look at the information headings in the JSON file:

  • chainId : This is your chain’s identifier, and is used in replay protection.
  • homesteadBlock, eip155Block, eip158Block, byzantiumBlock : These relate to chain forking and versioning, so in this particular case lets just keep them aside as you are starting a new Blockchain.
  • Difficulty: This dictates how difficult it is to mine a block. Setting this to a low value (~10–10000) is helpful in a private Blockchain as it lets you mine blocks quickly, which equals fast transactions, and plenty of ETH to test with.
  • gasLimit: This is the total amount of gas that can be used in each block. With such a low mining difficulty, blocks will be moving pretty quick, but you should still set this value pretty high to avoid hitting the limit and slowing down your network.
  • Alloc: Here you can allocate ETH to specific addresses. This won’t create the account for you, so make sure its an account you already have control of. You will need to add the account to your private chain in order to use it and to do so you need access to the keystore/utc file

3. Initialize your data-directory for the first node creation.

geth --datadir ./node1 init ./firstblock.json

You should see output similar to this:

INFO [09-04|10:07:13.814] Maximum peer count                       ETH=25 LES=0 total=25
INFO [09-04|10:07:13.815] Allocated cache and file handles database=/home/vinay/my-chain/node1/geth/chaindata cache=16 handles=16
INFO [09-04|10:07:13.821] Writing custom genesis block
INFO [09-04|10:07:13.821] Persisted trie from memory database nodes=3 size=413.00B time=83.769µs gcnodes=0 gcsize=0.00B gctime=0s livenodes=1 livesize=0.00B
INFO [09-04|10:07:13.822] Successfully wrote genesis state database=chaindata hash=9d236a...641806
INFO [09-04|10:07:13.822] Allocated cache and file handles database=/home/vinay/my-chain/node1/geth/lightchaindata cache=16 handles=16
INFO [09-04|10:07:13.827] Writing custom genesis block
INFO [09-04|10:07:13.827] Persisted trie from memory database nodes=3 size=413.00B time=57.041µs gcnodes=0 gcsize=0.00B gctime=0s livenodes=1 livesize=0.00B
INFO [09-04|10:07:13.827] Successfully wrote genesis state database=lightchaindata hash=9d236a...641806

4. Now you can start your node with the below command:

geth --datadir ./node1 --networkid 111 console 2>> node1.log

This will ensure that all the logs are redirected to node1.log under your specified working directory for your node, which is node1 in our case.

After running the above command, you should see something like this in your output:

INFO [09-04|10:07:27.687] Maximum peer count                       ETH=25 LES=0 total=25
INFO [09-04|10:07:27.688] Starting peer-to-peer node instance=Geth/v1.8.15-stable-89451f7c/linux-amd64/go1.10
INFO [09-04|10:07:27.688] Allocated cache and file handles database=/home/vinay/my-chain/node1/geth/chaindata cache=768 handles=512
INFO [09-04|10:07:27.698] Initialised chain configuration config="{ChainID: 1994 Homestead: 0 DAO: DAOSupport: false EIP150: EIP155: 0 EIP158: 0 Byzantium: 0 Constantinople: Engine: unknown}"
INFO [09-04|10:07:27.698] Disk storage enabled for ethash caches dir=/home/vinay/my-chain/node1/geth/ethash count=3
INFO [09-04|10:07:27.698] Disk storage enabled for ethash DAGs dir=/root/.ethash count=2
INFO [09-04|10:07:27.699] Initialising Ethereum protocol versions="[63 62]" network=1114
INFO [09-04|10:07:27.700] Loaded most recent local header number=0 hash=9d236a...641806 td=400
INFO [09-04|10:07:27.700] Loaded most recent local full block number=0 hash=9d236a...641806 td=400
INFO [09-04|10:07:27.700] Loaded most recent local fast block number=0 hash=9d236a...641806 td=400
INFO [09-04|10:07:27.700] Regenerated local transaction journal transactions=0 accounts=0
INFO [09-04|10:07:27.700] Starting P2P networking
INFO [09-04|10:07:29.811] UDP listener up self=enode://75dc65374999c58d39ae9f8e8e40d3c750ff4561d67995827a907c91d0e1ed718239dd1e5817f99d3544ad32a81a002cdd925e21afb3f1c39823cb8fcdf28b7b@
INFO [09-04|10:07:29.811] RLPx listener up self=enode://75dc65374999c58d39ae9f8e8e40d3c750ff4561d67995827a907c91d0e1ed718239dd1e5817f99d3544ad32a81a002cdd925e21afb3f1c39823cb8fcdf28b7b@
INFO [09-04|10:07:29.815] IPC endpoint opened url=/home/vinay/my-chain/node1/geth.ipc
Welcome to the Geth JavaScript console!
instance: Geth/v1.8.15-stable-89451f7c/linux-amd64/go1.10
modules: admin:1.0 debug:1.0 eth:1.0 ethash:1.0 miner:1.0 net:1.0 personal:1.0 rpc:1.0 txpool:1.0 web3:1.0

This is your javascript console where you can use different Blockchain commands to play around with your Blockchain.

5. Create your personal account:
If you have already created this as a part of JSON file created (alloc param), then you can simply import that into your keystore folder created during data directory instantiation, which in our case is “/node1/keystore” and jump to the next step.

You can create a new account using the following command:


Remember the passphrase you give to your account because if you forget it, there is no way to recover your account.

You can view the accounts created using the following command:

> web3.eth.accounts
["0x46574bcfce83947b684097fd21395fa22c4d8cb8", "0x1ef45cc951acfff4c2101c9b3ca7131a2fd7c809"]

To set your default account, use the following command:

> miner.setEtherbase(web3.eth.accounts[0])

This will set the first account in the list to be the default account.

You can check your balance for the given account with the following command:

> eth.getBalance(eth.coinbase)

6. Run mining command and you will see your account balance increasing:


You should also see the mining logs being dumped to the log that we instantiated as part of data directory initialization.


This will stop the mining action.

Now that your first node is ready, you can add peer nodes to the original node by following these steps:

1. Initialize a new data directory for the new node just like your first node using the same JSON that you created initially.

geth --datadir ./node2 init ./firstnode.json

2. Launch the peer node from some different port on a separate console:

geth --datadir ./node2 --networkid 111 --port 30304 console 2>> node2.log

Remember that you need to provide the same networkid that you used for the first node so that it becomes a peer node for the first node.

This will open a new javascript console and you can run all the Ethereum commands similar to your first node.

3. Type the following on the javascript console of the first node:


You should see an output similar to this:


4. Now run the following command on your second node’s console:

> admin.addPeer("enode://483ae85d264b8ebdc6c01565694cd8e24d17cd9ad9ba9c05ab83e8a9d477ad9b397eb2afd84d65e581ef2007f1e0338268f526cbd4b93481713c1ae2080533c5@")

5. Verify that your nodes are communicating.
Type the following command on the console of the second node:

> admin.peers
The output should be something similar to this:
caps: ["eth/63"],
id: "483ae85d264b8ebdc6c01565694cd8e24d17cd9ad9ba9c05ab83e8a9d477ad9b397eb2afd84d65e581ef2007f1e0338268f526cbd4b93481713c1ae2080533c5",
name: "Geth/v1.8.15-stable-89451f7c/linux-amd64/go1.10",
network: {
inbound: false,
localAddress: "",
remoteAddress: "",
static: true,
trusted: false
protocols: {
eth: {
difficulty: 72443634457,
head: "0x49a60106a525099d51f1a093d21676a2081c8e4b3d0322c5cc40d95563ba13bd",
version: 63

remoteAddress: "" -> indication that the node is listening to the first node that is created over 30303.

Congratulations! Your Blockchain is ready!

Topics: Python, Ethereum, Blockchain

Leave Comment

Subscribe Email

    Post By Topic

    See all