首頁 > 軟體

從0編寫區塊鏈之用python解釋區塊鏈最基本原理

2022-02-14 19:01:12

人工智慧和區塊鏈誕生至今已經有了十幾年,當這些技術出現時,人們都說他們會改變世界,但至今為止,這兩項技術對現實的影響依然有限。從技術上看人工智慧的原理其實是從大量資料中尋找規律或模式,但區塊鏈的技術原理是什麼呢?在我看來區塊鏈的原理一直處於雲裡霧裡,有很多近乎玄學的解釋將其籠罩,有人從經濟學解釋,有人從社會學解釋,從”人文“角度解釋的區塊鏈總是過於誇大其詞,這些說法中往往又包含不良用心。

由此我想去蕪存真,我們不用關心區塊鏈如何”改變世界“,我們就從純技術角度去探討,其實區塊鏈和人工智慧一樣,從技術的角度看去,他們都有著極為美妙的設計思想,這些設計的美妙就像唐詩宋詞,就像畢加索的話,如果我們沒有去欣賞它的美,那豈不可惜。相比於人工智慧,我認為區塊鏈在技術上更容易被普通人觸碰,因為前者需要大量的資料和算力,而後者只要我們掌握其技術原理就能參與其中,不需要太高的硬體門檻。

話不多說,我們看看如何用python程式碼把最基本的區塊鏈原理編寫出來。首先我們看區塊鏈的資料結構,它包含三部分資訊,一是用於標誌自己的id,它是一個整數,第二個是用於記錄前一個區塊的id,也是一個整數,由於區塊用於記錄資訊,因此它還包含一個欄位,我們用history來表示,這個欄位用來記錄當前發生了的資訊,區塊鏈最大的作用就是讓這段資訊可驗證而且不可更改,我們先看資料結構的定義,先建立檔案block.:

class Block:
    def __init__(self):
        self.id = None
        self.history = None
        self.parent_id = None

接下來我們看看區塊如何行成”鏈“,同時如何記錄資訊。假設我們想要記錄這麼一個事件:張三想跟李四用一百塊買三條魚,李四收到一百塊後給了張三三條魚”,那麼我們可以使用下面程式碼用區塊鏈進行記錄,建立main.py,然後給出如下程式碼:

from block import *

block_A = Block()
block_A.id = 1
block_A.history = '張三想要三條魚'
block_B = Block()
block_B.id = 2
block_B.parent_id = block_A.id
block_B.history = '張三跟李四買三條魚'
block_C = Block()
block_C.id = 3
block_C.parent_id = block_B.id
block_C.history = '張三給李四一百塊'
block_D = Block()
block_D.id = 3
block_D.parent_id = block_B.id
block_D.history = '李四收到張三一百塊'
block_E = Block()
block_E.id = 3
block_E.parent_id = block_B.id
block_E.history = '李四給張三三條魚'

從程式碼上看不同區塊之間通過parent_id形成了前後連線關係,這就是區塊鏈中的“鏈”,但現在還有一個嚴重問題,那就是資訊可以更改,假設張三想來著,他把block_E裡面的history改成李四給張三兩條魚,然後找李四算賬那怎辦,或者李四想賴賬,把block_D中的history改成“李四收到張三五十塊”,然後又找張三要錢,那怎麼辦。

為了確保資訊不被更改,我們需要對每個區塊的內容進行加密或者雜湊,因此上面程式碼修改如下:

# This is a sample Python script.

# Press ⌃R to execute it or replace it with your code.
# Press Double ⇧ to search everywhere for classes, files, tool windows, actions, and settings.
from block import *
import hashlib
import json
block_A = Block()
block_A.id = 1
block_A.history = '張三想要三條魚'
block_B = Block()
block_B.id = 2
block_B.parent_id = block_A.id
block_B.history = '張三跟李四買三條魚'
block_B.parent_hash = hashlib.sha256(json.dumps(block_A.__dict__).encode('utf-8')).hexdigest()
block_C = Block()
block_C.id = 3
block_C.parent_id = block_B.id
block_C.history = '張三給李四一百塊'
block_C.parent_hash = hashlib.sha256(json.dumps(block_B.__dict__).encode('utf-8')).hexdigest()
block_D = Block()
block_D.id = 4
block_D.parent_id = block_C.id
block_D.history = '李四收到張三一百塊'
block_D.parent_hash = hashlib.sha256(json.dumps(block_C.__dict__).encode('utf-8')).hexdigest()
block_E = Block()
block_E.id = 5
block_E.parent_id = block_B.id
block_E.history = '李四給張三三條魚'
block_E.parent_hash = hashlib.sha256(json.dumps(block_D__dict__).encode('utf-8')).hexdigest()

