DEV Community

Cover image for Creating a blockchain in 60 lines of Javascript
FreakCdev
FreakCdev

Posted on • Updated on

Creating a blockchain in 60 lines of Javascript

In recent years, cryptocurrencies and blockchains are two uprising fields, so today, I will share my way of creating a blockchain in Javascript in just 60 lines of codes.

There's also my full tutorial on Youtube. You can check it out for more details.

Also, my new article is released, check it out! It's about creating transactions for our blockchain, basically the first step of building a cryptocurrency.

If two of those are already too familiar for you, consider checking out the third article about how to create a p2p network and release your cryptocurrency. Consider checking it out!

What is a blockchain?

Before we do any coding, we need to understand what a blockchain is. Technically, a blockchain at its bare minimum is just a list containing objects that have some basic information on it like timestamp, transactions, hash,... Its data must be immutable and unhackable. Modern platforms like Ethereum, Cardano, Polkadot,... have way more complex stuff, but we are staying simple in this article.

Setup

We are using Node.js for this project, so be sure to install it if you haven't.

Throughout the article, I will be using the object-oriented programming style, so I expect you to know basic knowledge about it.

Creating a block

As I have said, a block is just an object that has some information on it, so we should have a Block class like this:

class Block {
    constructor(timestamp = "", data = []) {
        this.timestamp = timestamp;
        // this.data should contain information like transactions.
        this.data = data;
    }
}
Enter fullscreen mode Exit fullscreen mode

So we have our timestamp and data, but a blockchain needs immutability. We can gain that effect by using a hashing function that hashes all of our properties in the block. I suggest reading about hasing on wikipedia, it plays an essential role in a blockchain. Basically, it takes in a message and outputs a "hashed" one with fixed length, a slight change to the message will make the output completely different.

I'm using the sha256 algorithm. To implement its hashing function, I'll just going to use the Nodejs' built-in crypto package:

const crypto = require("crypto"), SHA256 = message => crypto.createHash("sha256").update(message).digest("hex");
Enter fullscreen mode Exit fullscreen mode

The code above should give us what we wanted, but if you want to know how it works, check out Node.js's official doc about the hash class.

We should have something like this:

// Get the sha256 hash function.
const crypto = require("crypto"), SHA256 = message => crypto.createHash("sha256").update(message).digest("hex");

class Block {
    constructor(timestamp = "", data = []) {
        this.timestamp = timestamp;
        this.data = data;
        this.hash = this.getHash();
        this.prevHash = ""; // previous block's hash
    }

    // Our hash function.
    getHash() {
        return SHA256(this.prevHash + this.timestamp + JSON.stringify(this.data));
    }
}
Enter fullscreen mode Exit fullscreen mode

Because every time anything is changed, SHA256 will throw out something completely different, so that can some what ensures the immutability.

The prevHash property also plays a big role in immutability, it ensures that the blocks will stay unchanged along the blockchain's lifespan. It contains the hash of the previous block, so you can assure the immutability of that previous block since a slight change will make the current block's getHash be different. You can see that it's empty, but we will do something with it later in this article.

The blockchain

Let's move over to the blockchain class.

Like I have said, a blockchain is a list with blocks, so we can have a basic form like this:

class Blockchain {
    constructor() {
        // This property will contain all the blocks.
        this.chain = [];
    }
}
Enter fullscreen mode Exit fullscreen mode

You must have a genesis block, which is technically just the first block:

class Blockchain {
    constructor() {
        // Create our genesis block
        this.chain = [new Block(Date.now().toString())];
    }
}
Enter fullscreen mode Exit fullscreen mode

Just for convenience, I'll create a function to get the latest block:

    getLastBlock() {
        return this.chain[this.chain.length - 1];
    }
Enter fullscreen mode Exit fullscreen mode

Now, we should have a way to add a block to the blockchain.

    addBlock(block) {
        // Since we are adding a new block, prevHash will be the hash of the old latest block
        block.prevHash = this.getLastBlock().hash;
        // Since now prevHash has a value, we must reset the block's hash
        block.hash = block.getHash();

        // Object.freeze ensures immutability in our code
        this.chain.push(Object.freeze(block));
    }
Enter fullscreen mode Exit fullscreen mode

Validation

We need to know whether the chain is still valid or not, so we need a method to check validation. The chain is valid if a block's hash is equal to what its hashing method returns, and a block's prevHash property should be equal to the previous block's hash.

    isValid(blockchain = this) {
        // Iterate over the chain, we need to set i to 1 because there are nothing before the genesis block, so we start at the second block.
        for (let i = 1; i < blockchain.chain.length; i++) {
            const currentBlock = blockchain.chain[i];
            const prevBlock = blockchain.chain[i-1];

            // Check validation
            if (currentBlock.hash !== currentBlock.getHash() || prevBlock.hash !== currentBlock.prevHash) {
                return false;
            }
        }

        return true;
    }
