What the Heck is Blockchain, and Lets Blow Up the Internet (Part 2)

Shmuel Lotman
6 min readJan 30, 2018

--

We’ve written about what Blockchain is. Now, let’s implement it.

Disclaimer: This is by no means a complete implementation of a Blockchain. This is meant as an example, to help understand the basic concepts. For a really excellent, in depth implementation, please check out: https://lhartikk.github.io/

Ok. So last time we explored what a Blockchain was in a lot of words, and a lot of concepts. Let’s see if we can make things a bit clearer with a basic implementation.

Oh, and it’s also 4 in the morning because screw sleep it’s blockchain.

Step 1: Create a block.

class Block {
constructor(index, hash, previousHash, timestamp, data, nonce) {
this.index = index;
this.hash = hash;
this.previousHash = previousHash;
this.timestamp = timestamp;
this.data = data;
this.nonce = nonce;
}
}

Each block in the chain must have its own index. We figured as much. But it also must keep track of the previous block’s hash. That’s how we ensure that a change to one block will invalidate all subsequent blocks. If one hash changes, the previousHash chain of all subsequent blocks will be ruined. We also throw in the hash of this block itself, the data that will go into the block, and the “number only used once.” This concept will become a lot clearer once we actually put that part into action. Bear with me.

Get it, “bear” with me? …IM SORRY ITS 4AM OK?!

Step 2:

Implement the chain.

Quick heads up: there are a bunch of ways to do this. I’m just using one method, based on the excellent tutorial I mentioned above. There are a bunch more ways to do it, so feel free to check out some awesome other tutorials that helped me put this together as well.

Let’s go with a BlockChain class:

class BlockChain {
constructor(difficulty) {
this.chain = [this.createGenesis()];
this.difficulty = difficulty;
}
}

First part of this: define the class and pass the constructor a difficulty. We’ll also get to this in a bit. Hang tight. The other part of the constructor is the core of our implementation: the actual chain. Inside of it is a function that we will implement next, which will create the first block in that chain. We’ll also get to that (I’m not avoiding all this stuff, I promise).

createGenesis() {
return new Block(0, this.calculateHash(0, '', new
Date().getTime()/1000, '', 0), new Date().getTime() / 1000,
'GENESIS BLOCK')
}
getLatestBlock() {
return this.chain[this.chain.length-1]
}

Here is the method that goes right inside our chain array within the constructor. We simply instantiate a new Block that will serve as the commonly known “Genesis Block.” It’s the first one of our chain.

Next, we have a method that simply returns the last block added to the chain.

Moving right along:

 isValidBlockStructure(block) {
return typeof block.index === 'number'
&& typeof block.hash === 'string'
&& typeof block.previousHash === 'string'
&& typeof block.timestamp === 'number'
&& typeof block.data === 'string';
}
isValidNewBlock(newBlock, previousBlock) {
if(!this.isValidBlockStructure(newBlock) ) {
return false;
}
if (previousBlock.index + 1 !== newBlock.index) {
console.log('wrong index');
return false;
} else if (previousBlock.hash !== newBlock.previousHash) {
console.log('invalid previoushash');
return false;
} else if (this.calculateHashForBlock(newBlock) !==
newBlock.hash) {
console.log('incorrect hash value')
return false;
}
return true;
}

Next step: We validate our new block.

We check to ensure that the types of every value inside of the block are correct ( we need to check this to make sure the block doesn’t ruin the chain with some uncaught type issue).

Then, we compare each block to the previous block, starting just after the genesis block and looping through the chain to ensure that all of the hashes mach up. We also throw in a critical check to ensure that no hash has changed within any block itself. This prevents someone from changing data and changing the hash, thinking that they could simply adjust both and leave it that way.

On that note, let’s make sure that the chain is valid:

isValidChain() {
for(let i = 1; i<this.chain.length; i++) {
let cur = this.chain[i],
prev = this.chain[i-1];
if(!this.isValidNewBlock(cur, prev)) {
return false
}
}
return true;
}

