写一个区块链的概念原型

# 一个区块链原型

比特币区块链说神秘说复杂,它也是人创造出来。我们用几行代码写一个简单的原型。

说明都写在每行代码前面

const tracer = require('tracer').colorConsole()
const console = tracer
const bitcoin = require('bsv')

//挖矿的尝试次数
const maxTried = 100000//Number.MAX_VALUE

//区块
class Block {
    constructor(data, previousHash, difficulty) {
        this.data = data.toString() //区块数据
        this.previousHash = previousHash //前一个区块的哈希值
        this.timestamp = Date.now().toString() //当前区块的时间戳
        this.difficulty = difficulty //难度
        this.mine() //挖矿,计算本区块的哈希值
    }

    //计算哈希值
    hash256() {
        const str = this.previousHash + this.data + this.timestamp + this.answer.toString()
        return bitcoin.crypto.Hash.sha256(Buffer.from(str, 'utf8')).toString('hex')
    }

    //挖矿
    mine() {
        //不断修改answer的值,计算区块哈希值,要求获取的哈希值前面必须有指定难度数量的0
        this.answer = -1
        do {
            this.answer++
            if(this.answer >= maxTried) {
                throw Error('No Answer')
            }
            this.hash = this.hash256()
        } while(this.hash.substr(0, this.difficulty) !== '0'.repeat(this.difficulty))
    }


}

//区块链
class Blockchain {
    constructor(genesis) {   
        //包含创世区块 
        this.chain = [genesis]
    }

    //检测区块是否有效,要求每一个新的区块都包含前一个区块的哈希值
    isValid() {
        //循环检测除创世区块之外的所有区块
        for(let i=1; i<this.chain.length; i++) {
            const currentBlock = this.chain[i]
            const previoudBlock = this.chain[i-1]
            //计算当前区块的哈希值是否正确地被计算
            if(currentBlock.hash != currentBlock.hash256()) {
                console.debug(currentBlock.hash, currentBlock.hash256())
                return false
            }
            //前一个区块的哈希值应该等于当前区块保存的值
            if(previoudBlock.hash != currentBlock.previousHash) {
                console.debug(previoudBlock.hash, currentBlock.previousHash)
                return false
            }
            //当前区块的哈希值符合难度要求
            if(currentBlock.hash.substr(0, currentBlock.difficulty) !== '0'.repeat(currentBlock.difficulty)) {
                console.debug(currentBlock.hash.substr(0, currentBlock.difficulty) , '0'.repeat(currentBlock.difficulty))
                return false
            }
        }
        return true
    }

    //添加一个新的区块
    append(data, difficulty) {
        const newBlock = new Block(data, this.chain[this.chain.length-1].hash, difficulty)
        this.chain.push(newBlock)
    }

}

//创世区块, 前一个区块的哈希值设为0, 难度为0,也就是hash前面不需要有0
const genesisBlock = new Block('Born', 0, 0)
//创建区块链
const blockchain = new Blockchain(genesisBlock)
//不断追加新的区块,难度不断增加
blockchain.append('Love', 1)
blockchain.append('Marry', 2)
blockchain.append('Life', 3)
blockchain.append('How to change your wife(life) in 21 days', 4)
//输出所有的区块
console.log(blockchain.chain)
//检查区块链的有效性
console.log(blockchain.isValid())

一种可能的运行结果

[
  Block {
    data: 'Born',
    previousHash: 0,
    timestamp: '1591838675564',
    difficulty: 0,
    answer: 0,
    hash: '01cf61bbf7046125aeebb26970fc1c0634860a15ba281c9bd4026dc743e20d2d'
  },
  Block {
    data: 'Love',
    previousHash: '01cf61bbf7046125aeebb26970fc1c0634860a15ba281c9bd4026dc743e20d2d',
    timestamp: '1591838675565',
    difficulty: 1,
    answer: 2,
    hash: '0fe6e95260b8ab357761eec89032e354ff67a8b56cb2d61d0e4aa505acab3211'
  },
  Block {
    data: 'Marry',
    previousHash: '0fe6e95260b8ab357761eec89032e354ff67a8b56cb2d61d0e4aa505acab3211',
    timestamp: '1591838675565',
    difficulty: 2,
    answer: 9,
    hash: '005a3cadb9caa0dd2f5488325fc29f0b448d9c0ceb4b1ae2a1cdd78c4f5190a7'
  },
  Block {
    data: 'Life',
    previousHash: '005a3cadb9caa0dd2f5488325fc29f0b448d9c0ceb4b1ae2a1cdd78c4f5190a7',
    timestamp: '1591838675565',
    difficulty: 3,
    answer: 1277,
    hash: '0002a9bf4f568a9c4b3f8694de2aeef6a6f8e1a459486883859249d0ab23cf66'
  },
  Block {
    data: 'How to change your wife(life) in 21 days',
    previousHash: '0002a9bf4f568a9c4b3f8694de2aeef6a6f8e1a459486883859249d0ab23cf66',
    timestamp: '1591838675575',
    difficulty: 4,
    answer: 20139,
    hash: '0000ee25262cb5701b95d655e73eeed4c551384ce71b0815e694d0bc30455010'
  }
]

为什么说是“一种可能的运行结果“呢?聪明的你可以给我留言。

可以运行的代码库在:https://github.com/baryon/blockchain-prototype (opens new window)

享受真正的比特币,使用 Note.SV (opens new window)