How to Build a Blockchain in JavaScript

How to Build a Blockchain in JavaScript

For the purpose of this blog, let’s build a blockchain written in JavaScript. Hopefully, this doesn’t just serve as a simple code example but also gives a very basic understanding of how a blockchain actually works.

Blockchain is all the buzz now. And for good reason! A distributed public ledger that is extremely secure through encryption?! Imagine the millions of applicable use cases. A blockchain can be created and maintained using any modern language.

For the purpose of this blog, let’s dive into a blockchain written in JavaScript. Hopefully, this doesn’t just serve as a simple code example but also gives a very basic understanding of how a blockchain actually works.

Creating A Block

Let’s first create a block and give it some attributes.

  • BlockIndex – the position of the block on the blockchain.
  • BlockCreatedWhen – when the block was created.
  • BlockTransaction – a type of data to be stored on the block. This could be any exchange of value really. Perhaps an array of sorts.
  • BlockPreviousHash – hash of the previous block. This ties one block to another.
  • Hash – calculated hash function using the properties of the block. This is the block identifier on the blockchain. There is currently no built-in functionality for hash functions outside of the WebCryptoAPI. But there are plenty of other external libraries such as object-hash, crypto-hs, SJCL, forge SHA-256, etc.
  • Nonce – Proof of work
  • Merkle Root – A Merkle Root hash that houses all hashed transactions tied to a particular block.
const hash = require('crypto-js/sha256'); // could also use object-hash, Stanford Javascript Crypto Library (SJCL), forge SHA-256, jsSHA, etc

class VincentsBlock{

    constructor(blockIndex, blockCreatedWhen, blockTransactions, blockPreviousHash) {
        this.blockIndex = blockIndex;
        this.blockCreatedWhen = blockCreatedWhen;
        this.blockTransactions = blockTransactions;  // an array of transactions
        this.blockPreviousHash = blockPreviousHash;
        this.hash = this.calculateBlockHash();
        this.nonce = 0;  // needed for proof of work
        this.merkleRoot = this.computeMerkleRoot()  // used to validate transactions within block
    } 

    calculateBlockHash() { 
        return hash(this.blockIndex + JSON.stringify(this.blockTransaction) + this.blockPreviousHash + this.blockCreatedWhen + this.nonce + this.merkleTreeRoot).toString();
    }

    computeMerkleRoot() {
        let treeList = this.generateMerkleTreeRoot();

        return treeList[treeList.length-1];
    }

    generateMerkleTreeRoot() {
        let tree = [];
        let transactionCount = this.blockTransactions.length;

        for (var i=0; i<transactionCount; i++) { tree.push(this.blockTransactions[i].hash); } let levelOffset = 0; for (let levelSize = transactionCount; levelSize > 1; levelSize = (levelSize + 1) / 2) {          
            for (let left = 0; left < levelSize; left += 2) {            
                let right = Math.min(left + 1, levelSize - 1);
                let tleft = tree[levelOffset + left];
                let tright = tree[levelOffset + right];
                tree.push(hash(tleft + tright));
            }            
            levelOffset += levelSize;
        }

        return tree;
    }
}

module.exports = VincentsBlock;

Notice the Merkle Root property on the block. Given that a transaction has its own hash generated, we can create a Merkle Tree out of the transaction list. This tree can then be used to validate the block transactions. Now that a block is generated, let’s go back and look at a transaction object. This should illustrate that a transaction can be anything really. This is where the many applications of blockchain come into play.

These particular transactions consist of a

  • transactionId (id of transaction),
  • inputAccount (sender),
  • outputAccount (receiver),
  • fee (perhaps in BTC or any other currency),
  • the amount (processed amount),
  • type,
  • misc (notes)
  • timestamp (timestamp of transaction)
  • hash (hash of transaction)

Creating a Block Transaction Object

I created a block transaction object as follows:

const hash = require('crypto-js/sha256');

class VincentsTransaction{

    constructor(transactionId, inputAccount, outputAccount, fee, amount, type, misc, timestamp) {
        this.transactionId = transactionId,   // could be hex address
        this.inputAccount = inputAccount;    // sender
        this.outputAccount = outputAccount;   // receiver
        this.fee = fee;    // fee of transaction
        this.amount = amount;    // amount of transaction processed
        this.type = type;      // type of transaction
        this.misc = misc;     // misc note text
        this.timestamp = timestamp    // timestamp of block
        this.hash = this.calculateTransactionHash();  // hash of the transaction
    } 

