Create Blockchain With Node.js. Learn by creating your own blockchain… | by Abhishek Chauhan | Apr, 2022

blockchain development | photo credit: Tezos

In this chapter, we will dive deep into the code, and the examples in this chapter are simple in nature and intended for learning purposes. They will give you a better understanding of blockchain and the elements that are needed to achieve a fully working prototype of a blockchain.

  1. Creating a basic P2P network
  2. Sending and receiving blocks
  3. Registering miners and creating new blocks
  4. Setting up a name-value database, LevelDB
  5. Creating a private-public wallet
  6. Creating an API
  7. Creating a command-line interface

Peer-to-peer (P2P) is a type of computer network that uses a distributed architecture. Each peer or node shares the workload and is equal to the other peers, meaning there should not be any privileged peer.

Create a folder and name it Blockchain.

Your code needs to find and connect peers, deploy servers that are used to discover other peers, and get an available TCP port. That is done by utilizing these three libraries:

  • discovery-swarm: Used to create a network swarm that uses discovery-channel to find and connect peers
  • dat-swarm-defaults: Deploys servers that are used to discover other peers
  • get-port: Gets available TCP ports

To install these libraries, run this command:

npm install crypto discovery-swarm dat-swarm-defaults get-port@5.1.1 --save

Now that the libraries are installed, create a file and name it p2p.js and write the following code. Alternatively, you could just copy the gist,

p2p.js

Open two Terminal instances and navigate to the location of the library. Run the following command in both terminals:

node p2p.js
output p2p

As you can see above, the network generated a random peer ID for your machine and picked a random port utilizing the discovery libraries you installed. Then the code was able to discover other peers on the network and send and receive messages to and from these peers. You are now connected on a P2P network with other users.

Creating Genesis Block and Sharing Blocks

The Block object is not the same for every blockchain. Different blockchains utilize different types of Block objects; you will be using a Block object similar to bitcoin.

block flow

the Block object contains the following properties:

  • index: GenesisBlock is our first block, we assign the block index with the value of 0.
  • txns: This is the raw transaction in the block. I don’t want to focus on just cryptocurrencies in this chapter, so think of this as any type of data you want to store.

Included in the Block object is the BlockHeader object, which contains the following properties:

  • Version: At the time of writing, there are four block versions. Version 1 is the genesis block (2009), and version 2 is a soft fork of bitcoin core 0.7.0 (2012). Version 3 blocks were a soft fork of bitcoin core 0.10.0 (2015). Version 4 blocks are BIP65 in bitcoin core 0.11.2 (2015).
  • Previous block header hash: This is an SHA-256 (Secure Hash Algorithm) hash function of the previous block’s header. It ensures that the previous block cannot be changed as this block needs to be changed as well.
  • Merkle root hash: A Merkle tree is a binary tree that holds all the hashed pairs of the tree.
  • Time: This is the Unix epoch time when the miner started hashing the header.

As you recall, bitcoin also includes a difficulty property for the miners that gets recalculated every 2,016 blocks. Here you won’t use the nBits and nounce params, as you are not doing PoW.

  • nounce: The nonce in a bitcoin block is a 32-bit (4-byte) field whose value is adjusted by miners so that the hash of the block will be less than or equal to the current target of the network.
  • nBits: This refers to the target. The target is a 256-bit number and is inversely proportional to the difficulty. It is recalculated every 2,016 blocks.

In terms of P2P communication, the flow of blocks between each peer on the P2P network consists of requesting the latest block from a peer on the network and then receiving a block request.

Flow diagram of P2P communications requesting latest block and receiving latest block

Now that you understand the architecture and the flow of blocks in the P2P network, next, you will be sending and requesting blocks.

P2P network sending block

Setting Up a Block Class and Chain Library

The blockchain consists of two files: block.jsand chain.js. The file block.js will hold the block class object, and chain.js will be the glue with methods to handle the interactions with the blocks. In terms of the Block object, you will be creating properties similar to the properties that bitcoin core holds. Take a look at block.js file includes Block and BlockHeader objects.

block.js

