欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

python區(qū)塊鏈實現簡版工作量證明

 更新時間:2022年05月24日 16:48:41   作者:曉彬_  
這篇文章主要為大家介紹了python區(qū)塊鏈實現簡版工作量證明詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪

說明

本文根據https://github.com/liuchengxu/blockchain-tutorial的內容,用python實現的,但根據個人的理解進行了一些修改,大量引用了原文的內容。文章末尾有"本節(jié)完整源碼實現地址"。

回顧

上一節(jié),我們構造了一個非常簡單的數據結構 – 區(qū)塊,它也是整個區(qū)塊鏈數據庫的核心。目前所完成的區(qū)塊鏈原型,已經可以通過鏈式關系把區(qū)塊相互關聯(lián)起來:每個塊都與前一個塊相關聯(lián)。

但是,當前實現的區(qū)塊鏈有一個巨大的缺陷:向鏈中加入區(qū)塊太容易,也太廉價了。而區(qū)塊鏈和比特幣的其中一個核心就是,要想加入新的區(qū)塊,必須先完成一些非常困難的工作。在本文,我們將會彌補這個缺陷。

工作量證明

區(qū)塊鏈的一個關鍵點就是,一個人必須經過一系列困難的工作,才能將數據放入到區(qū)塊鏈中。正是由于這種困難的工作,才保證了區(qū)塊鏈的安全和一致。此外,完成這個工作的人,也會獲得相應獎勵(這也就是通過挖礦獲得幣)。

這個機制與生活現象非常類似:一個人必須通過努力工作,才能夠獲得回報或者獎勵,用以支撐他們的生活。在區(qū)塊鏈中,是通過網絡中的參與者(礦工)不斷的工作來支撐起了整個網絡。礦工不斷地向區(qū)塊鏈中加入新塊,然后獲得相應的獎勵。在這種機制的作用下,新生成的區(qū)塊能夠被安全地加入到區(qū)塊鏈中,它維護了整個區(qū)塊鏈數據庫的穩(wěn)定性。值得注意的是,完成了這個工作的人必須要證明這一點,即他必須要證明他的確完成了這些工作。

整個 “努力工作并進行證明” 的機制,就叫做工作量證明(proof-of-work)。要想完成工作非常地不容易,因為這需要大量的計算能力:即便是高性能計算機,也無法在短時間內快速完成。另外,這個工作的困難度會隨著時間不斷增長,以保持每 10 分鐘出 1 個新塊的速度。在比特幣中,這個工作就是找到一個塊的哈希,同時這個哈希滿足了一些必要條件。這個哈希,也就充當了證明的角色。因此,尋求證明(尋找有效哈希),就是礦工實際要做的事情。

哈希計算

獲得指定數據的一個哈希值的過程,就叫做哈希計算。一個哈希,就是對所計算數據的一個唯一表示。對于一個哈希函數,輸入任意大小的數據,它會輸出一個固定大小的哈希值。下面是哈希的幾個關鍵特性:

  • 無法從一個哈希值恢復原始數據。也就是說,哈希并不是加密。
  • 對于特定的數據,只能有一個哈希,并且這個哈希是唯一的。
  • 即使是僅僅改變輸入數據中的一個字節(jié),也會導致輸出一個完全不同的哈希。

本質上哈希是一個摘要算法。

哈希函數被廣泛用于檢測數據的一致性。軟件提供者常常在除了提供軟件包以外,還會發(fā)布校驗和。當下載完一個文件以后,你可以用哈希函數對下載好的文件計算一個哈希,并與作者提供的哈希進行比較,以此來保證文件下載的完整性。

在區(qū)塊鏈中,哈希被用于保證一個塊的一致性。哈希算法的輸入數據包含了前一個塊的哈希,因此使得不太可能(或者,至少很困難)去修改鏈中的一個塊:因為如果一個人想要修改前面一個塊的哈希,那么他必須要重新計算這個塊以及后面所有塊的哈希。

Hashcash

比特幣使用 Hashcash ,一個最初用來防止垃圾郵件的工作量證明算法。它可以被分解為以下步驟:

取一些公開的數據(比如,如果是 email 的話,它可以是接收者的郵件地址;在比特幣中,它是區(qū)塊頭)

給這個公開數據添加一個計數器。計數器默認從 0 開始

將 data(數據) 和 counter(計數器) 組合到一起,獲得一個哈希

