Python學(xué)習(xí)入門(mén)之區(qū)塊鏈詳解
前言
本文將給大家簡(jiǎn)單介紹關(guān)于區(qū)塊鏈(BlockChain)的相關(guān)知識(shí),并用Python做一簡(jiǎn)單實(shí)現(xiàn)。下面話不多說(shuō),來(lái)一起看看詳細(xì)的介紹:
什么是區(qū)塊鏈
簡(jiǎn)單來(lái)說(shuō),區(qū)塊鏈就是把加密數(shù)據(jù)(區(qū)塊)按照時(shí)間順序進(jìn)行疊加(鏈)生成的永久、不可逆向修改的記錄。具體來(lái)說(shuō),它區(qū)塊鏈?zhǔn)怯梢淮褂妹艽a學(xué)方法產(chǎn)生的數(shù)據(jù)塊組成的,每一個(gè)區(qū)塊都包含了上一個(gè)區(qū)塊的哈希值(hash),從創(chuàng)始區(qū)塊(genesis block)開(kāi)始連接到當(dāng)前區(qū)塊,形成塊鏈。每一個(gè)區(qū)塊都確保按照時(shí)間順序在上一個(gè)區(qū)塊之后產(chǎn)生,否則前一個(gè)區(qū)塊的哈希值是未知的。它是比特幣的一個(gè)重要概念。
特點(diǎn)
區(qū)塊鏈有如下特點(diǎn):
- 去中心化:區(qū)塊鏈不依賴(lài)于某個(gè)中心節(jié)點(diǎn),而是依賴(lài)于分布式的各個(gè)節(jié)點(diǎn)。
- 無(wú)須信任系統(tǒng):區(qū)塊鏈中基于密碼學(xué)算法,數(shù)據(jù)需要網(wǎng)絡(luò)內(nèi)其他用戶(hù)的批準(zhǔn),所以不需要一套第三方中介結(jié)構(gòu)或信任機(jī)構(gòu)背書(shū)。
- 不可篡改和加密安全性:區(qū)塊鏈采取單向哈希算法,同時(shí)每個(gè)新產(chǎn)生的區(qū)塊嚴(yán)格按照時(shí)間線形順序推進(jìn),時(shí)間的不可逆性導(dǎo)致任何試圖入侵篡改區(qū)塊鏈內(nèi)數(shù)據(jù) 信息的行為都很容易被追溯,導(dǎo)致被其他節(jié)點(diǎn)的排斥,從而可以限制相關(guān)不法行為。
以上特點(diǎn)使得區(qū)塊鏈在銀行、證券市場(chǎng)和金融等諸多領(lǐng)域有著越來(lái)越多的應(yīng)用。
區(qū)塊鏈工作原理
區(qū)塊鏈?zhǔn)揭幌盗屑用艿臄?shù)據(jù)塊。這些區(qū)塊由一個(gè)包含元數(shù)據(jù)的區(qū)塊頭和緊跟其后的構(gòu)成區(qū)塊主體的一長(zhǎng)串交易組成。比特幣中的區(qū)塊結(jié)構(gòu)如下:
區(qū)塊頭
區(qū)塊頭中包含了與區(qū)塊鏈中其它區(qū)塊中的連接信息、時(shí)間戳和nonce等信息,具體如下:
區(qū)塊標(biāo)識(shí)符
區(qū)塊有兩個(gè)標(biāo)示符,一是區(qū)塊頭的哈希值,二是區(qū)塊高度。區(qū)塊頭的哈希值是通過(guò)SHA256算法對(duì)區(qū)塊頭進(jìn)行二次哈希計(jì)算而得到的數(shù)字。區(qū)塊哈希值可以唯一、明確地標(biāo)識(shí)一個(gè)區(qū)塊,并且任何節(jié)點(diǎn)通過(guò)簡(jiǎn)單地對(duì)區(qū)塊頭進(jìn)行哈希計(jì)算都可以獨(dú)立地獲取該區(qū)塊哈希值。區(qū)塊高度是指該區(qū)塊在區(qū)塊鏈中的位置。區(qū)塊高度并不是唯一的標(biāo)識(shí)符。雖然一個(gè)單一的區(qū)塊總是會(huì)有一個(gè)明確的、固定的區(qū)塊高度,但反過(guò)來(lái)卻并不成立,一個(gè)區(qū)塊高度并不總是識(shí)別一個(gè)單一的區(qū)塊。兩個(gè)或兩個(gè)以上的區(qū)塊可能有相同的區(qū)塊高度,在區(qū)塊鏈里爭(zhēng)奪同一位置。
了解了以上基礎(chǔ)后下面開(kāi)始用Python實(shí)現(xiàn)一個(gè)簡(jiǎn)單的區(qū)塊鏈。
區(qū)塊鏈的Python實(shí)現(xiàn)
一、定義區(qū)塊結(jié)構(gòu)
In [16]:
# block.py import hashlib import uuid class Block(object): def __init__(self, data=None, previous_hash=None): self.identifier = uuid.uuid4().hex # 產(chǎn)生唯一標(biāo)示 self.nonce = None # nonce值 self.data = data # 區(qū)塊內(nèi)容 self.previous_hash = previous_hash # 父節(jié)點(diǎn)哈希值 def hash(self, nonce=None): ''' 計(jì)算區(qū)塊的哈希值 ''' 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): ''' 校驗(yàn)區(qū)塊哈希值有否有效 ''' return the_hash.startswith('0000') def __repr__(self): return 'Block<Hash: {}, Nonce: {}>'.format(self.hash(), self.nonce)
以上就是一個(gè)區(qū)塊結(jié)構(gòu),這里實(shí)現(xiàn)的是一個(gè)簡(jiǎn)化版,沒(méi)有完全對(duì)應(yīng)比特幣中的區(qū)塊。這里的區(qū)塊包含一個(gè)唯一標(biāo)識(shí)符、父節(jié)點(diǎn)的哈希值、nonce值和該區(qū)塊的內(nèi)容字段??梢钥吹揭粋€(gè)區(qū)塊的哈希值必須滿(mǎn)足一定的條件才是有效的,比如以0000開(kāi)始。下面對(duì)這個(gè)區(qū)塊結(jié)構(gòu)進(jìn)行初始化。
In [37]:
# 創(chuàng)建一個(gè)內(nèi)容為hello world的內(nèi)容塊 block = Block('Hello World') block
Out[37]:
Block<Hash: 238a65a101c8829d7fc406eb78a71cfc19ad702b437e2c1be8d9061ddb81e900, Nonce: None>
以上一個(gè)區(qū)塊雖然創(chuàng)建完成,但其哈希值不是有效的。
In [38]:
block.hash_is_valid(block.hash())
Out[38]:
False
改變nonce的值就可以得到一個(gè)新的哈希值。
In [39]:
block.hash(1)
Out[39]:
'a6431938ba10270dfcfdf7a2371312446914fedadf79632c2c0adb3b463f4838'
哈希值更新了,但還不是有效的哈希值。為了得到有效哈希值,是一個(gè)不斷更新nonce值的過(guò)程,或者說(shuō)一個(gè)挖礦(mine)過(guò)程。下面添加一個(gè)mine函數(shù)用來(lái)得到一個(gè)合適的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 # 產(chǎn)生唯一標(biāo)示 self.nonce = None # nonce值 self.data = data # 區(qū)塊內(nèi)容 self.previous_hash = previous_hash # 父節(jié)點(diǎn)哈希值 def hash(self, nonce=None): ''' 計(jì)算區(qū)塊的哈希值 ''' 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): ''' 校驗(yàn)區(qū)塊哈希值有否有效 ''' return the_hash.startswith('0000') def __repr__(self): return 'Block<Hash: {}, Nonce: {}>'.format(self.hash(self.nonce), self.nonce) ''' 新增挖礦函數(shù) ''' def mine(self): # 初始化nonce為0 cur_nonce = self.nonce or 0 # 循環(huán)直到生成一個(gè)有效的哈希值 while True: the_hash = self.hash(nonce=cur_nonce) if self.hash_is_valid(the_hash): # 如果生成的哈希值有效 self.nonce = cur_nonce # 保持當(dāng)前nonce值 break # 并退出 else: cur_nonce += 1 # 若當(dāng)前哈希值無(wú)效,更新nonce值,進(jìn)行加1操作
In [75]:
block = Block('Hello World') # 挖礦,循環(huán)直至找到合適的nonce block.mine() # 打印 block
Out[75]:
Block<Hash: 000087359d5264153d624556f0a0c6f25cba06e453975c1c02587862e823911b, Nonce: 64751>
至此,第一個(gè)有效的區(qū)塊生成完成,下面開(kāi)始定義區(qū)塊鏈。
二、定義區(qū)塊鏈結(jié)構(gòu)
In [81]:
class BlockChain(object): def __init__(self): self.head = None # 指向最新的一個(gè)區(qū)塊 self.blocks = {} # 包含所有區(qū)塊的一個(gè)字典 ''' 添加區(qū)塊函數(shù) ''' def add_block(self, new_block): previous_hash = self.head.hash() 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 )
定義好區(qū)塊鏈結(jié)構(gòu)后,下面就開(kāi)始初始化一條區(qū)塊鏈。
In [82]:
# 初始化 chain = BlockChain() # 打印 chain
Out[82]:
Blockchain<0 Blocks, Head: None>
In [83]:
# 添加區(qū)塊 chain.add_block(block) # 打印 chain
Out[83]:
Blockchain<1 Blocks, Head: 364c0cf963384ca28a2763499a140405>
In [84]:
# 添加更多的區(qū)塊 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>
以上就是一個(gè)簡(jiǎn)單區(qū)塊鏈,后面還會(huì)涉及到區(qū)塊鏈的有效性。當(dāng)區(qū)塊鏈中一個(gè)區(qū)塊被改變后,這個(gè)區(qū)塊的哈希就會(huì)改變,從而影響到這塊區(qū)塊之后的區(qū)塊,致使這個(gè)區(qū)塊鏈不再有效。這些將在后續(xù)繼續(xù)深入。
總結(jié)
以上就是這篇文章的全部?jī)?nèi)容了,希望本文的內(nèi)容對(duì)大家的學(xué)習(xí)或者工作能帶來(lái)一定的幫助,如果有疑問(wèn)大家可以留言交流,謝謝大家對(duì)腳本之家的支持。
- 詳解python實(shí)現(xiàn)簡(jiǎn)單區(qū)塊鏈結(jié)構(gòu)
- python區(qū)塊及區(qū)塊鏈的開(kāi)發(fā)詳解
- python簡(jiǎn)單區(qū)塊鏈模擬詳解
- Python實(shí)現(xiàn)基于POS算法的區(qū)塊鏈
- Python實(shí)現(xiàn)類(lèi)似比特幣的加密貨幣區(qū)塊鏈的創(chuàng)建與交易實(shí)例
- 使用Python從零開(kāi)始擼一個(gè)區(qū)塊鏈
- Python從零開(kāi)始創(chuàng)建區(qū)塊鏈
- 用不到50行的Python代碼構(gòu)建最小的區(qū)塊鏈
- 如何用用Python制作NFT區(qū)塊鏈作品
相關(guān)文章
應(yīng)用OpenCV和Python進(jìn)行SIFT算法的實(shí)現(xiàn)詳解
這篇文章主要介紹了應(yīng)用OpenCV和Python進(jìn)行SIFT算法的實(shí)現(xiàn)詳解,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2019-08-08Python判斷某個(gè)用戶(hù)對(duì)某個(gè)文件的權(quán)限
這篇文章主要為大家詳細(xì)介紹了Python如何判斷某個(gè)用戶(hù)對(duì)某個(gè)文件的權(quán)限,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2016-10-10python中l(wèi)ogging庫(kù)的使用總結(jié)
Python的logging模塊提供了通用的日志系統(tǒng),可以方便第三方模塊或者是應(yīng)用使用,下面這篇文章主要給大家介紹了關(guān)于python中l(wèi)ogging庫(kù)使用的一些知識(shí)總結(jié),文中給出了詳細(xì)的示例代碼,需要的朋友可以參考借鑒,下面來(lái)一起看看吧。2017-10-10python編程實(shí)現(xiàn)清理微信重復(fù)緩存文件
這篇文章主要為大家介紹了使用python編程來(lái)實(shí)現(xiàn)清理微信重復(fù)緩存文件的示例代碼過(guò)程,有需要的朋友可以借鑒參考下,希望能夠有所幫助2021-11-11Python3讀取Excel數(shù)據(jù)存入MySQL的方法
今天小編就為大家分享一篇Python3讀取Excel數(shù)據(jù)存入MySQL的方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2018-05-05windows下 兼容Python2和Python3的解決方法
這篇文章主要介紹了windows下 兼容Python2和Python3的解決方法,需要的朋友可以參考下2018-12-12