关注微信公众号 「心谭博客」,前往 「xin-tan.com」
专注前端与算法的系列干货分享,欢迎关注(¬‿¬)
之前由于课程要求,基于Nodejs做了一个实现简易区块链。要求非常简单,结构体记录区块结构,顺便能向链中插入新的区块即可。
但是如果要支持多用户使用,就需要考虑“可信度”的问题。那么按照区块链要求,链上的数据不能被篡改,除非算力超过除了攻击者本身之外其余所以机器的算力。
想了想,就动手做试试咯。
技术调研
在google上搜了搜,发现有个项目不错: https://github.com/lhartikk/naivechain 。大概只有200行,但是其中几十行都是关于搭建ws和http服务器,美中不足的是没有实现批量插入区块链和计算可信度。
结合这个项目,基本上可以确定每个区块会封装成一个class(结构化表示),区块链也封装成一个class,再对外暴露接口。
区块定义
为了方便表示区块,将其封装为一个class,它没有任何方法:
/**
* 区块信息的结构化定义
*/
class Block {
/**
* 构造函数
* @param {Number} index
* @param {String} previousHash
* @param {Number} timestamp
* @param {*} data
* @param {String} hash
*/
constructor(index, previousHash, timestamp, data, hash) {
this.index = index // 区块的位置
this.previousHash = previousHash + '' // 前一个区块的hash
this.timestamp = timestamp // 生成区块时候的时间戳
this.data = data // 区块本身携带的数据
this.hash = hash + '' // 区块根据自身信息和规则生成的hash
}
}
至于怎么生成hash,这里采用的规则比较简单:
- 拼接index、previouHash、timestamp和data,将其字符串化
- 利用sha256算法,计算出的记过就是hash
为了方便,会引入一个加密库:
const CryptoJS = require('crypto-js')
链结构定义
很多区块链接在一起,就组成了一条链。这条链,也用class来表示。并且其中实现了很多方法:
- 按照加密规则生成hash
- 插入新块和检查操作
- 批量插入块和检查操作以及可信度计算
1. 起源块
起源块是“硬编码”,因为它前面没数据呀。并且规定它不能被篡改,即不能强制覆盖。我们在构造函数中,直接将生成的起源块放入链中。
class BlockChain {
constructor() {
this.blocks = [this.getGenesisBlock()]
}
/**
* 创建区块链起源块, 此块是硬编码
*/
getGenesisBlock() {
return new