檢查哈希是否符合一定的條件:

  • 如果符合條件,結束
  • 如果不符合,增加計數器,重復步驟 3-4

因此,這是一個暴力算法:改變計數器,計算新的哈希,檢查,增加計數器,計算哈希,檢查,如此往復。這也是為什么說它的計算成本很高,因為這一步需要如此反復不斷地計算和檢查。

現在,讓我們來仔細看一下一個哈希要滿足的必要條件。在原始的 Hashcash 實現中,它的要求是 “一個哈希的前 20 位必須是 0”。在比特幣中,這個要求會隨著時間而不斷變化。因為按照設計,必須保證每 10 分鐘生成一個塊,而不論計算能力會隨著時間增長,或者是會有越來越多的礦工進入網絡,所以需要動態(tài)調整這個必要條件。

為了闡釋這一算法,我從前一個例子(“I like donuts”)中取得數據,并且找到了一個前 3 個字節(jié)是全是 0 的哈希。

實現

這里我們實現一個簡易的區(qū)塊鏈,就不動態(tài)調節(jié)難度了,使用固定的難度。

class ProofOfWork(object):
    """
    pow 
    """
    _N_BITS = 16
    MAX_BITS = 256
    MAX_SIZE = sys.maxsize
    def __init__(self, block, n_bits=_N_BITS):
        self._n_bits = n_bits
        self._target_bits = 1 << (self.MAX_BITS - n_bits)
        self._block = block

這里的_n_bits就是難度值。 在比特幣中,當一個塊被挖出來以后,“n_bits” 代表了區(qū)塊頭里存儲的難度,也就是開頭有多少個 0。這里的 16 指的是算出來的哈希前 16 位必須是 0,如果用 16 進制表示,就是前 6 位必須是 0,這一點從最后的輸出可以看出來。目前我們并不會實現一個動態(tài)調整目標的算法,所以將難度定義為一個全局的常量即可。

16 其實是一個可以任意取的數字,其目的只是為了有一個目標而已,這個目標占據不到 256 位的內存空間。同時,我們想要有足夠的差異性,但是又不至于大的過分,因為差異性越大,就越難找到一個合適的哈希。這里的
_target_bits則表示滿足要求的最大值,即一個上界,它是由1左移256-n_bits位來的。計算出來的哈希只要滿足小于它就滿足條件了。

接下來我們要準備用于計算哈希的數據:

    def _prepare_data(self, nonce):
        data_lst = [str(self._block.block_header.prev_block_hash),
                    str(self._block.block_header.hash_merkle_root),
                    str(self._block.block_header.timestamp),
                    str(self._block.block_header.height),
                    str(nonce)]
        return utils.encode(''.join(data_lst))

nonce就是我們要不斷嘗試要尋找的值,就是上面 Hashcash 所提到的計數器,它是一個密碼學術語。其他數據都是區(qū)塊頭的數據。我們需要把這些數據進行合并作為計算哈希的原數據。

尋找nonce的方法:

    def run(self):
        nonce = 0
        found = False
        hash_hex = None
        print('Mining a new block')
        while nonce < self.MAX_SIZE:
            data = self._prepare_data(nonce)
            hash_hex = utils.sum256_hex(data)
            hash_val = int(hash_hex, 16)
            sys.stdout.write("try nonce == %d hash_hex == %s \r" % (nonce, hash_hex))
            if (hash_val < self._target_bits):
                found = True
                break
            nonce += 1
        if found: 
            print('Found nonce == %d' % nonce)
        else:
            print('Not Found nonce')
            raise NonceNotFoundError('nonce not found')
        return nonce, hash_hex

為防止溢出,我們要設定一個上線為int64的上限。然后我們不斷循環(huán)尋找目標值,直到滿足難度要求。當然,如果難度設計得過高,有可能尋找不到,所以也需要判斷一下。所以我們再循環(huán)內做了一下事:

1. 準備數據

2. 用 SHA-256 對數據進行哈希

3. 將哈希轉換成一個大整數

4. 將這個大整數與目標進行比較

然后我們還需要很方便的去檢驗這個塊的難度值是否滿足我們的要求:

    def validate(self):
        """
        validate the block
        """
        data = self._prepare_data(self._block.block_header.nonce)
        hash_hex = utils.sum256_hex(data)
        hash_val = int(hash_hex, 16)
        return hash_val < self._target_bits

最后運行以前的main.py,結果如下:

