Building a Simple JavaScript Blockchain
When I learn about a new technology, I like to dive in deep: reading articles and documentation, watching videos, and experimenting with code. Recently, I got into blockchain technology and after wrapping my head around the initial concept, I was inspired to create my own blockchain (albeit rudimentary).
If you are new to the blockchain, I highly recommend watching this video where the concept is explained in five levels of difficulty. Everyone should take away something new, whether a beginner or expert.
As for our introductory blockchain, we'll be using JavaScript as our programming language, and you should also be familiar working within the browser console. Let's get into it!
Setup
There is one thing about blockchain that we'll be depending on other code for: the Secure Hashing Algorithm (SHA), specifically SHA-256.
In short, SHA-256 is a cryptographic "hashing" function that takes a string of any length and coverts it into a fixed-length 256 bit "hash value". It only works one way and is therefore secure for passwords or anything you don't want someone to guess or know.
SHA is a whole other subject we won't get into here, but you can find the code you need for this project here.
In your project directory, create a three files:
index.html
sha256.js
blockchain.js
Copy the SHA code from the link above into the sha256.js
file. You can now close this file. We're done with it.
In your index.html
file create a basic HTML boilerplate with an empty body, or whatever you'd like to put in there. Inside the <body>
tag (and preferably at the end) insert two <script>
tags.
...
<body>
<script src="sha256.js"></script>
<script src="blockchain.js"></script>
</body>
</html>
These tags insert the code you need for hashing your blockchain as well as the code we're about to write for the actual blockchain.
The Block Object
Opening your blockchain.js
file, we'll start things off by writing a function to create a object representing each block of our blockchain.
function Block() {
}
Inside this function we'll initialize three properties:
previousHash
: The hash value of the previous block on the chain.data
: The data in this block.hash
: The calculated hash of this block. We'll use the code from thesha256.js
file here.
The final code for this function should be as follows:
function Block(previousHash, data) {
this.previousHash = previousHash;
this.data = data;
this.hash = SHA256(JSON.stringify(this));
}
The Blockchain Object
Now we'll get to the actual blockchain object. There are several variables and methods we'll code inside this function.
chain
: An array of block objects (the actual blockchain!)add()
: This will add a block to the blockchain.print()
: This will print a log of the entire blockchain to the console.
function Blockchain() {
// The blockchain
let chain = [];
// Add a block to the chain
this.add = function() {
}
// Print the blockchain to the console
this.print = function() {
}
}
Adding a Block
Inside the add()
method, we'll add a parameter named data
. This is the data inside the block we want added to the blockchain.
this.add = function(data) {
}
We need this method to do three things:
- Find the hash of the previous block on the chain
- Create the new block we want added to the chain (with the previous hash included in it)
- Push that new block onto the chain array
To find the previous hash on the block we'll reference the chain
and access the last block on it at index [chain.length - 1]
and finally reference its hash
property through dot notation.
this.add = function(data) {
let previousHash = chain[chain.length - 1].hash;
}
Using this previousHash
value, we'll create a new block object essentially "chaining" it to the previous block and holding its own data from the data
parameter.
this.add = function(data) {
let previousHash = chain[chain.length - 1].hash;
let block = new Block(previousHash, data);
}
Finally, we'll take that block
object and push it onto the chain
, finishing our add()
method's functionality!
this.add = function(data) {
let previousHash = chain[chain.length - 1].hash;
let block = new Block(previousHash, data);
chain.push(block);
}
The Genesis Block
The funny thing about adding a block, is that you need to have previous blocks on the chain. Because of this, a blockchain usually is created with a first or "genesis" block that all other blocks lead back to. Because our add()
method needs a previousHash
that won't exist initially, we can hardcode the create of our own genesis block when the blockchain object is instantiated.
At the bottom of our Blockchain()
function we'll add the following code:
chain.push(new Block('0', 'Genesis Block'));
This will push our first block object onto the chain
array with a previousHash
of '0'
and the data
being simply 'Genesis Block'
. Now our first normal block we add will reference this genesis block's new hash and "chain" itself to it.
Initial Usage
If we open our index.html
file in a new browser window and open the developer console, we can finally add blocks to our blockchain!
let blockchain = new Blockchain();
blockchain.add('hello world');
But how do we know if it worked? How can we see our hard work chaining these blocks together? We'll need another method for that...
Printing the Blockchain
Inside our print()
method, we only need one line of code, though it is a little complicated. We'll add it first and then I'll explain.
this.print = function() {
console.log(JSON.stringify(chain, null, 2));
}
The console.log()
function call should be straightforward enough. It logs the argument to the console for us to see, but what exactly are we logging?
In essence, we are logging the chain
array (the blockchain we want to see) to the console. We just need to modify how it is handled by the console.log()
function.
JSON
is an object built into JavaScript that helps parse or analyze JavaScript Object Notation (JSON). We are using its stringify()
method to convert our chain
"object" into a "string" that can be logged and easily read at once.
You can read more about this method and its parameters here if you like or just use the adapted code above to nicely log our chain
object as a string for us to enjoy.
Usage
Finally, our simple JavaScript blockchain is complete!
Navigating back to the browser console, we can utilize our code in the following ways:
1) Instantiation
Create an instance of our blockchain object and initialize the Genesis Block to it.
let blockchain = new Blockchain();
2) Adding a Block
Add any data we like to a new block and chain it to our immutable blockchain.
blockchain.add('hello world');
blockchain.add(['hello', 'world']);
blockchain.add({ message: 'hello world'});
3) Printing our Blockchain
Log our blockchain array of block objects to the console.
blockchain.print();
[
{
"previousHash": "0",
"data": "Genesis Block",
"hash": "6068c315b086271eee3bf312a4e2b3596f6e1f8b08f2bde0384b37d765f1d7c1"
},
{
"previousHash": "6068c315b086271eee3bf312a4e2b3596f6e1f8b08f2bde0384b37d765f1d7c1",
"data": "hello world",
"hash": "7c0f4b696749784e1afcaa62f2476ae4c25a0960920cbf0122a41a989803baea"
},
{
"previousHash": "7c0f4b696749784e1afcaa62f2476ae4c25a0960920cbf0122a41a989803baea",
"data": [
"hello",
"world"
],
"hash": "bb724ed2e9c6f7a3cf51459f06b570833b1bdaf30e51aab6e3d33859b1207d14"
},
{
"previousHash": "bb724ed2e9c6f7a3cf51459f06b570833b1bdaf30e51aab6e3d33859b1207d14",
"data": {
"message": "hello world"
},
"hash": "252f30a80d37da4731bed4ad4b0fb900a197c061678c87a7a757d86dce35642b"
}
]
Conclusion
There you have it. I simple (very simple) implementation of blockchain technology. I hope you enjoyed this initial foray into the potential future of the world wide web!
// Block Object
function Block(previousHash, data) {
this.previousHash = previousHash;
this.data = data;
this.hash = SHA256(JSON.stringify(this));
}
// Blockchain Object
function Blockchain() {
// Chain of all blocks
let chain = [];
// Add block to chain
this.add = function(data) {
let previousHash = chain[chain.length - 1].hash;
let block = new Block(previousHash, data);
chain.push(block);
}
// Print chain to console
this.print = function() {
console.log(JSON.stringify(chain, null, 2));
}
// Add Genesis Block
chain.push(new Block('0', 'Genesis Block'));
}