@TOC

什么是区块链

一个维护着一个持续增长的有序数据记录列表的这么一个分布式数据库

下面我将简单用nodejs实现一个简单的区块链,它具有区块链的基本特性,但没有涉及PoS of PoW。

块结构

在这里插入图片描述 一个块Block一般有:

  • index 块号
  • previousHash 上一个区块的hash值
  • timestamp 时间戳
  • data 存放的数据
  • hash 区块的hash值
class Block {
    constructor(index, previousHash, timestamp, data, hash) {
        this.index = index;
        this.previousHash = previousHash;
        this.timestamp = timestamp;
        this.data = data;
        this.hash = hash.toString();
    }
    toString(){
        return "\n{\nindex:"+this.index+",\npreviousHash:'"+this.previousHash+"',\ntimestamp:"+this.timestamp+",\ndata:'"+this.data+"',\nhash:'"+this.hash+"'\n}\n"
    }
}

我们每生成一个区块,我们都会给这个区块按照特定的hash算法,来得到一个hash值,一般来说,只要这个区块的index,previoushash,timestamp,data有改动,那么它所算出的hash值也会改变,所以当你想要篡改某个区块的数据时,你需要将后面所有的区块的previoushash都进行篡改。

创世区块

第一个区块是没有前置hash的,是特殊的一个区块,我们用代码将这个区块写死

const genesisBlock = new Block.Block(
    0, null, 1619079309.946, "genesis block", '80dea37cccca5fb56b9b78dbe2733fb19e8ee2aa7bb03d4ac1e361fe3fad7b51'
);

hash

本文采用sha256来求得hash值

exports.caHash=function (index, previousHash, timestamp, data){
   	return sha256(index + previousHash + timestamp + data).toString();
}

验证块的有效性

下面是验证单个块是否有效,可以根据下面遍历整个链是否有效。

vaildBlock(block,lastBlock) {
        if (!Block.isValidBlockStructure(block))
            return false;
        if (
            (block.index==lastBlock.index+1)
            &&(block.previousHash==lastBlock.previousHash)
            &&Block.caHash(block.index,block.previousHash,block.timestamp,block.data)
        )
            return true;
        return false;
    }

记录数据

creatBlock(data){
        var lastBlock=this.getLastBlock();
        var newIndex=lastBlock.index+1;
        var newTime=new Date().getTime()/1000;
        var newPreHash=lastBlock.hash;
        var newhash=Block.caHash(newIndex,newPreHash,newTime,data.toString());
        return this.blocks[this.blocks.length]= new Block.Block(
            newIndex, newPreHash, newTime, data, newhash
        );

    }

从其他节点接收一个块

addBlock(block){
        if (validBlock(block,this.getLastBlock())){
            blocks.push(block);
            return true;
        }
        return false;
    }

编写测试代码

var Chain=require("./Chain");
var BlockChain=new Chain.BlockChain();
var http=require('http');
var fs=require('fs');
var querystring=require('querystring');

var server=http.createServer(function (req,res) {
    var url=req.url;
    if (url=="/get"){
        res.writeHead(200,{'content-type':'text/plain'+'charset=UTF8'});
        var str=BlockChain.blocks;
        res.end(str.toString());
    }else if (url=="/creat"){
        var data=[];
        req.on('data',function (chunk) {
            data.push(chunk);
        })
        req.on('end',function (chunk){
            var dataObj=querystring.parse(data.toString())
            BlockChain.creatBlock(dataObj["data"]);
            var lastblock=BlockChain.getLastBlock();
            res.setHeader('content-type','text/plain;charset=UTF8');
            res.write(lastblock.toString());
            res.end("生成区块"+lastblock.index+"号成功!");
        })

    }else {
        res.setHeader('content-type','text/html;charset=UTF8');
        fs.readFile('./client.html',function (err,data) {
            res.write(data);
            res.end();
        })
    }

});
server.listen(2345);

测试结果

在这里插入图片描述 输入一些数据,然后点击生成区块: 在这里插入图片描述 点击获取区块链: 在这里插入图片描述

完整代码

你可以从仓库里获取完整代码:

github: https://github.com/Lixingwei0623/ablockchain. gitee: https://gitee.com/li-xingwei/simple-block-chain.