Tuesday, May 7, 2013

Bitcoin 採礦機開發 1 - 簡介 getwork

本文目標
從 2009 年以來,Bitcoin 採礦技術已經從 CPU 到 GPU 再到 FPGA,目前 (2013) 最先進的是 ASIC。本文從基礎開始分析 Bitcoin 採礦技術,歡迎有志開發自己的採礦機的讀者指教。

啟動測試網路
由於目前 Bitcoin 的難度相當高,要自己挖掘一個 block 的機率極低。為了減低計算難度,我們將使用測試網路(testnet),而非一般的 Bitcoin 網路。testnet 是你測試 Bitcoin 的好夥伴。
首先準備好官方的 bitcoind。假設讀者使用 Linux,可以下列參數啟動:

$ bitcoind -testnet -daemon

text 參數告訴 bitcoind 要連接到 testnet。
daemon 參數告訴 bitcoind 要在背景作為服務執行。

取得work
確認 bitcoind 在背景執行之後,就可以透過 JSON-RPC 從它取得一個 work

$ bitcoind -testnet getwork

執行結果如下:(數字會有不同)

{
    "midstate" : "f412665e9eaf2aef805289d0e8779ea5ce42beee7d76aec5cb036870e250db01",
    "data" : "0000000246a19088cb6e4d779bc8b6f223e748ec6da48aafb4d53ffe00cdcf99000000001b081cdb63293b7b117cb2d53a98a1ecb3e1e2dfbb322045159743673dae9de7517c91841c06305100000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000080020000",
    "hash1" : "00000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000010000",
    "target" : "0000000000000000000000000000000000000000000000000051300600000000"
}

取得 work 後,miner 的工作就是去找出一個稱之為 nonce 的32-bit 正整數,放入 data 之中,以滿足特定條件。此條件在下面會說明。而這整個過程就稱之為採礦。

Proof-of-work
那這個條件是甚麼呢?簡單來說就是對 data 取兩次 hash 值,使得 hash(hash(data)) < target
如果條件不成立的話,就把 nonce 加一,然後更新 data 重新計算,直到條件成立為止。Bitcoin 使用的 hash 函數是 SHA-256。

work 資料結構
從上面我們得知 bitcoind 會傳回四個數值,都是以 hexadecimal 編碼,little-endian 順序存放。其中 data 和 target 是必要欄位,midstate 和 hash1 是選擇性的。data 的長度是128 bytes,不過目前只用到 80 bytes。data 實際上是一個 structure,由 6 個欄位組成。我們現在不必深究所有的欄位,只要知道這 80 bytes 的最後面 4 個 bytes 是存放 nonce。而 nonce 欄位會是零,因為這是要 miner 去計算的。

0000000246a19088cb6e4d779bc8b6f223e748ec6da48aafb4d53ffe00cdcf99
000000001b081cdb63293b7b117cb2d53a98a1ecb3e1e2dfbb32204515974367
3dae9de7517c91841c0630510000000000000080000000000000000000000000
0000000000000000000000000000000000000000000000000000000080020000

由於 SHA-256 採用 big-endian,而 getwork 傳回的資料是以 4-byte 為一個 word,所以我們需要以四個 bytes 為單位先轉回 big-endian。以下的 python 程式可以容易的作到:

b = data.decode('hex')
h = ''.join([b[x:x+4][::-1] for x in range(0, len(b), 4)]).encode('hex')


結果為:

020000008890a146774d6ecbf2b6c89bec48e723af8aa46dfe3fd5b499cfcd00
00000000db1c081b7b3b2963d5b27c11eca1983adfe2e1b3452032bb67439715
e79dae3d84917c515130061c0000000080000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000280

注意到紅色的部份 4 bytes 全為零,這就是 miner 需要計算的 nonce,nonce 從零開始不斷加一後重新計算 hash,直到滿足條件為止。而最後面的橘色 4 bytes 的數值為 0x00000280,換成 10 進位就是 640,640 bits 即 80 bytes,這就是先前提到的實際資料長度 80 bytes,除非資料結構有更動,不然 miner 可以直接忽略這些資料。

下期預告
最簡單的 miner : pyminer

參考資料
Bitcoin wiki - getwork
Bitcoin wiki - block hashing algorithm

No comments:

Post a Comment