How To Build A Blockchain with JavaScript (Part 1)
Creating a blockchain with JavaScript part 1
In this tutorial, we'll write a very tiny blockchain in JavaScript. It won't be too fancy, but it’ll be enough to give you an understanding of how a blockchain works.
We'll call this blockchain SavjeeCoin. Let's get started!
Set up the Blockchain
We'll start by creating a new JavaScript file to store all of our code. We'll call it main.js
and let's start by defining what a blockchain and blocks should look like.
Let's begin with creating a Block
class and giving it a constructor. When you create a new block, you need to pass it a timestamp, some data and the hash of the block that went before it:
class Block{
constructor(timestamp, data, previousHash = '') {
this.previousHash = previousHash;
this.timestamp = timestamp;
this.data = data;
}
}
Here’s what each property means:
-
The
timestamp
tells us when the block was created. You can use any format you like (in this example we'll use a UNIX timestamp) -
The
data
parameter can include any type of data that you want to associate with this block. If you want to build a cryptocurrency you can store transaction details in here like sender/receiver and the amount of money that was transferred. -
The
previousHash
is a string that contains the hash of the previous block. This is what will create the chain of blocks and will be very important to ensure the integrity of our blockchain later.
Hashes
Each block points towards the previous block (that's why we have the previousHash
attribute). That means that each block needs a hash.
A hash is basically like a fingerprint. It's unique for each block. You can calculate a hash of a block by taking all of its contents and running it through a hash function.
So let's start by writing a method that can calculate the hash of the current block. So inside the Block
class, we create a calculateHash
function:
calculateHash() {
return SHA256(this.previousHash + this.timestamp + JSON.stringify(this.data)).toString();
}
Notice that I choose to use the SHA256 hash function. However, the SHA256 hash is not available in JavaScript and requires you to use an external library. I found that crypto-js is a great library and contains secure implementations for different hash functions. Install it with npm like this:
npm install crypto-js
Then afterwards we can import it in our main.js
file like so:
const SHA256 = require("crypto-js/sha256");
Now that we have our calculateHash()
method, let's use it in the constructor of our Block
:
class Block{
constructor(timestamp, data, previousHash = '') {
this.previousHash = previousHash;
this.timestamp = timestamp;
this.data = data;
// When creating a new Block, automatically calculate its hash.
this.hash = this.calculateHash();
}
}
Blockchain class
After defining what a Block looks like, we can define what a Blockchain should look like. So let's create a new class for that:
class Blockchain{
constructor() {
this.chain = [];
}
}
In this case, the blockchain is a very simple object that contains a property chain
. This is an array containing all the blocks on the chain.
Before we can add new blocks, we have to add what is called a "genesis block". This is the first block on the chain and it's a bit special because it cannot point to a previous block (it's the first one!)
So to create the genesis block, I'll add a method to our class called createGenesisBlock()
:
createGenesisBlock()
return new Block("01/01/2017", "Genesis block", "0");
}
Back in the constructor of our Blockchain
class, we can now add the genesis block whenever we create a new Blockchain instance:
class Blockchain{
constructor() {
this.chain = [this.createGenesisBlock()];
}
More Blockchain methods
Now, let’s add some methods to our Blockchain class to allow us to do basic things like adding new blocks and getting the latest block.
The getLatestBlock
method is the most simple one. It just returns the last element on the chain
array:
getLatestBlock(){
return this.chain[this.chain.length - 1];
}
The addBlock
method is a bit more complicated. Before we can add a new block to our chain, we have to correctly set the previousHash
property of that block. It has to be set to the hash of the latest block on our chain. And we also have to calculate the hash of the new block:
addBlock(newBlock){
// The new block needs to point to the hash of the latest block on the chain.
newBlock.previousHash = this.getLatestBlock().hash;
// Calculate the hash of the new block
newBlock.hash = newBlock.calculateHash();
// Now the block is ready and can be added to chain!
this.chain.push(newBlock);
}
Just a side note: in reality, adding blocks to a blockchain requires you to "mine" it. That's something we'll add in part 2 of this post (so keep reading!)
Testing
Let's test it. To do that, create an instance of the blockchain:
let savjeeCoin = new Blockchain();
And let's add a few blocks:
savjeeCoin.addBlock(new Block("20/07/2017", { amount: 4 }));
savjeeCoin.addBlock(new Block("22/07/2017", { amount: 10 }));
There — we have created two new blocks. Let's see what our blockchain now looks like. We'll stringify SavjeeCoin and use four spaces to format it:
console.log(JSON.stringify(savjeeCoin, null, 4));
The output is what our blockchain looks like right now. Our blockchain's object contains a property chain (an array), which contains all of our blocks.
Verify the integrity of the blockchain
Great! Now that we know it works, let's try to do something different. Blockchains are great because once a block is added, it cannot be changed without invalidating the rest of the chain.
In this implementation, however, there is no way for me to verify the integrity of our blockchain. Let's add a new method to our blockchain, called isChainValid
. This will return true if the chain is valid or false if something is wrong:
isChainValid(){
}
In order to verify the integrity, we have to loop over the entire chain (not looking at the genesis block). Inside this loop we're going to check two things:
-
Is the block's hash still valid? To check that we will recalculate the hash of each block. If something changed inside a block, it will change the hash of that block.
-
Does each block point to the correct previous block? To check this, we will see if the
previousHash
of the block, equals thehash
property of the block that went before it. -
Is the genesis block still intact or has it been tampered with?
Here is the full method:
isChainValid(){
for (let i = 1; i < this.chain.length; i++){
const currentBlock = this.chain[i];
const previousBlock = this.chain[i - 1];}
// Recalculate the hash of the block and see if it matches up.
// This allows us to detect changes to a single block
if (currentBlock.hash !== currentBlock.calculateHash()) {
return false;
}
// Check if this block actually points to the previous block (hash)
if (currentBlock.previousHash !== previousBlock.hash) {
return false;
}
}
// Check the genesis block
if(this.chain[0] !== this.createGenesisBlock()){
return false;
}
// If we managed to get here, the chain is valid!
return true;
}
Testing integrity
Now we can test the integrity of our blockchain by running:
console.log('Blockchain valid? ' + savjeeCoin.isChainValid());
If we run it now, it will say that yes, our chain is indeed valid (we didn't tamper with it).
Now, let's try and tamper with our blockchain. Let's change block 2 and overwriting its data (let's say we want to pretend that we transferred 100 coins instead of 4):
// Tamper with the chain!
savjeeCoin.chain[1].data = { amount: 100 };
// Check if it's valid again
console.log('Blockchain valid? ' + savjeeCoin.isChainValid()); // will return false!
When we run this, notice that the program has detected our attempt to tamper with the chain!
However, you might think that there's another way I can tamper with this. I've changed the block’s data, but I didn't recalculate the hash. So you might try to be clever, take that same block, and recalculate its hash.
// Tamper with the chain!
savjeeCoin.chain[1].data = { amount: 100 };
// Recalculate its hash, to make everything appear to be in order!
savjeeCoin.chain[1].hash = savjeeCoin.chain[1].calculateHash():
However, when we run this again, it till detects that we tampered with the chain. That's because block 2 now has a previousHash
attribute that doesn't match the hash of block 1.
Summary
So that was it for our simple blockchain implementation! It allows us to add new blocks and detect when someone is tampering with the data inside the chain.
However, it's far from complete!
Next up
In the next part of this series we will take a look at how we can implement the proof-of-work algorithm so we can prevent people from adding a lot of spam blocks to our chain and to make tampering even harder:
Continue reading: "Implementing proof-of-work (Blockchain in JavaScript, part 2)"
Source code
The source code is available on GitHub and there’s a video tutorial if you want to follow along step-by-step.
Very cool…now I’m building blox & using es6 classes! Thanks!
can we run this code on Visual Studio Community 2019
Awesome explanation over BlockChain and it is easy to understand what is all about the Blockchain even for the novice user as well.