    calculateTransactionHash() { 
        return hash(this.transactionId + this.inputAccount + this.outputAccount + this.fee + this.amount + this.type + this.misc + this.timestamp).toString();
    }
}

module.exports = VincentsTransaction;

The Chain

Moving on to the good part, let’s take a look at a basic immutable blockchain using the above blocks.

Below, in the constructor, you will notice a manual creation of the first block. This is needed to get the ball rolling. Every chain needs a first link!

Let’s manually create it and give it an index of 0 to show its placement on the chain. Many functions can be added to this class to assist on tasks such as adding blocks, checking for an empty chain, grabbing the latest block, validation, etc.

The process of creating additional blocks can be a complex one involving tons of validation if needed. We must keep in mind to regenerate the hash if any other property changes on a block.

In regards to validation of the blockchain, for now, we will focus on blocks linked together. Since index 0 corresponds to the manually created first block, we can skip it and check the hash of corresponding linked blocks.

let VincentsBlock = require('./VincentsBlock');

class VincentsBlockChain {

    constructor() {
        this.chain = [this.createBrandNewBlock()];

        //this.current_transactions = [];
    }

    createBrandNewBlock() {
        return new VincentsBlock(0, "01/01/2019", "Initial Block", ""); //no hash needed here since this is a manual creation of the first block.
    }

    createAdditionalBlock(newBlock) {
        ///very simplistic... could have more validation in place here.  
        let previousBlock = this.getLatestBlock();
        newBlock.index = previousBlock.index + 1; 
        newBlock.blockPreviousHash = this.getLatestBlock().hash;
        newBlock.hash = newBlock.calculateBlockHash(); //need to regenerate hash if any properties in our block changes
        this.chain.push(newBlock);
    }

    getLatestBlock() {
        return this.chain.slice(-1)[0];        
    }

    isEmpty() {
        return this.chain.length == 0;
    } 

    isBlockChainValid() { 
        for(let i = 1;i < this.chain.length; i++) {
            const currentBlock = this.chain[i];
            const previousBlock = this.chain[i - 1];

            if (currentBlock.blockPreviousHash != previousBlock.hash) { // does our block match up to correct previous hash property? 
                return false;
            }            

            if (currentBlock.hash != currentBlock.calculateBlockHash()) { // does the actual hash of the block match up to it's current hash property?
                return false;
            }     

            if (previousBlock.index + 1 !== currentBlock.index) { // do the indexes line up in order?
                return false;
            }  
        }

        return true;
    }
};

module.exports = VincentsBlockChain;

Adding to the Chain

For this simplistic example, let’s create 10 blocks, each with multiple transactions, and add them to the chain.

let VincentsBlockChain = require( "./blockchain/VincentsBlockChain");
let VincentsBlock = require( "./blockchain/VincentsBlock");
let VincentsTransaction = require( "./blockchain/VincentsTransaction");

