?
區塊鏈技術被譽為信任的機器,它正在重塑金融、供應鏈、數字身份等眾多領域。但對于許多開發者來說,它仍然像一個神秘的黑盒子。今天,我們將拋開炒作的泡沫,深入技術本質,用大約100行Python代碼構建一個簡易的區塊鏈,并逐一解析其核心概念。
?
一、區塊鏈是什么?一個簡單的比喻
?
想象一個公共的記賬本( Ledger )。這個本子的每一頁( Block )都記錄著多條交易信息,并且每一頁的頁眉都包含了前一頁的摘要( Hash )。如果有人篡改了某一頁的內容,那么這一頁的摘要就會改變, subsequently 導致后續所有頁的頁眉信息都對不上,從而立刻被所有人發現。這個按時間順序首尾相連的記賬本,就是區塊鏈。
?
二、核心概念與代碼實現
?
我們將實現一個名為 SimpleBlockchain 的類,它包含以下核心功能:
?
1. 區塊結構 (Block Structure)
2. 哈希函數 (Hashing) - 保證數據不可篡改
3. 生成創世區塊 (Genesis Block)
4. 工作量證明 (Proof-of-Work) - 保證挖礦難度
5. 鏈式結構 (Chaining Blocks) - 通過哈希連接
?
讓我們開始寫代碼!
?
1. 導入依賴庫
?
我們主要需要兩個庫:hashlib 用于計算哈希,time 為區塊提供時間戳。
?
```python
import hashlib
import time
```
?
2. 定義區塊結構
?
每個區塊都包含一些關鍵信息:索引、時間戳、數據、前一個區塊的哈希、當前區塊的隨機數(Nonce)和自身的哈希。
?
```python
class Block:
? ? def __init__(self, index, timestamp, data, previous_hash):
? ? ? ? self.index = index
? ? ? ? self.timestamp = timestamp
? ? ? ? self.data = data # 在真實區塊鏈中,這通常是交易列表的Merkle根
? ? ? ? self.previous_hash = previous_hash
? ? ? ? self.nonce = 0 # 用于工作量證明的隨機數
? ? ? ? self.hash = self.calculate_hash() # 計算當前區塊的哈希值
?
? ? def calculate_hash(self):
? ? ? ? # 將區塊的所有信息組合成一個字符串,并計算其SHA-256哈希值
? ? ? ? block_string = f"{self.index}{self.timestamp}{self.data}{self.previous_hash}{self.nonce}".encode()
? ? ? ? return hashlib.sha256(block_string).hexdigest()
```
?
代碼解析:
?
· previous_hash:這是鏈式結構的核心!它指向上一個區塊,從而形成了鏈。任何對舊區塊的修改都會導致其哈希變化,進而破壞整個后續鏈。
· calculate_hash 方法:它接收區塊的所有屬性(包括 nonce),生成一個唯一的、固定長度的“數字指紋”(哈希值)。SHA-256算法保證了計算的單向性,即極易驗證但極難破解。
?
3. 創建區塊鏈類
?
區塊鏈類負責管理鏈,提供添加新區塊的方法。
?
```python
class SimpleBlockchain:
? ? def __init__(self):
? ? ? ? self.chain = [self.create_genesis_block()] # 初始化鏈,并創建創世區塊
? ? ? ? self.difficulty = 4 # 工作量證明的難度,表示哈希值必須以多少個'0'開頭
?
? ? def create_genesis_block(self):
? ? ? ? # 創世區塊是第一個區塊,沒有前一個區塊,所以previous_hash設為0
? ? ? ? return Block(0, time.time(), "Genesis Block", "0")
?
? ? def get_latest_block(self):
? ? ? ? return self.chain[-1]
```
?
代碼解析:
?
· create_genesis_block:區塊鏈的第一個區塊是特殊的,它沒有前任,必須被硬編碼到系統中。
· difficulty:這是一個動態調整的參數,用來控制“挖礦”(生成新區塊)的速度。難度值越大,找到有效哈希所需的計算時間就越長。
?
4. 實現工作量證明 (Proof-of-Work)
?
這是區塊鏈(尤其是比特幣)的靈魂所在。礦工需要通過大量計算找到一個滿足特定條件的 nonce 值。
?
```python
? ? def proof_of_work(self, block):
? ? ? ? # 目標:找到一個nonce,使得區塊的哈希值的前difficulty位是0
? ? ? ? target = '0' * self.difficulty
? ? ? ? while block.hash[:self.difficulty] != target:
? ? ? ? ? ? block.nonce += 1 # 不斷嘗試新的nonce值
? ? ? ? ? ? block.hash = block.calculate_hash() # 重新計算哈希
? ? ? ? print(f"Block mined: {block.hash}")
? ? ? ? return block
```
?
代碼解析:
?
· 礦工(proof_of_work 函數)不斷地改變 nonce 的值,并重新計算區塊哈希。
· 只有當計算出的哈希值的前 difficulty 位都是 ‘0’ 時,才算成功。
· 這個過程極其耗時且耗電,但驗證卻非常容易(只需計算一次哈希并檢查前導零)。這就是“工作量證明”的含義——它證明了礦工投入了真實的計算資源。
?
5. 添加新區塊
?
現在,我們可以將挖礦成功后的區塊添加到鏈上。
?
```python
? ? def add_block(self, new_block):
? ? ? ? new_block.previous_hash = self.get_latest_block().hash # 設置新區塊的previous_hash
? ? ? ? new_block = self.proof_of_work(new_block) # 執行挖礦!
? ? ? ? self.chain.append(new_block) # 將挖礦后的有效區塊添加到鏈上
?
? ? def is_chain_valid(self):
? ? ? ? for i in range(1, len(self.chain)):
? ? ? ? ? ? current_block = self.chain[i]
? ? ? ? ? ? previous_block = self.chain[i-1]
? ? ? ? ? ? # 檢查1:當前區塊存儲的哈希值是否真的等于它計算出的哈希值?
? ? ? ? ? ? if current_block.hash != current_block.calculate_hash():
? ? ? ? ? ? ? ? print(f"Data tampered in block {current_block.index}!")
? ? ? ? ? ? ? ? return False
? ? ? ? ? ? # 檢查2:當前區塊的previous_hash是否等于上一個區塊的哈希值?
? ? ? ? ? ? if current_block.previous_hash != previous_block.hash:
? ? ? ? ? ? ? ? print(f"Chain broken between block {previous_block.index} and {current_block.index}!")
? ? ? ? ? ? ? ? return False
? ? ? ? return True
```
?
代碼解析:
?
· add_block:在添加區塊前,必須先進行耗時的挖礦過程。這保證了區塊不能隨意被添加,確保了網絡的安全性和一致性。
· is_chain_valid:驗證區塊鏈的完整性。它會遍歷整個鏈,檢查每個區塊的哈希是否正確,以及區塊間的鏈接是否未被破壞。任何微小的篡改都會導致 calculate_hash() 的結果與存儲的 hash 不匹配。
?
三、測試我們的迷你區塊鏈
?
讓我們運行一下,看看它的效果。
?
```python
# 初始化我們的區塊鏈
my_blockchain = SimpleBlockchain()
?
print("Mining block 1...")
my_blockchain.add_block(Block(1, time.time(), "Alice pays Bob 1 BTC", ""))
?
print("Mining block 2...")
my_blockchain.add_block(Block(2, time.time(), "Bob pays Charlie 0.5 BTC", ""))
?
# 打印所有區塊
for block in my_blockchain.chain:
? ? print(f"Index: {block.index}")
? ? print(f"Hash: {block.hash}")
? ? print(f"Previous Hash: {block.previous_hash}")
? ? print(f"Data: {block.data}")
? ? print(f"Nonce: {block.nonce}\n")
?
# 驗證區塊鏈是否有效
print(f"Is blockchain valid? {my_blockchain.is_chain_valid()}")
?
# 嘗試篡改數據!
print("\nAttempting to tamper with data...")
my_blockchain.chain[1].data = "Alice pays Bob 100 BTC" # 修改第一個區塊的數據
# 由于數據被修改,它的哈希值變了,但后續區塊的previous_hash指向的還是舊的、錯誤的哈希。
print(f"Is blockchain valid after tampering? {my_blockchain.is_chain_valid()}") # 輸出:False
```
?
輸出結果示例:
?
```
Mining block 1...
Block mined: 0000a1b2c3d4...(哈希值以4個0開頭)
Mining block 2...
Block mined: 0000e5f6g7h8...(哈希值以4個0開頭)
?
Index: 0 (Genesis Block)
Hash: 89ab...
Previous Hash: 0
...
?
Index: 1
Hash: 0000a1b2c3d4... # 以0000開頭
Previous Hash: 89ab... # 指向創世區塊的哈希
Data: Alice pays Bob 1 BTC
Nonce: 68452 # 一個很大的數字,說明礦工嘗試了68452次才找到有效的nonce
?
...
?
Is blockchain valid? True
Attempting to tamper with data...
Data tampered in block 1! # 驗證函數發現了數據被篡改
Is blockchain valid after tampering? False
```
?
四、總結與展望
?
通過這不到100行的代碼,我們實現了一個具備核心功能的區塊鏈:
?
· 不可篡改性:通過哈希函數保證,修改數據會立即使哈希失效。
· 鏈式結構:通過 previous_hash 將區塊按時間順序鏈接起來。
· 工作量證明:通過挖礦機制保證網絡的安全性和去中心化共識。
?
當然,這只是一個極其簡化的模型。一個生產級的區塊鏈(如比特幣、以太坊)要復雜得多,它還包括:
?
· 點對點網絡:節點如何發現和通信。
· 交易模型:UTXO(比特幣)或賬戶余額(以太坊)。
· ** Merkle 樹**:高效地驗證大量交易的存在性。
· 共識算法:PoW(工作量證明)之外的PoS(權益證明)等。
· 智能合約:在區塊鏈上運行的自動化代碼。
?
?