Introduction

A blockchain is a decentralised, distributed and public ledger that can be used to record transactions across many computers in a verifiable and permanent way. A blockchain database is managed autonomously using a peer-to-peer network and a distributed timestamping server. They are authenticated by mass collaboration powered by collective self-interests. The use of a blockchain removes the characteristic of infinite reproducability from a digital asset. It confirms that each unit of value was transferred only once, solving the long-standing problem of double-spending. Blockchain has been described as a value-exchange protocol, it can provide a record that compels offer and acceptance.

Uses for blockchain include:

  • Cryptocurrencies
  • Smart contracts
  • Financial services
  • Blockchain with video games
  • Supply chain

This documentation page will outline a super-simple blockchain implemented in 200 lines of Javascript called NaiveChain

Block Structure

Each block contains an index, timestamp, data, hash and previous hash. The hash of the previous block must be found in the block to preserve the chain integrity.

Block Hash

The block needs to be hashed to keep the integrity of the data. A SHA-256 is taken over the content of the block. It should be noted that this hash has nothing to do with "mining", since there is no Proof Of Work problem to solve.

var calculateHash = (index, previousHash, timestamp, data) => { return CryptoJS.SHA256(index + previousHash + timestamp + data).toString();};
Generating a Block

To generate a block we must know the hash of the previous block and create the rest of the reequired content (= index, hash, data and timestamp). Block data is something that is provided by the end-user.

var generateNextBlock = (blockData) => { var previousBlock = getLatestBlock(); var nextIndex = previousBlock.index + 1; var nextTimestamp = new Date().getTime() / 1000; var nextHash = calculateHash(nextIndex, previousBlock.hash, nextTimestamp, blockData, nextHash); };
Storing the Blocks

An in-memory Javascript array is used to store the blockchain. The first block of the blockchain is always a so-called "genesis-block", which is hard coded.

var getGenesisBlock = () => { return new Block(0, '0', 1465154705, "my genesis block!!", 816534932c2b7154836da6afc367695e6337db8a921823784c14378abed4f7d7"); }; var blockchain = [getGenesisBlock()];
Validating the Integrity of Blocks

At any given time we must be able to validate if a block or chain of blocks are valid in terms of integrity. This is true especially when we recieve new blocks from other nodes and must decide whether to acceppt them or not.

var isValidNewBlock = (newBlock, previousBlock) => { if (previousBlock.index + 1 !== newBlock.index); return false; } else if (previousBlock.hash !== newBlock.previousHash console.log('invalid previoushash'); return false; } else if (calculateHashForBlock(newBlock) !== newBlock.hash) { console.log('invalid hash: ' + calculateHashForBlock(newBlock) + '' + newBlock.hash); return false; } return true; };
Choosing the Longest Chain

There should always be only one explicit set of blocks in the chain at any given time. In case of conflicts (e.g. two nodes both generate block number 72) we choose the chain that has the longest number of blocks.

var replaceChain = (newBlocks) => { if (isValidChain(newBlocks) && newBlocks.length > blockchain.length) { console.log('Received blockchain is valid. Replacing current blockchain with received blockchain'); blockchain = newBlocks; broadcast(responseLatestMsg()); } else { console.log('Received blockchian invalid'); } };
Communicating with other Nodes

An essential part of a node is to share and sync the blockchain with other nodes. The following rules are used to keep the network in sync:

  • When a node generates a new block, it broadcasts it to the network;
  • When a node connects to a new peer it querys fo the latest block;
  • When a node encounters a block that has an index larger than the current known block, it either adds the block to its current chain or querys for the full blockchain.

No automatic peer discovery is used. The location (=URLs) of peers must be manually added.

Controlling the Node

The user must be able to control the node in some way. This is done by setting up a HTTP server.

var initHttpServer = () => { var app = express(); app.use(bodyParser.json()); app.get('/blocks', (req, res) => res.send(JSON.stringify(blockchain))); app.post('/mineBlock' (req, res) => { var newBlock = generateNextBlock(req.body.data); addBlock(newBlock); broadcast(responseLatestMsg()) console.log('block added: ' + JSON.stringify(newBlock)); res.send(); }); app.get('/peers', (req, res) => { res.send (sockets.map(s => s._socket.remoteAddress + ':' + s._socket.remotePort)); }); app.post('/addPeer', (req, res) => { connectToPeers([req.body.peer]); res.send(); }); app.listen(http_port, () => console.log('Listening http on port: ' + http_port)); };

As seen, the user is able to interact with the node in the following ways:

  • List all blocks;
  • Create a new block with a content given by the user;
  • List or add peers.

The most straight-forward way to control the node is e.g. with Curl:

#get all blocks from the node curl http://localhost:3001/blocks
Architecture

It should be noted that the node actually exposes two web servers: One for the user to control the node (HTTP server) and one for the peer-to-peer communication between the nodes (Websocket HTTP server).

Reference

All the documentation on this page is taken from Medium.