Implementing PBFT in Blockchain
By: Kashish Khullar
Tags: Tech, Blockchain, Cryptocurrency, Ethereum, Technology

Prerequisites

Node.js Postman VS code Knowledge about blockchain concepts

Architecture and Design

To implement PBFT we will develop the following components:

Wallet class — for public key and signing data. Transaction class — to create transactions and verify them. Block class — to create blocks, verify blocks and verify proposer of the block. Blockchain class — to create a chain, add blocks, calculate proposer, validate blocks, update blocks. P2p Server class — to broadcast and receive data among peers. Validators — to generate and verify validators Transaction pool, block pool, commit pool, prepare pool and message pool — to store transactions, blocks, commits, prepare and new round messages respectively. App — Express API to interact with the blockchain Config — to store global variables Chain Utilities — to store common functions such as hashing and verifying signatures.

Code

Create a root directory pbft and cd into it. All the files in this project are present in the root directory.

mkdir pbft && cd pbft

The ChainUtil Class

We will start off by creating a chain-util.js file which will be used multiple times in this project. This file will be used to create key pair for signing data, generating id’s for transactions, hashing data and verifying signatures.

We need three modules to perform these functions. Therefore we need to install them.

npm i --save elliptic uuid crypto-js

Create a class ChainUtil and export it.

The Transaction Class

Next, we’ll make a transaction class. Create file transaction.js in the project folder. Transactions in this project will contain the following properties:

id — for identification from — the senders address input — an object that further contains data to be stored and timestamp hash — the SHA256 of input signature — the hash signed by the sender

Create a class Transaction in the file and export it.

The Wallet Class

Up next is wallet. The wallet holds the public key and key pair. It is also responsible for signing data hashes and creating signed transactions.

Create a file wallet.js in the project directory. Add a class Wallet and export it.

The Validator Class

Since PBFT is a permissioned blockchain consensus algorithm we need to store the address of all the nodes in each nodes system. We can do this manually by choosing a secret, creating a wallet, getting its public key and storing this key into a file and when we run our project it reads this file for keys.

But instead of doing this manually we can automate this by creating a class and adding a function that can return a list of public keys of N number of nodes.

We will create a Validator class that will generate a list of public keys known to every node. In this project, we have used the secret phrase for each node as

NODE1, NODE2, NODE3......

This way it would be easier for us to make a list of public keys and create the nodes from the command line with the same public key.

NOTE: Secret phrase should never be made public. It is only for the demonstration that we have used such Secret phrases. In real-world projects, a registration request is sent to make a node a validator. If the whole network approves this request, the node becomes a validator and the public key is added to the list.

The Config.js file

The number of validators in the network can be passed through the command line but instead it easier to store it in a file and import it where ever needed.

Create a file config.js and create three variables NUMBER_OF_NODES , MIN_APPROVALS and TRANSACTION_THRESHOLD

The Block Class

Next we will create the block class. In the project directory, create a file block.js and make a class Block in it. Block will have the following properties:

timestamp — the time at which the block was made lastHash — hash value of the last block hash — hash value of the current block data — the transactions that the block holds proposer — the public key of the creator of the block signature — the signed hash of the block sequenceNo — the sequence number of block

The TransactionPool Class

We need a place to store transactions received from other nodes. Therefore we will make a TransactionPool class to store all transactions. Create a file called transaction-pool.js

The BlockPool Class

To store blocks temporarily we will also make block pool. Create a file block-pool.js in which the BlockPool class holds the blocks until it is added to the chain. A block is added to the block pool when a PRE-PREPARE message is received.

There are many other data objects received from the nodes that need to be stored. PREPARE , COMMIT and NEW_ROUND messages

Therefore will create three more pools namely, PreparePool , CommitPool and MessagePool . MessagePool will hold the NEW_ROUND messages.

The PreparePool Class

The CommitPool Class

Commit messages are added after 2f+1 prepare messages are received, therefore we use the prepare message to get the block hash instead of passing the entire block.

The MessagePool Class

MessagePool will work similarly to the other two pools. The only difference would be the extra message it takes with it.

The Blockchain Class

We have all of the classes required to make our blockchain class. We can now create a file blockchain.js The Blockchain class will have the following properties:

chain — list of blocks that are confirmed validatorsList — validators list for the given network

The P2pserver Class

How do we send messages to other nodes? We will make a P2p Server. Create a class P2pserver in a file p2p-server.js

To create a p2p server we will make use of sockets. In order to use sockets we will install a ‘ws’ module. This module makes it utterly easy to work with sockets.

npm i --save ws

P2pserver class is where the consensus algorithm is implemented. It is the core of the project. This class is responsible for handling messages and broadcasting them.

The App

Now we will connect all the files using an application created using express module. Install the express module using npm.

npm i express --save

Our application will instantiate the pools, wallet, blockchain, p2pserver and declare some endpoints to interact with our blockchain.

Following are the minimum endpoints required, (you may add more):

POST: ‘/transact’ — creates transactions, request object consists of data to be stored in the transaction GET: ‘/transactions’ — sends the transactions in the transaction pool as a response GET: ‘/blocks’ — sends the chain of the blockchain as a response

This completes our coding. You test this application by running the following in the separate terminals:

First node:

SECRET="NODE0" P2P_PORT=5000 HTTP_PORT=3000 node app

Second node:

SECRET="NODE1" P2P_PORT=5001 HTTP_PORT=3001 PEERS=ws://localhost:5000 node app

Third node:

SECRET="NODE2" P2P_PORT=5002 HTTP_PORT=3002 PEERS=ws://localhost:5001,ws://localhost:5000 node app

You can make as many as you want. Do update the total number of nodes config file before creating more nodes.

Hit the endpoint for any node until the pool fills up and check the chain by hitting the /blocks endpoint.

Also, hit the endpoint /transactions to check if the transaction pool is empty.

You can also make more such endpoints for commit, prepare and message pool.