179

200行代码搞懂区块链

 6 years ago
source link: http://mp.weixin.qq.com/s/9g-c3_YR4MJ3JWzrQN_b6A
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

200行代码搞懂区块链

Original cheng 待字闺中 2017-10-13 00:27
640?wx_fmt=jpeg&wxfrom=5

区块链的概念好理解,也不好理解。区块链是很多技术的合集,尤其是密码学对大多数工程师来说很陌生,更不用说更复杂的比特币。其实区块链很简单,最近看了一篇英文文章,介绍得很清楚,我根据自己的理解翻译,并且加上我的注解,希望可以让大家明白什么是区块链。

区块链的基本概念很简单:

区块链是一个基于共识机制的、去中心化的、公开的、不可篡改的分布式数据库。

有几个特点:

  • 共识机制,很巧妙的设计,保证了数据的一致性

  • 去中心化,是所有的节点都是对等的,没有中央节点,网络中的节点平起平坐。

  • 公开的,大家都可以看到。实际上,一种理想的情况,各个节点都有完整的数据,然后共识机制来保证数据一致。

  • 不可篡改,所有节点的监督,以及可以通过算法检查,密码学相关部分

我认为区块链的几个特点中,共识机制是最创新的。其他的只是技术的合集。去中心化这个特点,只能说看上去很美。比较理想的状况了。这里底层是有原因的,算力和资源的本质就是集中的。所以,挖矿这件事是违背去中心化的。不过已经很好了。这一点,很多比特币的狂热粉丝会和我争论,我们后面找机会展开。

第一步了解下区块的结构,因为是了解区块链,所以进行了简化,像重要的norance并没有提,所以,工作量证明也不包含在这篇文章里。一个区块包括:

  • index

  • timestamp 时间有序

  • previous hash

Image

代码如下:

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();
    }
}

用来保证数据完整性,保证没有被篡改,我们这里采用和比特币一样的SHA-256算法。

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

比特币中区块是通过“挖矿”得到的,不断的计算满足某个条件的hash值,这里通过简单的计算模拟:

sha256(index+hash+data+timestamp)

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);
};

这里,我们采用一个JS的数组来存储区块链,做一个模拟,我们初始化一个“创世区块”

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

验证区块的完整性

这个是很重要的一点,实际上就是看数据是否一致,是否被篡改。计算hash进行比对。

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;
};

区块链合并

在网络中,同时会有多个矿工在挖矿,如果大家几乎同时提交,那么比特币就会出现“分叉”,那么怎么办呢?做法很简单,就是选择最长的链。如下图:

Image

代码如下:

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

网络节点之间的通信

这部分很重要,比较关键的点在于保证网络中的区块链是同步的。如何保证呢?

  • 当一个节点产生了一个新的区块,要广播给其他节点。

  • 当一个节点和一个另一个节点建立了连接,要查询最新的区块。为了检查区块链是否一致,如果出现情况,按照下一步处理。

  • 当接受到一个区块的index大于当前链的index,有几种情况:

    • 如果当前区块链上最新区块的hash和接受区块的previousHash相同,则加入区块链

    • 如果不相同:

      • 接受的区块数为1,则广播获取完整区块链,然后在合并

      • 接受的区块数大于1,则合并区块链

Image

这里没有实现节点发现的机制,可以通过配置固定一些peer进行测试。

提供rest接口,对节点进行控制,模拟挖矿:

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));
};

网络中节点暴露rest接口和websocket接口,websocket接口主要用户网络节点之间的数据同步,维护数据一致性,rest接口主要用户提供功能操作。

Image

这篇文章,主要是为了大家理解什么是区块链,或者单纯的区块链,不包含比特币相关特性的。有代码,差不多200行就实现了简单的功能完善的区块链,JavaScrip实现,代码简单很容易理解。相信通过这篇文章,都可以明白什么是区块链。至于挖矿、共识机制机制,我们在后续的文章中介绍。

如果要一起讨论区块链,可以加入“待字闺中读者群”小密圈,一起讨论区块链应用。

Image

本文代码:

github:https://github.com/lhartikk/naivechain/blob/master/main.js


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK