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!

What is in a block? - Blockchain

In my previous article, I tried to described the concept of a blockchain with code. This time, I'll try to describe the structure of a single block. I will use the Bitcoin blockchain to explain blocks, but keep in mind that the concepts will remain more or less the same. It could be useful to read my&nbsp;<a href="https://dev.to/damcosset/trying-to-understand-blockchain-by-making-one-ce4" target="_blank">last article</a>to understand a few things first.

Introduction

In my previous article, I tried to described the concept of a blockchain with code. This time, I'll try to describe the structure of a single block. I will use the Bitcoin blockchain to explain blocks, but keep in mind that the concepts will remain more or less the same. It could be useful to read my last articleto understand a few things first.

Structure of a block

A block is a container data structure. In the Bitcoin world, a block contains more than 500 transactions on average. The average size of a block seems to be 1MB (source). In Bitcoin Cash ( a hard fork from the Bitcoin blockchain ), the size of a block can go up to 8MB. This enables more transactions to be processed per second.

Anyway, a block is composed of a header and a long list of transactions. Let's start with the header.

Block Header

The header contains metadata about a block. There are three different sets of metadata:

  • The previous block hash. Remember that in a blockchain, every block is inherits from the previous block because we use the previous block's hash to create the new block's hash. For every block N, we feed it the hash of the block N-1.
  • Mining competition. For a block to be part of the blockchain, it needs to be given a valid hash. This contains the timestamp, the nonce and the difficulty. Mining is another crucial part of the blockchain technology, but it is outside the scope of this article.
  • The third part is a merkle tree root. This is a data structure to summarize the transactions in the block. And we will leave it at that for now. More on this later.
Block identifiers

To identify a block, you have a cryptographic hash, a digital signature if you will. This is created by hashing the block header twice with the SHA256 algorithm. For example, this is a block. I will refer to this block as an example for this article.

The block header hash for this particular block is (right column): 000000000000000000301fcfeb141088a93b77dc0d52571a1185b425256ae2fb

We also can see the previous block's hash (right column): 0000000000000000004b1ef0105dc1275b3adfd067aed63a43324929bed64fd7

Remember that we used the second hash to create the first. Every block uses the previous block's hash to construct its own hash. The block hash is a unique identifier. You won't find two blocks with the same hash.

The other way to identify a specific block is the block height. The is the position of the block in the blockchain. Our example's block is in the 500312 position. This means that there are 500311 blocks before this one. Since the creation of the Bitcoin blockchain in 2009, 500312 blocks have been created ( at the time of writing obviously ).

A block height is not unique. Several blocks can compete for the same position in the case of a fork, like Bitcoin Cash for example.

Merkle Trees

The transactions in a block are contained in a structure called a merkle tree or binary hash tree.

I feel that topics like that are easier to understand with actual examples. So we'll go coding for this. A merkle tree is constructed by recursively hashing pairs of nodes ( in this case, transactions ), until there is only one hash, called the root or merkle root. If we stay in the Bitcoin world, the cryptographic hash algorithm used is SHA256. This is applied twice each time.

An example: We have a block with 4 transactions. For the sake of simplicity, each transaction is a string:

const tA = 'Hello'
const tB = 'How are you?'
const tC = 'This is Thursday'
const tD = 'Happy new Year'

To construct our merkle tree, we start from the bottom. We take each transaction and double-hash them. I'll use the js-sha256 package here.

const sha256 = require('js-sha256').sha256

// Double-hashing here
const hA = sha256(sha256(tA))
const hB = sha256(sha256(tB))
const hC = sha256(sha256(tC))
const hD = sha256(sha256(tD))

//Results
52c87cd40ccfbd7873af4180fced6d38803d4c3684ed60f6513e8d16077e5b8e //hA
426436adcaca92d2f41d221e0dd48d1518b524c56e4e93fd324d10cb4ff8bfb9 //hB
6eeb307fb7fbc0b0fdb8bcfdcd2d455e4f6f347ff8007ed47475481a462e1aeb //hC
fd0df328a806a6517e2eafeaacea72964f689d29560185294b4e99ca16c63f8f //hD

Ok, great. Now remember that I wrote a merkle tree is constructed hashing pairs of nodes. So, we will pair our transactions and concatenate their hashes. Then, we will double hash them too. We will create a hash using the hashes hA and hB, and another for hC and hD. Then, we repeat that process until we have only one hash left and no more pairs to work with. The last hash will be our merkle root.

With only four transactions, this will be rather quick:

//Pairing hA and hB

const hAB = sha256(sha256(hA + hB))
//5dc23d1a2151665e2ac258340aa9a11ed227a4cc235e142a3e1738333575590b

//Pairing hC and hD

const hCD = sha256(sha256(hC + hD))
//ff220daefda29821435691a9aa07dd2c47ca1d2574b8b77344aa783142bae330

// We do it again. We pair hAB and hCD
// This is our root!
const hABCD = sha256(sha256(hAB + hCD))
//301faf21178234b04e1746ee43e126e7b2ecd2188e3fe6986356cc1dd7aa1377

The node at the top of the merkle tree is called the root. This is the information that is stored in the block header in each block on the blockchain. This is how transactions are summarized in each block. In our example block given earlier, the merkle root can be found in the right column: 

a89769d0487a29c73057e14d89afafa0c01e02782cba6c89b7018e5129d475cc

It doesn't matter how many transactions are contained in a block, they always will be summarized by a 32 bytes hash.

Note: The merkle tree is a binary tree. If there is an odd number of transactions, the last one will be duplicated so we can construct our tree.

Because all the leaves in our tree depends on other leaves, it is impossible to alter one leaf without altering others. If you change only one leaf ( one transaction ), the hash changes, therefore the hash you constructed by pairing it with another leaf changes, therefore the merkle root will be different.

You can prove that any transaction is included in a block by creating a authentification path or merkle path. You only need to know log base 2(N) 32-byte hashes. For example:

-For my 4 transactions merkle tree:

log base 2( 4 ) = 2 => If I have a path of 2 hashes for a tree of 4 transactions, I can manage to prove if a transaction belongs to this merkle tree.

For a 16 transactions merkle tree:

log base 2( 16 ) = 4 => If I have a path of 4 hashes for a tree of 16 transactions, I can manage to prove if a transaction belongs to this merkle tree.

log base 2( 1500 ) = 10.55 => If I have a path of 11 hashes for a tree of 1500 transactions, I can manage to prove if a transaction belongs to this merkle tree.

Perhaps a little diagram will help.

There are 16 leaves in this tree. We construct our tree from the bottom up by pairing each leaf. Now, anybody can prove that the leaf I ( in orange ) is part of this block by having the path given in green. We have only 4 hashes, but that is enough to know if the leaf I belongs here. That is because with those informations, we are able to construct every single leaf we need( in yellow ). We can create IJIJKLIJKLMNOP and the root and check if those hashes correspond. This is why it is very complicated to cheat a blockchain. To change one thing means you must change everything.

Well, that's pretty much what a block contains in the Bitcoin blockchain. Hope it helped!


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

Cryptocurrencies, The decision is yours

I’ve been told by naysayers that Bitcoin “will never hit $100k” and such a proposition is absurd. With a combination of the factors above, I believe that Bitcoin will usurp the $100k barrier within the next 3 years, but the path won’t be seamless. There will be cycles of boom and bust. Also, it’s possible that Bitcoin fails to reach such valuations or is halted by a massive setback like a black swan event. However, my bet is clearly on Bitcoin. In fact, I envision that someday we’ll look back and realize that the greater risk was not investing in Bitcoin at all.