有了雜湊,如何任何一個區塊被修改,那麼當前區塊和後續區塊的雜湊都得修改,例如李四把block_C的history改成“張三給李四五十塊”,那麼我們看到李四必須要把block_C到block_E的雜湊全部改了,如果這條鏈很長的話,李四改起來就非常吃力。同時為了確保資訊的可靠性,
張三和李四需要把上面的區塊鏈傳送給其他一百個人進行儲存,這樣一來張三或李四想要賴賬那就更加困難,因為有一百個見證者。

區塊鏈資訊記錄的特點是隻增不刪,因此張三想要賴賬的話,他只能在上面基礎上再增加一個區塊,也就是block_F, 裡面的history寫上了“張三收到李四兩條魚”,然後將這個區塊發給其他100個人,為了防止隨意新增區塊造成資訊混亂的情況,在區塊鏈中有一個專門的角色負責將新增的區塊新增到現有的區塊鏈上,這個角色拿到區塊資料後,,在不考慮parent_hash欄位的情況下將資料序列化,接著找到一個特定字串,這個字串必須滿足給定要求,那就是它與區塊序列化的資料合併後,算出來的雜湊值必須以5個0開頭,我們從程式碼上看看這是什麼意思:

#proof-of-work
block_F = Block()
block_F.id = 6
block_E.parent_id = block_E.id
block_E.history = '李四給張三三條魚'
#注意我們這裡沒有設定parent_hash欄位
block_F_serialized = json.dumps(block_F.__dict__).encode('utf-8')
print(block_F_serialized)
for i in range(10000000):
    proof_of_work = str(i).encode('utf-8')
    result = hashlib.sha256(block_F_serialized + proof_of_work).hexdigest()
    if result[:5] == '00000': #雜湊結果只有以5個0開頭才能新增區塊到公鏈
        print(proof_of_work)
        print(result)
        break 
    #找到特定字串後獲取回報,所謂挖礦就是幹這個事情

上面程式碼執行後所得結果為:

b'{"id": 6, "history": null, "parent_id": null, "parent_hash": null}'
b'553448'
0000034ba1dabbf794212082b47a6bcc98cb33eed86d363993270ca58e243bb9

也就是說特定字串內容為"553448",它能使得新區塊內容和它結合後算出來的雜湊以5個0開頭,專門負責給區塊查詢這種字串的角色就叫“礦工”,這個查詢過程就叫挖礦,一旦找到這個特定字串後他就能獲取回報,也就是加密貨幣。

現在我們實現了資料的修改很困難,同時區塊的新增也需要付出一定成本,但假設李四就是拼了老命也想把以前記錄的資訊修改掉,併為此願意付出一切代價,假設當前區塊鏈有1000個資料塊,他想修改第一個塊記錄的資訊,於是他修改了後面999個資料塊的資料,但原始資料被其他人掌握著,因此他自己修改的資料就不會被採納。由於區塊鏈資料被分佈儲存在不同地方,於是在某項地方資料可能會被修改,這樣就會出現資料不一致的情況,區塊鏈還有一個重要任務就是在這種情況下達成共識。

同時當有新的區塊需要加入公鏈時,我們需要將新增區塊通過廣播的方式通知所有人,於是就有個問題,那就是有些人較早獲得通知,有些獲得通知較晚,更有可能你會同時收到多個訊息,假設現在公鏈上最後一個訊息編號為5,此時你同時收到了兩個訊息東邊發來的訊息為history:王五想跟李四買一斤蝦;西邊發來的訊息為history:李六想跟張三買兩條魚,那麼我們應該將哪個訊息作為編號6呢,此時的做法是先等等,如果過了一會西邊發來了5條訊息,同時東邊只發來2條訊息,那麼就把訊息少的拋棄,將訊息多的經過處理後新增到公鏈。

通過選擇資料多的新增到公鏈有個好處就是讓資料的修改變得幾乎不可能,例如李四辛辛苦苦花了半小時修改了999個區塊,然後想要廣播給其他人,但是很可能這段時間內有10000個新區塊生成,於是他修改的999個區塊就會被丟棄掉,這樣他就無法進行任何修改。這個過程其實涉及到非常複雜的分散式計算理論,我們無法簡單使用程式碼實現。

區塊鏈的設計思想非常偉大,它集合了很多智慧的結晶,例如加密演演算法,分散式演演算法,心理學,經濟學等,由於它跨越領域太多,這也是它特別“玄學”的原因,我們後面僅從技術的角度進行思考,看看區塊鏈採用的演演算法原理,同時也逐步探討如何基於區塊鏈的基礎上進行應用開發。

到此這篇關於從0編寫區塊鏈之用python解釋區塊鏈最基本原理的文章就介紹到這了,更多相關python解釋區塊鏈內容請搜尋it145.com以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援it145.com!


IT145.com E-mail:sddin#qq.com