如何从比特币矿池Stratum响应中获取nbits值并验证计算结果
Stratum协议mining.notify中nbits的Target计算与难度验证
问题场景
处理Stratum协议的mining.notify方法时,遇到nbits值的解析问题,原始返回参数如下:
{"id": "None","method": "mining.notify","params": ["1699124683_1302771","ee660a3e315357a42aec582931e4f34ba34f036300002ffd0000000000000000","01000000010000000000000000000000000000000000000000000000000000000000000000ffffffff5803d4700c1b4d696e656420627920416e74506f6f6c393037e7011403d450e402fabe6d6d6c647bfdf35ceb9cb31fc901909bb0ddc3606eb3c759c913e9e6911bf1e8db200200000000000000","ffffffff04744067290000000017a9144b09d828dfc8baaba5d04ee77397e04b1050cc73870000000000000000266a24aa21a9ed594ccb04beb39e38815daf25c37cb2d079d3bad05a51503bbde3ce5a8e471f6300000000000000002f6a2d434f52450164db24a662e20bbdf72d1cc6e973dbb2d12897d55997be5a09d05bb9bac27ec60419d0b373f32b2000000000000000002b6a2952534b424c4f434b3a05132c25672f671084924566f64aaa2b1926fa6e31ecd96555220a2d005839d600000000",["b9010d426ed693832149456aa442a4cbb7e2d282b07f4f76d5086fc84638afbb","90f71b47ceb606f0b38d7a82665742a983776e08ae2718dc4fb116db53480b92","5a4a665be6ee63d059bda0a83d263adcca48344f7e5a64c1ebbfce604eda6f74","e33225e435e3cfb370c27111c7db196eaad3863763f5146ccc1f7c780eb6bcac","6581f12b1f60767dcdc571159fd75e2504e7eea7f052cb35e7664bf61c234fe8","834fe4b0bdb10673c2b317d848cb93cf2b7b3a8af7a5051f0887163a1f829ecb","695e04507d0f3b0bcd1466e7edb39dc6cf7ba940557df25d65d116251685ba29","cd10e9a17b67de88e5f792908000024269f247486c3b2b8ee7ee4c3564209838","cc858f4d2cc6ce86cc0ee532ee5d65ccb3ccd5684499be004ee6e4f662b3a4ef","43f0be9cf3e65de59662316bab91419d098906715a2ce109a16f7aacd4ef81f0","cf0e82af3926d6dd0d3be1822e1c3806614130e4a0bf95403b39d524bc7e465d","c686bb9cb5b284ccd7d42fd5d1e55a5d78e8c6bb2585d0d89e6b084db2f73ef8"],"20000000","17048194","654695cb",false]}
你当前使用的计算代码:
nbits = 17048194 target = ( nbits[2:] + '00' * ( int( nbits[:2], 16 ) ) ).zfill( 64 ) print( target ) # prints 0000000000000481940000000000000000000000000000000000000000000000
你疑惑两点:
- 计算得到的难度值2是否有效(是否为新手低难度?)
- 当前计算的target是否正确
核心问题分析与修正
1. nbits的正确解析逻辑
Stratum协议中的nbits是十六进制字符串,而非十进制数字,它遵循比特币难度编码规则:
- 前2个十六进制字符表示target的字节长度(记为
length) - 剩余字符表示target的有效系数(记为
coefficient) - 最终target是将
coefficient左移(length - 3) * 8位,即在coefficient后补充(length - 3) * 2个十六进制0,再补前导零到64位(256位)。
你的代码第一个错误是把nbits当成十进制数字赋值,正确做法是直接使用参数中的字符串"17048194"。
2. 正确的Target计算
按照规则解析:
- nbits字符串:
"17048194" - 前两位
"17"转十进制是23(即target的字节长度为23) - 剩余系数部分:
"048194" - 需要补充的零的数量:
(23 - 3) * 2 = 40个十六进制0 - 最终target(补前导零到64位):
0000000000000000000000000000000000000000000481940000000000000000
你的代码错误地使用int(nbits[:2],16)直接作为补零数量(23个"00"),而非length-3,导致补零过多,得到的target是错误的。
3. 难度值的验证
难度值基于比特币基准target(难度1对应的target:00000000FFFF0000000000000000000000000000000000000000000000000000),公式为:
难度 = 基准target数值 / 当前target数值
代入正确的target计算:
- 基准target数值:
0xFFFF << 208 - 当前target数值:
0x048194 << 160 - 计算结果:
(0xFFFF / 0x048194) << 48 ≈ 6.16×10^13
这个数值远大于2,说明你得到的难度值2是错误target导致的结果。如果是新手低难度,矿池会返回对应编码,比如"1d00ffff"(对应难度1),而非当前的"17048194"。
总结
- 你当前的target计算错误,原因是nbits赋值方式和补零逻辑有误,修正后的target如上述所示。
- 计算得到的难度值2无效,是错误target导致的结果,当前nbits对应的实际难度远高于2。
- 新手低难度的nbits编码通常为
"1d00ffff"(难度1)或类似低阈值的字符串。
内容的提问来源于stack exchange,提问作者Sajjad Hossain Sagor
相关产品推荐
相关产品推荐

