D~DIDI~DIDIDI!!!!

0%

区块链学习四-共识

​ 共识是一个区块链系统稳定运行的基础,只有所有节点对区块链达成了共识,这个区块链才是一个健康的系统,这篇文章主要讲了如何添加peer节点以及当节点区块数据不一致时如何解决冲突,达成一致访问。

一、Blockchain类扩展

想要解决和其它节点的区块冲突问题,首先需要能够获取其它节点的数据,我们再Blockchain类里添加一个nodes属性

this.nodes = new Set();

1

这里使用集合,即使重复添加也不受影响。

再添加一个节点注册的方法(需要使用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}`);

}

2

添加一个冲突解决的方法,这个方法背后逻辑为:本节点会轮询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;
}

3

BlockChain里面的isChainValid也要进行修改,添加代码:

1
2
3
if(!currentBlock.hasValidTransactions()){
return false;
}

4

二、添加路由

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来挖几个区块

5

我们再在3000端口上开始一个服务,访问120.0.0.1:3000/chain

6

在3000端口的服务上注册节点信息

7

接着调用解决冲突的API,可以看到3000的区块链已被3001端口的所替代,本节点已经和其他节点的最长区块链达成共识:

8

源码地址

这样下来,四篇学习笔记就写(chao)完了,虽然文章设计的内容都时最基础的知识,但也让我对区块链,已经区块链中一些基础的知识有了初步的了解,又学到了新的东西还是非常高兴的!!!

2019062609