如何徒手挖比特幣

比特幣在最近幾年突然火了起來(lái),它巨大的經(jīng)濟(jì)利益的促使很多人都加入了挖礦浪潮,按照現(xiàn)在的行情,你算出一個(gè)區(qū)塊,比特幣網(wǎng)絡(luò)一次不是給你一個(gè)比特幣,加上手續(xù)費(fèi)一次給你約13.5個(gè)比特幣,約合人民幣60萬(wàn)元。高玩梁也想想去湊熱鬧,但是高玩梁家計(jì)算機(jī)的性能不行,而這樣的話呢,高玩梁就想能不能通過(guò)一些其他的方法來(lái)進(jìn)行計(jì)算呢。我在想啊,我好歹數(shù)學(xué)也是1×2=4的水平,那可是數(shù)一數(shù)二啊。我能不能徒手挖比特幣呢?后來(lái)經(jīng)過(guò)一段時(shí)間的查詢(xún),可行。下面我就來(lái)和大家說(shuō)一說(shuō)如何來(lái)進(jìn)行計(jì)算。

想要徒手挖比特幣,我們就需要一些工具。你看人家挖礦用的都是什么礦卡呀?什么gtx1060啊,都是高端配置。我徒手挖比特幣也不能示弱,那我們要準(zhǔn)備什么東西呢?我們要準(zhǔn)備以下幾樣?xùn)|西。
一支鉛筆或者是自動(dòng)鉛筆,一塊橡皮和多張格子紙。

