区块链的概念好理解,也不好理解。区块链是很多技术的合集,尤其是密码学对大多数工程师来说很陌生,更不用说更复杂的比特币。其实区块链很简单,最近看了一篇英文文章,介绍得很清楚,我根据自己的理解翻译,并且加上我的注解,希望可以让大家明白什么是区块链。
区块链的基本概念很简单:
区块链是一个基于共识机制的、去中心化的、公开的、不可篡改的分布式数据库。
有几个特点:
●共识机制,很巧妙的设计,保证了数据的一致性
●去中心化,是所有的节点都是对等的,没有中央节点,网络中的节点平起平坐。
●公开的,大家都可以看到。实际上,一种理想的情况,各个节点都有完整的数据,然后共识机制来保证数据一致。
●不可篡改,所有节点的监督,以及可以通过算法检查,密码学相关部分
我认为区块链的几个特点中,共识机制是最创新的。其他的只是技术的合集。去中心化这个特点,只能说看上去很美。比较理想的状况了。这里底层是有原因的,算力和资源的本质就是集中的。所以,挖矿这件事是违背去中心化的。不过已经很好了。这一点,很多比特币的狂热粉丝会和我争论,我们后面找机会展开。
区块结构
第一步了解下区块的结构,因为是了解区块链,所以进行了简化,像重要的norance并没有提,所以,工作量证明也不包含在这篇文章里。一个区块包括:
●index
●timestamp 时间有序
●data
●hash
●previous hash
代码如下:
classBlock { 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算法。
varcalculateHash = (index, previousHash, timestamp, data) => { returnCryptoJS.SHA256(index + previousHash + timestamp + data).toString();}; 产生区块
比特币中区块是通过“挖矿”得到的,不断的计算满足某个条件的hash值,这里通过简单的计算模拟:
sha256(index+hash+data+timestamp)
vargenerateNextBlock = (blockData) => { varpreviousBlock = getLatestBlock(); varnextIndex = previousBlock.index + 1; varnextTimestamp = new Date().getTime() / 1000; varnextHash = calculateHash(nextIndex, previousBlock.hash, nextTimestamp, blockData); return newBlock(nextIndex, previousBlock.hash, nextTimestamp, blockData, nextHash);}; 区块存储
这里,我们采用一个JS的数组来存储区块链,做一个模拟,我们初始化一个“创世区块”
vargetGenesisBlock = () => { returnnewBlock( 0, "0", 1465154705, "my genesis block!!", "816534932c2b7154836da6afc367695e6337db8a921823784c14378abed4f7d7");}; varblockchain = [getGenesisBlock()]; 验证区块的完整性
这个是很重要的一点,实际上就是看数据是否一致,是否被篡改。计算hash进行比对。
varisValidNewBlock = (newBlock, previousBlock) => { if(previousBlock.index + 1!== newBlock.index) { console.log( 'invalid index'); returnfalse; } elseif(previousBlock.hash !== newBlock.previousHash) { console.log( 'invalid previoushash'); returnfalse; } elseif(calculateHashForBlock(newBlock) !== newBlock.hash) { console.log( 'invalid hash: '+ calculateHashForBlock(newBlock) + ' '+ newBlock.hash); returnfalse; } returntrue;}; 区块链合并
在网络中,同时会有多个矿工在挖矿,如果大家几乎同时提交,那么比特币就会出现“分叉”,那么怎么办呢?做法很简单,就是选择最长的链。如下图:
代码如下:
varreplaceChain = (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,则合并区块链
这里没有实现节点发现的机制,可以通过配置固定一些peer进行测试。
节点控制
提供rest接口,对节点进行控制,模拟挖矿:
varinitHttpServer = () => { varapp = express(); app.use(bodyParser.json()); app.get( '/blocks', (req, res) => res.send( JSON.stringify(blockchain))); app.post( '/mineBlock', (req, res) => { varnewBlock = 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接口主要用户提供功能操作。
结论
这篇文章,主要是为了大家理解什么是区块链,或者单纯的区块链,不包含比特币相关特性的。有代码,差不多200行就实现了简单的功能完善的区块链,JavaScrip实现,代码简单很容易理解。相信通过这篇文章,都可以明白什么是区块链。至于挖矿、共识机制机制,我们在后续的文章中介绍。
如果要一起讨论区块链,可以加入“待字闺中读者群”小密圈,一起讨论区块链应用。
上文内容不用于商业目的,如涉及知识产权问题,请权利人联系博为峰小编(021-64471599-8017),我们将立即处理。