NodeJS blockchain implementation: BrewChain: Chain+WebSockets+HTTP Server
I am going to create BrewChain. A verifiable chain of which member of the team made a brew and when. Protecting the history of events from any swindlers who may attempt to claim they have made more brews than they actually did.
Our application will consist of the following:
Our block and blockchain
A Node which will run on team members machines, listening for new blocks broadcast and also broadcasting new blocks and updating the chain.
An HTTP server and web interface for interacting with brew activities, the log and other data
Blockchain is essentially a linked list in which each item contains a hash of the previous item.
The fundamental element in this chain is the block. Each block contains data, and a hash of the previous block. This hashed pointer maintains the integrity of the data and makes the list immutable.
To start with we need to determine the essential elements of our block.
data - whatever we wish to store in the block
hash - (a hash of the timestamp,index,data and previous hash)
previous hash - the hash of the previous block
(We’ll come to proof of work later on)
Given the last block and the new data, the function will create and return a new block.
We’d then need a genesis block to begin our chain at element 0.
We can then create our blocks, adding them to the chain.
Taking the above and building a chain, we get the following:
(The code in this post is in somewhat rough form while I workout exactly how it is going to work)
This will setup our chain object, creating a genesis block and adding it to the chain.
Our Brewchain contains the ability to create new blocks, add new blocks to our chain and also check the validity of a block.
The test code at the end adds two blocks and then outputs the chain to check that the blocks are successfully being created.
We’ll now begin building our P2P brewNode server..
Brew Node P2P network
Each BrewNode server will have a chain, a web socket server, and an http server for controlling it
We’ll start by creating our node using web sockets..
On init our server sets up a listening socket server, we add a handler for incoming messages and add the incoming connection to an array of socket connections.
We also add some methods for adding a new peer, broadcasting messages to connected peers and removing disconnected peers from our collection of sockets.
The node also contains our BrewChain, a method which will create a block based on a teammembers name and add it to the chain.
Next we’ll add an HTTP server for sending commands to our server , which will also be used by our future UI interface.
(node1 in the above being our BrewNode)
So we now have an HTTP server for invoking actions on our node via the browser.
The next stage of development is to begin communication between our nodes, distributing the chain
Each node needs to do the following:
Generate new chain blocks
When it connects to a new node, request the latest block
If we have no blocks, request the entire chain
On receiving a new block with an index greater than ours from another node, determine if it is valid - if it is , and it is the next in the chain, add it. If it isn’t the next in the chain , we must have missed a few so lets request a full chain
To do this, lets begin by having it so that when a node generates a block it will dispatch it to all connected nodes.
To test this is happening, lets load up two brew nodes on different ports.
I’ll then run the following url to connect node 2 to node 1
Running ‘http://localhost:3004/spawnBrew/barry’ should create a block and dispatch it to the connected node
That now works, with node 1 recieving the barry brew block
A quick alteration we must make here is to fix our genesis block to be the same across our nodes.
Now we are going to process the recieved block(s) and create a consensus between our nodes.
We’ll add some constants for our events and then setup the block processor
Reloading up our two test nodes on different ports and running the following on node 1
Node 2 successfully recieves the new blocks and adds them to it’s chain
Next we will add in our request chain functionality
Our server now recieves the requested chain, sorted. Before replacing our own chain for this one, we to verify it is a valid chain…
Before we do that though, I am going to implement a basic Proof of Work (for the sake of it)
Proof of work
In replacing our chain with the have the issue of consensus and knowing which chain is the ‘truth’. With blockchain, one way of helping do this is to add in the concept of ‘proof of work’. This requires a computational task to be carried out in order to generate (mine) a new block, the proof of this computation (called a nonce) is then stored in the block.
The purpose of this is to add a time(energy) consuming element/puzzle into the process of creation, which is easy for others to verify as correct.
Without this, it would be possible to spam the chain by creating a lot of blocks quickly and attempt to replace it with a chain that is longer.
The inputs to this computational task are the based on the data of the previous block/block to be formed, and an integer which is our ‘guess’.
A common way of doing this is to iterate, incrementing an integer x. In each iteration we hash our block together with x. The computation is successful when the trailing characters of the resulting hash string have 3 zeroes (or more to increase the difficulty).
Ok, to implement this we’ll begin by adding the nonce property to our genesis block
We’ll also alter our create hash function to take into account the nonce
Next we will alter our create block method to include a default nonce of 0. We’ll then add a new method proofOfWork, this is going to create a hash of the block. It will then examine to see if the last 3 characters of the blocks hash have 3 trailing zeroes, if not it will increment the nonce within the block and try again until it is successful before finally returning the block.
We can always know that the work has been done by examining that the contents of the block are valid and that the hash of the contents ends with 3 trailing zeroes.
Now we will continue on with our p2p network, checking to see if our recieved chain is valid.
To do this we will add a method to our chain which takes a new chain array. If the first element is our genesis we then iterate over each block in the chain, checking to see that it’s contents are valid and that the hash indicates proof of work took place.
We’ll also add a method for replacing the chain.
We’ll now invoke these methods in the brew node. The consensus rule in our brew node is the longest valid chain is the ‘truth’. We’ll therefore do a check to see if new chain is longer than our own and is valid, and if it is, replace our chain with it
The final step is to have a brew node request the chain on startup and on connecting to a new brew node, request the nodes latest block.
Our P2P network now has basic functionality, brew nodes will connect, request the latest block and replace the chain if neccesary.
The final step is to create a UI from which the brews can be made passing in the team members name and also view the chain on that node..
To be continued..
(Source available on my github - link on the right)