原文排版实在是惨不忍睹,所以手工校正了一下,方便大家阅读,如果侵权请及时联系我,我立即撤稿.
译者:申屠青春 深圳大学ATR国防科技重点实验室博士 新浪微博 @我看比特币
注意:本文可随意转发,请留下译者信息,如果觉得本文对你有用,请给译者捐赠,以便翻译更多比特币的核心资料。捐赠地址:1faVxBp2KmST98p3tJjx2MQP98JLLnF2Q
译者前言
比特币在国内已经众所周知,但是技术研究并未有效开展,大部分人处于知道和了解程度,目前比特圈中许多人对比特币能做什么,同样了解不多。一个重要原因是大多数比特币核心资料都是英文,很少有人能静心看完如此繁杂的英文资料。本人博士论文的研究方向是比特币,在研究其英文技术的同时,拟对一些重要资料进行翻译,让更多的圈内人对比特币有更多的理解。
本文主题是比特币区块、创世块、挖矿原理、难度等的技术资料,综合了比特币官方威客上的众多资料翻译和编写而成。
正文
1区块(Block)
比特币网络中,数据以文件的形式被永久记录,我们称之为区块。一个区块是一些或所有最新比特币交易的记录集,且未被其他先前的区块记录。区块可以想像为一个城市记录者的记录本上的单独一页纸(对房地产产权的变更记录)或者是股票交易所的总帐本。在绝大多数情况下,新区块被加入到记录最后(在比特币中的名称为:块链),一旦写上,就再也不能改变或删除。每个区块记录了它被创建之前发生的所有事件。
1.1区块结构(Block Structure)
**数据项****** | **描述****** | **长度****** |
---|---|---|
Magic no 魔术数 | 总是0xD9B4BEF9 | 4 字节 |
Blocksize 块大小 | 到区块结束的字节长度 | 4 字节 |
Blockheader 块头 | 包含6个数据项 | 80字节 |
Transaction counter 交易数量 | 正整数 VI = VarInt | 1 – 9字节 |
transactions 交易 | 交易列表(非空) |
1.2详细说明(Explanation)
每个区块包括一些或所有近期交易、前一个区块的引用、以及其他数据。它还包括一个挖矿难度的答案-该答案对每个区块是唯一的。新区块如果没有正确答案,不能被发送到网络中-“挖矿”的过程本质上是在竞争中 “解决”当前区块。每个区块中的数学问题难以解决,但是一旦发现了一个有效解,其他网络节点很容易验证这个解的正确性,对于给定的区块可能有多个有效解-但对于要解决的区块来说只需一个解。
因为每解决一个区块,都会得到新产生的比特币奖励,每个区块包含一个记录,记录中的比特币地址是有权获得比特币奖励的地址。这个纪录被称为生产交易、或者coinbase交易,它经常是每个区块的第一个交易。每个块区生产的比特币数量是50个,每产生21万个区块后减少一半(时间大约是4年)。
发送者在网络中广播比特币交易,所有试图解决区块的矿工节点,收集了这些交易记录,把它们加到矿工节点正在解决的区块中。
挖矿难度由比特币网络自动调整,使之实现平均每小时解决6个区块的目标。每2016个区块(大约两周)后,所有客户端把新区块的实际数目与目标数量相比较,并且按照差异的百分比调整目标HASH值,来增加(或降低)产生区块的难度。
因为所有区块包含前一个区块的引用,现存的所有区块的集合可以说是形成了一条链,然而,块链有可能产生暂时分叉-举个例子,如果两个矿工同时为一个区块产生不同的有效解,两者相互不知。P2P网络会在一段短时间内消除这些分叉,该链仅有一个分支存活。
客户端接受“最长”块链作为有效链,整条块链的“长度”是指具有最大难度的链,而不是指具有最多区块数量的块链,可防止某些人创建大量低难度区块,故意使块链分叉,并且让网络接受它成为“最长”的块链。
(译者按:以下非标准区块内容来自https://en.bitcoin.it/wiki/Nonstandard_block ,略有改动)
非标准区块:是指包括非标准交易的区块,交易的标准与否,要参考比特币客户端源代码中的IsStandard()函数。客户端不会传播非标准交易,但是某些矿池的矿工会把合法的非标准交易加入到区块中,形成非标准区块,客户端在计算难度最长的块链时,会考虑非标准区块。
区块的一般问题
- (1)目前有多少个区块?
目前的区块数,访问:http://blockexplorer.com/q/getblockcount
- (2)区块的最大数量是多少?
没有最大数量,区块以平均每10分钟一个的速度,源源不断地加到块链结尾。
- (3)甚至当所有的2100万个比特币全部被挖完,还是没有最大数量吗?
对的,区块用来确认交易在某一特定时间存在,即使比特币全部被挖完,交易还是会发生,所以只要人们还在交易比特币,区块还会被创建。
- (4)我要花多少时间生成一个区块?
没有人能够准确回答,这里有个生产计算器https://en.bitcoin.it/wiki/Generation_Calculator ,可以告诉你可能要花多少时间。
- (5)如果我完成计算一个区块的1%进度…
没有解决一个区块的1%的说法,你不会在解决区块上有任何进展,在工作24小时后,你解决一个区块的机率和24小时前一样,若非信仰比特币就是众所周知的赌徒谬误。
这就像同时抛53枚硬币,使得它们人头向上,每次你试验,你的成功机率都是一样的。
- (6)我还能找到更多的技术细节吗?
在下面的区块HASH算法中,有更多的技术细节。
2创世块(Genesis Block)
创世块是指块链的第一个块,现在的比特币客户端版本把块号定为0,以前的版本把该块块号定为1。
以下是创世块的一种表示,它出现在以前的比特币代码的注释中(第1613行),第一个代码段定义了创建该块所需的所有变量,第二个代码段是标准的区块类格式,还包含了第一个代码段中缩短版本的数据。
GetHash()= 0x000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f
hashMerkleRoot = 0x4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b
txNew.vin[0].scriptSig = 486604799 4 0x736B6E616220726F662074756F6C69616220646E6F63657320666F206B6E697262206E6F20726F6C6C65636E61684320393030322F6E614A2F33302073656D695420656854
txNew.vout[0].nValue = 5000000000
txNew.vout[0].scriptPubKey =
0x5F1DF16B2B704C8A578D0BBAF74D385CDE12C11EE50455F3C438EF4C3FBCF649B6DE611FEAE06279A60939E028A8D65C10B73071A6F16719274855FEB0FD8A6704 OP_CHECKSIG
block.nVersion = 1
block.nTime = 1231006505
block.nBits = 0x1d00ffff
block.nNonce = 2083236893
CBlock(hash=000000000019d6, ver=1, hashPrevBlock=00000000000000, hashMerkleRoot=4a5e1e, nTime=1231006505, nBits=1d00ffff, nNonce=2083236893, vtx=1)
CTransaction(hash=4a5e1e, ver=1, vin.size=1, vout.size=1, nLockTime=0)
CTxIn(COutPoint(000000, -1), coinbase 04ffff001d0104455468652054696d65732030332f4a616e2f32303039204368616e63656c6c6f72206f6e206272696e6b206f66207365636f6e64206261696c6f757420666f722062616e6b73)
CTxOut(nValue=50.00000000, scriptPubKey=0x5F1DF16B2B704C8A578D0B)
vMerkleTree: 4a5e1e
coinbase参数(看上面的十六进制)包含了以下一段话:
The Times 03/Jan/2009 Chancellor on brink of second bailout for banks
“2009年1月3日,首相第二次对处于崩溃边缘的银行进行紧急救助”,这句话正是泰晤士报当天的头版文章标题。这应该是一个该区块在2009年1月3日或之后创建的一个证据,同时也是对银行系统采用部分准备金制度导致不稳定性的一个说明。
创世块的收益不可能被花掉,因为创世块是用代码表示的(这个巧合可能是故意的),尽管如此,其50BTC收益还是被发送到地址:1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa。
(译者按:创世块的收益花不掉,原因如下:比特币客户端把区块和交易分开存贮在两个数据库中,当客户端发现区块数据库为空时,用代码直接生成一个创世块,但是没有生成这个交易,所以客户端中的交易数据库中是没有发送到上述地址这个交易的,因而一旦收到要花掉该收益的交易时,都会拒绝,所以无法得到任何确认,就花不掉这50个币。出现这种情况很可能是中本聪故意的。)
原始区块数据
创世块的原始十六进制如下所示:
00000000 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 …………….
00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 …………….
00000020 00 00 00 00 3B A3 ED FD 7A 7B 12 B2 7A C7 2C 3E ….;£íýz{.²zÇ,>
00000030 67 76 8F 61 7F C8 1B C3 88 8A 51 32 3A9F B8 AA gv.a.È.ÈŠQ2:Ÿ¸ª
00000040 4B 1E 5E 4A 29 AB 5F 49 FF FF 00 1D 1D AC 2B 7C K.^J)«_Iÿÿ…¬+|
00000050 01 01 00 00 00 01 00 00 00 00 00 00 00 00 00 00 …………….
00000060 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 …………….
00000070 00 00 00 00 00 00 FF FF FF FF 4D 04 FF FF 00 1D ……ÿÿÿÿM.ÿÿ..
00000080 01 04 45 54 68 65 20 54 69 6D 65 73 20 30 33 2F ..EThe Times 03/
00000090 4A 61 6E 2F 32 30 30 39 20 43 68 61 6E 63 65 6C Jan/2009 Chancel
000000A0 6C6F 72 20 6F 6E 20 62 72 69 6E 6B 20 6F 66 20 lor on brink of
000000B0 73 65 63 6F 6E 64 20 62 61 69 6C6F 75 74 20 66 second bailout f
000000C0 6F 72 20 62 61 6E 6B 73 FF FF FF FF 01 00 F2 05 or banksÿÿÿÿ..ò.
000000D0 2A 01 00 00 00 43 41 04 67 8A FD B0 FE 55 48 27 *….CA.gŠý°þUH’
000000E0 19 67 F1 A6 71 30 B7 10 5C D6 A8 28 E0 39 09 A6 .gñ¦q0·.\Ö¨(à9.¦
000000F0 79 62 E0 EA 1F 61 DE B6 49 F6 BC 3F4C EF 38 C4 ybàê.aÞ¶Iö¼?Lï8Ä
00000100 F3 55 04 E5 1E C1 12 DE 5C 38 4D F7 BA 0B 8D 57 óU.å.Á.Þ\8M÷º..W
00000110 8A4C 70 2B 6B F1 1D 5F AC 00 00 00 00 ŠLp+kñ._¬….
分开来看,如下所示:
01000000 – 版本号
0000000000000000000000000000000000000000000000000000000000000000 – prev block
3BA3EDFD7A7B12B27AC72C3E67768F617FC81BC3888A51323A9FB8AA4B1E5E4A – merkle root
29AB5F49 – 时间戳
FFFF001D – 目标HASH值
1DAC2B7C – 随机数
01 – 交易个数
01000000 – 版本
01 – 输入
0000000000000000000000000000000000000000000000000000000000000000FFFFFFFF – 前一个输出
4D – 脚本长度
04FFFF001D0104455468652054696D65732030332F4A616E2F32303039204368616E63656C6C6F72206F6E206272696E6B206F66207365636F6E64206261696C6F757420666F722062616E6B73 – scriptsig脚本
FFFFFFFF – 序列号
01 – 输出
00F2052A01000000 – 50 BTC的收益
43 – 脚本scriptPubKey的长度
4104678AFDB0FE5548271967F1A67130B7105CD6A828E03909A67962E0EA1F61DEB649F6BC3F4CEF38C4F35504E51EC112DE5C384DF7BA0B8D578A4C702B6BF11D5FAC – 脚本scriptPubKey
00000000 –锁定时间
JSON版本的创世块如下所示(译者按:JSON表示方式是译者加的,方便读者对照研究):
{
"hash": "000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f",
"ver": 1,
"prev_block": "0000000000000000000000000000000000000000000000000000000000000000",
"mrkl_root": "4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b",
"time": 1231006505,
"bits": 486604799,
"nonce": 2083236893,
"n_tx": 1,
"size": 285,
"tx": [
{
"hash": "4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b",
"ver": 1,
"vin_sz": 1,
"vout_sz": 1,
"lock_time": 0,
"size": 204,
"in": [
{
"prev_out": {
"hash": "0000000000000000000000000000000000000000000000000000000000000000",
"n": 4294967295
},
"coinbase": "04ffff001d0104455468652054696d65732030332f4a616e2f32303039204368616e63656c6c6f72206f6e206272696e6b206f66207365636f6e64206261696c6f757420666f722062616e6b73"
}
],
"out": [
{
"value": "50.00000000",
"scriptPubKey": "04678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38c4f35504e51ec112de5c384df7ba0b8d578a4c702b6bf11d5f OP_CHECKSIG"
}
]
}
],
"mrkl_tree": [
"4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b"
]
}
3块链(Block Chain)
块链是所有比特币节点共享的交易数据库,这些节点基于比特币协议参与到比特币网络中来。块链包含每一个曾在比特币系统执行过的交易。根据这个信息,人们可以找到任何时候任一个地址中的币数量,
每个区块包含前一个区块的HASH值,这就使得从创世块到当前块形成了一条块链,每个区块必定按时间顺序跟随在前一个区块之后,因为如果不知道前一块区块的HASH值就没法生成当前区块。要改变一个已经在块链中存在一段时间的区块,从计算上来说是不可行的,因为如果它被改变,它之后的每个区块必须随之改变。这些特性使得双花比特币非常困难,块链是比特币的最大创新。
如果一个区块是最长块链的最后一个区块,诚实的矿工只会在这个区块基础生成后续块(创建新块时通过引用该块来实现)。“长度”是被计算成块链的所有联合难度,而不是区块数目,尽管这个区别仅仅在防御几个潜在攻击时有用。如果一个块链中的所有区块和交易有效,则该块链有效,并且要以创世块开头。
对于块链中的任何区块来说,只有一条通向创世块的路径。然而,从创世块出发,却可能有分叉。当两个区块产生的时间仅相差几秒时,可能会产生包含一个区块的分叉。当以上现象出现时,矿工节点会根据收到区块的时间,在先收到的区块基础上继续挖矿。哪个区块的后续区块先出现,这个区块就被包括进主链,因为这条块链更长。在修正需要向后兼容的程序BUG后,出现过更严重的分叉。
短块链(或有效块链)中的区块没有作用,当比特币客户端转向另一个长块链时,短块链中所有有效的交易将被重新加入到交易队列池中,将被包括中另一个块中。短块链中的区块收益不会在长链中出现,因而这些收益实际上是丢失了,这就是比特币网络强化的100个区块成熟时间的存在原因。
在短块链中的区块经常被称为“孤立”区块,这是因为在长块链中的生产交易没有父区块,因而这些生产交易在交易列表的RPC调用中表现为孤立。几个矿池误解了这些信息并且把这些区块叫作“孤儿”,事实上这些区块都有父区块,可能还有子区块。
因为一个区块只能引用一个父区块,因而不可能把两个已经分叉的块链合并。
可以把块链算法用于非金融目的,请看:山寨块链 https://en.bitcoin.it/wiki/Alternative_chain。
块链以洪水协议被广播到网络上的所有节点,请看:块链下载
译者按:区块成熟时间(Maturation Time),是指矿工产生一个新区块得到25BTC收益后,要等过了100个块后,才能使用这些币;这个100区块时间,即收到100个确认的时间,就是区块成熟时间。为什么要设这个时间?如果这个区块在分叉时变成了孤立区块,25个BTC的收益将消失,如果矿工挖到比特币后可以马上花掉,就会造成后续的一系列接收者损失比特币,因而设定了100个确认的限制,在这之后产生分叉的可能性非常小,即使产生分叉,也只会影响矿工收益,不会影响到其他人。
4区块HASH算法(Block hashing Algorithm)
当挖矿时,你会经常对区块头进行HASH,你正在挖的区块也会时常更新,一个区域头包含以下数据项:
**数据项****** | 目的 | **更新时间****** | **大小****** |
---|---|---|---|
Version 版本 | 区域版本号 | 更新软件后,它指定了一个新版本号 | 4 |
hashPrevBlock 前一区块的HASH | 前一区块的256位HASH值 | 新的区块进来时 | 32 |
hashMerkleRootMerkele根节点HASH值 | 基于一个区块中所有交易的256位HASH值。 | 接受一个交易时 | 32 |
Time 时间戳 | 从1970-01-01 00:00 UTC开始到现在,以秒为单位的当前时间戳 | 每几秒就更新 | 4 |
Bits 当前目标HASH值 | 压缩格式的当前目标HASH值 | 当挖矿难度调整时 | 4 |
Nonce 随机数 | 从0开始的32位随机 | 产生HASH时A (每次产生HASH随机数要增长) | 4 |
区块内包含许多交易,它们通过Merkle根节点间接被HASH,因为所有交易不可能直接被HASH,HASH包含一个交易的区块所花的时间,和HASH包含1万个交易的区块一样。
目标HASH值的压缩格式是一个特殊的浮点编码类型,首字节是指数(仅使用了5个最低位),后3个字节是尾数,它能表示256位的数值。一个区块头的SHA256值必定要小于或等于目标HASH值,该区块才能被网络所接受,目标HASH越低,产生一个新区块的难度越大。
上述大部分数据项对所有用户是一致的,可能在时间戳上有些区别。(译者按:该段的以下内容来自:)如果当前区块的时间戳大于前11个区块的的平均时间戳,并且小于“网络调整时间(Network-Adjusted Time)”+2小时,则认为该时间戳是有效的。其中的“网络调整时间”是指与你相连接的所有节点的平均时间。当节点A连接到节点B时,A从B处得到一个UTC标准的时间戳,A先转换成本地UTC标准时间保存起来,网络调整时间等于所有节点的本地UTC时间+所有相连节点的偏移量平均值,然而,该网络时间永远不会调整到超过本地系统时间70分钟以上。
Nonce随机数通常不同,但是它以严格的线性方式增长,从0开始,每次HASH时都会增长,当Nonce溢出时(此事经常发生),生产交易的extraNonce项会增长,将改变Merkle树的根节点。
假定针对这些数据项,人们经常会独自产生同样序列号的HASH值,最快的CPU通常会赢。然而,两人产生同样的Merkle根节点基本是(或近似)不可能的,因为区块中的第一个交易是生产交易并且“发送”到你的独一无二的比特币地址。因为你的区块与其他人的区块不同,产生的HASH也肯定(近似肯定)不同,你计算的每个HASH和网络中的其他人一样,都有同样的获胜机会。
比特币使用:SHA256(SHA256(区块头))计算HASH,但你要注意字节序。
例如:以下python代码用于计算某一区块的HASH值,使用2011年6月的区块号125552的最小HASH值。该区块头建立上述6个数据项之上,并且以十六进制的小端结尾方式连接在一起。
>>> import hashlib
>>> header_hex = (“01000000″ +
“81cd02ab7e569e8bcd9317e2fe99f2de44d49ab2b8851ba4a308000000000000″ +
“e320b6c2fffc8d750423db8b1eb942ae710e951ed797f7affc8892b0f1fc122b” +
“c7f5d74d” +
“f2b9441a” +
“42a14695″)
>>> header_bin = header_hex.decode(‘hex’)
>>> hash = hashlib.sha256(hashlib.sha256(header_bin).digest()).digest()
>>> hash.encode(‘hex_codec’)
’1dbd981fe6985776b644b173a4d0385ddc1aa2a829688d1e0000000000000000′
>>> hash[::-1].encode(‘hex_codec’)
’00000000000000001e8d6829a8a21adc5d38d0a473b144b6765798e61f98bd1d’
注意:实际的HASH值是一串256位的数值,首部有许多零。当以大头端十六进制常数方式打印或存贮时,它的首部有许多零;如果它以小头端打印或存贮,零就会变换到尾部。例如:如果表示成字节串-最低(或者开头)的字节串地址显示最小位的数,这样就是小头端表示。blockexplorer的输出把HASH值显示为大头端表示的数值,因为数字的表示通常是-首部数字是最大数字,从左向右读。
举另外一个例子:这儿是纯C版本,未进行任何优化、线程化和错误检查。
以下是同样的例子,用PHP写,没有任何优化。
//This reverses and then swaps every other char
function SwapOrder($in){
$Split = str_split(strrev($in));
$x=;
for ($i = 0; $i < count($Split); $i+=2) {
$x .= $Split[$i+1].$Split[$i];
}
return $x;
}
//makes the littleEndian
function littleEndian($value){
return implode (unpack(‘H*’,pack(“V*”,$value)));
}
$version = littleEndian(1);
$prevBlockHash = SwapOrder(’00000000000008a3a41b85b8b29ad444def299fee21793cd8b9e567eab02cd81′);
$rootHash = SwapOrder(’2b12fcf1b09288fcaff797d71e950e71ae42b91e8bdb2304758dfcffc2b620e3′);
$time = littleEndian(1305998791);
$bits =littleEndian( 440711666);
$nonce = littleEndian(2504433986);
//concat it all
$header_hex = $version . $prevBlockHash . $rootHash . $time . $bits . $nonce;
//convert from hex to binary
$header_bin = hex2bin($header_hex);
//hash it then convert from hex to binary
$pass1 = hex2bin( hash(‘sha256′, $header_bin ) );
//Hash it for the seconded time
$pass2 = hash(‘sha256′, $pass1);
//fix the order
$FinalHash = SwapOrder($pass2);
echo $FinalHash;
?>
5难度(Difficulty)
难度是对挖矿困难程度的度量,即指:计算符合给定目标的一个HASH值的困难程度。比特币网络有一个全局的区块难度,有效的区域必须有一个HASH值,该HASH值必须小于给定的目标HASH。矿池也会有一个自定义的共享难度用来设定产生股份的最低难度限制。
难度每过2016块改变一次,计算公式:difficulty = difficulty_1_target / current_target
。目标(target)是一个256位长的数值。
有许多不同测量难度的方法,得到的difficulty_1_target可能不同。传统地,它表示一个HASH值,前32位为0,后续部分为1(称之为:矿池难度或pdiff),比特币协议把目标HASH表示成一个固定精度的自定义浮点类型,因而,比特币客户端用该值来估计难度(称之为:bdiff)。
难度经常被存贮在区块中,每个块存贮一个十六制的目标HASH的压缩表达式(称之为:Bits),目标HASH可以以预先定义的公式计算出来。例如:如果区块中压缩的目标HASH为0x1b0404cb,那十六进制的目标HASH如下所示:
0x0404cb * 2^(8*(0x1b - 3)) = 0x00000000000404CB000000000000000000000000000000000000000000000000
因而目标HASH为0x1b0404cb时,难度为:
0x00000000FFFF0000000000000000000000000000000000000000000000000000 /
0x00000000000404CB000000000000000000000000000000000000000000000000
= 16307.420938523983 (bdiff)
或者:
0x00000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF /
0x00000000000404CB000000000000000000000000000000000000000000000000
= 16307.669773817162 (pdiff)
其中:0x00000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
是挖矿机使用的最大目标HASH值。
而0x00000000FFFF0000000000000000000000000000000000000000000000000000
则是比特币网络使用的浮点编码类型,后面的位数被缩短。
下面是一个快速计算比特币难度的方法,它的算法使用修改的泰勒序列(你可以看wikipedia上的教程),并且依赖记录来转换难度计算。
#include
#include
inline float fast_log(float val){
int * const exp_ptr = reinterpret_cast (&val);
int x = *exp_ptr;
const int log_2 = ((x >> 23) & 255) – 128;
x &= ~(255 << 23);
x += 127 << 23;
*exp_ptr = x;
val = ((-1.0f/3) * val + 2) * val – 2.0f/3;
return ((val + log_2) * 0.69314718f);
}
float difficulty(unsigned int bits){
static double max_body = fast_log(0x00ffff), scaland = fast_log(256);
return exp(max_body – fast_log(bits & 0x00ffffff) + scaland * (0x1d – ((bits & 0xff000000) >> 24)));
}
int main(){
std::cout << difficulty(0x1b0404cb) << std::endl;
return 0;
}
如果要看以上一般难度计算的数字原理,以下是python代码:
import decimal, math
l = math.log
e = math.e
print 0x00ffff * 2**(8*(0x1d – 3)) / float(0x0404cb * 2**(8*(0x1b – 3)))
print l(0x00ffff * 2**(8*(0x1d – 3)) / float(0x0404cb * 2**(8*(0x1b – 3))))
print l(0x00ffff * 2**(8*(0x1d – 3))) – l(0x0404cb * 2**(8*(0x1b – 3)))
print l(0x00ffff) + l(2**(8*(0x1d – 3))) – l(0x0404cb) – l(2**(8*(0x1b – 3)))
print l(0x00ffff) + (8*(0x1d – 3))*l(2) – l(0x0404cb) – (8*(0x1b – 3))*l(2)
print l(0x00ffff / float(0x0404cb)) + (8*(0x1d – 3))*l(2) – (8*(0x1b – 3))*l(2)
print l(0x00ffff / float(0x0404cb)) + (0x1d – 0x1b)*l(2**8)
目前难度可以通过http://blockexplorer.com/q/getdifficulty来得到,下一个难度可以通过http://blockexplorer.com/q/estimate 来获得。难度的变化情况可以查看http://bitcoin.sipa.be/。
最大难度大约=maximum_target / 1 (因为0会导致无穷大),这是一个非常大的数值,大约2^224;当maximum_target为最小1时,最小难度值为1。
难度根据以前2016个区块的产生时间,每2016块改变一次。预计每隔10分钟产生一个区块,因而产生2016个区块要花费2周时间。如果前2016个区块的产生时间多于两周,则难度会降低;否则难度就会增加。
为了找到新区块,该区块的HASH值必须小于目标HASH傎,实际上是一个在0到2^256-1之间的随机数,难度1的偏移量是:
0xffff * 2^208
难度D的偏移量是
(0xffff * 2^208)/D
在难度D下,为了找到新区块,我们预期要计算的HASH数量是
D * 2^256 / (0xffff * 2^208)
或者只是
D * 2^48 / 0xffff
难度的设定,是为了以每10分钟一个区块的产生速度产生2016个区块,因而我们在600秒内计算 (D * 2^48 / 0xffff) 个HASH,这就意味着产生2016个区块的网络HASH速率(算力)是
D * 2^48 / 0xffff / 600
可以进一步简化为:
D * 2^32 / 600
以上公式有较好的精度。
在难度1下,算力是7Mhashes/秒,译者在翻译这篇文章时难度是5,006,860,589,这就意味着以前2016个区块被找到,其平均算力是:35.840PHash/s。
5,006,860,589 * 2^32 / 600 = 大约在35.840 PHash/s
发现一个区块的平均时间,可以用以下公式估计:
时间 = 难度 * 2^32 / 算力
其中,难度是当前的难度,算力你的矿机的计算能力,是hashes/s为单位,时间是你找到的两个区块之间的平均时间。举例:使用Python计算,算力为1Ghashes/s的矿机,难度在20000时,产生一个新区块的时间,(其中**表示指数):
$ python -c "print 20000 * 2**32 / 10**9 / 60 / 60.0"
23.85
意思就是:找到一个新区块要花费近1小时。
挖矿硬件对比,这里有一些统计,可以帮助你预测收入。
收支计算器1,收支计算器2,能帮你计算收支。
记住:这只是可能性,并不能保证你每天都能找到新区块。建议加入矿池挖矿,通过共享区块收益的方式,能得到稳定长期的回报。
本文译自比特币WIKI:
- https://en.bitcoin.it/wiki/Block_chain
- https://en.bitcoin.it/wiki/Block
- https://en.bitcoin.it/wiki/Block_hashing_algorithm
- https://en.bitcoin.it/wiki/Genesis_block
- https://en.bitcoin.it/wiki/Nonstandard_block
- https://en.bitcoin.it/wiki/Difficulty
- https://en.bitcoin.it/wiki/Target