編者按:比特幣相信無人不知,。區(qū)塊鏈也許也有很多人聽說過,,但是區(qū)塊鏈究竟是怎么回事,?它的工作機制又是怎樣的,?為什么說挖礦消耗的電力居然要比某些國家消耗的電力都要多?asthasr試圖用簡單的程序來說明清楚,,原文發(fā)表在其個人博客上,,標(biāo)題是:How Blockchains Work
很可能你已經(jīng)知道區(qū)塊鏈是什么東西了,。畢竟,,一個比特幣的價格一度曾超過47000美元的。不過,,這篇文章要講的不是商業(yè)層面的東西,,也不是要探討比特幣是不是投機泡沫。我只是想解釋一下它的機制,。
基礎(chǔ):哈希與賬本
首先,,哈希算法將某給定字符串轉(zhuǎn)換為不可預(yù)測的,固定長度字符串(摘要)的一種方法,。
哈希算法將文本生成長度固定的摘要
以下是用來演示哈希算法的一小段Python 程序:
#!/usr/bin/env python3
from argparse import ArgumentParser
from hashlib import md5
#將輸入的string參數(shù)生成十六進制摘要
def hash_string(string):
hash = md5()
hash.update(string.encode(“utf-8”))
return hash.hexdigest()
if __name__ == “__main__”:
parser = ArgumentParser()
parser.add_argument(“STRING”, help=”The string to be hashed”)
args = parser.parse_args()
print(hash_string(args.STRING))
用不同的字符串參數(shù)運行這段程序就能得到該參數(shù)的摘要(以下“ninjia”和“samurai”的摘要):
$ ./hash ninja
3899dcbab79f92af727c2190bbd8abc5
$ ./hash samurai
99b1983cf3ee09bbaf6f43ac7b4c8748
這種類型的哈希可用來校驗密碼——你可以檢查密碼是否匹配,,而不需要把密碼本身保存起來,。(注)
區(qū)塊鏈是一種賬本:這種賬本會逐漸添加條目。而哈希的作用是可以對添加到賬本里面的消息的次序和內(nèi)容進行保護,。
區(qū)塊鏈捕捉之前的摘要以及當(dāng)前的消息從而生成一個摘要的圖解,。
下面是一個簡單的實現(xiàn):
def hash_ledger_entry(string, previous_digest=None):
“””對字符串及賬本之前條目的摘要(如果有的話)進行哈希運算”””
hash = md5(string.encode(“utf-8”))
if previous_digest:
hash.update(previous_digest.encode(“utf-8”))
return hash.hexdigest()
def generate_ledger(*strings):
“””生成含一系列字符串的賬本的記錄”””
digest = None
for string in strings:
digest = hash_ledger_entry(string, digest)
yield digest, string
if __name__ == “__main__”:
parser = ArgumentParser()
parser.add_argument(“STRINGS”, help=”The ledger entries”, nargs=”+”)
args = parser.parse_args()
for digest, string in generate_ledger(*args.STRINGS):
print(f”{digest}\t{string}”)
給這一腳本提供一組字符串的話,將會生成一個唯一且有序的賬本:
$ ./hash ninja samurai
3899dcbab79f92af727c2190bbd8abc5 ninja
6bf8d2cadde40af53d7f0fef95d4ec2c samurai
這些經(jīng)過哈希的賬本是可防篡改的,,因為后面條目的摘要取決于前面的條目,。修改或添加條目會改變之后的條目的摘要。
$ ./hash ninja pirate samurai
3899dcbab79f92af727c2190bbd8abc5 ninja
7ec21dcf528e12036b04774754ecc4e0 pirate 假設(shè)這里被黑進了一條記錄636730d86709d03fed9ba64f84fc9be6 samurai 可注意到這條的摘要已經(jīng)跟前面的不一樣了
我們還可以在賬本里面添加一條已知的結(jié)束記錄,,從而保護最后那條記錄不被篡改:
$ ./hash ninja pirate samurai
3899dcbab79f92af727c2190bbd8abc5 ninja
7ec21dcf528e12036b04774754ecc4e0 pirate
636730d86709d03fed9ba64f84fc9be6 samurai
b233d566fe677d394aafb5eaf149e453 END
驗證
要想對賬本進行驗證,,可以對事務(wù)進行重放,并確保在每一個步驟都能得到相同的哈希值:
our_digest = None
for line in fileinput.input():
#將摘要和文本拆出來
file_digest, word = line.strip().split(“\t”)
#計算文本的摘要
our_digest = hash_ledger_entry(word, our_digest)
#將計算結(jié)果跟存進賬本里面的摘要進行比較
if our_digest != file_digest:
sys.exit(f”The digest for {word} does not match.”)
print(“All entries match.”)
通過利用防篡改的賬本,,鑒于其中的每個條目都要取決于之前的條目,,我們就有效地實現(xiàn)了一個非常簡單的區(qū)塊鏈。不過,,這跟真正的區(qū)塊鏈還是有所不同,;為了實現(xiàn)真正的區(qū)塊鏈,我們需要……
無權(quán)威證明
比特幣的新穎之處在于它是一個沒有所有者的分布式系統(tǒng),。這就是狂熱分子所聲稱的區(qū)塊鏈無需信任的意思所在:很多的“礦工”并不是像銀行這樣的中央權(quán)威,,他們會互相競爭,看誰能夠成功地向區(qū)塊鏈寫入一條新消息,。他們通過工作量證明算法的手段來做到這一點,,我們也可以在我們的賬本里面去實現(xiàn)。
# 把下面這行加入你的import里面.
from secrets import token_bytes
def hash_ledger_entry_with_salt(salt, string, previous_digest=None):
“””對字符串及賬本之前條目的摘要(如果有的話)進行哈希運算.”””
hash = md5(string.encode(“utf-8”))
hash.update(salt)
if previous_digest:
hash.update(previous_digest.encode(“utf-8”))
return hash.hexdigest()
def generate_ledger(difficulty, *strings):
# Difficulty決定了我需要在摘要的前面有多少個0.
prefix = “0” * difficulty
digest = None
previous_digest = None
for string in strings:
# 添加入隨機的salt,,反復(fù)對一個字符串進行哈希運算,,直到滿足prefix所確定的0的數(shù)量.
while digest is None or not digest.startswith(prefix):
salt = token_bytes(16)
digest = hash_ledger_entry_with_salt(salt, string, previous_digest)
# 跟之前一樣,要yield回摘要和條目,,但也需要salt
# 否則的話,,沒法重演那些記錄并加以驗證
yield digest, salt.hex(), string
previous_digest = digest
digest = None
yield hash_ledger_entry_with_salt(salt, “END”, previous_digest), salt, “END”
if __name__ == “__main__”:
parser = ArgumentParser()
parser.add_argument(
“DIFFICULTY”, help=”The difficulty of confirming a ledger entry.”, type=int
)
parser.add_argument(“STRINGS”, help=”The ledger entries”, nargs=”+”)
args = parser.parse_args()
for digest, salt, string in generate_ledger(args.DIFFICULTY, *args.STRINGS):
print(f”{digest}\t{salt}\t{string}”)
這個新的程序會接受一個額外的參數(shù),難度,,并嘗試生成一個鹽值,,這個值又會生成一個跟預(yù)期的0的數(shù)量匹配的哈希值:
$ ./hash 5 ninja pirate samurai
00000ad72553509e6c197e45ab7fa436 af0dce7ac4c87c2b9d9eafb6561c09f4 ninja
000000f556426cfa894ba2ce57383b1d b9d51e0e8ea977ba004e7c30be757144 pirate
000006373b2b336d6dac403a5fa90a73 dd9c6ad89f5014a0901bcb142e04e28b samurai
fa35b5a39bc0318015620684d60a27f0 dd9c6ad89f5014a0901bcb142e04e28b END
“挖礦”的過程可能需要大量計算。這個例子平均需要大約 250 萬次嘗試,。所以比特幣挖礦消耗的帶能力比很多國家消耗的電力都要多:在“真正的”區(qū)塊鏈上,,礦工要計算和重新計算每個被開采出來的比特幣的千萬億個哈希值。
注:請注意,,實際應(yīng)用不應(yīng)該拿 md5 用于此目的,。本文選擇md5是出于它生成摘要的簡潔性,但md5并不安全,。
譯者:boxi,。
免責(zé)聲明:本文來自網(wǎng)絡(luò)收錄或投稿,觀點僅代表作者本人,不代表芒果財經(jīng)贊同其觀點或證實其描述,,版權(quán)歸原作者所有,。轉(zhuǎn)載請注明出處:http://lequren.com/1097673.html
溫馨提示:投資有風(fēng)險,入市須謹慎,。本資訊不作為投資理財建議,。