50 / 736NONCE

Nonce

区块头中的挖矿计数器

Nonce 是挖矿设备在寻找 Bitcoin 新区块时不断修改的一个数。每次修改都会为计算提供不同的输入,让设备再试一次,看结果是否符合挖矿规则。

矿工计算的是区块头的哈希,也就是一种数字指纹。要满足 Proof of Work(工作量证明),结果必须小于或等于规定的上限,称为 target。Nonce 是可以修改以准备下一次尝试的数值之一。它不是密码,也不是秘密密钥:区块公布后,任何人都能看到它。

Anna 有一台挖矿设备,正在尝试生成一个包含交易的新区块。设备取出区块头,也就是一组精简的区块信息,用 SHA-256 算出数字指纹,称为哈希。Bitcoin 连续进行两次这种计算,因此叫 double-SHA-256。如果结果超过允许的上限,设备就可以把 Nonce 从 10 改成 11,再算一次。Anna 不用手动猜数字,设备会自动完成海量尝试。但 Nonce 更大,不代表哈希更小,也不代表更接近成功。完全相同的区块头总会产生相同哈希,反复计算它不会增加新的机会。 [1] [2]

Nonce 占四个字节,也就是 32 位,可以表示从 0 到 4,294,967,295 的整数,两端都包括在内。总共是 4,294,967,296 种可能,写作 2^32。对人来说很多,但专用挖矿设备 ASIC 很快就能遍历这个范围。试完全部数值也不保证成功。如果区块头的其他数据没有变化,重新从头计算只会重复原来的结果。因此,挖矿软件还需要准备不同的区块头。 [1] [5]

一种方法是修改 Extranonce。名称相近容易让人误会:它不是区块头里的额外字段,而是在 coinbase 交易内部。Coinbase 是区块的第一笔交易,用于分配挖矿奖励。修改其中的数据,会改变这笔交易的标识 txid,进而改变区块头中的 Merkle root,即交易的共同指纹。这样,设备就有了不同的输入。它可以再次使用同样的 Nonce 数值,但这次计算的是其他区块头的哈希。新的 2^32 种可能依然不保证找到区块。 [2] [3]

区块浏览器可能显示一个区块的 Nonce 很小,另一个很大。单看这个数,既无法判断找到区块有多难,也无法判断哪个更好。Full Node 是按照 Bitcoin 规则独立验证区块和交易的程序,它计算整个区块头的哈希,再与有效的 target 比较;target 的紧凑表示存储在 nBits 字段中。关键是哈希是否小于或等于这个上限,而不是 Nonce 的大小。检查到这里还没结束:节点还必须验证交易和区块的其他有效性规则。 [1] [8]

阅读交易签名的资料时,也会遇到 nonce。此时它可以指一个秘密的辅助数,技术上称为标量,签名算法将它与 Private Key,也就是授权花费资金的私钥,一起使用。如果错误地对不同消息重复使用这个辅助数,可能泄露私钥。挖矿 Nonce 则是公开的,同一个数可以出现在不同的区块头中。签名的公开部分也不是这个秘密辅助数。因此,不能脱离语境,把一种用途的安全规则直接套到另一种用途上。 [9]

许多设备在 Mining Pool 中共同挖矿时,不应全部计算相同区块头的哈希,因为重复计算不会增加新的尝试。协调方会分配不同的数据,例如不同的 coinbase 和 Extranonce 参数。Stratum 等协议负责传递任务,连接的挖矿单元也称为 workers。BIP23 还描述了可选参数 noncerange,用来指定 Nonce 的范围。这并不意味着所有矿池都必须使用它,更不意味着矿池可以修改区块有效性规则。 [4] [2]

Merkle Tree 逐步合并各笔交易的指纹,最终得到一个共同指纹 Merkle root。Coinbase 交易的标识 txid 作为树的一片叶子参与计算。因此,修改 Extranonce 会产生新的 txid,再产生新的 Merkle root。矿工可以保留其他交易和对前一区块的引用,同时得到不同的区块头。这不是改写已确认的区块,而是修改一个尚未找到有效 Proof of Work 的新区块候选方案。 [1] [2]

软件还可以在允许范围内修改时间 nTime,或修改获准使用的版本位,来生成更多区块头。后一种方法称为 version rolling。BIP320 提议将部分 nVersion 位用于通用用途;提案本身并不允许随意修改所有位。网络规则和分配的挖矿任务规则仍然适用。这些方法都不能绕过最终哈希必须满足有效 target 的要求。 较新的 BIP323 提议使用更多位,目前仍处于 Draft(草案)状态。 [4] [5] [10]

阅读技术文档时,了解具体格式也有帮助。区块头共 80 字节,包含版本、前一区块哈希、Merkle root、时间、nBits,以及四字节的 Nonce。Nonce 的类型是 uint32,即 32 位无符号整数,按 little-endian 小端顺序编码,最低有效字节在前。只修改 Nonce 会改变区块头及其 double-SHA-256 哈希,不会改变交易列表。软件必须遵守这个精确格式,但理解挖矿的意义并不要求你手工拼出这些字节。 [1]

进阶读者可以在 Bitcoin Core 中使用 getblockheader 命令,并提供某个区块的哈希。默认的详细输出包括 nonce、bits、time 等字段。把 verbose 参数设为 false,就会返回以十六进制表示的精确 80 字节区块头。可以据此重新计算 double-SHA-256,并将数值结果与有效 target 比较。自己编写实现时,必须遵守 Bitcoin 的字节顺序;错误地反转字节会改变比较结果。只在区块浏览器中读出 Nonce,不能代替这项验证。 [1] [6] [8]

要获得更完整的理解,请将本词条与以下词条结合阅读: Block Header, 挖矿, Proof of Work, Mining Target, Coinbase交易, Bitcoin. 反向关联还来自: Block Header, Coinbase交易, ASIC Miner, Stratum V1.

DOC · 001Bitcoin Developer Reference — Block headers文档 DOC · 002Bitcoin Developer Guide — Mining文档 DOC · 003Bitcoin Developer Reference — Transactions文档 DOC · 004BIP 23 — getblocktemplate pooled mining规范 DOC · 005BIP 320 — nVersion bits for general purpose use规范 DOC · 006Bitcoin Core RPC — getblockheader文档 DOC · 007Bitcoin Core RPC — getblocktemplate文档 DOC · 008Bitcoin Core v30.0 — Proof of Work validation一手来源 DOC · 009BIP 340 — Schnorr Signatures规范 DOC · 010BIP 323 — 24 nVersion bits for general purpose use文档
修订日期: 来源优先 · 非投资建议