let blockChain = new VincentsBlockChain();
blockChain.createAdditionalBlock(new VincentsBlock(1, "01/02/2019", [new VincentsTransaction(123, "abcxyz", "xyzabc", 30, "btc"), new VincentsTransaction(999, "uyyuyy", "xxdzkj", 550, "btc"), new VincentsTransaction(653, "drerea", "kioolk", 70, "eth")]));
blockChain.createAdditionalBlock(new VincentsBlock(2, "01/03/2019", [new VincentsTransaction(234, "sfgfsd", "rrttyu", 50, "eth"), new VincentsTransaction(555, "iuiuii", "rrttyu", 50, "eth"), new VincentsTransaction(553, "hghghg", "ffgfff", 80, "eth")]));
blockChain.createAdditionalBlock(new VincentsBlock(3, "01/04/2019", [new VincentsTransaction(345, "srthhf", "oouyuu", 65, "btc"), new VincentsTransaction(452, "jhghgg", "rrttyu", 11, "eth"), new VincentsTransaction(230, "wewfgf", "ghjgtt", 230, "eth")]));
blockChain.createAdditionalBlock(new VincentsBlock(4, "01/05/2019", [new VincentsTransaction(456, "sfgfss", "xzsdee", 4, "btc"), new VincentsTransaction(780, "fgtfdd", "rrttyu", 22, "eth"), new VincentsTransaction(112, "qwewue", "hgyuyu", 280, "eth")]));
blockChain.createAdditionalBlock(new VincentsBlock(5, "01/06/2019", [new VincentsTransaction(567, "xxcbbf", "nbvbcx", 545, "eth"), new VincentsTransaction(677, "fdfsaa", "uytttt", 33, "eth"), new VincentsTransaction(111, "hjhjh", "huiuii", 5480, "eth")]));
blockChain.createAdditionalBlock(new VincentsBlock(6, "01/07/2019", [new VincentsTransaction(678, "uiyuyy", "dfgree", 5, "btc"), new VincentsTransaction(553, "ooouio", "yuyuuu", 55, "eth"), new VincentsTransaction(467, "eeeewq", "jgftft", 880, "eth")]));
blockChain.createAdditionalBlock(new VincentsBlock(7, "01/08/2019", [new VincentsTransaction(789, "iughff", "opoiii", 125, "btc"), new VincentsTransaction(988, "aqQQQQ", "trewew", 01, "eth"), new VincentsTransaction(432, "eeeee", "khuuuu", 40, "eth")]));
blockChain.createAdditionalBlock(new VincentsBlock(8, "01/09/2019", [new VincentsTransaction(890, "sdsrer", "sdfser", 99, "eth"), new VincentsTransaction(886, "gfgfdg", "qqqqqq", 88, "eth"), new VincentsTransaction(444, "gfgfd", "llllkl", 70, "eth")]));
blockChain.createAdditionalBlock(new VincentsBlock(9, "01/10/2019", [new VincentsTransaction(901, "mnghjy", "dfgxbg", 65, "btc"), new VincentsTransaction(644, "dddsds", "wwwwww", 55, "eth"), new VincentsTransaction(333, "sdsaqq", "ererew", 50, "eth")]));
blockChain.createAdditionalBlock(new VincentsBlock(10, "01/11/2019", [new VincentsTransaction(012, "vccvff", "uiyfvv", 74, "btc"), new VincentsTransaction(994, "mnmnmm", "qqqqhh", 66, "eth"), new VincentsTransaction(323, "qwqwqq", "wreret", 30, "eth")]));

console.log(JSON.stringify(blockChain, null, 2)); // let's view entire blockchain

console.log('Validate entire blockchain: ' + blockChain.isBlockChainValid()); // let's validate the blockchain is secure

blockChain.chain[5].hash = blockChain.chain[5].calculateBlockHash();  // let's try to recalculate hash for block 5

console.log('Is blockchain valid? ' + blockChain.isBlockChainValid()); 

Alright, let’s run this bad boy and see the blockchain we created.

