区块链由一个一个区块组成,通过 chain 来将一个个 block 区块链接起来
人们可以把区块链看成人人都可以信任的分布式账簿
区块 block
一个区块大体上面可以被分为三个部分:
一旦数据被更改,那么哈希值就会发生变化,这样人们就能通过哈希值来发现数据的更改。
区块链的第一个区块没有前哈希值,可以被叫做祖先区块(Genesis Block)。
是的,区块链这样说就和链表很像了
区块链为了放置区块被篡改,引入了一个 Proof of Work(POW)工作量证明机制
区块链还引入了 Peer to Peer(P2P)的网络,形成了分布式存储
一旦有一个区块需要被加入,需要 P2P 网络中所有人达成共识,这个区块才能被加入。
区块链防篡改并不是让数据不能被篡改,而是让做这件事(窜改数据)的成本变的极高。
哈希(散列)函数 Hash Function
F(x) = y (y 为定长)
已知 x,求 y ==》 容易
已知 y,求 x ==》 困难
例如:x^18 + x^5 + x^0.5 + x - 5 = y
我们可以尝试猜数字
猜 = 穷举/试值 = WORK
穷举的越快(算力越高),理论上就能越快得到结果的
复制代码
crypto-js
crypto 模块的目的是为了提供通用的加密和哈希算法。用纯 JavaScript 代码实现这些功能不是不可能,但速度会非常慢。Nodejs 用 C/C++实现这些算法后,通过 cypto 这个模块暴露为 JavaScript 接口,这样用起来方便,运行速度也快。
crypto-js 的安装下载和使用
const sha256 = require("crypto-js/sha256");
console.log(sha256('hello').toString());console.log(sha256('world').toString());
复制代码
测试结果: 对于不同的输入,哪怕只是一个很微小的改动,输出都是不一样的
得到的结果就是哈希值
对于同一个输入,输出结果是一样的。
function proofOfWork() { let data = "hello world"; let x = 1; while (true) { if(sha256(data + x).toString()[0]!== "0") { x = x + 1; } else { console.log(sha256(data + x).toString()); console.log(x); break; } } }proofOfWork();
复制代码
结果:
function proofOfWork() { let data = "hello world"; let x = 1; while (true) { if ( sha256(data + x).toString() // 可以通过调整字符串长度来控制难度,自己可以试一下。 // 也可以用自己喜欢的语言,来实现这个函数。 // 这个函数真的不复杂。 .substring(0, 4) !== "0000" ) { x = x + 1; } else { console.log(sha256(data + x).toString()); console.log(x); break; } } } proofOfWork();
复制代码
结果:
创建一个区块的类
const sha256 = require("crypto-js/sha256");
/**区块 * data * 之前区块的哈希值 * 自己的哈希值——由存储在区块里的信息算出来的(data + 之前区块的哈希值) *///写一个区块的类 class Block{ constructor(data, previousHash) { this.data = data; this.previousHash = previousHash; this.hash = this.computeHash() }
computeHash(){ return sha256(this.data + this.previousHash).toString() } }
const block = new Block("转账10元","KLOP"); console.log(block)
复制代码
运行之后:
编写一个链的类
class Block{ constructor(data, previousHash) { this.data = data; this.previousHash = previousHash; this.hash = this.computeHash() }
computeHash(){ return sha256(this.data + this.previousHash).toString() } }
// const block = new Block("转账10元","KLOP");// console.log(block)class Chain { constructor(){ this.chain = [this.bigBang()]; }
bigBang(){ //定义一个祖先区块 const genesisBlock = new Block("我是祖先区块",""); return genesisBlock; }}
const chain = new Chain();console.log(chain);
复制代码
输出的一个具有祖先区块的链
添加一个区块到区块链上
class Chain { constructor(){ this.chain = [this.bigBang()]; }
bigBang(){ //定义一个祖先区块 const genesisBlock = new Block("我是祖先区块",""); return genesisBlock; } //找到最近一个block的hash getLatestBlock(){ return this.chain[this.chain.length - 1]; } //添加区块到区块链上 addBlocktoChain(newBlock){ //找到最近一个block的hash //这个hash就是新区块的previousHash newBlock.previousHash = this.getLatestBlock().hash; newBlock.hash = newBlock.computeHash(); this.chain.push(newBlock); }}
const chain = new Chain();const block1 = new Block("转账10元","");
chain.addBlocktoChain(block1);console.log(chain);
复制代码
效果:
验证区块链中数据是否被篡改
class Chain { constructor(){ this.chain = [this.bigBang()]; }
bigBang(){ //定义一个祖先区块 const genesisBlock = new Block("我是祖先区块",""); return genesisBlock; } //找到最近一个block的hash getLatestBlock(){ return this.chain[this.chain.length - 1]; } //添加区块到区块链上 addBlocktoChain(newBlock){ //找到最近一个block的hash //这个hash就是新区块的previousHash newBlock.previousHash = this.getLatestBlock().hash; newBlock.hash = newBlock.computeHash(); this.chain.push(newBlock); }
//验证这个当前的区块链是否合法 //当前的数据有没有被篡改 //我们要验证区块的previousHash是否等于previous区块的hash validateChain() { if (this.chain.length === 1) { if (this.chain[0].hash !== this.chain[0].computeHash()) { return false; } return true; } // this.chain[1] 是第二个区块 // 我们从第二个区块开始 验证 // 验证到最后一个区块 this.chain.length -1 for (let i = 1; i <= this.chain.length - 1; i++) { const blockToValidate = this.chain[i]; //当前的数据有没有被篡改 if (blockToValidate.hash !== blockToValidate.computeHash()) { console.log("数据篡改"); return false; } //我们要验证区块的previousHash是否等于previous区块的hash const previousBlock = this.chain[i - 1]; if (blockToValidate.previousHash !== previousBlock.hash) { console.log("前后区块链接断裂"); return false; } } return true; }}
const chain = new Chain();
const block1 = new Block("转账10元","");const block2 = new Block("转账20元","");const block3 = new Block("转账30元","");const block4 = new Block("转账40元","");
chain.addBlocktoChain(block1);chain.addBlocktoChain(block2);chain.addBlocktoChain(block3);chain.addBlocktoChain(block4);
//尝试篡改这个区块链chain.chain[1].data = "转账一百个十元";console.log(chain);console.log(chain.validateChain())
复制代码
效果:
学习来源
https://www.bilibili.com/video/av78391502
评论