一下就露出了王者氣質(zhì),那真是不知道比他們高到哪里去了。當(dāng)然在這之前呢,我們需要準(zhǔn)備一些數(shù)據(jù)。
第一個(gè)叫做時(shí)間戳,時(shí)間戳是指格林威治時(shí)間1970年1月1日0:00:00起至現(xiàn)在的總秒數(shù)。去網(wǎng)上(https://tool.lu/timestamp/)可以輕易的查到,當(dāng)然你也可以手算啊,這個(gè)也不是什么特別難算的事情啊。
第二個(gè)呢,需要找到前一個(gè)塊的哈希,默克爾樹(shù)根和nbit,這個(gè)你可以在網(wǎng)絡(luò)(https://btc.com/)上查到,等會(huì)我們會(huì)詳細(xì)的給大家說(shuō)一說(shuō)。
還有你需要準(zhǔn)備的一個(gè)叫做target的東西,這個(gè)呢,可以在網(wǎng)絡(luò)上查到difficulty(https://bitcoinwisdom.com/bitcoin/difficulty),然后根據(jù)相關(guān)公式進(jìn)行計(jì)算,我們等會(huì)說(shuō)。

好了,那我們所有的數(shù)據(jù)就都準(zhǔn)備完成了,那我們就可以正式的開(kāi)始挖礦了。比特幣呢是基于一種叫做sha-256的算法來(lái)實(shí)現(xiàn)挖礦的,雖然這樣說(shuō)并不準(zhǔn)確,但是鑒于大家好理解,我就簡(jiǎn)單說(shuō)了。sha呢,全稱(chēng)叫做安全散列算法,是NSA的發(fā)明。256呢,是指你不管輸入多么長(zhǎng)的文本,它最終呢都會(huì)輸出一個(gè)256位的二進(jìn)制數(shù)。你可能會(huì)想啊,那這樣會(huì)不會(huì)很麻煩???經(jīng)過(guò)高玩梁的實(shí)測(cè),并不麻煩,你只要有小學(xué)四年級(jí)的數(shù)學(xué)水平就可以進(jìn)行計(jì)算(說(shuō)NSA只有小學(xué)四年級(jí)水平,舉報(bào)了 #滑稽)。
首先呢,你需要準(zhǔn)備幾個(gè)他所規(guī)定的數(shù)值,8個(gè)哈希初值和64個(gè)哈希常量,大家注意了,這些數(shù)都是16進(jìn)制的,但是別害怕,一點(diǎn)都不難。
十六進(jìn)制(英文名稱(chēng):Hexadecimal),是計(jì)算機(jī)中數(shù)據(jù)的一種表示方法。同我們?nèi)粘I钪械谋硎痉ú灰粯印K?-9,A-F組成,字母不區(qū)分大小寫(xiě)。與10進(jìn)制的對(duì)應(yīng)關(guān)系是:0-9對(duì)應(yīng)0-9;A-F對(duì)應(yīng)10-15;N進(jìn)制的數(shù)可以用0~(N-1)的數(shù)表示,超過(guò)9的用字母A-F。
這8個(gè)哈希初值分別是:(0x表示后面的數(shù)是16進(jìn)制的)
A = 0x6a09e667
B = 0xbb67ae85
C = 0x3c6ef372
D = 0xa54ff53a
E = 0x510e527f
F = 0x9b05688c
G = 0x1f83d9ab
H = 0x5be0cd19
這些初值是對(duì)自然數(shù)中前8個(gè)質(zhì)數(shù)(2,3,5,7,11,13,17,19)的平方根的小數(shù)部分取前32bit而來(lái)(不必理解,記住即可)
64個(gè)哈希常量是
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個(gè)哈希初值類(lèi)似,這些常量是對(duì)自然數(shù)中前64個(gè)質(zhì)數(shù)(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…)的立方根的小數(shù)部分取前32bit而來(lái)。(不必理解,記住即可)
準(zhǔn)備好這些之后,我們就開(kāi)始梳理剛才的數(shù)據(jù),按高玩梁現(xiàn)在撰稿的時(shí)間(2018-08-23 12:56:16),我們?nèi)tc.com挑選一個(gè)最新的區(qū)塊538053(看高度)

我們需要算出這個(gè)參數(shù)C= version + prev_hash + merkle_root + ntime + nbits,其中
version = 版本號(hào)
prev_hash = 前一區(qū)塊ID的字節(jié)反轉(zhuǎn)
merkle_root = 本區(qū)塊中所有交易的SHA256的墨克哈希樹(shù)根的字節(jié)反轉(zhuǎn)
ntime = 時(shí)間戳
nbits = 網(wǎng)絡(luò)難度
第一個(gè)需要的是版本:0x20000000
第二個(gè)是需要前一個(gè)塊的數(shù)據(jù)反轉(zhuǎn):0e7168bdd5ebcf97485b74eb10de19a3e718bc42136e12000000000000000000
第三個(gè)我們需要Merkle Root的數(shù)據(jù)反轉(zhuǎn):66cda53c8201a0f003048fe50522124415944351c7a4b63429fdd64b0c50e4af
第四個(gè)我們需要當(dāng)前的時(shí)間戳:1535000176,然后轉(zhuǎn)換成16進(jìn)制:0x5b7e3e70
十進(jìn)制數(shù)轉(zhuǎn)換成十六進(jìn)制方法是:除以16取余數(shù)
十進(jìn)制數(shù)除以16,所得余數(shù)就是轉(zhuǎn)換后的16進(jìn)制數(shù)的最低位,所得的商再除以16得到的余數(shù)就是轉(zhuǎn)換后的16進(jìn)制數(shù)的第二位,直到商是0為止,把所有余數(shù)分別轉(zhuǎn)換成16進(jìn)制數(shù),再按順序排列即可。例如:723轉(zhuǎn)換成16進(jìn)制過(guò)程:
723÷16=45...........3
45÷16=2...............13(D)
2÷16=0................2
注意:13=D
所以:723=0x2D3
第五個(gè)是nbit,也就是bits:0x172c0da7
還需要一個(gè)隨機(jī)數(shù)X,這個(gè)你從0到2^32-1之間選一個(gè)數(shù),然后轉(zhuǎn)換成16進(jìn)制,這里我選擇24857190(0x017b4a66,轉(zhuǎn)換成16進(jìn)制不滿8位在前面用0補(bǔ)齊)
然后把他們組合起來(lái),也就是:200000000e7168bdd5ebcf97485b74eb10de19a3e718bc42136e1200000000000000000066cda53c8201a0f003048fe50522124415944351c7a4b63429fdd64b0c50e4af5b7e3e70172c0da7017b4a66
這也就是我們要運(yùn)算的數(shù)據(jù),好,我們正式開(kāi)始進(jìn)行sha-256運(yùn)算,SHA256算法中的預(yù)處理就是在想要Hash的消息后面補(bǔ)充需要的信息,使整個(gè)消息滿足指定的結(jié)構(gòu)。信息的預(yù)處理分為兩個(gè)步驟:附加填充比特
和附加長(zhǎng)度

在報(bào)文末尾進(jìn)行填充,使報(bào)文長(zhǎng)度在對(duì)512取模以后的余數(shù)是448(在二進(jìn)制情況下)
首先我們數(shù)數(shù)這些一共多少位,得到位數(shù)為160位,然后乘4,得到640(二進(jìn)制位),除以512,得余數(shù)為128。然后用448減128,得320,除4,得80,所以我們要在剛才算出的數(shù)據(jù)后面加80個(gè)0。至于為什么這么做,大家可以看文末的參考文章1。
200000000e7168bdd5ebcf97485b74eb10de19a3e718bc42136e1200000000000000000066cda53c8201a0f003048fe50522124415944351c7a4b63429fdd64b0c50e4af5b7e3e70172c0da7017b4a6600000000000000000000000000000000000000000000000000000000000000000000000000000000
附加長(zhǎng)度值
附加長(zhǎng)度值就是將原始數(shù)據(jù)(第一步填充前的消息)的長(zhǎng)度信息補(bǔ)到已經(jīng)進(jìn)行了填充操作的消息后面。我們需要附加上一個(gè)64bit(二進(jìn)制)的數(shù)據(jù),用來(lái)表示原始報(bào)文的長(zhǎng)度信息。我們知道剛才的數(shù)據(jù)一共160位,轉(zhuǎn)換成二進(jìn)制就是160×4=640位,640轉(zhuǎn)換成十六進(jìn)制就是0x280,補(bǔ)成64÷4=16位,就是0x0000000000000280,補(bǔ)在剛才的數(shù)據(jù)后面:
200000000e7168bdd5ebcf97485b74eb10de19a3e718bc42136e1200000000000000000066cda53c8201a0f003048fe50522124415944351c7a4b63429fdd64b0c50e4af5b7e3e70172c0da7017b4a66000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000280
然后將其轉(zhuǎn)換為8個(gè)一組
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
我們就可以正式開(kāi)始計(jì)算了
首先,先準(zhǔn)備好那八個(gè)哈希初值,ABC一組,D單獨(dú)一組,EFG一組,H單獨(dú)一組的順序排放在上面,各組之間留出足夠的空間。寫(xiě)數(shù)字的時(shí)候也是間隔三個(gè)寫(xiě)一個(gè)。便于我們將其轉(zhuǎn)化成二進(jìn)制。最終排放的方法如圖所示。

首先我們要了解下相關(guān)的計(jì)算:



圖中,ABCDEFGH這8個(gè)字(word)在按照一定的規(guī)則進(jìn)行更新,其中
深藍(lán)色方塊是事先定義好的非線性邏輯函數(shù),上文已經(jīng)做過(guò)鋪墊
紅色田字方塊代表 mod 2^32addition,即將兩個(gè)數(shù)字加在一起,如果結(jié)果大于2^32,你必須除以2^32并找到余數(shù)。
ABCDEFGH一開(kāi)始的初始值分別為Hi?1(0),Hi?1(1),...,Hi?1(7)Hi?1(0),Hi?1(1),...,Hi?1(7)
Kt是第t個(gè)密鑰,對(duì)應(yīng)我們上文提到的64個(gè)常量
Wt是本區(qū)塊產(chǎn)生第t個(gè)word。原消息被切成固定長(zhǎng)度512-bit的區(qū)塊,對(duì)每一個(gè)區(qū)塊,產(chǎn)生64個(gè)word,通過(guò)重復(fù)運(yùn)行循環(huán)n次對(duì)ABCDEFGH這八個(gè)字循環(huán)加密。
最后一次循環(huán)所產(chǎn)生的八個(gè)字合起來(lái)即是第i個(gè)塊對(duì)應(yīng)到的散列字符串Hi
有人可能就要說(shuō)啦啊,高玩梁啊,你是不是對(duì)四年級(jí)有什么誤解呀,這個(gè)運(yùn)算完全不太適合四年級(jí)的學(xué)生來(lái)運(yùn)算啊,別說(shuō)四年級(jí)了,我這大學(xué)生也算不了啊。別慌,其實(shí)一點(diǎn)都不難,看看下面我的操作你就知道有多簡(jiǎn)單了
先把ABC和EFG轉(zhuǎn)化為二進(jìn)制


首先對(duì)ABC進(jìn)行maj運(yùn)算,因?yàn)樗?span id="s0sssss00s" class="color-pink-03">按位運(yùn)算,所以說(shuō)大家一位一位的看,也就是豎著看。我先給大家算一遍,寫(xiě)出結(jié)果。最后結(jié)果轉(zhuǎn)化為16進(jìn)制


這個(gè)maj運(yùn)算怎么算呢?非常簡(jiǎn)單,拋開(kāi)復(fù)雜的數(shù)學(xué)計(jì)算你可以發(fā)現(xiàn),你只要看見(jiàn)三個(gè)數(shù)中超過(guò)兩個(gè)1,當(dāng)然包括兩個(gè)。那maj運(yùn)算的結(jié)果就是1,反之就是0。
然后呢在對(duì)A進(jìn)行Σ0運(yùn)算。這個(gè)運(yùn)算的就是分別把A的二進(jìn)制分別向右移動(dòng)兩位,移動(dòng)13位和移動(dòng)22位。當(dāng)然移走的那些位 移到前面去。然后呢?在對(duì)其進(jìn)行異或運(yùn)算。我先給大家算一遍,大家看看結(jié)果。最后結(jié)果轉(zhuǎn)換成16進(jìn)制


移位我就不說(shuō)了,我們來(lái)看看異或運(yùn)算。拋開(kāi)復(fù)雜的數(shù)學(xué)計(jì)算,我們又發(fā)現(xiàn)只要三個(gè)數(shù)中有奇數(shù)個(gè)1,結(jié)果就是1。偶數(shù)個(gè)1呢,就是0。
ABC這邊的運(yùn)算已經(jīng)結(jié)束了。我們?cè)倏碋FG,對(duì)EFG進(jìn)行ch運(yùn)算,ch運(yùn)算是所有運(yùn)算里面最難的。我在給大家算一遍,大家看看結(jié)果,

