一個探勘區塊的小程序
任何人都可以逐步解釋下面的程式碼(如果可能,使用 ac/c++ 等效項)?
import hashlib, struct ver = 2 prev_block = "000000000000000117c80378b8da0e33559b5997f2ad55e2f7d18ec1975b9717" mrkl_root = "871714dcbae6c8193a2bb9b2a69fe1c0440399f38d94b3a0f1b447275a29978a" time_ = 0x53058b35 # 2014-02-20 04:57:25 bits = 0x19015f53 # https://en.bitcoin.it/wiki/Difficulty exp = bits >> 24 mant = bits & 0xffffff target_hexstr = '%064x' % (mant * (1<<(8*(exp - 3)))) target_str = target_hexstr.decode('hex') nonce = 0 while nonce < 0x100000000: header = ( struct.pack("<L", ver) + prev_block.decode('hex')[::-1] + mrkl_root.decode('hex')[::-1] + struct.pack("<LLL", time_, bits, nonce)) hash = hashlib.sha256(hashlib.sha256(header).digest()).digest() print nonce, hash[::-1].encode('hex') if hash[::-1] < target_str: print 'success' break nonce += 1
我正在嘗試創建自己的實現;我已經用 json-rpc 讀取了塊數據並儲存在這個結構中:
struct block { unsigned char* hash; int confirmations; long strippedsize; long size; long weight; long height; long version; unsigned char* versionHex; unsigned char* merkleroot; long blocktime; long mediantime; long nonce; unsigned char* bits; double difficulty; unsigned char* chainwork; unsigned char* previousblockhash; };
現在我想從這個結構中提取數據並用於在這段程式碼中執行相同的計算,但我需要了解程式碼的更多細節。
首先我們定義區塊上的一些資訊,即區塊是什麼版本,前一個區塊雜湊是什麼(因為每個區塊都引用前一個來創建鏈),這個區塊中所有交易的默克爾根是什麼(如果您不知道這是什麼,請參閱Wikipedia
bits
)、目前時間戳和編碼在變數中的目前難度:import hashlib, struct ver = 2 prev_block = "000000000000000117c80378b8da0e33559b5997f2ad55e2f7d18ec1975b9717" mrkl_root = "871714dcbae6c8193a2bb9b2a69fe1c0440399f38d94b3a0f1b447275a29978a" time_ = 0x53058b35 # 2014-02-20 04:57:25 bits = 0x19015f53
然後我們
bits
取值,並根據連結的 wiki 頁面中列出的步驟將其轉換為難度目標。目標基本上是一個我們想要在下面找到雜湊的數字(例如,如果目標是 10,那麼只有小於 10 的雜湊才有效):# https://en.bitcoin.it/wiki/Difficulty exp = bits >> 24 mant = bits & 0xffffff target_hexstr = '%064x' % (mant * (1<<(8*(exp - 3)))) target_str = target_hexstr.decode('hex')
現在我們開始一個循環,用不同的 nonce 值對塊進行多次散列,直到找到小於目標的散列。我們從 0 開始隨機數,並在每個循環中將其增加 1,這樣我們每次都會得到不同的雜湊值:
nonce = 0 while nonce < 0x100000000:
這只是將我們之前定義的數據(包括 nonce)放在一起準備好進行散列的序列化塊中:
header = ( struct.pack("<L", ver) + prev_block.decode('hex')[::-1] + mrkl_root.decode('hex')[::-1] + struct.pack("<LLL", time_, bits, nonce))
這是我們實際對序列化塊數據進行雜湊處理的地方,獲得一個雜湊值,我們將其列印出來(編碼為十六進製字元串)和 nonce 用於記錄目的:
hash = hashlib.sha256(hashlib.sha256(header).digest()).digest() print nonce, hash[::-1].encode('hex')
最後,我們將雜湊值與目標進行比較,如果它低於目標,我們就成功找到了一個有效塊,否則嘗試下一個隨機數:
if hash[::-1] < target_str: print 'success' break nonce += 1
請注意,這是一個非常簡單的程序,易於理解,但在實際挖礦中並不能真正發揮作用,因為僅更改 nonce 已不足以找到一個塊,coinbase 交易中的數據也會變化以更改 merkle 根也是。那隻是因為目標太低(難度如此之高)以至於擊中它的機會非常低,無法對抗網路上的大量挖礦算力。該程序也不計算 merkle 根本身,如果您直接從交易開始,則需要這樣做。