天天看點

POW概念實作

概念

對于單向散列函數,輸出是不可知的。但在假設輸出結果是随機平均分布的情況下,可以預先計算出特定範圍的結果的可能性,推導要計算出滿足特定條件的結果所花費的工作量。

在比特币的區塊鍊實作中,POW是一種保護區塊鍊網絡,維持通貨穩定的手段。因為對比特币來說,一個非常重要的原則是維持每10分鐘生成一個區塊。新的通貨隻會從新區塊的第一個交易(coinbase transaction)産生。如此,維持區塊的生成頻率就是維持通貨的穩定。

比特币區塊頭部會有一個字段Target和一個字段nonce(最後一個字段)。簡單來說,POW就是通過改變nonce字段,使得區塊頭部的散列值在數值上小于Target字段。通過設定特殊的Target值,使得調整nonce以得出滿足條件的散列值這一過程的平均時間為10分鐘。而隻有區塊頭部散列值在數值上小于Target的區塊,才會被視為是有效的區塊。

target

關于target的格式,前2位16進制數為指數(exponent),後6位16進制數是系數(coefficient)。

計算出實際的Target的公式為:

Target = coefficient * 2 ^ (8 * (exponent - 3))

retargeting

每10分鐘建立一個區塊是比特币的核心原則,保證通貨發行的穩定性。随着礦機的性能的提高,Target也需要周期性的調整以維持該原則,保證比特币的穩定。

比特币的每個節點會每隔2016個區塊重新調整一次target,以維持每10分鐘生成一個區塊的原則。

調整公式為:

新Target = 舊Target * (前2016個區塊所花費的時間 / 20160 分)

實作

#! /usr/bin/env python
# example of proof-of-work algorithm

import hashlib
import time

max_nonce =  **  # 4 billion

def proof_of_work(header, difficulty_bits):

    # calculate the difficulty target
    target =  ** ( - difficulty_bits)

    for nonce in xrange(max_nonce):
        hash_result = hashlib.sha256(str(header) + str(nonce)).hexdigest()   

        # check if this is a valid result, below the target
        if long(hash_result, ) < target:
            print "Success with nonce %d" % nonce
            print "Hash is %s" % hash_result
            return (hash_result, nonce)
    print "Failed after %d (max_nonce) tries" % nonce
    return nonce

if __name__ == '__main__':
    nonce = 
    hash_result = ''

    # difficulty from 0 to 31 bits
    for difficulty_bits in xrange():
        difficulty =  ** difficulty_bits
        print "Difficulty: %ld (%d bits)" % (difficulty, difficulty_bits)

        print "Starting search..."

        # checkpoint the current time
        start_time = time.time()

        # make a new block which includes the hash from the previous block
        # we fake a block of transactions - just a string
        new_block = 'test block with transactions' + hash_result

        # find a valid nonce for the new block
        (hash_result, nonce) = proof_of_work(new_block, difficulty_bits)

        # checkpoint how long it took to find a result
        end_time = time.time()

        elapsed_time = end_time - start_time
        print "Elapsed Time: %.4f seconds" % elapsed_time

        if elapsed_time > :

            # estimate the hashes per second
            hash_power = float(long(nonce)/elapsed_time)
            print "Hashing Power: %ld hashes per second" % hash_power
           

繼續閱讀