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;
}
}
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");
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));
}
}
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 = [];
}
}
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())];
}
}
Just for convenience, I'll create a function to get the latest block:
getLastBlock() {
return this.chain[this.chain.length - 1];
}
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));
}
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;
}
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();
}
}
}
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;
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));
}
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 };
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);
It should look like this:
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
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;
(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;
}
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:
nguyenphuminh / JeChain
JeChain decentralized application platform and 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.