<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
本文根據https://github.com/liuchengxu/blockchain-tutorial的內容,用python實現的,但根據個人的理解進行了一些修改,大量參照了原文的內容。文章末尾有"本節完整原始碼實現地址"。
在上一節,我們構造了一個非常簡單的資料結構 – 區塊,它也是整個區塊鏈資料庫的核心。目前所完成的區塊鏈原型,已經可以通過鏈式關係把區塊相互關聯起來:每個塊都與前一個塊相關聯。
但是,當前實現的區塊鏈有一個巨大的缺陷:向鏈中加入區塊太容易,也太廉價了。而區塊鏈和位元幣的其中一個核心就是,要想加入新的區塊,必須先完成一些非常困難的工作。在本文,我們將會彌補這個缺陷。
區塊鏈的一個關鍵點就是,一個人必須經過一系列困難的工作,才能將資料放入到區塊鏈中。正是由於這種困難的工作,才保證了區塊鏈的安全和一致。此外,完成這個工作的人,也會獲得相應獎勵(這也就是通過挖礦獲得幣)。
這個機制與生活現象非常類似:一個人必須通過努力工作,才能夠獲得回報或者獎勵,用以支撐他們的生活。在區塊鏈中,是通過網路中的參與者(礦工)不斷的工作來支撐起了整個網路。礦工不斷地向區塊鏈中加入新塊,然後獲得相應的獎勵。在這種機制的作用下,新生成的區塊能夠被安全地加入到區塊鏈中,它維護了整個區塊鏈資料庫的穩定性。值得注意的是,完成了這個工作的人必須要證明這一點,即他必須要證明他的確完成了這些工作。
整個 “努力工作並進行證明” 的機制,就叫做工作量證明(proof-of-work)。要想完成工作非常地不容易,因為這需要大量的計算能力:即便是高效能運算機,也無法在短時間內快速完成。另外,這個工作的困難度會隨著時間不斷增長,以保持每 10 分鐘出 1 個新塊的速度。在位元幣中,這個工作就是找到一個塊的雜湊,同時這個雜湊滿足了一些必要條件。這個雜湊,也就充當了證明的角色。因此,尋求證明(尋找有效雜湊),就是礦工實際要做的事情。
獲得指定資料的一個雜湊值的過程,就叫做雜湊計算。一個雜湊,就是對所計算資料的一個唯一表示。對於一個雜湊函數,輸入任意大小的資料,它會輸出一個固定大小的雜湊值。下面是雜湊的幾個關鍵特性:
本質上雜湊是一個摘要演演算法。
雜湊函數被廣泛用於檢測資料的一致性。軟體提供者常常在除了提供軟體包以外,還會發布校驗和。當下載完一個檔案以後,你可以用雜湊函數對下載好的檔案計算一個雜湊,並與作者提供的雜湊進行比較,以此來保證檔案下載的完整性。
在區塊鏈中,雜湊被用於保證一個塊的一致性。雜湊演演算法的輸入資料包含了前一個塊的雜湊,因此使得不太可能(或者,至少很困難)去修改鏈中的一個塊:因為如果一個人想要修改前面一個塊的雜湊,那麼他必須要重新計算這個塊以及後面所有塊的雜湊。
位元幣使用 Hashcash ,一個最初用來防止垃圾郵件的工作量證明演演算法。它可以被分解為以下步驟:
取一些公開的資料(比如,如果是 email 的話,它可以是接收者的郵件地址;在位元幣中,它是區塊頭)
給這個公開資料新增一個計數器。計數器預設從 0 開始
將 data(資料) 和 counter(計數器) 組合到一起,獲得一個雜湊
檢查雜湊是否符合一定的條件:
因此,這是一個暴力演演算法:改變計數器,計算新的雜湊,檢查,增加計數器,計算雜湊,檢查,如此往復。這也是為什麼說它的計算成本很高,因為這一步需要如此反覆不斷地計算和檢查。
現在,讓我們來仔細看一下一個雜湊要滿足的必要條件。在原始的 Hashcash 實現中,它的要求是 “一個雜湊的前 20 位必須是 0”。在位元幣中,這個要求會隨著時間而不斷變化。因為按照設計,必須保證每 10 分鐘生成一個塊,而不論計算能力會隨著時間增長,或者是會有越來越多的礦工進入網路,所以需要動態調整這個必要條件。
為了闡釋這一演演算法,我從前一個例子(“I like donuts”)中取得資料,並且找到了一個前 3 個位元組是全是 0 的雜湊。
這裡我們實現一個簡易的區塊鏈,就不動態調節難度了,使用固定的難度。
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” 代表了區塊頭裡儲存的難度,也就是開頭有多少個 0。這裡的 16 指的是算出來的雜湊前 16 位必須是 0,如果用 16 進位製表示,就是前 6 位必須是 0,這一點從最後的輸出可以看出來。目前我們並不會實現一個動態調整目標的演演算法,所以將難度定義為一個全域性的常數即可。
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 所提到的計數器,它是一個密碼學術語。其他資料都是區塊頭的資料。我們需要把這些資料進行合併作為計算雜湊的原資料。
尋找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的上限。然後我們不斷迴圈尋找目標值,直到滿足難度要求。當然,如果難度設計得過高,有可能尋找不到,所以也需要判斷一下。所以我們再回圈內做了一下事:
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區塊鏈實現簡版工作量證明的詳細內容,更多關於python區塊鏈工作量證明的資料請關注it145.com其它相關文章!
相關文章
<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
综合看Anker超能充系列的性价比很高,并且与不仅和iPhone12/苹果<em>Mac</em>Book很配,而且适合多设备充电需求的日常使用或差旅场景,不管是安卓还是Switch同样也能用得上它,希望这次分享能给准备购入充电器的小伙伴们有所
2021-06-01 09:31:42
除了L4WUDU与吴亦凡已经多次共事,成为了明面上的厂牌成员,吴亦凡还曾带领20XXCLUB全队参加2020年的一场音乐节,这也是20XXCLUB首次全员合照,王嗣尧Turbo、陈彦希Regi、<em>Mac</em> Ova Seas、林渝植等人全部出场。然而让
2021-06-01 09:31:34
目前应用IPFS的机构:1 谷歌<em>浏览器</em>支持IPFS分布式协议 2 万维网 (历史档案博物馆)数据库 3 火狐<em>浏览器</em>支持 IPFS分布式协议 4 EOS 等数字货币数据存储 5 美国国会图书馆,历史资料永久保存在 IPFS 6 加
2021-06-01 09:31:24
开拓者的车机是兼容苹果和<em>安卓</em>,虽然我不怎么用,但确实兼顾了我家人的很多需求:副驾的门板还配有解锁开关,有的时候老婆开车,下车的时候偶尔会忘记解锁,我在副驾驶可以自己开门:第二排设计很好,不仅配置了一个很大的
2021-06-01 09:30:48
不仅是<em>安卓</em>手机,苹果手机的降价力度也是前所未有了,iPhone12也“跳水价”了,发布价是6799元,如今已经跌至5308元,降价幅度超过1400元,最新定价确认了。iPhone12是苹果首款5G手机,同时也是全球首款5nm芯片的智能机,它
2021-06-01 09:30:45