您當前的位置:首頁 > 文化

Python之區塊鏈入門,揭秘比特幣

作者:由 Python程式設計師 發表于 文化時間:2017-09-01

本文將簡單介紹區塊鏈(BlockChain)並用Python做一簡單實現。

什麼是區塊鏈

簡單來說,區塊鏈就是把加密資料(區塊)按照時間順序進行疊加(鏈)生成的永久、不可逆向修改的記錄。具體來說,它區塊鏈是由一串使用密碼學方法產生的資料塊組成的,每一個區塊都包含了上一個區塊的雜湊值(hash),從創始區塊(genesis block)開始連線到當前區塊,形成塊鏈。每一個區塊都確保按照時間順序在上一個區塊之後產生,否則前一個區塊的雜湊值是未知的。它是比特幣的一個重要概念。

特點

區塊鏈有如下特點:

去中心化:區塊鏈不依賴於某個中心節點,而是依賴於分散式的各個節點。

無須信任系統:區塊鏈中基於密碼學演算法,資料需要網路內其他使用者的批准,所以不需要一套第三方中介結構或信任機構背書。

不可篡改和加密安全性:區塊鏈採取單向雜湊演算法,同時每個新產生的區塊嚴格按照時間線形順序推進,時間的不可逆性導致任何試圖入侵篡改區塊鏈內資料 資訊的行為都很容易被追溯,導致被其他節點的排斥,從而可以限制相關不法行為。

以上特點使得區塊鏈在銀行、證券市場和金融等諸多領域有著越來越多的應用。

區塊鏈工作原理

區塊鏈式一系列加密的資料塊。這些區塊由一個包含元資料的區塊頭和緊跟其後的構成區塊主體的一長串交易組成。比特幣中的區塊結構如下:

Python之區塊鏈入門,揭秘比特幣

Python之區塊鏈入門,揭秘比特幣

區塊頭

區塊頭中包含了與區塊鏈中其它區塊中的連線資訊、時間戳和nonce等資訊,具體如下:

Python之區塊鏈入門,揭秘比特幣

Python之區塊鏈入門,揭秘比特幣

區塊識別符號

區塊有兩個標示符,一是區塊頭的雜湊值,二是區塊高度。區塊頭的雜湊值是透過SHA256演算法對區塊頭進行二次雜湊計算而得到的數字。區塊雜湊值可以唯一、明確地標識一個區塊,並且任何節點透過簡單地對區塊頭進行雜湊計算都可以獨立地獲取該區塊雜湊值。區塊高度是指該區塊在區塊鏈中的位置。區塊高度並不是唯一的識別符號。雖然一個單一的區塊總是會有一個明確的、固定的區塊高度,但反過來卻並不成立,一個區塊高度並不總是識別一個單一的區塊。兩個或兩個以上的區塊可能有相同的區塊高度,在區塊鏈裡爭奪同一位置。

瞭解了以上基礎後下面開始用Python實現一個簡單的區塊鏈。

區塊鏈的Python實現

一、定義區塊結構

In [16]:

# block。py

import hashlib

import uuid

class 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’。format(self。hash(), self。nonce)

以上就是一個區塊結構,這裡實現的是一個簡化版,沒有完全對應比特幣中的區塊。這裡的區塊包含一個唯一識別符號、父節點的雜湊值、nonce值和該區塊的內容欄位。可以看到一個區塊的雜湊值必須滿足一定的條件才是有效的,比如以0000開始。下面對這個區塊結構進行初始化。

In [37]:

# 建立一個內容為hello world的內容塊

block = Block(‘Hello World’)

block

Out[37]:

Block

以上一個區塊雖然建立完成,但其雜湊值不是有效的。

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。py

import hashlib

import uuid

class 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’。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’)

# 挖礦,迴圈直至找到合適的nonce

block。mine()

# 列印

block

Out[75]:

Block

至此,第一個有效的區塊生成完成,下面開始定義區塊鏈。

二、定義區塊鏈結構

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之區塊鏈入門

推薦免費影片教程:Python3爬蟲三大案例實戰分享:貓眼電影、今日頭條街拍美圖、淘寶美食 Python3爬蟲三大案例實戰分享

公眾號:Python愛好者社群(微信ID:python_shequ)

小編個人微信:tsdatajob ,來不急回覆的,可以加小編微信溝通,謝謝。

標簽: 區塊  self  hash  nonce  雜湊