我們繼續(xù)挖礦代碼的分析,上篇我們看到了BitcoinMiner()函數(shù)的第二部分創(chuàng)建區(qū)塊和整合交易?,F(xiàn)在我們繼續(xù)往下看。

這部分首先申請了三塊內(nèi)存空間,做為哈希緩沖區(qū),并16字節(jié)對齊(alignup<16>)。具體什么是字節(jié)地齊我在網(wǎng)上找了些概念我們也簡單介紹下:
現(xiàn)代計算機中內(nèi)存空間都是按照byte劃分的,從理論上講似乎對任何類型的變量的訪問可以從任何地址開始,但實際情況是在訪問特定類型變量的時候經(jīng)常在特定的內(nèi)存地址訪問,這就需要各種類型數(shù)據(jù)按照一定的規(guī)則在空間上排列,而不是順序的一個接一個的排放,這就是對齊。
對齊的作用和原因:各個硬件平臺對存儲空間的處理上有很大的不同。一些平臺對某些特定類型的數(shù)據(jù)只能從某些特定地址開始存取。比如有些架構(gòu)的CPU在訪問一個沒有進行對齊的變量的時候會發(fā)生錯誤,那么在這種架構(gòu)下編程必須保證字節(jié)對齊.其他平臺可能沒有這種情況,但是最常見的是如果不按照適合其平臺要求對數(shù)據(jù)存放進行對齊,會在存取效率上帶來損失。比如有些平臺每次讀都是從偶地址開始,如果一個int型(假設(shè)為32位系統(tǒng))如果存放在偶地址開始的地方,那么一個讀周期就可以讀出這32bit,而如果存放在奇地址開始的地方,就需要2個讀周期,并對兩次讀出的結(jié)果的高低字節(jié)進行拼湊才能得到該32bit數(shù)據(jù)。顯然在讀取效率上下降很多。

以上就是字節(jié)對齊的函數(shù)模板。我們簡單說下原理:
(1)(nBytes-1),表示對齊所需的對齊位,如:2字節(jié)對齊為1,4字節(jié)為11,8字節(jié)為111,16字節(jié)為1111...
(2)(u.n+(nBytes-1)),表示u.n補齊對齊所需數(shù)據(jù)
(3)&~(nBytes-1),表示去除由于補齊造成的多余數(shù)據(jù)
(4) (u.n+(nBytes-1))&~(nBytes-1),表示對齊后的數(shù)據(jù)
舉例:如8字節(jié)對齊。起始地始是6
6 + (8 - 1)=0000 0110 + 0000 0111 = 0000 1101
0000 1101 & ~(0000 0111) = 0000 1000 ?//去除由于補齊造成的多余數(shù)據(jù)
總的來說,這里使用字節(jié)對齊的目的是適配不同的cpu和提高對內(nèi)存的存取效率。然后調(diào)用FormatHashBuffers()格式化哈希緩沖區(qū)。

這個函數(shù)的 先定義了名為tmp的臨時結(jié)構(gòu)體,其中包括包含了區(qū)塊頭信息的block結(jié)構(gòu)和表示區(qū)塊哈希值的hash1。然后將相應區(qū)塊中的數(shù)據(jù)賦給相應的數(shù)據(jù)。我們這里說下pchPadding0和pchPadding1這兩個數(shù)組,表面上看沒什么用,其實這里就是我們前面說的字節(jié)對齊的擴展。目的是為了后面的FormatHashBlocks()格式化函數(shù),因為了格式化相應的數(shù)據(jù),所以需要固定的位數(shù),也是為了加密用,由于加密算法涉及很多分組異或運算,一般加密分組就必須長度固定。這是我個人理解,如果大家有別的更好的解釋,歡迎指正并留言。
我的理解是這樣來的,在調(diào)用FormatHashBuffers(pblock, pmidstate, pdata, phash1)這個函數(shù)的參數(shù)中,都是固定好的內(nèi)存空間。其中pdata需要128 + 16字節(jié),phash1需要64+16位。而我們的結(jié)構(gòu)體的內(nèi)存空間是不夠的,其中block的區(qū)塊頭信息的內(nèi)存大小為:(int + unit256+unit256 + int + int +int )= (4 + 32 + 32 + 4 + 4 + 4) = 80字節(jié)。不夠128 + 16字節(jié)的,所以需要補位(pchPadding0[64] )正好補上 64字節(jié),然后將多余的位數(shù)補0,也就是memset(&tmp,0,sizeof(tmp))的作用。最后通過FormatHashBlocks()格式化tmp.block ,tmp.hash1的內(nèi)存數(shù)據(jù)。
下面的代碼就好理解了,首先將結(jié)構(gòu)體tmp內(nèi)存區(qū)域中的數(shù)據(jù)按字節(jié)反序交換,然后把tmp中的結(jié)構(gòu)對象block用pSHA256InitState定義的狀態(tài)以SHA256算法加密,作為pmidstate的數(shù)據(jù),最后使用memcpy將tmp.block的前128字節(jié)數(shù)據(jù)賦給傳過來的參數(shù)pdata,將tmp.hash1的前64字節(jié)數(shù)據(jù)賦給參數(shù)值pash1。
回到最上面的頭部代碼中。在調(diào)用完FormatHashBuffers()格式化緩存區(qū)后,將格式化后的數(shù)據(jù)的內(nèi)存地址賦給相應的指針變量:

這里的內(nèi)存地址nBlockTime,nBlockBits,nBlockNonce正好是FomatHashBuffers()中tmp結(jié)構(gòu)中nTime,nBits,nNonce的變量地址。
? ? 由于今天這篇文章比較抽象,涉及到字節(jié)對齊的知識和內(nèi)存格式化的知識,關(guān)于具體的算法原理,由于水平有限,也不是太清楚,希望大家也諒解并指正。我們也就先了解到這里。
作者:區(qū)塊鏈研習社比特幣源碼研讀班,black