算完之后似乎沒(méi)有規(guī)律可循。但是高玩梁也還是發(fā)現(xiàn)了一個(gè)不太規(guī)范的規(guī)律,只要三個(gè)數(shù)中只有最后一個(gè)是1,或者是由兩個(gè)1挨在一起的,結(jié)果是1,反之就是0。
然后在對(duì)E進(jìn)行Σ1運(yùn)算。Σ1運(yùn)算和Σ0運(yùn)算大致相同。只不過(guò)它是向右移動(dòng)6位,11位,和25位。我們?nèi)匀豢梢杂蒙厦嬲业囊?guī)律對(duì)它進(jìn)行運(yùn)用。最后把算出來(lái)的二進(jìn)制轉(zhuǎn)化為十六進(jìn)制。


接下來(lái)我們要計(jì)算一個(gè)值t1 = h + Σ1 + ch + k[i] + w[i],其中i表示輪數(shù)減一,現(xiàn)在我們是第一次運(yùn)算,i=0,k[0]表示第一個(gè)哈希常數(shù),也就是0x428a2f98,w[0]我們表示第一塊參數(shù),也就是0x20000000

還記得那個(gè)紅色田字嗎?紅色田字方塊代表 mod 2^32addition,即將兩個(gè)數(shù)字加在一起,如果結(jié)果大于2^32,你必須除以2^32并找到余數(shù)。其實(shí)意思就是超過(guò)8位的數(shù)統(tǒng)統(tǒng)刪掉。
然后我們就可以計(jì)算新E=t1+D

