JavaScript only needs 200 lines of code to develop blockchain

Keywords: Blockchain JSON Javascript network

Implement a simple blockchain with JavaScript development. Through this development process, you will understand what blockchain technology is: blockchain is a distributed database, and the storage structure is a growing linked list, which contains many orderly records.

However, in general, when we talk about blockchain, we also talk about using blockchain to solve problems, which are easy to confuse. This is the case with blockchain based projects like popular bitcoin and Ethereum. The term "blockchain" is often associated with concepts such as transactions, smart contracts, cryptocurrencies.

This makes understanding blockchain unnecessary and complicated, especially when you want to understand the source code. Next, I will help you understand the super simple blockchain implemented by 200 lines of JS. I will name this code NaiveChain. You can be there. Github
See more technical details.

Block structure

The first logical step is to determine the block structure. To keep things as simple as possible, we only choose the most necessary parts: index, timestamp, data, hash and previous hash.

The hash value of the previous block must be found in this block to ensure the integrity of the whole chain.

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

Block hash

In order to save the complete data, the chunk must be hashed. SHA-256 encrypts the contents of the block. Recording this value should have nothing to do with "mining", because there is no need to solve the problem of workload proof here.

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

Block generation

To generate a block, you must know the hash value of the previous block, and then create the rest of the required content (= index, hash, data and timestamp). The data part of the block 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);
    return new Block(nextIndex, previousBlock.hash, nextTimestamp, blockData, nextHash);
};

Block storage

In memory Javascript arrays are used to store blockchains. The first block of a blockchain is often referred to as the "origin block" and is hard coded.

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

Verify block integrity

At any time, it must be able to confirm whether a block or a block of the whole chain is complete. This is particularly important when we receive new blocks from other nodes and need to decide to accept or reject them.

var isValidNewBlock = (newBlock, previousBlock) => {
    if (previousBlock.index + 1 !== newBlock.index) {
        console.log('invalid 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;
};

Select the longest chain

There should be only a clear set of blocks in the chain at any time. In case of conflict (for example, when both nodes generate block 72), the chain with the largest number of blocks will be selected.

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 blockchain invalid');
    }
};

Communication with other nodes

The essence of nodes is to share and synchronize blockchain with other nodes. The following rules can ensure network synchronization.

  • When a node generates a new block, it spreads the block across the network.
  • When a node connects to a new peer, it queries the latest block.
  • When a node encounters a block whose index is greater than that of all current blocks, it will add the block to its current chain,
    Or query this block in the whole blockchain.

I didn't use the tool to automatically discover peer. The location (URL) of peers must be added manually.

Node control

To some extent, the user must be able to control the node. This can be achieved by building an 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));
};

Users can interact with nodes in the following ways:

  • List all blocks
  • Create a new block with user supplied content
  • List or add peers

The following Curl example is the most direct way to control nodes:

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

system architecture

It should be noted that the node actually represents two web servers: one (HTTP server) is to let users control the node, and the other (Websocket HTTP server).

summary

NaiveChain was created to demonstrate and learn, because it has no "mining" algorithm (PoS or PoW),
It can't be used in public networks, but it implements the basic characteristics of blockchain operation.

In addition, Amway has two courses: 1 Introduction to DApp development of Ethereum 2.DApp practice of Ethereum blockchain E-commerce

Posted by kylebragger on Mon, 03 Feb 2020 05:14:03 -0800