Enter fullscreen mode Exit fullscreen mode

This method will play a really important role when our blockchain is ran on a p2p network.

Proof-of-work

In a peer-to-peer network, where there are no 3rd party system to approve people's action, without any consensus mechanism, nodes (people to be simple) will agree with the majority, but people can start being attackers and take control of the majority, so we need a consensus mechanism. A consensus mechanism exist not entirely to stop attacks, they exist to make people not be attackers. Proof-of-work is one of them.

Before we go more on to that, the system works by making you increase a value called nonce to get the hash which starts with a number of zeros equals/relates to the difficulty.

PoW can help with 2 things: It prevents attackers because it's near impossible to catch up with other nodes alone, and it provides mining rewards so people would try to be neutral rather than being attackers. We will implement mining rewards in the next article when we have a transaction system.

We can implement the PoW system by adding a mine method and a nonce property to our block:

class Block {
    constructor(timestamp = "", data = []) {
        this.timestamp = timestamp;
        this.data = data;
        this.hash = this.getHash();
        this.prevHash = ""; // previous block's hash
        this.nonce = 0;
    }

    // Our hash function.
    getHash() {
        return SHA256(this.prevHash + this.timestamp + JSON.stringify(this.data) + this.nonce);
    }

    mine(difficulty) {
        // Basically, it loops until our hash starts with 
        // the string 0...000 with length of <difficulty>.
        while (!this.hash.startsWith(Array(difficulty + 1).join("0"))) {
            // We increases our nonce so that we can get a whole different hash.
            this.nonce++;
            // Update our new hash with the new nonce value.
            this.hash = this.getHash();
        }
    }
}
Enter fullscreen mode Exit fullscreen mode

Because when we change a small detail in our block, the hash will be completely different, so we are just incrementing nonce over and over again until the hash matches the one we need.

(Note that Bitcoin and others normally use a different way to check difficulty, but we are staying simple)

Moving over to the Blockchain class, we should create a difficulty property:

    this.difficulty = 1;
Enter fullscreen mode Exit fullscreen mode

I will set it to 1, the difficulty should update based on how many blocks mined.

We must update the addBlock method from the Blockchain too:

    addBlock(block) {
        block.prevHash = this.getLastBlock().hash;
        block.hash = block.getHash();
        block.mine(this.difficulty);
        this.chain.push(Object.freeze(block));
    }
Enter fullscreen mode Exit fullscreen mode

Now, all blocks need to be mined before being added to the chain.

Quick note

Because we are staying simple, so I used the proof-of-work system for this blockchain. Note that most modern blockchains use a way better system called proof-of-stake (or many of its upgraded variations).

Testing out the chain!

Create a new file, that file will be the entry file.

Let's use our freshly created blockchain! I'll call it JeChain for now.

Export the needed classes first:

module.exports = { Block, Blockchain };
Enter fullscreen mode Exit fullscreen mode
const { Block, Blockchain } = require("./your-blockchain-file.js");

const JeChain = new Blockchain();
// Add a new block
JeChain.addBlock(new Block(Date.now().toString(), { from: "John", to: "Bob", amount: 100 }));
// (This is just a fun example, real cryptocurrencies often have some more steps to implement).

// Prints out the updated chain
console.log(JeChain.chain); 
Enter fullscreen mode Exit fullscreen mode

It should look like this:

Image description

The first block is our genesis block, the second block is the added block.

Updated bonus: Difficulty and block time

Block time

Block time is a constant value that resembles estimated time for a block to be added to the chain. Platforms like Bitcoin has block time of 10 minutes, while Ethereum has block time of 13 seconds.

Bitcoin's difficulty formula

With Bitcoin, its difficulty is updated every 2016 blocks were mined. It uses this formula to calculate its new difficulty:

old difficulty * (2016 blocks * 10 minutes) / mining time for the previous 2016 blocks
Enter fullscreen mode Exit fullscreen mode

Now, let's code!

First, we must have our block time first, I'll just set it to 30 seconds, which is equal to 30000ms. I'm using millisecond because it works better with Date.now().

    this.blockTime = 30000;
Enter fullscreen mode Exit fullscreen mode

(Note that we are coding in the Blockchain class here).