然后我們計(jì)算新A=Σ0+maj+t1

剩下的就可以結(jié)束了,因?yàn)樾耯=g,新g=f,新f=d,新d=c,新c=b,新b=a

你認(rèn)為這樣就完成了嗎?那是絕對(duì)不可能的,這只是進(jìn)行了sha256的第一輪,其實(shí)sha256共有64輪。我們只需要把算出來(lái)的這些新的abcdefg投入新的運(yùn)算當(dāng)中,繼續(xù)進(jìn)行下一輪,只要64輪結(jié)束之后,將abcdefg組合起來(lái),就能得到我們想要的sha256的值。

你可能會(huì)想啊,這么簡(jiǎn)單,這也不難啊,64輪我算算也不是不可能的事情啊。那我算出來(lái)是不是就能挖到比特幣了呢?你要是能挖出來(lái),那些買(mǎi)礦卡的老板不得虧死呀,他直接叫你去算不就好了。實(shí)際上比特幣算法的公式是這樣的:

對(duì)你沒(méi)有看錯(cuò),比特幣的算法并不是一層sha256,而是兩層sha256,也就是說(shuō)你需要進(jìn)行64+64=128輪的運(yùn)算。
而且呢,最終難度要小于一個(gè)值叫target,這個(gè)target可以由下面的一個(gè)公式進(jìn)行計(jì)算。首先大家需要找到剛才的那個(gè)nbit=0x172c0da7。我們需要通過(guò)一個(gè)算式來(lái)進(jìn)行計(jì)算。
0x2c0da7 * 2**(8*(0x17 - 3))