Here, we implement the solution to the aforementioned concern: for each block that is not the genesis block, we want to ensure that the chain we are looking at has the correct block data based on the current block and the block before it. The “isValidNewBlock” above runs through the checks we need on each of those pairings. If the isValidChain returns true, we know that nothing has been tampered with.

Ok. Drum roll please.

Umm…. that will do, I guess?

It’s time for the main event: adding another block to the chain. Remember, this part involves multiple steps (some of which we will not be implementing here, for simplicity’s sake).

First, we need to write a function that will generate the basic material that will go into this block, since we are not actually going to implement the entire transaction gathering, mining and adding process completely.

generateNextBlock(blockData) {
let prevBlock = this.getLatestBlock(),
nextIdx = prevBlock.index + 1,
nextTime = new Date().getTime() / 1000,
nonce = 0,
nextHash = this.calculateHash(nextIdx, prevBlock.hash,
nextTime, blockData, nonce ),
newBlock = new Block(nextIdx, nextHash, prevBlock.hash,
nextTime, blockData, nonce);
this.addNewBlock(newBlock);
return newBlock;
}

This function takes blockData, which could be your transaction or text, and runs through a few steps: it gets the previous block, the new index, the timestamp of the new block, the all-important nonce, the new hash of this block, and the instantiated block with all of this info. We then pass this new block into the addNewBlock function. Almost there.

Those calculateHash functions that you’ve seen? Let’s address those:

calculateHash(index, previousHash, timestamp, data, nonce) {
return CryptoJS.SHA256(index + previousHash + timestamp + data +
nonce).toString()
}
calculateHashForBlock(block) {
return this.calculateHash(block.index, block.previousHash,
block.timestamp, block.data, block.nonce)
}

One calculates a hash, the second does it for a particular block. There is a reason for this, which we will see in a second.

Next, we have to write the addBlock function to begin the adding process:

addNewBlock(newBlock) {
if(this.isValidNewBlock(newBlock, this.getLatestBlock())) {
this.mineBlock(newBlock)
this.chain.push(newBlock);
}
}

Ok. I know. More nested functions. But don’t worry! We are going step by step. Remember, we called generateNewBlock, which made the block from the data we passed in plus all that other magic. Then, we called this function with that new block passed in. Here, we check validity against the latest block plus our new one, and then call mineBlock. That’s the last step before we add the block to the chain, and the big one that we need to talk about.

Let’s see the function first:

mineBlock(blockToMine) {
while(blockToMine.hash.substring(0, this.difficulty) !==
Array(this.difficulty +1).join('0')) {
blockToMine.nonce++
blockToMine.hash = this.calculateHash(blockToMine.index, blockToMine.previousHash, blockToMine.timestamp, blockToMine.data, blockToMine.nonce)

}
console.log('block mined', blockToMine.hash);
}

Here’s our mining function. This function loops through our block’s hash. While the hash does not start with the requisite amount of zeroes, we continue calculating the hash of our block until we arrive at the desired result. Once we do, we can then finally push this block into our chain. But wait! I promised this was a big deal. Why?

Well, two reasons: First, because this shows how important mining is. Based on the mining difficulty, which the protocol determines, the amount of time it takes to find that proper number with the zeroes changes. This creates our “proof of work,” and it also shows how this process can be used to create a system in which adding new blocks can be regulated relatively efficiently with a simple and intuitive change to a single value. Second, this demonstrates the critical importance of a nonce. Think about what would happen without it: This loop would run until we reach the hash with the correct amount of starting zeroes, right? But if all the information in the block must remain the same, what changes? How does the loop ever get closer to finishing (hint: it won’t). Well, unless there’s a nonce! That’s the whole reason it’s there. With the nonce, we can finally have something to show that we worked through some serious number crunching to get to the correct value, and we avoid the whole “infinite loop” thing! How convenient!

So. This was a simple, naive implementation of a Blockchain. There are certainly more features, both not covered in implementation here and not discussed. But this is big stuff. Like really, really big stuff. Read more, discover, and join me on this amazing journey into blockchain.

In part 3, we will discuss a particular use of blockchain tech that I think is going to be the next big revolution.

‘Night.

--

--