Just as an example, I'll create my own system: the difficulty will be incremented by 1 if block time is less than the actual time the block's mined, it will be decremented otherwise.

    addBlock(block) {
        block.prevHash = this.getLastBlock().hash;
        block.hash = block.getHash();
        block.mine(this.difficulty);
        this.chain.push(Object.freeze(block));

        this.difficulty += Date.now() - parseInt(this.getLastBlock().timestamp) < this.blockTime ? 1 : -1;
    }
Enter fullscreen mode Exit fullscreen mode

Important note!!!

Because of how we checked difficulty earlier, this should work fine. However, it is better to check difficulty using log16(difficulty) rather than the difficulty itself, and by doing that, you can now use the Bitcoin's difficulty formula.

You can come up with your own formula though. You should consider what is the best for security while still having good performance.

Source code

You can get the full source code at this repo:

GitHub logo nguyenphuminh / JeChain

JeChain decentralized application platform and experimental smart contract blockchain network

Honorable mention

I have learnt a lot about blockchains from Simply Explained. This article might never exist without help from their videos. Please check them out on Youtube, they have really good blockchain tutorial series.

I also grabbed some info on this article too. Check them out!

Off-topic

Should I continue the series? And if yes, what should I write about? Proof-of-stake? Full cryptocurrency? Smart contracts? Please let me know in the comment section.

Contacts

Oldest comments (58)

Collapse
 
aidenybai profile image
Aiden Bai

cool stuff!

Collapse
 
freakcdev297 profile image
FreakCdev

cool!

Collapse
 
jonrandy profile image
Jon Randy 🎖️ • Edited

Thank you sincerely for writing a post titled like this that doesn't just: include a library, set some parameters, and call a function - those kind of posts are garbage.

Dev.to needs more posts like this - real content that is actually interesting. Please keep up the good work 👍

Collapse
 
freakcdev297 profile image
FreakCdev

Thanks a lot man!

Collapse
 
wahidn profile image
WahidN

I totally agree! I hate those posts/tutorials that do nothing but use a package and doesnt explain anything

Collapse
 
alvarezgarcia profile image
Alvarez García

I think that maybe another post showing differences between var, let and const it' s the real deal.

...

Being serious, I wish we have more quality posts like this.

Collapse
 
jonrandy profile image
Jon Randy 🎖️

Like this one?

Collapse
 
walteralvar profile image
WalterAlvar

Wow, I am also student but definitely gonna study this

Collapse
 
bolonhadev profile image
Bolonha Dev

Dope

Collapse
 
smaranh profile image
Smaran Harihar

Please continue the series.

Collapse
 
freakcdev297 profile image
FreakCdev

Sure man!

Collapse
 
bvince77 profile image
bvince77

This is interesting. I've wanted to read up on this to get some basic understanding. Great article

Collapse
 
jesanhe profile image
jesanhe

This article helped me to better understand Blockchain on an easy way. Great work!! Please continue writing this series.

Collapse
 
noxklax profile image
Nox Klax

This is awesome! It helps me to understand a little bit better what's happening under the hood.

Collapse
 
dariozz profile image
Dario Mendez

Marvelous to deep understand blockchain, I would like to suggest the smart contracts version

Collapse
 
andrescass profile image
Andres Cassagnes

Excellent post. Please continue the series, maybe with proof of stake, which I think is the logical following post.
Thank you for the post

Collapse
 
freakcdev297 profile image
FreakCdev

Thanks! I'm planning to write a proof-of-stake system soon!

Collapse
 
tomavelev profile image
Toma • Edited

Good post for understanding the basics. The only thing left is some simple synchronisation with a network and the solution of the Byzantine Generals Problem offered by Satoshi.

Collapse
 
luizc91 profile image
LuizC91 • Edited

Is there a possibility of you teach us how to do it in another language?
Before I forget: thank you for the post. It will help me a lot.

Collapse
 
freakcdev297 profile image
FreakCdev

I picked Javascript because it's pretty widely used and easy. I might write some variations of this in different languages and upload it to the JeChain repository on Github. In the mean time, I think you can try to write your own by following the concepts mentioned in the article :D

Collapse
 
luizc91 profile image
LuizC91

I will do.

Collapse
 
rineezlivares profile image
Rineez Ahmed

Please write about Proof of stake

Collapse
 
freakcdev297 profile image
FreakCdev

Sure! Follow me to get the notification of the next article!

Collapse
 
jaybit33 profile image
Justin Roseman

Smart contracts would be great

Collapse
 
raymclee profile image
Collapse
 
freakcdev297 profile image
FreakCdev

Thanks for commenting this, I have learnt a lot of Simply Explained!