Understanding the concept of blockchain is simple (block chain, trading chain block): It is distributed (ie not placed on the same machine, different network devices on the) database to support the hosting record of the growing list. However, it is also easy to confuse blockchain with the idea that we are trying to help him solve the goal--at that moment in people's minds, the word is pretty strong about trading, contracts or smart cryptocurrency concepts.
Only here blockchain-is not the same coin, and understanding the basic knowledge of the chain is easier than it seems, especially in that it is based on source code. In this article, we propose a simple model for building 200 lines of code in JavaScript. This project, which we call the Naivechain source code, can be found on the GitHub. Parts 1th and 2nd: If you need to brush up on its function, use our cheat sheet, we will use the standard ECMAScript 6.
block structure The first step-determine which elements should contain blocks. For simplicity, we only include the most necessary: previous block indices (exponents), time markers (timestamps), data (data), hashes, and hashes to be recorded to maintain the integrity of the circuit's structure.
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 ();
}
}
Hash Unit
The hash block needs to preserve the integrity of the data. In our example, this applies to algorithmic SHA-256. This type of hash is not related to mining, because in this case we do not use the performance proof to enforce the protection.
var Calculatehash = (index, Previoushash, timestamp, data) => {return
cryptojs.sha256 (index + Previoushash + times Tamp + data). ToString ();
Generating unit to generate blocks, we need to know the hash of the previous block so that we have the remainder of the element defined in the struct. The data 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 to new block (Nextindex, Previousblock.hash, Nexttimestamp, Blockdata, Nexthash);
The storage unit uses the blockchain storage array. The first block is always hard-coded "Genesis Block".
var getgenesisblock = () => {return
new blocks (0, "0", 1465154705, "My Genesis block!!", "816534932C2B7154836DA6AFC 367695e6337db8a921823784c14378abed4f7d7 ");
var blockchain = [Getgenesisblock ()];
confirm the integrity of the block
We must always be able to confirm the integrity of the unit or circuit. Especially when you have new units from other units, you must decide whether to accept 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 (typeof) + ' + Newblock.hash typeof Atehashforblock (Newblock));
Console.log (' Invalid hash: ' + calculatehashforblock (newblock) + ' + Newblock.hash ');
return false;
}
return true;
};
The longest selection chain in the circuit block order must be explicitly specified, but in the case of conflict (for example, two nodes in the same generated block and the same number), we select the circuit, which contains more than the 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 blockchain Invalid ');
}
;
messages to other network nodesAn integral part of the site-exchange data with other nodes. The following rules are used to maintain network synchronization:
When a node produces a new unit, it is reported to the network;
When this machine connects to a new feast, he asks about the last generated block information;
When a node is facing a block, which has an indicator larger than he is, he adds a block to the circuit or requests the complete chain of information.
Auto Search peers do not perform, all links are manually added.
control of the unitThe user should be able to control the node in some way, by resolving the HTTP server. When interacting with nodes, the following functions are available:
Print a list of all cells;
Create a new unit of user-generated content;
Print a list, or add a holiday.
The most direct way of interacting--by curling:
List of all blocks on a node
Curl Http://localhost:3001/blocks
Architecture
It is noteworthy that the site refers to two Web servers: HTTP for user-controlled devices and peer-to-peer connections between nodes that are installed to the WebSocket http.
The following is JS 200 line code
' Use strict ';
var Cryptojs = require ("Crypto-js");
var express = require ("Express");
var bodyparser = require (' Body-parser ');
var WebSocket = require ("WS"); var http_port = Process.env.HTTP_PORT | |
3001; var p2p_port = Process.env.P2P_PORT | |
6001; var initialpeers = Process.env.PEERS?
Process.env.PEERS.split (', '): [];
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 ();
} var sockets = [];
var messagetype = {query_latest:0, query_all:1, response_blockchain:2}; var getgenesisblock = () => {return new blocks (0, "0", 1465154705, "My Genesis block!!", "816534932C2B7154836DA6AFC
367695e6337db8a921823784c14378abed4f7d7 ");
};
var blockchain = [Getgenesisblock ()];
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.remote
Port));
});
App.post ('/addpeer ', (req, res) => {connecttopeers ([req.body.peer]);
Res.send ();
});
App.listen (Http_port, () => console.log (' Listening HTTP on port: ' + Http_port '));
};
var initp2pserver = () => {var server = new Websocket.server ({port:p2p_port});
Server.on (' connection ', WS => initconnection (WS));
Console.log (' Listening websocket peer-to-peer port on: ' + p2p_port);
};
var initconnection = (ws) => {sockets.push (WS);
Initmessagehandler (WS);
Initerrorhandler (WS); Write (WS, QUERYCHAINLENGTHMSG ());
};
var initmessagehandler = (ws) => {ws.on (' message ', (data) => {var message = Json.parse (data);
Console.log (' Received message ' + json.stringify);
Switch (message.type) {case MessageType.QUERY_LATEST:write (WS, Responselatestmsg ());
Break
Case MessageType.QUERY_ALL:write (WS, Responsechainmsg ());
Break
Case MessageType.RESPONSE_BLOCKCHAIN:handleBlockchainResponse (message);
Break
}
});
}; var initerrorhandler = (ws) => {var closeconnection = (ws) => {console.log (' connection failed to peer:
' + Ws.url);
Sockets.splice (Sockets.indexof (WS), 1);
};
Ws.on (' Close ', () => closeconnection (WS));
Ws.on (' Error ', () => closeconnection (WS));
}; 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 to new block (Nextindex, Previousblock.hash, Nexttimestamp, Blockdata, Nexthash);
}; var calculatehashforblock = (block) => {return Calculatehash (Block.index, Block.previoushash, Block.timestamp, Blo
Ck.data);
}; var Calculatehash = (index, Previoushash, timestamp, data) => {return cryptojs.sha256 (index + Previoushash + times
Tamp + data). ToString ();
}; var addblock = (Newblock) => {if (Isvalidnewblock (Newblock, Getlatestblock ())) {Blockchain.push (Newblock)
;
}
}; var isvalidnewblock = (Newblock, previousblock) => {if (Previousblock.index + 1!== newblock.index) {cons
Ole.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 (typeof) + "+ Newblock.hash
Calculatehashforblock (Newblock));
Console.log (' Invalid hash: ' + calculatehashforblock (newblock) + ' + Newblock.hash ');
return false;
return true;
};
var connecttopeers = (newpeers) => {Newpeers.foreach (peer) => {var ws = new WebSocket (peer);
Ws.on (' Open ', () => initconnection (WS));
Ws.on (' Error ', () => {console.log (' Connection failed ')});
});
}; var handleblockchainresponse = (message) => {var receivedblocks = Json.parse (message.data). Sort (B1, B2) => (B1
. Index-b2.index));
var latestblockreceived = receivedblocks[receivedblocks.length-1];
var Latestblockheld = Getlatestblock (); if (Latestblockreceived.index > Latestblockheld.index) {console.log (' Blockchain possibly behind. We got: ' + latestblockheld.index + ' PeerGot: ' + Latestblockreceived.index '; if (Latestblockheld.hash = = Latestblockreceived.previoushash) {console.log ("We can append the received block
To our Chain ");
Blockchain.push (latestblockreceived);
Broadcast (responselatestmsg ());
else if (receivedblocks.length = = 1) {Console.log ("We have to query the chain from our peer");
Broadcast (queryallmsg ());
else {console.log ("Received blockchain is longer than current blockchain");
Replacechain (receivedblocks); } else {Console.log (' received blockchain is not longer than received.
Do nothing ');
}
}; 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 ');
}
}; var isvalidchain = (blockchaintovalidate) => {if (json.stringify (blockchaintovalidate[0))!== JSON.stringify (getGe
Nesisblock ()) {return false;
} var tempblocks = [Blockchaintovalidate[0]]; for (var i = 1; i < blockchaintovalidate.length i++) {if (Isvalidnewblock (blockchaintovalidate[i), tempblocks [I-1])
{Tempblocks.push (blockchaintovalidate[i]);
else {return false;
} return true;
};
var getlatestblock = () => blockchain[blockchain.length-1];
var querychainlengthmsg = () => ({' type ': Messagetype.query_latest});
var queryallmsg = () => ({' type ': Messagetype.query_all});
var responsechainmsg = () => ({' type ': Messagetype.response_blockchain, ' Data ': json.stringify (Blockchain)}); var responselatestmsg = () => ({' type ': Messagetype.response_blockchain, ' Data ': json.stringify ([geTlatestblock ()])};
var write = (WS, message) => ws.send (json.stringify);
var broadcast = (message) => Sockets.foreach (Socket => Write (sockets, message));
Connecttopeers (initialpeers);
Inithttpserver (); Initp2pserver ();