How to build a Decentralized Blockchain Network in Javascript

How-to-build-a-Decentralized-Blockchain-Network-in-Javascript

In previous post, we have a single Blockchain and the only way to access it is through API from a single server. It is centralized and not good because this API totally controls the whole Blockchain with all data inside it. Today we will build a decentralized Blockchain network that has many different instances of the API. So instead of just having our Blockchain hosted on a single centralized node, it is hosted across a decentralized network which will be very powerful because of the security: we don’t have to trust only one single entity.

Previous Post: How to create Blockchain API in Javascript

Next Post: How to Synchronize Blockchain Network in JavaScript

Overview

To create a network, we need a way of registering these nodes.
So we will make 3 endpoints:

– POST /register-node: registers a node with specific node.
– POST /register-bulk-nodes: registers a node with multiple nodes at once.
– POST /register-and-broadcast-node will register a node and broadcast that node to the entire network with node’s url on the body.

*Note: In this example, ‘register’ nodeA with nodeB means add nodeA’s nodeUrl to nodeB’s networkNodes array.


app.post('/register-node', function (req, res) {
    const nodeUrl = req.body.nodeUrl;

    // add nodeUrl to this.networkNodes
}

app.post('/register-bulk-nodes', function (req, res) {
    const networkNodes = req.body.networkNodes;

    // forEach(nodeUrl in networkNodes)
    // add nodeUrl to this.networkNodes
}

app.post('/register-and-broadcast-node', function (req, res) {
    const nodeUrl = req.body.nodeUrl;
    // add nodeUrl to this.networkNodes

    // forEach(node in this.networkNodes)
    // POST /register-node to node
    // with body: { nodeUrl }

    // POST /register-bulk-nodes to nodeUrl
    // with body: { [ this.networkNodes, this.nodeUrl ] }
}

To understand deeply, please look at diagram below:

build-decentralized-blockchain-network-javascript-outline

Assume that we want to register node5 to the network. node1 has already connected to node2, node3, node4 before.
=> We just use /register-and-broadcast-node, everything will be done.

So, the process can be explained as below:
1- First, we register node5 with node1 using /register-and-broadcast-node. node5 will be add to node1 networkNodes array.
2- Next, node1 automatically broadcasts node5 to all nodes inside networkNodes array (node2, node3, node4) using /register-node.
3- Finally, node1 calls /register-bulk-nodes endpoint of node5 to register all nodes inside its networkNodes array (including itself) with node5. node5 now connects to node1, node2, node3, node4.

Practice

Setup Environment

This was our project folder before:

build-blockchain-api-javascript-structure

Install UUID

Because our network contains many nodes, each node should have its own address. We can generate theses address by UUID.
Run command: npm install uuid.

Inside app.js, import uuid and use:

const uuid = require('uuid/v1');
const nodeAddr = uuid();

Install Request-Promise

request-promise is simplified HTTP request client ‘request’ with Promise support.
Run command: npm install request-promise.

Inside app.js, import request-promise:


const reqPromise = require('request-promise');

We will use it to POST data to a Rest API:


const requestOptions = {
    uri: 'http://api.blockchain.com/register-node',
    method: 'POST',
    body: { nodeUrl: nodeUrl },
    json: true
}

reqPromise(requestOptions)
    .then(function () {
        // ...
    })
    .catch(function (err) {
        // ...
    });

We also need request to work with request-promise.
Run command: npm install request.

Create multiple nodes

We have multiple instances of API and each of them acts as a network node.
>> We will run this api.js file on different ports.

Open package.json file, add these script:


{
  "name": "blockchain",
  "version": "1.0.0",
  "description": "JSA blockchain demo",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "node1": "nodemon --watch src -e js src/api.js 3001 http://localhost:3001",
    "node2": "nodemon --watch src -e js src/api.js 3002 http://localhost:3002",
    "node3": "nodemon --watch src -e js src/api.js 3003 http://localhost:3003",
    "node4": "nodemon --watch src -e js src/api.js 3004 http://localhost:3004",
    "node5": "nodemon --watch src -e js src/api.js 3005 http://localhost:3005"
  },
  "author": "JavaSampleApproach",
  "license": "ISC",
  "dependencies": {
    "body-parser": "^1.18.3",
    "express": "^4.16.3",
    "nodemon": "^1.17.5",
    "request": "^2.87.0",
    "request-promise": "^4.2.2",
    "sha256": "^0.2.0",
    "uuid": "^3.2.1"
  },
  "keywords": [
    "jsa-blockchain"
  ]
}

To access to the port and url variable:


// api.js
const port = process.argv[2];
app.listen(port, function () {
    console.log(`> listening on port ${port}...`);
});

// blockchain.js
const nodeUrl = process.argv[3];

Add Network Nodes to Blockchain

Open blockchain.js, add nodeUrl field and networkNodes array to constructor method of Blockchain class:


const nodeUrl = process.argv[3];

class Blockchain {
    constructor() {
        this.chain = [];
        this.pendingTransactions = [];

        this.nodeUrl = nodeUrl;
        this.networkNodes = [];

        this.creatNewBlock(100, '0', 'Genesis block');
    }
    ...
}

Create Endpoints

Register Node

Get nodeUrl, then put it in networkNodes:


app.post('/register-node', function (req, res) {
    const nodeUrl = req.body.nodeUrl;

    if ((bitcoin.networkNodes.indexOf(nodeUrl) == -1)
        && (bitcoin.nodeUrl !== nodeUrl)) {
        bitcoin.networkNodes.push(nodeUrl);

        res.json(
            {
                message: 'A node registers successfully!'
            }
        );
    }
    else {
        res.json(
            {
                message: 'This node cannot register!'
            }
        );
    }
});

Register Nodes in Bulk

Receive list of Nodes in networkNodes, add each item in the list to networkNodes.


app.post('/register-bulk-nodes', function (req, res) {
    const networkNodes = req.body.networkNodes;

    networkNodes.forEach(nodeUrl => {
        if ((bitcoin.networkNodes.indexOf(nodeUrl) == -1)
            && (bitcoin.nodeUrl !== nodeUrl)) {
            bitcoin.networkNodes.push(nodeUrl);
        }
    });

    res.json(
        {
            message: 'Registering bulk successfully!'
        }
    );
});

Register and Broadcast Node

– Register new Node with itself.
– Broadcast that new Node to all the other Nodes that are already present in current Node’s networkNodes.
– Register all of the nodes that are currently inside of networkNodes (including current Node) with the new Node.


app.post('/register-and-broadcast-node', function (req, res) {
    const nodeUrl = req.body.nodeUrl;

    if (bitcoin.networkNodes.indexOf(nodeUrl) == -1) {
        bitcoin.networkNodes.push(nodeUrl);
    }

    const registerNodes = [];
    bitcoin.networkNodes.forEach(networkNode => {
        const requestOptions = {
            uri: networkNode + '/register-node',
            method: 'POST',
            body: { nodeUrl: nodeUrl },
            json: true
        }

        registerNodes.push(reqPromise(requestOptions));
    });

    Promise.all(registerNodes)
        .then(data => {
            const bulkRegisterOptions = {
                uri: nodeUrl + '/register-bulk-nodes',
                method: 'POST',
                body: { networkNodes: [...bitcoin.networkNodes, bitcoin.nodeUrl] },
                json: true
            }

            return reqPromise(bulkRegisterOptions);
        }).then(data => {
            res.json(
                {
                    message: 'A node registers with network successfully!'
                }
            );
        });
});

Run and Check results

– Run the API on each Terminal with command:
npm run node1
npm run node2
npm run node3
npm run node4
npm run node5

– Register node2, node3, node4 with node1:

build-decentralized-blockchain-network-javascript-register-node

– Open url http://localhost:3001/blockchain to check node1 networkNodes:

build-decentralized-blockchain-network-javascript-register-node-result

– Register and broadcast node5:

build-decentralized-blockchain-network-javascript-register-broadcast-node

– Open url http://localhost:3001/blockchain and view node1 with node5 insides networkNodes:

build-decentralized-blockchain-network-javascript-register-broadcast-node-result-1

– To check node2, node3, node4, open url http://localhost:3002/blockchain / http://localhost:3003/blockchain / http://localhost:3004/blockchain, we can see node5 has been added:

build-decentralized-blockchain-network-javascript-register-broadcast-node-result-3

– Open url http://localhost:3005/blockchain, all Nodes in Network have registered with node5:

build-decentralized-blockchain-network-javascript-register-broadcast-node-result-5

Source Code

Blockchain-decentralizedNetwork

24 thoughts on “How to build a Decentralized Blockchain Network in Javascript”

  1. Woah! I’m really digging the template/theme of this blog. It’s simple, yet effective. A lot of times it’s tough to get that “perfect balance” between user friendliness and visual appeal. I must say you’ve done a superb job with this. In addition, the blog loads very quick for me on Chrome. Outstanding Blog!

    Rankcircles.com

  2. hello there aand thanks forr your injfo – I
    have certainly picked up anything new from proper here. I did then again expertise some technical points using this web site,
    since I experienced to reloa the web site lots of instances prior
    to I may just get itt to load correctly. I wede considering iif your hosting is OK?
    Not tht I’m complaining, however slow loading circumstances occasions will sometimes impact your placement in google and could damage your
    quality rating if advertising and ***********

  3. I truly love your website.. Pleasant colors & theme.
    Did you develop this site yourself? Please reply back as I’m trying to create
    my own site and would like to learn where you got this
    from or what the theme is called. Kudos!

  4. Great blog! Do you have any tips and hints for aspiring writers?
    I’m planning to start my own website soon but I’m a little lost
    on everything. Would you suggest starting with a free platform like WordPress
    or go for a paid option? There are so many
    choices out there that I’m totally confused .. Any ideas?
    Many thanks!

  5. My developer is trying to convince me to move to
    .net from PHP. I have always disliked the idea because of
    the expenses. But he’s tryiong none the less.
    I’ve been using WordPress on several websites for about a year and
    am anxious about switching to another platform. I have heard very good things about
    blogengine.net. Is there a way I can import all my wordpress posts into it?

    Any kind of help would be greatly appreciated!

  6. Simply wish to say your article is as amazing.
    The clearness for your put up is simply nice and that i can assume
    you’re knowledgeable on this subject. Well with your permission allow me to snatch your RSS feed to keep up to date with imminent post.
    Thank you 1,000,000 and please continue the gratifying work.

  7. I’m extremely pleased to find this great site. I wanted to thank you
    for ones time for this particularly wonderful read!! I definitely appreciated every
    little bit of it and i also have you book marked to look
    at new things on your site.

  8. I’m no longer positive where you’re getting your information, but good topic.
    I needs to spend some time studying more or figuring out more.
    Thank you for excellent information I was on the
    lookout for this info for my mission.

  9. First off Ӏ want to say awesome bⅼog! I had a quick questiⲟn that I’d like to ask if you don’t mind.
    I was interеsted to find out howw you center yourself and clear your tһoughts before writing.
    I’ve had a tough time clearing my thօughts in etting my ideas ᧐ut.
    I do take pleasure іn writing but it just seems ⅼіke the first 10 to 15 minutes are wasted juѕt trying to figure out how to begin. Any
    гecommendations or tips? Chеers!

  10. Woah! I’m really digging the template/theme of this
    blog. It’s simple, yet effective. A lot of times it’s difficult to get that “perfect balance”
    between superb usability and visual appearance.

    I must say you’ve done a amazing job with this. Also, the blog loads very
    fast for me on Opera. Outstanding Blog!

Leave a Reply

Your email address will not be published. Required fields are marked *