這個(gè)nbit實(shí)際上是target的一個(gè)壓縮版本,我們需要將其解壓縮。最后解壓出的值是這樣的
target=0x2c0da70000000000000000000000000000000000000000
只要你算的sha256小于這個(gè)值,就可以說(shuō)你算出了比特幣。

但是果真如此嗎?其實(shí)從第一步開(kāi)始就錯(cuò)了。你所計(jì)算的都是人家算完了的,也就是說(shuō)你玩的都是人家玩剩下的。你可能會(huì)問(wèn)啊,這是怎么回事兒???實(shí)際上在計(jì)算的過(guò)程中,你發(fā)現(xiàn)有一個(gè)值叫做默克爾樹(shù)根Merkle Root了嗎?這個(gè)呢,是當(dāng)前區(qū)塊所有交易的哈希值反轉(zhuǎn)。這個(gè)值只能通過(guò)比特幣網(wǎng)絡(luò)來(lái)獲取,并不能在本地實(shí)現(xiàn)獲取,所以說(shuō)呢,你獲取到的默克爾樹(shù)根是人家已經(jīng)算完了的,而不是你自己算的。就因?yàn)檫@一個(gè)東西你做不到。
所以說(shuō),用手挖比特幣基本是不可能完成的,當(dāng)然如果你能連接比特幣網(wǎng)絡(luò),得到這個(gè)默克爾樹(shù)根,你仍然可以通徒手來(lái)進(jìn)行計(jì)算。
其實(shí)比特幣真正難的地方不是在挖礦的sha256,而是在于后面有一些橢圓曲線,它涉及到一些32位的大整數(shù)的運(yùn)算,這個(gè)高玩梁比較笨啊,那就不詳細(xì)說(shuō)了。

參考文獻(xiàn):
SHA256算法原理詳解:https://blog.csdn.net/u011583927/article/details/80905740
比特幣挖礦一定要用計(jì)算機(jī)嗎?用紙筆來(lái)計(jì)算可行嗎?:https://www.zhihu.com/question/65177936
比特幣開(kāi)發(fā)者參考:https://bitcoin.org/zh_CN/developer-reference#target-nbits
理解與計(jì)算比特幣難度值Difficulty:https://yushuangqi.com/blog/2017/understand-bitcoin-difficulty.html