比特币挖矿是区块链技术中最具神秘色彩的环节之一,虽然现实中真正的比特币挖矿早已被专业矿机(ASIC)垄断,但用JavaScript实现一个简化版的挖矿程序,依然是理解区块链工作原理(Proof of Work,工作量证明)的最佳方式,本文将从原理入手,带你用JS一步步实现一个“迷你挖矿机”。
比特币挖矿的本质
比特币挖矿并不是“挖”出什么虚拟矿石,其实质是:
- 收集交易:矿工从网络中收集未确认的交易,打包成候选区块;
- 构造区块头:区块头包含版本号、前一区块哈希、Merkle根、时间戳、难度目标(Bits)和随机数(Nonce);
- 暴力计算哈希:不断改变Nonce,对区块头做双重SHA-256运算(
SHA256(SHA256(区块头))); - 难度校验:如果算出的哈希值小于目标值(直观上看就是前面有足够多的0),即挖矿成功,区块被广播到全网。
这就是所谓的“工作量证明”,找到一个有效Nonce需要大量试错计算,但验证它只需要一次哈希运算。
用Node.js实现简化版挖矿
下面用Node.js实现一个最简化的挖矿演示:
const crypto = require('crypto');
// 简化的区块结构
const block = {
version: 1,
previousBlockHash: '00000000000000000001a2b3c...',
merkleRoot: '7f3a9c1e5b8d2...',
timestamp: Math.floor(Date.now() / 1000)
};
// 难度:要求哈希值前导0的个数
const difficulty = 5;
const target = '0'.repeat(difficulty);
let nonce = 0;
let hash = '';
let attempts = 0;
const startTime = Date.now();
console.log('开始挖矿...');
while (true) {
const data = `${block.version}${block.previousBlockHash}${block.merkleRoot}${block.timestamp}${nonce}`;
hash = crypto.createHash('sha256').update(data).digest('hex');
if (hash.startsWith(target)) {
console.log('🎉 挖矿成功!');
console.log('Nonce:', nonce);
console.log('Hash:', hash);
console.log('尝试次数:', attempts);
console.log('耗时:', ((Date.now() - startTime) / 1000).toFixed(2), '秒');
break;
}
nonce++;
attempts++;
}
代码要点说明:
nonce是核心变量,每轮循环递增,产生不同的输入从而产生不同的哈希;- 难度值每增加一个前导0,平均计算量就增加约16倍(16进制字符);
- 真实比特币需要将区块头序列化为80字节的二进制再做双SHA-256,这里做了简化。
在浏览器中挖矿:Web Worker + Web Crypto API
如果想在前端页面运行,可以利用Web Worker避免阻塞UI线程,并用原生crypto.subtle获得更好的性能:
// miner.worker.js
self.onmessage = function (e) {
const { blockData, difficulty } = e.data;
const target = '0'.repeat(difficulty);
let nonce = 0;
// 注意:crypto.subtle.digest 是异步的,
// 高频调用时可改用纯JS实现的SHA-256库做同步循环
function mine() {
const encoder = new TextEncoder();
crypto.subtle.digest('SHA-256',
encoder.encode(blockData + nonce)
).then(buf => {
const hash = Array.from(new Uint8Array(buf))
.map(b => b.toString(16).padStart(2, '0'))
.join('');
if (hash.startsWith(target)) {
self.postMessage({ nonce, hash });
} else {
nonce++;
mine();
}
});
}
mine();
};
JS挖矿的性能现实:为什么它不能赚钱
必须清醒地认识到,JavaScript挖矿在商业上完全不可行:
| 设备类型 | 大致算力(TH/s) |
|---|---|
| 专业ASIC矿机 | 100 ~ 300+ |
| 高端GPU | 05 ~ 0.1 |
| 普通CPU(C++优化) | 约 0.00001 |
| Node.js / 浏览器JS | 远低于CPU原生代码 |
JavaScript作为解释型语言,单线程性能远逊于C/C++,即使借助WebAssembly也只能接近原生水平,用JS挖比特币,电费成本将是收益的无数倍。
历史与警示:从Coinhive到挖矿劫持
2017年,名为Coinhive的服务曾让网站通过嵌入JS脚本,用访客CPU挖门罗币(Monero),一度有“用挖矿代替广告”的设想,但由于严重拖慢用户设备、且大量网站被恶意植入脚本(即加密劫持 Cryptojacking),该服务于2018年关闭,浏览器厂商也纷纷将未经同意的挖