以太坊 2.0 之后侧链不断分叉,但「共识机制」永远是面试必问。想要一次搞懂 工作量证明(Proof of Work,PoW)又不被 100 页白皮书本天书击倒?本文教你 95% 纯英文变量名、零第三方库、不带区块链钱包广告 的 Java 手写 PoW 生块流程。
关键词:PoW机制、Java区块链、SHA256碰撞、比特币难度调节、nonce随机值、创世区块、挖矿模拟
什么是 PoW
PoW,即 工作量证明机制,网络把一道「难于计算、却极易校验」的 Hash 题扔给矿工。矿工跑满 CPU,谁先找到满足条件的哈希,谁就拿到记账权与区块奖励;全网其他节点一秒钟就能验证答案正确。
一句话:挖矿 = 在 SHA256 的汪洋大海里反复撒网,直到捞到一串以 N 个 0 开头的中奖数字。
一个普通交易如何变成区块
- 矿工打包交易,组成
data。 - 用上一区块哈希
preHash、当前时间戳timestamp、难度值diff等拼接字符串。 - 修改随机数
nonce,不断计算 SHA256 直到结果前缀 连续diff个 0。 - 提交新区块,全网轻节点秒级校验,接受即上链。
本文只挖前两步:生块 + 接链,后续广播、持久化留给你课后挑战。
Java 从零撸一条迷你链
1. Block 实体
跳过无用 getter/setter,保留最关键 7 个属性:
private String preHash; // 上一区块 hash
private String hashCode; // 当前区块 hash
private Timestamp ts; // 时间戳
private int diff; // 前导0个数
private String data; // 交易
private int index; // 高度
private int nonce; // 随机值2. 创世区块生成
首个区块没爹没娘,把 preHash = 0 即可。设定小难度值 diff=4,本地毫秒级即可挖到:
public Block genesis(String data){
this.preHash="0";
this.ts=new Timestamp(System.currentTimeMillis());
this.diff=4;
this.data=data;
this.index=1;
this.nonce=0;
this.hashCode=genHash();
return this;
}3. SHA256 工具方法
用标准 java.security.MessageDigest 简单包装:
public static String sha256(String input){
try{
MessageDigest md=MessageDigest.getInstance("SHA-256");
byte[]hash=md.digest(input.getBytes(StandardCharsets.UTF_8));
StringBuilder hex=new StringBuilder();
for(byte b:hash){
String h=Integer.toHexString(0xff & b);
if(h.length()==1) hex.append('0');
hex.append(h);
}
return hex.toString();
}catch(Exception e){
throw new RuntimeException(e);
}
}4. 挖矿核心:暴力 nonce 循环
在 PoW 挖矿模拟器 方法 pow(int diff, Block block) 中,先把 “难度” 转成 0000 这样一段前缀:
String target="0".repeat(diff);随后死循环迭加 nonce:
do{
block.setNonce(block.getNonce()+1);
hash=sha256(block.header()); // header = index+nonce+diff+ts
}while(!hash.startsWith(target));第 43257 次时,我们样例机器终于输出:
0000e5b2a3f6a4b1c7c82f... // 4 个 0 通关👉 亲手跑 numer 次 SHA256,才发现挖矿有多暴力!
5. 把区块挂进链
为了别把自己绕进复杂 Merkle Tree,我们用一条 单向链表 模拟即可:
Node head = new Node(genesisBlock,null);
Node second = new Node(nextBlock,head);控制台完整链条打印:
{genesis} -> {block2, nonce=43257, diff=4, preHash=...}FAQ:新手最常问的 6 件事
Q1:难度值 dif=5 为什么一下跑到 90 万 nonce?
A:概率按 16 进制算,每增加一位 0,工作量 ≈ +16 倍。家用笔记本 4 秒变 80 秒纯属正常。
Q2:真正比特币怎么动态调 diff?
A:每 2016 个区块统计前两周出块时间,若低于 10 分钟就上调难度,保证平均 10 分钟落成新区块。
Q3:Java 写 PoW 会慢死吗?
A:Java 单线程跑不过 C/Go,但多线程 + ForkJoinPool 可逼近 C 的效率。生产级矿机直接走 ASIC,不算我们用 Java 的事。
Q4:nonce 最大值会炸 int?
A:int 上限 2^31-1 足够模拟。真实矿池用 long,概率问题才是天花板。
Q5:演示里一直 fixed diff=4,怎么写动态算 diff?
A:序贯链表长度一旦满 2016 块,统计总耗时 realTime,重置 diff = 预期时间 / realTime * oldDiff。
Q6:本文代码能直接部署到主网吗?
A:不能。没有 P2P 网络、交易池验证、MPT 状态树、签名脚本。用于教学 + 面试秀肌肉足矣。
课后彩蛋:代码仓库一键跑
把完整工程塞到 IDE,右键执行 Minichain.main,即见创世区块秒出与新区块「挖矿成功」。
👉 点击获取完整源码,3 分钟上手 Java PoW 课程对照表
小结
深度学习不必 1000 行:
- 把 SHA256 循环跑明白,你就抓住了 矿工的心酸;
- 把难度调节写出来,你就抓住了 区块链的灵魂。
现在你已经能用 15 行 Java 给自己挖个玩具区块了。下一步:网速、共识、经济学,才是魔鬼细节。