{
  "chain": [
    {
      "blockIndex": 0,
      "blockCreatedWhen": "01/01/2019",
      "blockTransactions": "Initial Block",
      "blockPreviousHash": "",
      "hash": "46d4d81e6047cccb6e856a4bc800ed344fbe4b78df5f5a7fe5862e8773cd022a",
      "nonce": 0,
      "merkleTreeRoot": {
        "words": [
          -474954686,
          -1728308204,
          -1694763832,
          -1720731356,
          665731556,
          1687917388,
          -1533699813,
          2018687061
        ],
        "sigBytes": 32
      }
    },
    {
      "blockIndex": 1,
      "blockCreatedWhen": "01/02/2019",
      "blockTransactions": [
        {
          "transactionId": 123,
          "inputAccount": "abcxyz",
          "outputAccount": "xyzabc",
          "fee": 30,
          "amount": "btc",
          "hash": "324cc491e4436b69299a905847124308c6dfc272642d9dbb3808bd79048bc110"
        },
        {
          "transactionId": 999,
          "inputAccount": "uyyuyy",
          "outputAccount": "xxdzkj",
          "fee": 550,
          "amount": "btc",
          "hash": "3beef24348997907eaa0263d3eb1393b1e74cb365e730649c60a910ecbbee0d5"
        },
        {
          "transactionId": 653,
          "inputAccount": "drerea",
          "outputAccount": "kioolk",
          "fee": 70,
          "amount": "eth",
          "hash": "a30e34266150f7b616aa4ebe88461406308280c9821425dbe0bfbc1fa7e6843a"
        }
      ],
      "blockPreviousHash": "46d4d81e6047cccb6e856a4bc800ed344fbe4b78df5f5a7fe5862e8773cd022a",
      "hash": "54ee7657f991b1341ecfa7d2ecfe7cf0501751f147ecc7b9ca08b2354068eeab",
      "nonce": 0,
      "merkleTreeRoot": {
        "words": [
          -474954686,
          -1728308204,
          -1694763832,
          -1720731356,
          665731556,
          1687917388,
          -1533699813,
          2018687061
        ],
        "sigBytes": 32
      },
      "index": null
    },
    {
      "blockIndex": 2,
      "blockCreatedWhen": "01/03/2019",
      "blockTransactions": [
        {
          "transactionId": 234,
          "inputAccount": "sfgfsd",
          "outputAccount": "rrttyu",
          "fee": 50,
          "amount": "eth",
          "hash": "f2378fced4de261dc5c531441d867b385f5726b76eb76d6ece8b739de3f6d2f7"
        },
        {
          "transactionId": 555,
          "inputAccount": "iuiuii",
          "outputAccount": "rrttyu",
          "fee": 50,
          "amount": "eth",
          "hash": "cb42ae591f275f7d265f749489c0830ef985252d256ad176430a9acee0b7c525"
        },
        {
          "transactionId": 553,
          "inputAccount": "hghghg",
          "outputAccount": "ffgfff",
          "fee": 80,
          "amount": "eth",
          "hash": "edb71da69f72d01fdefe7939665d8fc59489bb16e5f3d7e662a187b1d437ef8f"
        }
      ],
      "blockPreviousHash": "54ee7657f991b1341ecfa7d2ecfe7cf0501751f147ecc7b9ca08b2354068eeab",
      "hash": "f58b63c0fbe00f69b6b1bd04560ffdd72ebe7b71e70a16224bf45aad01308e0f",
      "nonce": 0,
      "merkleTreeRoot": {
        "words": [
          -474954686,
          -1728308204,
          -1694763832,
          -1720731356,
          665731556,
          1687917388,
          -1533699813,
          2018687061
        ],
        "sigBytes": 32
      },
      "index": null
    },
    {
      "blockIndex": 3,
      "blockCreatedWhen": "01/04/2019",
      "blockTransactions": [
        {
          "transactionId": 345,
          "inputAccount": "srthhf",
          "outputAccount": "oouyuu",
          "fee": 65,
          "amount": "btc",
          "hash": "eaa995a8b3a64237c3133fbb744ed1761ba716781b7026f7f956043173c452f6"
        },
        {
          "transactionId": 452,
          "inputAccount": "jhghgg",
          "outputAccount": "rrttyu",
          "fee": 11,
          "amount": "eth",
          "hash": "e867bcef38e0272776fc3fbeff0aac19cb366ca513945ddfa1491adc2f3257b2"
        },
        {
          "transactionId": 230,
          "inputAccount": "wewfgf",
          "outputAccount": "ghjgtt",
          "fee": 230,
          "amount": "eth",
          "hash": "d25b62651513ee902e063970b5b7baed30de4f9832b7a78db3247a09414a1495"
        }
      ],
      "blockPreviousHash": "f58b63c0fbe00f69b6b1bd04560ffdd72ebe7b71e70a16224bf45aad01308e0f",
      "hash": "288b9f37d503b22a5f4535e086ab84fdbff2e22f8880fb2f24baa29b5151235d",
      "nonce": 0,
      "merkleTreeRoot": {
        "words": [
          -474954686,
          -1728308204,
          -1694763832,
          -1720731356,
          665731556,
          1687917388,
          -1533699813,
          2018687061
        ],
        "sigBytes": 32
      },
      "index": null
    },
    {
      "blockIndex": 4,
      "blockCreatedWhen": "01/05/2019",
      "blockTransactions": [
        {
          "transactionId": 456,
          "inputAccount": "sfgfss",
          "outputAccount": "xzsdee",
          "fee": 4,
          "amount": "btc",
          "hash": "af15f83e9c599347351019f62309fb1b9077447a4e0fc8b48a6b5c487b1e144e"
        },
        {
          "transactionId": 780,
          "inputAccount": "fgtfdd",
          "outputAccount": "rrttyu",
          "fee": 22,
          "amount": "eth",
          "hash": "8984871129b02f0b09f83abd5c1161f6a0dee64f84c336a54f5c34e5454f02a7"
        },
        {
          "transactionId": 112,
          "inputAccount": "qwewue",
          "outputAccount": "hgyuyu",
          "fee": 280,
          "amount": "eth",
          "hash": "2631aa030dfbc44fe084d86f69c1d24ca64a154c59d13b42718211ed02e3b1dc"
        }
      ],
      "blockPreviousHash": "288b9f37d503b22a5f4535e086ab84fdbff2e22f8880fb2f24baa29b5151235d",
      "hash": "07205c43afea9e53d02dedce994c891babccd8397d082b431f986045cbc18e44",
      "nonce": 0,
      "merkleTreeRoot": {
        "words": [
          -474954686,
          -1728308204,
          -1694763832,
          -1720731356,
          665731556,
          1687917388,
          -1533699813,
          2018687061
        ],
        "sigBytes": 32
      },
      "index": null
    },
    {
      "blockIndex": 5,
      "blockCreatedWhen": "01/06/2019",
      "blockTransactions": [
        {
          "transactionId": 567,
          "inputAccount": "xxcbbf",
          "outputAccount": "nbvbcx",
          "fee": 545,
          "amount": "eth",
          "hash": "8030161e3fdb7038fb7e751236063996152897f9647c654fb47334da7f7295bb"
        },
        {
          "transactionId": 677,
          "inputAccount": "fdfsaa",
          "outputAccount": "uytttt",
          "fee": 33,
          "amount": "eth",
          "hash": "b327dfa8769ec04bc447313af98feeb783c95c198e926737ea916700f4b71994"
        },
        {
          "transactionId": 111,
          "inputAccount": "hjhjh",
          "outputAccount": "huiuii",
          "fee": 5480,
          "amount": "eth",
          "hash": "aae165434e054c42e7da129b08a7c99f6c544351b7383459e322ef253570f4a4"
        }
      ],
      "blockPreviousHash": "07205c43afea9e53d02dedce994c891babccd8397d082b431f986045cbc18e44",
      "hash": "55c88c98e497a9f300ca3ec8bec0129652a8e5e9b49e6ecaf4ab0c63b42ebf4f",
      "nonce": 0,
      "merkleTreeRoot": {
        "words": [
          -474954686,
          -1728308204,
          -1694763832,
          -1720731356,
          665731556,
          1687917388,
          -1533699813,
          2018687061
        ],
        "sigBytes": 32
      },
      "index": null
    },
    {
      "blockIndex": 6,
      "blockCreatedWhen": "01/07/2019",
      "blockTransactions": [
        {
          "transactionId": 678,
          "inputAccount": "uiyuyy",
          "outputAccount": "dfgree",
          "fee": 5,
          "amount": "btc",
          "hash": "134269524a221afb1f5ef218584b063ab4bea3aaa5dc2cdbfa66f439f2d1e36b"
        },
        {
          "transactionId": 553,
          "inputAccount": "ooouio",
          "outputAccount": "yuyuuu",
          "fee": 55,
          "amount": "eth",
          "hash": "19076e1cb35d8357b16f92794c5bd1ff020c8cb9e8ce5fcf03b560256a363c16"
        },
        {
          "transactionId": 467,
          "inputAccount": "eeeewq",
          "outputAccount": "jgftft",
          "fee": 880,
          "amount": "eth",
          "hash": "461ad65962d2d1cc1f767c1b9c0f569d19ef48be60ef2fe8c08898cc01d34492"
        }
      ],
      "blockPreviousHash": "55c88c98e497a9f300ca3ec8bec0129652a8e5e9b49e6ecaf4ab0c63b42ebf4f",
      "hash": "e1087468c2719f967584cab0a22938b81e9e956762f2c5a2d2dd91da2c92cfbd",
      "nonce": 0,
      "merkleTreeRoot": {
        "words": [
          -474954686,
          -1728308204,
          -1694763832,
          -1720731356,
          665731556,
          1687917388,
          -1533699813,
          2018687061
        ],
        "sigBytes": 32
      },
      "index": null
    },
    {
      "blockIndex": 7,
      "blockCreatedWhen": "01/08/2019",
      "blockTransactions": [
        {
          "transactionId": 789,
          "inputAccount": "iughff",
          "outputAccount": "opoiii",
          "fee": 125,
          "amount": "btc",
          "hash": "7149930eae17b35f22c02acb0765b829d79e5539c6e2e80b837045f89d0422c2"
        },
        {
          "transactionId": 988,
          "inputAccount": "aqQQQQ",
          "outputAccount": "trewew",
          "fee": 1,
          "amount": "eth",
          "hash": "d752f91eb8010b5c9d6066afb92a5fa6c4667f9fc18b6f8d4a7c1a32b104919c"
        },
        {
          "transactionId": 432,
          "inputAccount": "eeeee",
          "outputAccount": "khuuuu",
          "fee": 40,
          "amount": "eth",
          "hash": "c5c20ac19253cd6782f0a95eb628c719cafeac22d4c8bacbf2863b06e0e366db"
        }
      ],
      "blockPreviousHash": "e1087468c2719f967584cab0a22938b81e9e956762f2c5a2d2dd91da2c92cfbd",
      "hash": "63302ff671cee7c659e1bf9eb1cd659f054d4615c4692d5b425ad04b2f82deb6",
      "nonce": 0,
      "merkleTreeRoot": {
        "words": [
          -474954686,
          -1728308204,
          -1694763832,
          -1720731356,
          665731556,
          1687917388,
          -1533699813,
          2018687061
        ],
        "sigBytes": 32
      },
      "index": null
    },
    {
      "blockIndex": 8,
      "blockCreatedWhen": "01/09/2019",
      "blockTransactions": [
        {
          "transactionId": 890,
          "inputAccount": "sdsrer",
          "outputAccount": "sdfser",
          "fee": 99,
          "amount": "eth",
          "hash": "c4abc25fcc9ea1e78be488aac5ee9a3ee1f16b0915e23700ff6bb11e1df02c51"
        },
        {
          "transactionId": 886,
          "inputAccount": "gfgfdg",
          "outputAccount": "qqqqqq",
          "fee": 88,
          "amount": "eth",
          "hash": "fd454dbdfb263db527ed335116aab73a7dab8468d3d443aa0fd8e4c7e438f465"
        },
        {
          "transactionId": 444,
          "inputAccount": "gfgfd",
          "outputAccount": "llllkl",
          "fee": 70,
          "amount": "eth",
          "hash": "c9b9ebdcb469f0f5ae8c6653c10f45d88a59b807c87b9febe1be986844d558f4"
        }
      ],
      "blockPreviousHash": "63302ff671cee7c659e1bf9eb1cd659f054d4615c4692d5b425ad04b2f82deb6",
      "hash": "fec255eb642f1dd02ab7c5185bfd78f9574b50c0188a888b4227b8cef5497e0e",
      "nonce": 0,
      "merkleTreeRoot": {
        "words": [
          -474954686,
          -1728308204,
          -1694763832,
          -1720731356,
          665731556,
          1687917388,
          -1533699813,
          2018687061
        ],
        "sigBytes": 32
      },
      "index": null
    },
    {
      "blockIndex": 9,
      "blockCreatedWhen": "01/10/2019",
      "blockTransactions": [
        {
          "transactionId": 901,
          "inputAccount": "mnghjy",
          "outputAccount": "dfgxbg",
          "fee": 65,
          "amount": "btc",
          "hash": "6e94502eb38d14410141d87bd27a2369e14e62bf8efece8adbde9873a8e88777"
        },
        {
          "transactionId": 644,
          "inputAccount": "dddsds",
          "outputAccount": "wwwwww",
          "fee": 55,
          "amount": "eth",
          "hash": "7072d7ec51bf41a1f36744f7abf8e9e4f70d195b708420f77b5141bcb7567f45"
        },
        {
          "transactionId": 333,
          "inputAccount": "sdsaqq",
          "outputAccount": "ererew",
          "fee": 50,
          "amount": "eth",
          "hash": "199c710224da1e16f597c2eae088acd5c3d4b6fd9a12d84c0b76a735eed541a2"
        }
      ],
      "blockPreviousHash": "fec255eb642f1dd02ab7c5185bfd78f9574b50c0188a888b4227b8cef5497e0e",
      "hash": "fcec05a7f1afb3c91ddbf90f36e04d17e4eabd7e47545a9f08173767cd4d74c8",
      "nonce": 0,
      "merkleTreeRoot": {
        "words": [
          -474954686,
          -1728308204,
          -1694763832,
          -1720731356,
          665731556,
          1687917388,
          -1533699813,
          2018687061
        ],
        "sigBytes": 32
      },
      "index": null
    },
    {
      "blockIndex": 10,
      "blockCreatedWhen": "01/11/2019",
      "blockTransactions": [
        {
          "transactionId": 10,
          "inputAccount": "vccvff",
          "outputAccount": "uiyfvv",
          "fee": 74,
          "amount": "btc",
          "hash": "8f2abd539ef073b7d4053fe6090196f682f6361a619329e45a3a0df10919623c"
        },
        {
          "transactionId": 994,
          "inputAccount": "mnmnmm",
          "outputAccount": "qqqqhh",
          "fee": 66,
          "amount": "eth",
          "hash": "040dda42beee5673e882884e3e963292015253348b1db5c3feb5d54af4e4b728"
        },
        {
          "transactionId": 323,
          "inputAccount": "qwqwqq",
          "outputAccount": "wreret",
          "fee": 30,
          "amount": "eth",
          "hash": "af54b136d57904e80823c53649d4149092fb6ebb4bf1e8578facaae8aca2cf1c"
        }
      ],
      "blockPreviousHash": "fcec05a7f1afb3c91ddbf90f36e04d17e4eabd7e47545a9f08173767cd4d74c8",
      "hash": "9074846c6a4153802d86cd19b6d95266c56d082329c6f0f52ded270fae269c48",
      "nonce": 0,
      "merkleTreeRoot": {
        "words": [
          -474954686,
          -1728308204,
          -1694763832,
          -1720731356,
          665731556,
          1687917388,
          -1533699813,
          2018687061
        ],
        "sigBytes": 32
      },
      "index": null
    }
  ]
}

