区块链入门学习(2)--pow
什么是pow
上一篇的思考
经过上一篇简单的介绍后,我们对于区块链有了简单的成链及基本校验。但,细心的小伙伴们发现,我们依然可以篡改数据,(我们只要把异常数据节点后面的数据块hash都修改好,就可已成功篡改)所以,我们这一次来讲下pow,更加有效的抵制攻击。
我们在上一篇可以发现,创建区块毫不费力,不仅在创建新区块的同时,也有大量的消息充斥。易造成区块链过载。另外,区块链是依据谁的链长,判断谁是合法且有效的,所以,这样数据将会出现混乱。
好的,说了一通,我们这期的主角pow终于出场了。
为了加大算法难度和成本,以减少垃圾和负载,引入了对应的共识机制,只有开头连续出现对应次数0的hash值才为有效hash,例如:
0000000asdsada1231231 //有效hash
asdasd0000asdqwhwqdk //无效hash
由于hash是我们区块中的信息产生的,要改变hash的且同时不改变信息,我们额外引入一个参数,随机数nonce,该值会不断改变以求改变hash直到出现适合规则的hash。那么我们的区块类里需要引入一个参数nonce。
class EasyBlock {
constructor(index, timestamp, data,prevHash = '') {
this.index = index;
this.prevHash = prevHash;
this.timestamp = timestamp;
this.data = data;
this.hash = this.calHash();
this.nonce = 0;
}
calHash() {
return crypto
.createHash('sha256')
.update(this.index +this.nonce + this.timestamp + this.data + this.prevHash)
.digest('hex')
}
}
那么,问题又来了,需要连续多少个“0”呢,需要一个维度的变量。我们就加一个在EasyChain这个类里加上difficulty这个维度,来控制0 的个数来实现控制新区块产生的速度。
挖矿!
上述我们的不断去试着计算符合规则的hash值的过程,就是挖矿!
首先,我们需要在EasyBlock这个类里加一个挖矿的方法。
class EasyBlock {
constructor(index, timestamp, data, prevHash = '') {
this.index = index;
this.prevHash = prevHash;
this.timestamp = timestamp;
this.data = data;
this.hash = this.calHash();
this.nonce = 0;
}
calHash() {
return crypto
.createHash('sha256')
.update(this.index + this.timestamp + this.data + this.prevHash + this.nonce)
.digest('hex')
}
//difficulty为挖矿难度,hash前面连续0的个数
mine(difficulty) {
while (this.hash.slice(0, difficulty) !== '0'.repeat(difficulty)) {
this.nonce++;
this.hash = this.calHash()
}
console.log('挖矿成功!共挖矿次数为:' + this.nonce + '---hash值为:' + this.hash)
}
}
对应的EasyChain里,addBlock这个方法就需要修改一下,把挖矿mine带上,
addBlock(newblock) {
newblock.prevHash = this.getLastBlock().hash;
newblock.mine(this.difficulty)
if (this.isValid()) {
this.blockchain.push(newblock)
} else {
console.log('区块链出现异常')
}
}
最后我们输出一下,看看效果。
let easyChain = new EasyChain();
// console.log(easyChain.calHash(firstBlock))
// console.log('prevhash', easyChain.getLastBlock())
easyChain.addBlock(new EasyBlock(1, new Date().getTime(), 'firstMineBlock'))
easyChain.addBlock(new EasyBlock(2, new Date().getTime(), 'secondMineBlock'))
控制台输出:
挖矿成功!共挖矿次数为:38872---hash值为:00001e38c87007836ffaf3fd70c28217eb569bf7b7a90284f4818937200e7adf
挖矿成功!共挖矿次数为:6123---hash值为:000052965a670653d4610004beb5be82e6733d7825f3caaafb99bd4d5ec722e0
今天就先到这儿咯,简单的pow挖矿原理及代码实现,下次会给大家分享下区块链间的p2p通信!