As you can see, chain.js contains the first block, which is called the genesis block, as well as a method to receive the entire blockchain object, add a block, and retrieve a block. Note that you will be adding a library called moment to save the time in a Unix time format in your chain.js library. To do so, install moment with npm.

npm install moment --save

Now create the chain.js :

chain.js

Now we’ve got a block object that is included in chain.js. Our library can create a genesis block and add a block to your blockchain object. Also, we’ll be able to send and request blocks. Now, use the chain.js in p2p.js :

p2p.js

At this point, we have a basic P2P network, and we are able to connect peers in the network, create a genesis block, and send and receive blocks. The next step is being able to generate new blocks.

We’ll take an approach of proof of stake (PoS) where you trust each miner to generate blocks. Each peer will register as a miner and will take a turn to mine a block.

Your blockchain handles mining using a simple PoS mechanism

To automate the process of generating a block every X number of minutes, you can use a Node.js library called cron, which is similar to the Linux library that automates tasks. To install the cron open-source library, run the following command:

npm install cron --save

Next, in your p2p.js file, you will create two variables to keep track of the registered miners as well as who mined the last block so you can assign the next block to the next miner.

let registeredMiners = [];
let lastBlockMinedBy = null;

You are also going to add two messages types.

  • REQUEST_ALL_REGISTER_MINERS
  • REGISTER_MINER
let MessageType = { 
REQUEST_BLOCK: ‘requestBlock’,
RECEIVE_NEXT_BLOCK: ‘receiveNextBlock’,
RECEIVE_NEW_BLOCK: ‘receiveNewBlock’, REQUEST_ALL_REGISTER_MINERS: ‘requestAllRegisterMiners’,
REGISTER_MINER: ‘registerMiner’
};

Before you register your peers as miners, you will request to receive all the existing registered miners in the network, and then you will add your peer as a miner in a registeredMiners object. You do that by running a timer to update your miners every five seconds.

setTimeout(function(){ writeMessageToPeers(MessageType.REQUEST_ALL_REGISTER_MINERS, null); }, 5000);

Now, that has an automated timeout command that can point to a handler to update the list of registered miners you can also automate a command to register your peer as a miner;

setTimeout(function(){ registeredMiners.push(myPeerId.toString(‘hex’));
console.log(‘ — — — — — Register my miner — — — — — — — ‘); console.log(registeredMiners); writeMessageToPeers(MessageType.REGISTER_MINER, registeredMiners); console.log(‘ — — — — — Register my miner — — — — — — — ‘);
}, 7000);

In your switch command, modify the code to be able to set handlers for incoming messages regarding the registrations of miners. We want to keep track of the registered miners as well as handle a message once a new block is mined.

case MessageType.REQUEST_ALL_REGISTER_MINERS: 
console.log(‘ — — — — — -REQUEST_ALL_REGISTER_ MINERS — — — — — — — ‘ + message.to);
writeMessageToPeers(MessageType.REGISTER_MINER, registeredMiners); registeredMiners = JSON.parse(JSON.stringify(message. data)); console.log(‘ — — — — — -REQUEST_ALL_REGISTER_ MINERS — — — — — — — ‘ + message.to);
break;
case MessageType.REGISTER_MINER:
console.log(‘ — — — — — -REGISTER_MINER — — — — — — — ‘ + message.to);
let miners = JSON.stringify(message.data);
registeredMiners = JSON.parse(miners);
console.log(registeredMiners);
console.log('----------- REGISTER_MINER------------- ' + message.to);
break;

You also need to unregister a miner once a connection with the miner is closed or lost.

console.log(`Connection ${seq} closed, peerId: ${peerId}`); if (peers[peerId].seq === seq) { 
delete peers[peerId];
console.log(‘ — — registeredMiners before: ‘ + JSON.stringify(registeredMiners));
let index = registeredMiners.indexOf(peerId);
if (index > -1)
registeredMiners.splice(index, 1);
console.log(‘ — — registeredMiners end: ‘ +
JSON.stringify(registeredMiners));
}
});

Mine a new block

As opposed to bitcoin, which generates a block every 10 minutes, your blockchain will be improved and will generate a block every 30 seconds. To achieve that, you already installed the open-source cron library for Node.js. The cron library works the same as the Linux cron. You can use the cron library to set how often to call the same code again, which will be used to call your miners every 30 seconds.