NOTE: Within the merkleTreeRoot property, crypto-js utilizes word arrays encoded as UTF-8 when given a string.

Above, notice the hash and blockPreviousHash property of each block. This serves as the link for the chain.

But what happens if one were to modify a block somehow? Perhaps change the fee property or attempt to recalculate a block hash?

console.log('Validate entire blockchain: ' + blockChain.isBlockChainValid()); // let's validate the blockchain is secure

blockChain.chain[5].hash = blockChain.chain[5].generateBlockHash();  // let's try to recalculate hash for block 5

console.log('Is blockchain valid? ' + blockChain.isBlockChainValid()); 

Validate entire blockchain: true
Is blockchain valid? false

It appears that the blockchain validation function isBlockChainValid() caught an attempt to recalculate its hash. Of course, this is pretty basic validation, but it serves its purpose to illustrate the secure nature of blockchain.

Final Thoughts

In summary, a blockchain can be written in various languages. I hope this basic JavaScript version not only illustrates that but gives a little more overview of how blockchains work.

Thank for reading ! Please share if you liked it!

javascript blockchain bitcoin altcoins geek-cash

Bootstrap 5 Complete Course with Examples

Bootstrap 5 Tutorial - Bootstrap 5 Crash Course for Beginners

Nest.JS Tutorial for Beginners

Hello Vue 3: A First Look at Vue 3 and the Composition API

Building a simple Applications with Vue 3

Deno Crash Course: Explore Deno and Create a full REST API with Deno

How to Build a Real-time Chat App with Deno and WebSockets

Convert HTML to Markdown Online

HTML entity encoder decoder Online

What Is The Difference Between Blockchain And Bitcoin?

Get hands on experinece on block chain live industry experts with real world example at Block chain online Training. Enroll for free demo

How to Create a Blockchain Chat App with Javascript - Blockchain for Beginner

From beginner to blockchain. In this webinar recap, you'll learn how Proof of Stake works and then will build a simple blockchain chat app in Javascript!

Building a blockchain with Javascript

Want to understand how blockchains and cryptocurrencies work under the hood? Just build a simple version yourself with Javascript and learn while doing!

Master Blockchain Programming with JavaScript - Web3.js

In this video, you'll learn Blockchain Programming with JavaScript

Bitcoin to Surpass $100k by 2021? – Jared – Medium

Cryptocurrencies, The decision is yours