本文將簡單介紹區塊鏈(BlockChain)並用Python做一簡單實現。 什麼是區塊鏈
簡單來說,區塊鏈就是把加密資料(區塊)按照時間順序進行疊加(鏈)產生的永久、無法復原向修改的記錄。具體來說,它區塊鏈是由一串使用密碼學方法產生的資料區塊組成的,每一個區塊都包含了上一個區塊的雜湊值(hash),從創始區塊(genesis block)開始串連到當前區塊,形成塊鏈。每一個區塊都確保按照時間順序在上一個區塊之後產生,否則前一個區塊的雜湊值是未知的。它是比特幣的一個重要概念。
特點
區塊鏈有如下特點: 去中心化:區塊鏈不依賴於某個中心節點,而是依賴於分布式的各個節點。 無須信任系統:區塊鏈中基於密碼學演算法,資料需要網路內其他使用者的批准,所以不需要一套第三方中介結構或信任機構背書。 不可篡改和加密安全性:區塊鏈採取單向雜湊演算法,同時每個新產生的區塊嚴格按照時間軸形順序推進,時間的無法復原性導致任何試圖入侵篡改區塊鏈內資料 資訊的行為都很容易被追溯,導致被其他節點的排斥,從而可以限制相關不法行為。
以上特點使得區塊鏈在銀行、證券市場和金融等諸多領域有著越來越多的應用。 區塊鏈工作原理
區塊鏈式一系列加密的資料區塊。這些區塊由一個包含中繼資料的區塊頭和緊跟其後的構成區塊主體的一長串交易組成。比特幣中的區塊結構如下:
區塊頭
區塊頭中包含了與區塊鏈中其它區塊中的串連資訊、時間戳記和nonce等資訊,具體如下:
區塊標識符
區塊有兩個標示符,一是區塊頭的雜湊值,二是區塊高度。區塊頭的雜湊值是通過SHA256演算法對區塊頭進行二次雜湊計算而得到的數字。區塊雜湊值可以唯一、明確地標識一個區塊,並且任何節點通過簡單地對區塊頭進行雜湊計算都可以獨立地擷取該區塊雜湊值。區塊高度是指該區塊在區塊鏈中的位置。區塊高度並不是唯一的標識符。雖然一個單一的區塊總是會有一個明確的、固定的區塊高度,但反過來卻並不成立,一個區塊高度並不總是識別一個單一的區塊。兩個或兩個以上的區塊可能有相同的區塊高度,在區塊鏈裡爭奪同一位置。
瞭解了以上基礎後下面開始用Python實現一個簡單的區塊鏈。 區塊鏈的Python實現
一、定義區塊結構
In [16]:
# block.pyimport hashlibimport uuidclass Block(object): def __init__(self, data=None, previous_hash=None): self.identifier = uuid.uuid4().hex # 產生唯一標示 self.nonce = None # nonce值 self.data = data # 區塊內容 self.previous_hash = previous_hash # 父節點雜湊值 def hash(self, nonce=None): ''' 計算區塊的雜湊值 ''' message = hashlib.sha256() message.update(self.identifier.encode('utf-8')) message.update(str(nonce).encode('utf-8')) message.update(str(self.data).encode('utf-8')) message.update(str(self.previous_hash).encode('utf-8')) return message.hexdigest() def hash_is_valid(self, the_hash): ''' 校正區塊雜湊值有否有效 ''' return the_hash.startswith('0000') def __repr__(self): return 'Block<Hash: {}, Nonce: {}>'.format(self.hash(), self.nonce)
以上就是一個區塊結構,這裡實現的是一個簡化版,沒有完全對應比特幣中的區塊。這裡的區塊包含一個唯一識別碼、父節點的雜湊值、nonce值和該區塊的內容欄位。可以看到一個區塊的雜湊值必須滿足一定的條件才是有效,比如以0000開始。下面對這個區塊結構進行初始化。
In [37]:
# 建立一個內容為hello world的內容塊block = Block('Hello World')block
Out[37]:
Block<Hash: 238a65a101c8829d7fc406eb78a71cfc19ad702b437e2c1be8d9061ddb81e900, Nonce: None>
以上一個區塊雖然建立完成,但其雜湊值不是有效。
In [38]:
block.hash_is_valid(block.hash())
Out[38]:
False
改變nonce的值就可以得到一個新的雜湊值。
In [39]:
block.hash(1)
Out[39]:
'a6431938ba10270dfcfdf7a2371312446914fedadf79632c2c0adb3b463f4838'
雜湊值更新了,但還不是有效雜湊值。為了得到有效雜湊值,是一個不斷更新nonce值的過程,或者說一個挖礦(mine)過程。下面添加一個mine函數用來得到一個合適的nonce值。
In [78]:
# block.pyimport hashlibimport uuidclass Block(object): def __init__(self, data=None, previous_hash=None): self.identifier = uuid.uuid4().hex # 產生唯一標示 self.nonce = None # nonce值 self.data = data # 區塊內容 self.previous_hash = previous_hash # 父節點雜湊值 def hash(self, nonce=None): ''' 計算區塊的雜湊值 ''' message = hashlib.sha256() message.update(self.identifier.encode('utf-8')) message.update(str(nonce).encode('utf-8')) message.update(str(self.data).encode('utf-8')) message.update(str(self.previous_hash).encode('utf-8')) return message.hexdigest() def hash_is_valid(self, the_hash): ''' 校正區塊雜湊值有否有效 ''' return the_hash.startswith('0000') def __repr__(self): return 'Block<Hash: {}, Nonce: {}>'.format(self.hash(self.nonce), self.nonce) ''' 新增挖礦函數 ''' def mine(self): # 初始化nonce為0 cur_nonce = self.nonce or 0 # 迴圈直到產生一個有效雜湊值 while True: the_hash = self.hash(nonce=cur_nonce) if self.hash_is_valid(the_hash): # 如果產生的雜湊值有效 self.nonce = cur_nonce # 保持當前nonce值 break # 並退出 else: cur_nonce += 1 # 若當前雜湊值無效,更新nonce值,進行加1操作
In [75]:
block = Block('Hello World')# 挖礦,迴圈直至找到合適的nonceblock.mine()# 列印block
Out[75]:
Block<Hash: 000087359d5264153d624556f0a0c6f25cba06e453975c1c02587862e823911b, Nonce: 64751>
至此,第一個有效區塊產生完成,下面開始定義區塊鏈。
二、定義區塊鏈結構
In [81]:
class BlockChain(object): def __init__(self): self.head = None # 指向最新的一個區塊 self.blocks = {} # 包含所有區塊的一個字典 ''' 添加區塊函數 ''' def add_block(self, new_block): previous_hash = self.head.hash(self.head.nonce) if self.head else None new_block.previous_hash = previous_hash self.blocks[new_block.identifier] = { 'block': new_block, 'previous_hash': previous_hash, 'previous': self.head, } self.head = new_block def __repr__(self): num_existing_blocks = len(self.blocks) return 'Blockchain<{} Blocks, Head: {}>'.format( num_existing_blocks, self.head.identifier if self.head else None )
定義好區塊鏈結構後,下面就開始初始化一條區塊鏈。
In [82]:
# 初始化chain = BlockChain()# 列印chain
Out[82]:
Blockchain<0 Blocks, Head: None>
In [83]:
# 添加區塊chain.add_block(block)# 列印chain
Out[83]:
Blockchain<1 Blocks, Head: 364c0cf963384ca28a2763499a140405>
In [84]:
# 添加更多的區塊for i in range(6): new_block = Block(i) new_block.mine() chain.add_block(new_block) # 列印chain
Out[84]:
Blockchain<7 Blocks, Head: e7cb24ec7acd42a4aaebe7faee9e0713>
以上就是一個簡單區塊鏈,後面還會涉及到區塊鏈的有效性。當區塊鏈中一個區塊被改變後,這個區塊的雜湊就會改變,從而影響到這塊區塊之後的區塊,致使這個區塊鏈不再有效。這些將在後續繼續深入。 作者:Walker Python愛好者社區專欄作者 授權原創發布,請勿轉載,謝謝。
出處: Python之區塊鏈入門