工作量证明(Proof Of Work,POW)

Python例子

from itertools import count
from hashlib import md5
msg = 'randomstring'
for i in count():
    hashid = md5((msg+str(i)).encode("utf-8")).hexdigest()
    if hashid.startswith('0000000'):
        print(i,hashid)
        break
n = hashid

思考题:

  1. 如果搜索连续5个0开头的 hash 字符串,需要执行多少次 md5() 函数,耗时多少秒。
  2. 如果搜索连续6个0开头的 hash 字符串,需要执行多少次 md5() 函数,耗时多少秒。
  3. 如果搜索连续7个0开头的 hash 字符串,需要执行多少次 md5() 函数,耗时多少秒。
  4. 尝试从理论上估计不同数量0开头的hash字符串需要计算机最多执行多少次 md5() 函数。

从上至下依次为4,5,6,7个‘0’开头的测试结果。

从理论上估计不同数量(n)0开头的hash字符串需要计算机最多执行$16^n$次 md5() 函数。
因为不同数量(n)0开头的概率为$\frac{1}{16^n}$ ,当n = 8时 大概最多要执行4294967296次。


用JavaScript语言搭建一条区块链并实现工作量证明。

/*
 * @Author: kok-s0s
 * @Date: 2021-04-14 19:03:20
 * @LastEditTime: 2021-04-14 20:45:18
 * @Description: blockchain Proof of concept (概念验证) Proof of Work (工作量证明)
 */

// 区块链
// block
// chain


// data
// 之前区块的哈希值
// 自己的哈希值:是存储再区块里的信息 计算(data + 之前区块的哈希值)

const sha256 = require('crypto-js/sha256');

class Block {
    constructor(data, previousHash) {
        this.data = data;
        this.previousHash = previousHash;
        this.nonce = 1;
        this.hash = this.computeHash();
    }

    computeHash() {
        return sha256(this.data + this.previousHash + this.nonce).toString();
    }

    getAnswer(difficulty) {
        // 开头前n位为0的Hash
        let answer = ''
        for (let i = 0; i < difficulty; i++) {
            answer += '0';
        }
        return answer;
    }

    // 计算符合区块链难度要求的Hash
    mine(difficulty) {
        while (true) {
            this.hash = this.computeHash();
            if (this.hash.substring(0, difficulty) !== this.getAnswer(difficulty)) {
                this.nonce++;
                this.hash = this.computeHash();
            } else {
                break;
            }
        }
        console.log('挖矿结束', this.hash);
    }
}

// const block = new Block('转账100块', '123456')
// console.log(block)


class BlockChain {
    constructor() {
        this.chain = [this.bigBang()];
        this.difficulty = 3;
    }

    // 生成祖先区块
    bigBang() {
        const genesisBlock = new Block('我是祖先', '');
        return genesisBlock;
    }

    getLastestBlock() {
        return this.chain[this.chain.length - 1];
    }

    // 添加区块到区块链上
    addBlockToChain(newBlock) {
        // data
        // 找到最近一个block的Hash
        // 这个Hash即新区快的previousHash
        newBlock.previousHash = this.getLastestBlock().hash;
        // newBlock.hash = newBlock.computeHash();
        newBlock.mine(this.difficulty);
        // Hash要满足工作量证明
        this.chain.push(newBlock);
    }

    // 验证当前的区块链是否合法
    // 当前数据是否有被篡改
    // 区块的previousHash是否等于当前previous区块的Hash
    validateChian() {
        if (this.chain.length == 1) {
            if (this.chain[0].hash !== this.chain[0].computeHash()) {
                return false;
            }
            return true;
        }
        // 从第二区块开始验证
        for (let i = 1; i <= this.chain.length - 1; i++) {
            const blockRoValidate = this.chain[i];
            // 当前的数据是否有被篡改
            if (blockRoValidate.hash !== blockRoValidate.computeHash()) {
                console.log("数据被篡改");
                return false;
            }
            // 验证区块的previousHash是否等于previous区块的Hash
            const previousBlock = this.chain[i - 1];
            if (blockRoValidate.previousHash !== previousBlock.hash) {
                console.log("前后区块断裂")
                return false;
            }
        }
        return true;
    }
}

const chainTest = new BlockChain();
// console.log(chainTest);
// console.log(chainTest.validateChian());


const block1 = new Block('转账一千元', '');
chainTest.addBlockToChain(block1);
// console.log(chainTest);

const block2 = new Block('转账一元', '');
chainTest.addBlockToChain(block2);
console.log(chainTest);

// console.log(chainTest.validateChian())


// 尝试篡改区块
chainTest.chain[1].data = "kok-s0s";
chainTest.chain[1].mine(3);
console.log(chainTest.validateChian());

// chainTest.chain[1].data = '转账5元';
// chainTest.chain[1].hash = chainTest.chain[1].computeHash();
// console.log(chainTest.validateChian());

Last modification:October 6, 2023
兴趣使然