如何徒手挖比特币

比特币在最近几年突然火了起来,它巨大的经济利益的促使很多人都加入了挖矿浪潮,按照现在的行情,你算出一个区块,比特币网络一次不是给你一个比特币,加上手续费一次给你约13.5个比特币,约合人民币60万元。高玩梁也想想去凑热闹,但是高玩梁家计算机的性能不行,而这样的话呢,高玩梁就想能不能通过一些其他的方法来进行计算呢。我在想啊,我好歹数学也是1×2=4的水平,那可是数一数二啊。我能不能徒手挖比特币呢?后来经过一段时间的查询,可行。下面我就来和大家说一说如何来进行计算。

想要徒手挖比特币,我们就需要一些工具。你看人家挖矿用的都是什么矿卡呀?什么gtx1060啊,都是高端配置。我徒手挖比特币也不能示弱,那我们要准备什么东西呢?我们要准备以下几样东西。
一支铅笔或者是自动铅笔,一块橡皮和多张格子纸。

一下就露出了王者气质,那真是不知道比他们高到哪里去了。当然在这之前呢,我们需要准备一些数据。
第一个叫做时间戳,时间戳是指格林威治时间1970年1月1日0:00:00起至现在的总秒数。去网上(https://tool.lu/timestamp/)可以轻易的查到,当然你也可以手算啊,这个也不是什么特别难算的事情啊。
第二个呢,需要找到前一个块的哈希,默克尔树根和nbit,这个你可以在网络(https://btc.com/)上查到,等会我们会详细的给大家说一说。
还有你需要准备的一个叫做target的东西,这个呢,可以在网络上查到difficulty(https://bitcoinwisdom.com/bitcoin/difficulty),然后根据相关公式进行计算,我们等会说。

好了,那我们所有的数据就都准备完成了,那我们就可以正式的开始挖矿了。比特币呢是基于一种叫做sha-256的算法来实现挖矿的,虽然这样说并不准确,但是鉴于大家好理解,我就简单说了。sha呢,全称叫做安全散列算法,是NSA的发明。256呢,是指你不管输入多么长的文本,它最终呢都会输出一个256位的二进制数。你可能会想啊,那这样会不会很麻烦啊?经过高玩梁的实测,并不麻烦,你只要有小学四年级的数学水平就可以进行计算(说NSA只有小学四年级水平,举报了 #滑稽)。
首先呢,你需要准备几个他所规定的数值,8个哈希初值和64个哈希常量,大家注意了,这些数都是16进制的,但是别害怕,一点都不难。
十六进制(英文名称:Hexadecimal),是计算机中数据的一种表示方法。同我们日常生活中的表示法不一样。它由0-9,A-F组成,字母不区分大小写。与10进制的对应关系是:0-9对应0-9;A-F对应10-15;N进制的数可以用0~(N-1)的数表示,超过9的用字母A-F。
这8个哈希初值分别是:(0x表示后面的数是16进制的)
A = 0x6a09e667
B = 0xbb67ae85
C = 0x3c6ef372
D = 0xa54ff53a
E = 0x510e527f
F = 0x9b05688c
G = 0x1f83d9ab
H = 0x5be0cd19
这些初值是对自然数中前8个质数(2,3,5,7,11,13,17,19)的平方根的小数部分取前32bit而来(不必理解,记住即可)
64个哈希常量是
428a2f98 71374491 b5c0fbcf e9b5dba5 3956c25b 59f111f1 923f82a4 ab1c5ed5 d807aa98 12835b01 243185be 550c7dc3 72be5d74 80deb1fe 9bdc06a7 c19bf174 e49b69c1 efbe4786 0fc19dc6 240ca1cc 2de92c6f 4a7484aa 5cb0a9dc 76f988da 983e5152 a831c66d b00327c8 bf597fc7 c6e00bf3 d5a79147 06ca6351 14292967 27b70a85 2e1b2138 4d2c6dfc 53380d13 650a7354 766a0abb 81c2c92e 92722c85 a2bfe8a1 a81a664b c24b8b70 c76c51a3 d192e819 d6990624 f40e3585 106aa070 19a4c116 1e376c08 2748774c 34b0bcb5 391c0cb3 4ed8aa4a 5b9cca4f 682e6ff3 748f82ee 78a5636f 84c87814 8cc70208 90befffa a4506ceb bef9a3f7 c67178f2
和8个哈希初值类似,这些常量是对自然数中前64个质数(2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71,73,79,83,89,97…)的立方根的小数部分取前32bit而来。(不必理解,记住即可)
准备好这些之后,我们就开始梳理刚才的数据,按高玩梁现在撰稿的时间(2018-08-23 12:56:16),我们去btc.com挑选一个最新的区块538053(看高度)

我们需要算出这个参数C= version + prev_hash + merkle_root + ntime + nbits,其中
version = 版本号
prev_hash = 前一区块ID的字节反转
merkle_root = 本区块中所有交易的SHA256的墨克哈希树根的字节反转
ntime = 时间戳
nbits = 网络难度
第一个需要的是版本:0x20000000
第二个是需要前一个块的数据反转:0e7168bdd5ebcf97485b74eb10de19a3e718bc42136e12000000000000000000
第三个我们需要Merkle Root的数据反转:66cda53c8201a0f003048fe50522124415944351c7a4b63429fdd64b0c50e4af
第四个我们需要当前的时间戳:1535000176,然后转换成16进制:0x5b7e3e70
十进制数转换成十六进制方法是:除以16取余数
十进制数除以16,所得余数就是转换后的16进制数的最低位,所得的商再除以16得到的余数就是转换后的16进制数的第二位,直到商是0为止,把所有余数分别转换成16进制数,再按顺序排列即可。例如:723转换成16进制过程:
723÷16=45...........3
45÷16=2...............13(D)
2÷16=0................2
注意:13=D
所以:723=0x2D3
第五个是nbit,也就是bits:0x172c0da7
还需要一个随机数X,这个你从0到2^32-1之间选一个数,然后转换成16进制,这里我选择24857190(0x017b4a66,转换成16进制不满8位在前面用0补齐)
然后把他们组合起来,也就是:200000000e7168bdd5ebcf97485b74eb10de19a3e718bc42136e1200000000000000000066cda53c8201a0f003048fe50522124415944351c7a4b63429fdd64b0c50e4af5b7e3e70172c0da7017b4a66
这也就是我们要运算的数据,好,我们正式开始进行sha-256运算,SHA256算法中的预处理就是在想要Hash的消息后面补充需要的信息,使整个消息满足指定的结构。信息的预处理分为两个步骤:附加填充比特
和附加长度

在报文末尾进行填充,使报文长度在对512取模以后的余数是448(在二进制情况下)
首先我们数数这些一共多少位,得到位数为160位,然后乘4,得到640(二进制位),除以512,得余数为128。然后用448减128,得320,除4,得80,所以我们要在刚才算出的数据后面加80个0。至于为什么这么做,大家可以看文末的参考文章1。
200000000e7168bdd5ebcf97485b74eb10de19a3e718bc42136e1200000000000000000066cda53c8201a0f003048fe50522124415944351c7a4b63429fdd64b0c50e4af5b7e3e70172c0da7017b4a6600000000000000000000000000000000000000000000000000000000000000000000000000000000
附加长度值
附加长度值就是将原始数据(第一步填充前的消息)的长度信息补到已经进行了填充操作的消息后面。我们需要附加上一个64bit(二进制)的数据,用来表示原始报文的长度信息。我们知道刚才的数据一共160位,转换成二进制就是160×4=640位,640转换成十六进制就是0x280,补成64÷4=16位,就是0x0000000000000280,补在刚才的数据后面:
200000000e7168bdd5ebcf97485b74eb10de19a3e718bc42136e1200000000000000000066cda53c8201a0f003048fe50522124415944351c7a4b63429fdd64b0c50e4af5b7e3e70172c0da7017b4a66000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000280
然后将其转换为8个一组
20000000 0e7168bd d5ebcf97 485b74eb 10de19a3 e718bc42 136e1200 00000000 00000000 66cda53c 8201a0f0 03048fe5 05221244 15944351 c7a4b634 29fdd64b 0c50e4af 5b7e3e70 172c0da7 017b4a66 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000280
我们就可以正式开始计算了
首先,先准备好那八个哈希初值,ABC一组,D单独一组,EFG一组,H单独一组的顺序排放在上面,各组之间留出足够的空间。写数字的时候也是间隔三个写一个。便于我们将其转化成二进制。最终排放的方法如图所示。

首先我们要了解下相关的计算:



图中,ABCDEFGH这8个字(word)在按照一定的规则进行更新,其中
深蓝色方块是事先定义好的非线性逻辑函数,上文已经做过铺垫
红色田字方块代表 mod 2^32addition,即将两个数字加在一起,如果结果大于2^32,你必须除以2^32并找到余数。
ABCDEFGH一开始的初始值分别为Hi−1(0),Hi−1(1),...,Hi−1(7)Hi−1(0),Hi−1(1),...,Hi−1(7)
Kt是第t个密钥,对应我们上文提到的64个常量
Wt是本区块产生第t个word。原消息被切成固定长度512-bit的区块,对每一个区块,产生64个word,通过重复运行循环n次对ABCDEFGH这八个字循环加密。
最后一次循环所产生的八个字合起来即是第i个块对应到的散列字符串Hi
有人可能就要说啦啊,高玩梁啊,你是不是对四年级有什么误解呀,这个运算完全不太适合四年级的学生来运算啊,别说四年级了,我这大学生也算不了啊。别慌,其实一点都不难,看看下面我的操作你就知道有多简单了
先把ABC和EFG转化为二进制


首先对ABC进行maj运算,因为他是按位运算,所以说大家一位一位的看,也就是竖着看。我先给大家算一遍,写出结果。最后结果转化为16进制


这个maj运算怎么算呢?非常简单,抛开复杂的数学计算你可以发现,你只要看见三个数中超过两个1,当然包括两个。那maj运算的结果就是1,反之就是0。
然后呢在对A进行Σ0运算。这个运算的就是分别把A的二进制分别向右移动两位,移动13位和移动22位。当然移走的那些位 移到前面去。然后呢?在对其进行异或运算。我先给大家算一遍,大家看看结果。最后结果转换成16进制


移位我就不说了,我们来看看异或运算。抛开复杂的数学计算,我们又发现只要三个数中有奇数个1,结果就是1。偶数个1呢,就是0。
ABC这边的运算已经结束了。我们再看EFG,对EFG进行ch运算,ch运算是所有运算里面最难的。我在给大家算一遍,大家看看结果,

算完之后似乎没有规律可循。但是高玩梁也还是发现了一个不太规范的规律,只要三个数中只有最后一个是1,或者是由两个1挨在一起的,结果是1,反之就是0。
然后在对E进行Σ1运算。Σ1运算和Σ0运算大致相同。只不过它是向右移动6位,11位,和25位。我们仍然可以用上面找的规律对它进行运用。最后把算出来的二进制转化为十六进制。


接下来我们要计算一个值t1 = h + Σ1 + ch + k[i] + w[i],其中i表示轮数减一,现在我们是第一次运算,i=0,k[0]表示第一个哈希常数,也就是0x428a2f98,w[0]我们表示第一块参数,也就是0x20000000

还记得那个红色田字吗?红色田字方块代表 mod 2^32addition,即将两个数字加在一起,如果结果大于2^32,你必须除以2^32并找到余数。其实意思就是超过8位的数统统删掉。
然后我们就可以计算新E=t1+D

然后我们计算新A=Σ0+maj+t1

剩下的就可以结束了,因为新h=g,新g=f,新f=d,新d=c,新c=b,新b=a

你认为这样就完成了吗?那是绝对不可能的,这只是进行了sha256的第一轮,其实sha256共有64轮。我们只需要把算出来的这些新的abcdefg投入新的运算当中,继续进行下一轮,只要64轮结束之后,将abcdefg组合起来,就能得到我们想要的sha256的值。

你可能会想啊,这么简单,这也不难啊,64轮我算算也不是不可能的事情啊。那我算出来是不是就能挖到比特币了呢?你要是能挖出来,那些买矿卡的老板不得亏死呀,他直接叫你去算不就好了。实际上比特币算法的公式是这样的:

对你没有看错,比特币的算法并不是一层sha256,而是两层sha256,也就是说你需要进行64+64=128轮的运算。
而且呢,最终难度要小于一个值叫target,这个target可以由下面的一个公式进行计算。首先大家需要找到刚才的那个nbit=0x172c0da7。我们需要通过一个算式来进行计算。
0x2c0da7 * 2**(8*(0x17 - 3))

这个nbit实际上是target的一个压缩版本,我们需要将其解压缩。最后解压出的值是这样的
target=0x2c0da70000000000000000000000000000000000000000
只要你算的sha256小于这个值,就可以说你算出了比特币。

但是果真如此吗?其实从第一步开始就错了。你所计算的都是人家算完了的,也就是说你玩的都是人家玩剩下的。你可能会问啊,这是怎么回事儿啊?实际上在计算的过程中,你发现有一个值叫做默克尔树根Merkle Root了吗?这个呢,是当前区块所有交易的哈希值反转。这个值只能通过比特币网络来获取,并不能在本地实现获取,所以说呢,你获取到的默克尔树根是人家已经算完了的,而不是你自己算的。就因为这一个东西你做不到。
所以说,用手挖比特币基本是不可能完成的,当然如果你能连接比特币网络,得到这个默克尔树根,你仍然可以通徒手来进行计算。
其实比特币真正难的地方不是在挖矿的sha256,而是在于后面有一些椭圆曲线,它涉及到一些32位的大整数的运算,这个高玩梁比较笨啊,那就不详细说了。

参考文献:
SHA256算法原理详解:https://blog.csdn.net/u011583927/article/details/80905740
比特币挖矿一定要用计算机吗?用纸笔来计算可行吗?:https://www.zhihu.com/question/65177936
比特币开发者参考:https://bitcoin.org/zh_CN/developer-reference#target-nbits
理解与计算比特币难度值Difficulty:https://yushuangqi.com/blog/2017/understand-bitcoin-difficulty.html