共识是一个区块链系统稳定运行的基础,只有所有节点对区块链达成了共识,这个区块链才是一个健康的系统,这篇文章主要讲了如何添加peer节点以及当节点区块数据不一致时如何解决冲突,达成一致访问。
一、Blockchain类扩展
想要解决和其它节点的区块冲突问题,首先需要能够获取其它节点的数据,我们再Blockchain类里添加一个nodes属性
this.nodes = new Set();
这里使用集合,即使重复添加也不受影响。
再添加一个节点注册的方法(需要使用urlparse模块)
在最前面加上:
1
| const url = require("url");s
|
方法代码:
1 2 3 4 5 6 7
| registerNode(address){
const parsedURL = URLparse(address);
this.nodes.add(`${parsedURL.hostname}:${parsedURL.port}`);
}
|
添加一个冲突解决的方法,这个方法背后逻辑为:本节点会轮询this.nodes里节点的区块信息,如果有区块长度大于本节点的长度并且区块都有效的话,那就是用对方的区块信息替换本节点的区块。默认来说,最长的区块链包含了最多的工作量,大家都只承认最长的区块链就好了。这也是比特币中使用的机制。这里也需要使用到axios,以及async await异步操作;
所以需要在前面加上:
const axios = require('axios');
方法代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| async resolveConflicts() { const neighbours = this.nodes; let maxLength = this.chain.length; for (let node of neighbours) { const response = await axios.get(`http://${node}/chain`)
if (response.status === 200) { const chain = response.data.chain; const length = response.data.length; console.log('chain', chain); if ( length > maxLength && this.isChainValid(chain) ) { maxLength = length; this.chain = chain; return true } } return false } }
|
在Blok类里面也添加代码
1 2 3 4 5 6 7 8
| hasValidTransactions(){ for(const tx of this.transactions){ if(!tx.isChainValid()){ return false; } } return true; }
|
BlockChain里面的isChainValid也要进行修改,添加代码:
1 2 3
| if(!currentBlock.hasValidTransactions()){ return false; }
|
二、添加路由
1、添加节点注册路由
通过POST请求添加其他节点
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| app.post('/nodes/register', jsonParser, (req,res) => { const nodes = req.body.nodes; if(nodes === null){ res.status(400).send('错误:请提供有效的节点列表!') } for(let node of nodes){ console.log('node', node) xianyuCoin.registerNode(node); } const response = { message: '新的节点已添加', totalNodes: Array.from(xianyuCoin.nodes) } res.send(response) })
|
2、添加冲突解决路由
1 2 3 4 5 6 7 8 9 10 11 12 13
| app.get('/nodes/resolve', async (req, res) => { const replaced = await xianyuCoin.resolveConflicts(); console.log('replaced', replaced); let response = { 'message': 'Our chain is authoritative', 'new_chain': xianyuCoin.chain } if (replaced) { response.message = 'Our chain was replaced'; } res.send(response); })
|
三、测试
我们在3001端口开始一个服务,并且用127.0.0.1:3001/mine来挖几个区块
我们再在3000端口上开始一个服务,访问120.0.0.1:3000/chain
在3000端口的服务上注册节点信息
接着调用解决冲突的API,可以看到3000的区块链已被3001端口的所替代,本节点已经和其他节点的最长区块链达成共识:
源码地址
这样下来,四篇学习笔记就写(chao)完了,虽然文章设计的内容都时最基础的知识,但也让我对区块链,已经区块链中一些基础的知识有了初步的了解,又学到了新的东西还是非常高兴的!!!