Mining a new block
...
...
...
Block(_block_header=BlockHeader(timestamp='1548213145.24', hash_merkle_root='', prev_block_hash='', hash='00008fbcbe3a817641195652d9bad37fa8c974536f152f4bc575b3ead9dc6407', nonce=62489, height=0))Block(_block_header=BlockHeader(timestamp='1548213166.65', hash_merkle_root='', prev_block_hash='00008fbcbe3a817641195652d9bad37fa8c974536f152f4bc575b3ead9dc6407', hash='9e851f78295e7933cd9749f712d1f09f1408dff9bd37cc2f79f1c65d1ab39e2e', nonce=16184, height=1))Block(_block_header=BlockHeader(timestamp='1548213171.15', hash_merkle_root='', prev_block_hash='9e851f78295e7933cd9749f712d1f09f1408dff9bd37cc2f79f1c65d1ab39e2e', hash='f88e7a382dafc50b01c43cbbdbbdfa20ac2bffcf5ddf36b97439ff09203f8c2a', nonce=8286, height=2))

可以看到這次我們產生三個塊花費了25秒多,比沒有工作量證明之前慢了很多(也就是成本高了很多)。

參考:

[1] proof-of-work

[2] 完整源碼

以上就是python區(qū)塊鏈實現簡版工作量證明的詳細內容,更多關于python區(qū)塊鏈工作量證明的資料請關注腳本之家其它相關文章!

相關文章

  • Pytho樹的直徑的計算實現

    Pytho樹的直徑的計算實現

    樹的直徑是樹中任意兩個節(jié)點之間最長路徑的長度,本文主要介紹了Pytho樹的直徑的計算實現,具有一定的參考價值,感興趣的可以了解一下
    2023-11-11
  • opencv 攝像機標定的實現

    opencv 攝像機標定的實現

    本文主要介紹了opencv 攝像機標定的實現,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2022-02-02
  • 一篇文章教你掌握python數據類型的底層實現

    一篇文章教你掌握python數據類型的底層實現

    這篇文章主要介紹了Python 數據類型的底層實現原理分析,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2021-09-09
  • 詳解如何用python實現一個簡單下載器的服務端和客戶端

    詳解如何用python實現一個簡單下載器的服務端和客戶端

    這篇文章主要介紹了詳解如何用python實現一個簡單下載器的服務端和客戶端,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2019-10-10
  • django框架自定義用戶表操作示例

    django框架自定義用戶表操作示例

    這篇文章主要介紹了django框架自定義用戶表操作,結合實例形式分析了Django框架自定義用戶表替換自帶的user表具體操作步驟與相關使用技巧,需要的朋友可以參考下
    2018-08-08
  • python實現異常信息堆棧輸出到日志文件

    python實現異常信息堆棧輸出到日志文件

    今天小編就為大家分享一篇python實現異常信息堆棧輸出到日志文件,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2019-12-12
  • python多進程(加入進程池)操作常見案例

    python多進程(加入進程池)操作常見案例

    這篇文章主要介紹了python多進程(加入進程池)操作,結合常見案例形式分析了Python多進程復制文件、加入進程池及多進程聊天等相關操作技巧,需要的朋友可以參考下
    2019-10-10
  • Python3將jpg轉為pdf文件的方法示例

    Python3將jpg轉為pdf文件的方法示例

    這篇文章主要介紹了Python3將jpg轉為pdf文件的方法,結合完整實例形式分析了Python3針對jpg轉pdf格式的文件讀寫、編碼裝換等相關操作技巧,需要的朋友可以參考下
    2019-12-12
  • Python元類與迭代器生成器案例詳解

    Python元類與迭代器生成器案例詳解

    這篇文章主要介紹了Python元類與迭代器生成器案例詳解,本篇文章通過簡要的案例,講解了該項技術的了解與使用,以下就是詳細內容,需要的朋友可以參考下
    2021-08-08
  • scrapy+scrapyd+gerapy?爬蟲調度框架超詳細教程

    scrapy+scrapyd+gerapy?爬蟲調度框架超詳細教程

    Scrapy吸引人的地方在于它是一個框架,任何人都可以根據需求方便的修改。它也提供了多種類型爬蟲的基類,如BaseSpider、sitemap爬蟲等,最新版本又提供了web2.0爬蟲的支持,這篇文章主要介紹了scrapy+scrapyd+gerapy?爬蟲調度框架超詳細教程,需要的朋友可以參考下
    2022-06-06

最新評論