To do so, first include the library in your code’s import statement on top of the p2p.js file. Next, you set a cronjob to run every 30 seconds, and job.start(); will start the job,

After adding all the above functions your p2p.js file will look like this:

p2p.js

A LevelDB database stores name-value pairs in what is called a level-up and level-down fashion. It is an ideal option for blockchain networks. In fact, bitcoin uses LevelDB to store not only block information but also transaction information. To use it, install level with npm.

npm install level --save

Next, make a directory where you will be saving the database.

mkdir db

You can now implement the database. In chain.jsadd some code to save your block in the LevelDB database.

chain.js

Lastly, in your p2p.js file, all you need to do is create a database once you start the code.

chain.createDb(myPeerId.toString(‘hex’));
adding createDb in p2p.js

In cryptocurrency, a wallet is necessary in order to reward miners for generating blocks as well as to be able to create transactions and send transactions. In this section, you will create a wallet. You need to create a combination of public and private keys not just to authenticate a user but so you can store and retrieve data that the user owns. You will create a wallet with public and private keys.

You will be using the elliptic-curve cryptography library implementation to generate private-public key combos. Note that the elliptic-curve library uses secp256k1 as the ECDSA curve algorithm. To install it, run the following command,

npm i elliptic --save

Create a new file wallet.js and copy the following code,

Next, create a wallet directory to store the private key and run the script. The code will initialize the script and create your public key.

mkdir wallet
node wallet.js
cat wallet/private_key
output private key

Remember to comment out last lines 32 to 34 of wallet.jsbecause in the next, you will create an API to be able to create your keys via the browser.

The next step is creating an application program interface (API) to be able to access the code you write. This is an important part of a blockchain, as you want to access your blocks and wallet or any other P2P network operation using an HTTP service.

You will install express and body-parser. These libraries will allow you to create a server and display pages in the browser.

npm install express body-parser — save

Now open your p2p.js file and follow along,

To call your services, run the P2P network,

node p2p.js
p2p.js output

Now, open a browser and call the API,

http://localhost:8001/blocks
http://localhost:8001/getBlock
http://localhost:8001/getDBBlock
http://localhost:8001/getWallet
calling /blocks API in the browser

For the last step in this chapter, you will be creating a command-line interface (CLI). The CLI is needed to be able to easily access the services you created.

Next, install the libraries you will be utilizing to run promises, run the async function, add colors to the console, and store cookies.

npm i babel-polyfill async update-notifier handlebars colors nopt --save

Create a new directory cliand inside another cmds for commands

mkdir cli
cd cli
mkdir cmds
touch block.js help.js version.js wallet.js

In the block.jsyou will be setting two commands: get and all,

block.js cli

As you can see, the wallet.js will include the get and all methods to point to a curl command to run the HTTP service call,

wallet.js cli

Similarly, we will do for others please follow this link. Copy codes from the given link.

Now, create a directory bin and add cli.js ,

Now that you have your commands set up, you can add your CLI to the bash_profile as an alias to be able to run the CLI from any path location.

nano .bash_profilealias cli='node /<location>/Blockchain/bin/cli.js'

Press ctrl+o to save and ctrl+X to exit, then run bash_profile,

. ~/.bash_profile

Hurray!! Our command-line interface is ready 😃, let’s test it,

node p2p.js

Open another terminal and run,

cli block --get [port] 1 
cli block –all [port]
cli wallet --create [port]
cli interface output

Congrats👏 we have created our own blockchain 🔥🔥🔥🔥

In this article, we have covered how to create your very own basic P2P blockchain network; you were able to send and receive messages and include blocks in these messages; you were able to register and unregister miners and implement a simple PoS consensus mechanism; you created new blocks and sent them between the peers; you also set up a name-value LevelDB database to store blocks; you continued and created a wallet that consists of private-public key pairs. Lastly, you created ways to communicate with your P2P network via API services and the CLI.

Want to Connect?For the full code visit and if you like it, follow me on GitHub:
https://github.com/ac12644/Blockchain

Leave a Comment