鏈聞 ChainNews:

本文首先詳細介紹了區塊鏈的基本概念,然後一步步分析區塊鏈的工作過程並介紹其優缺點,最後用 python 代碼簡單實現一個挖礦的流程,值得學習閱讀!

來源:| BmwGaara 的博客
作者:| BmwGaara

概念解讀

區塊鏈幾乎是數日間成爲人盡皆知的名詞,這個名詞也勾起了我強烈的興趣,但是通過在網上搜羅資料,多方閱讀,發現很多介紹區塊鏈的文獻要麼模棱兩可,要麼作者本身的理解也很有限,導致很多關鍵的問題敘述不清。本人花了一些時間總結歸納,希望可以給讀者一個比較全面清晰的認識。

區塊鏈的官方定義是:一個分佈式賬本,一種通過去中心化、去信任的方式集體維護一個可靠數據庫的技術方案。那麼對於圈外人該如何理解呢?以下我會詳細描述一個區塊鏈的產生過程和實現意義,從而給大家構建出一個清晰的區塊鏈概念。我們先講原理、再說特點、然後論用途、最後迴歸代碼,這樣你就會有一種恍然大悟的感覺。

我們以 btc 爲例:「區塊鏈」,顧名思義,就是由一個個區塊依次連接起來組成的鏈條,可以類比爲一條無限長度的直線鐵鏈,每個鐵環就是一個區塊。那麼區塊的內容應該是什麼呢?區塊狹義上是有兩種的,一個是普通區塊,一個就是創世區塊。創世區塊就是一項區塊鏈項目中的第一個區塊,由於個人水平有限,對創世區塊沒有做過詳細研究,但是根據我的瞭解,創世區塊應該是具備與普通區塊相似結構的,但會肯定會加入一些創始人想說的東西,並且在有些項目中可能會多一條記錄,就是 coin 的發行量,例如 swtc 的 6000 億數目就是寫在創世區塊之中的,一旦發行,無法修改。

那麼,一個普通區塊中到底有什麼?

1.index:就是從 0-n 依次產生的數字,可以稱之爲鏈高度。

2.hash:一個長度爲 256 位隨機數,是這個區塊的唯一編號。

3.previous hash:上一個區塊的 hash,一個普通區塊有且僅有一個 previous hash,這就是區塊鏈之所以稱爲鏈的原因,就是這麼一環套一環鏈接而成的。

4.tempstamp:用於記錄該區塊誕生的時間。

5.difficulty:直觀體現創造該區塊的難度。

6.nonce:隨機數,用於產生下一個區塊。

上述的都存在區塊頭中。

7.data:存儲的交易記錄。只有這個存在區塊體中。

Ok,上述提到了一個區塊需要具備的最基本的幾條要素,可能你現在還處於一臉懵逼的狀態:這些東西到底是怎麼工作的呢?下面我將一步步分析區塊鏈的工作過程,不過,這裏要先問兩個問題:爲什麼要產生新的區塊?怎麼產生新的區塊?

爲什麼產生新區塊?

之前說了,一個區塊記錄的就是一份賬單,賬單中存儲着若干條交易記錄,是買賣雙方具體活動的最有力的證明,例如我們在淘寶上的購買記錄,就是我們的消費賬單。人們每天的消費記錄是不斷增長的,不可能永遠放在一個區塊裏,那麼跟現在的中心化存儲機制還有什麼區別?所以,隨着買賣記錄的不斷增加,就需要不斷產生新的區塊來存儲這些數據。

怎麼產生新的區塊?

我相信,最近除了區塊鏈這個名詞如雷貫耳以外,“挖礦”應該也沒少聽吧。挖礦實際上就是由那些礦工來生成新的區塊的過程。在 btc 項目中,btc 礦工挖礦成功(其實就是成功的創建了一個區塊)就可以獲得一定數量的被 btc 獎勵,所以 btc 數量是在一定範圍內慢慢增加的。在一般允許挖礦的區塊鏈項目(也存在限制 coin 數量不允許挖礦的區塊鏈項目)中,礦工的數量一般會大於 6 個,一般超過 6 個礦工認可的新區塊就可以加入到區塊鏈中。到此爲止,有人會說:哇!btc 這麼值錢,挖礦不是很爽?其實不然,如果區塊無限制的快速增加,會引起很大的問題,根據中本聰的設定,目前全網每 10 分鐘只能產生一個新區塊。而且這 10 分鐘不是靠自己掐表算的,生成新的區塊是需要大量的運算的,這 10 分鐘是人家預先設計好的,讓計算量大到全網 10 分鐘一般只能產生一個。

好了,至此,區塊鏈的基本概念已經介紹的差不多了,下面言歸正傳,講下區塊的工作流程:

1. 如果 A 要和 B 達成一筆交易,比如 A 轉給 B 一個 btc,B 給 A 打 10w 的 RMB。A 首先將自己的 btc 來源信息、交易人等發送給 B,同時還要拷貝一份發到全網。什麼?這樣還有隱私可言嗎?當然,聰明的中本聰當然不會犯這麼低級的錯誤。在區塊鏈中,每個交易個體(也可以理解爲每個網絡節點)都會有一對公鑰和私鑰,公鑰相當於一個“收款地址”,而私鑰是一個表明自己身份的 256 位的數字,目前一般是用 sha265 來生成的,這樣,別人並不知道交易的雙方是誰。發送報文時,發送方用一個哈希函數從報文文本中生成報文摘要,然後用自己的私鑰對摘要進行加密,加密後的摘要將作爲報文的數字簽名和報文一起發送給接收方,接收方首先用與發送方一樣的哈希函數從接收到的原始報文中計算出報文摘要,接着再用發送方的公鑰來對報文附加的數字簽名進行解密,如果這兩個摘要相同、那麼接收方就能確認該數字簽名是發送方的。

2. 那麼此時,這筆交易是否就完成了呢?如果這就算完成了,那跟 A 直接用包裹裝 10w 現金快遞給 B 有什麼區別呢?此時,全網的礦工都會得到這個交易記錄,那麼全網的礦工都會爲了若干獎勵開始創建區塊的工作,礦工會利用 hash 函數生成一個 256 位的唯一編號賦予這個區塊,但是這個編號並不是簡簡單單隨便生成的。編號是根據區塊的具體內容如交易內容、nonce 等唯一確定的,換句話說,兩塊內容相同的區塊所對應的編號一定是唯一的。可是你會問:這又怎麼了?並不難啊。錯!中本聰爲了控制區塊的生成時間,使區塊的生成速率滿足全網的每 10 分鐘一個的標準,制定了嚴格的區塊生成校驗規則,也就是說,能不能生成一個成功的區塊要看你的編號是否符合這個規則。例如:生成編號中的前 n 位必須爲「0」。

由於區塊的交易內容是無法修改的,因此礦工們只能通過修改 nonce 去不斷嘗試這個函數,直到生成了一個成功的區塊爲止。如果當區塊平均生成時間變快或者變慢,那麼系統會對區塊校驗規則進行相應的調整,從而使平均的生成時間能夠控制在規定範圍。

如果一個礦工完成了一個區塊,會立刻告知其他礦工,如果其他礦工此時沒有完成新的區塊生成,則會停下手頭的工作,對區塊進行驗證,需要確認的信息主要有如下幾點:

1). 區塊的編號有效;這個只要將區塊放入哈希函數中,看產生的編號是否和該區塊中的編號一致即可。
2). 區塊的前一個區塊有效;之前提過,區塊是一個串聯的,每一個普通區塊都會記載前一個區塊的編號,這需要其他礦工對比當前的區塊鏈的最後一個區塊,看是否相同。3). 交易清單有效;就是說要驗證 A 到底有沒有這一個 btc 可以給 B。在區塊鏈的交易信息中,會記錄交易中所有 btc 的前世今生,區塊鏈可以做到追本溯源,因此每一個 btc 在哪裏,爲什麼在這裏都可以一目瞭然,所以這點也沒問題。

當驗證完一個全新的區塊後,全網就會認爲這個區塊有效,會將它添加到現有的區塊鏈末端,同時結束針對該區塊的挖礦工作,投入到下一個挖礦週期中。

但是不難想象,這樣的機制是存在衝突的隱患的,就是這麼巧,兩個礦工同時製作了一個正確的區塊,那麼此時不必二選一,可以將原來線性的區塊鏈改成樹狀:

關於區塊鏈的解讀和簡單 Python 實現

但是這樣會導致未來在 A、B 後都會增加相應的區塊,那麼誰長誰將作爲主鏈延伸下去,另一個也許會漸漸被遺忘,除非哪天它變得更長。

好啦,這就是區塊鏈最基本的知識,接下來應該談談優缺點了。

世界上沒有一樣東西可以稱爲完美無瑕的,要知道區塊鏈一樣,雖然它被扣上了可以顛覆未來的帽子,但是仍然存在它的侷限性:1. 時效性。很容易發現,區塊鏈中存在很多的驗證、傳遞環節,這就會導致其時效性較差。2、能耗,這點也是顯而易見的,區塊鏈需要大量無用計算來控制區塊的生成時間。所以區塊鏈不適用於高時效的網絡中。
至於區塊鏈的優點,諸如安全、去中心化等等在網絡上已經描述的非常清楚,這裏就不再贅述。接下來我用一段 python 代碼來簡單實現一個挖礦的流程。

代碼示例

首先創建一個表示區塊鏈的類:

class_BlockChain:
def __init__(self\\, initialHash):
# init block chain
self.chain = []
# init pitman
self.pitmen = []
for i in range(6):
self.pitmen.append(Pitman)
# collect mine results
self.results = []
# generate GenesisBlock
self.newblock(initialHash
)

初始化函數中的 chain 表示當前的區塊鏈,我會在其中存儲區塊對象;pitmen 表示爲這個區塊鏈服務的礦工們,這個列表中也會存有礦工對象;results 則會存儲每個階段產生的區塊;new_block 方法是創建區塊的方法,如果當前生成的區塊爲第一個區塊,則產生創世區塊。

下面看看區塊鏈類型的方法:

@property_def_last_block(self):_
_if_len(self.chain):
return self.chain[-1]
else:
return None

_last_block 會返回當前區塊鏈的最後一個區塊對象。

def_get_trans(self):
_return_json.dumps({
\’sender\’: \’\’.join(random.sample(string.asciiletters + string.digits, 8)),
\’recipient\’: \’\’.join(random.sample(string.asciiletters + string.digits, 8)),
\’amount\’: random.randrange(1, 10000)
})

_get_trans 方法則用來隨機生成一份交易信息。

def_new_block(self,_initialHash=None):
_if_initialHash:
# generate Genesis Block
block = Block()
block.index = 0
block.nonce = random.randrange(0, 99999)
block.previousHash = \’0\’
block.difficulty = 0
block.transactionData = self.get_trans()_
guess = f\'{block.previousHash}{block.nonce}{block.transactionData}\’.encode()
block.hash = hashlib.sha256(guess).hexdigest()
block.time = time()
self.chain.append(block)
_else_:
_for_i in range(len(self.pitmen)):
pm = MyThread(target=self.pitmen[i].mine,
args=(self.pitmen[i],
len(self.chain),
self.last_block.get_block()[\’Hash\’]\\,
self.gettrans()))
pm.start()
pm.join()
self.results.append(pm.getresult())
# show all blocks
print(\”All blocks generated by pitmen:\”)
for result in self.results:
_print(result[0].get_block())
# get new block
firstblock = self.results[0][0]
mintime = Decimal(self.results[0][1])
for i in range(1, len(self.results)):
if Decimal(self.results[i][1]) < mintime:
firstblock = self.results[i][0]
else:
continue self.chain.append(firstblock)
self.results = []

這是生成區塊的核心部分,這個方法主要分成兩個部分:根據傳參區分是否是創世區塊,如果需要的是創世區塊,那就由該類型自動生成一個區塊佔據區塊鏈的頭一個位置。如果需要生成的是普通區塊,那麼則會將一些基本信息分發給礦工們進行挖礦操作。我在這裏設置了 6 個礦工,爲了公平起見,這裏也開了個多線程儘量讓礦工們同時收到消息從而可以同時進行挖礦操作。按理說,最先挖礦成功的礦工會將消息發給其他礦工,其他礦工會立刻停止進行校驗,但由於時間有限,這一步校驗環節我沒有實現。在這裏,我允許所有礦工都完成工作,並提交成果和相應的工作時間,生成耗時最短的區塊講作爲正確的區塊添加到區塊鏈上。本質上也是依照了「快者優先」的區塊鏈生成原則。

說了半天,區塊內部到底是什麼樣的呢?

_class_Block:
def __init__(self):
self.index = None self.time = None self.difficulty = None self.nonce = None self.hash = None self.previousHash = None self.transactionData = None def get_block(self):
_return_{
\’Index\’: self.index,
\’Time\’: self.time,
\’Difficulty\’: self.difficulty,
\’Hash\’: self.hash,
\’Nonce\’: self.nonce,
\’PreviousHash\’: self.previousHash,
\’TransactionData\’: self.transactionData
}

我用了一個相對簡單的類型表示區塊,在這裏區塊就是一個非常簡單的數據結構,這裏的所有字段在上述中已經有了詳細的說明,因此不再贅述。

那麼我們再看看礦工,畢竟礦工纔是區塊鏈的生產者和推動者,地位最爲核心。礦工類中我設計了兩個方法,一個 mine 方法,也就是挖礦的意思,用來生成新的區塊,並會返回該區塊生成的用時長短。

def_mine(self,_index,previousHash,transactionData):
beginTime = time()
block = Block()block.index = _index_block.previousHash = _previousHash_block.transactionData = _transactionData_block.difficulty\\, block.hash\\, block.nonce = self.generate_hash(_previousHash_\\, _transactionData_)block.time = time()endTime = time()_return_block\\, endTime \\- beginTime

另一個方法是 hash 生成的方法,生成原則我自己意淫了一個,大家莫怪,因爲本人計算機的實在不給力,區塊的成功標準很簡單,就是用 sha256 生成的編碼最後結尾是 0 就滿足要求,如果改成 00,那會半天看不到結果。

下面我們看下這套實例的運行結果,我設置了一個長度爲 6 的區塊鏈,由於第一個區塊是創世區塊,所以真正開始創建的區塊是從第二個開始的,大家注意 index。

這是 6 個礦工完成的第一區塊:

All blocks generated by pitmen:
{\’Index\’: 1, \’Time\’: 1516268156.5971138, \’Difficulty\’: 2, \’Hash\’: \’01f505a276e3f55a868d9ee18f70bcff75429e1de70f5ab59471a3551cc67a30\’, \’Nonce\’: 91554, \’PreviousHash\’: \’7532402844a1c130833a27600298d09a007d6124603cf44be9c05fcd5428c34a\’, \’TransactionData\’: \'{\”sender\”: \”OY8z0Rrx\”, \”recipient\”: \”iSGFJsEm\”, \”amount\”: 8723}\’}
{\’Index\’: 1, \’Time\’: 1516268156.5971138, \’Difficulty\’: 5, \’Hash\’: \’c3ba406bad0d87f816f629830a15e2997638bfa230484c224e5470eaa24d8790\’, \’Nonce\’: 62372, \’PreviousHash\’: \’7532402844a1c130833a27600298d09a007d6124603cf44be9c05fcd5428c34a\’, \’TransactionData\’: \'{\”sender\”: \”9o8UMDLe\”, \”recipient\”: \”qTOQu7kv\”, \”amount\”: 2746}\’}
{\’Index\’: 1, \’Time\’: 1516268156.5981123, \’Difficulty\’: 5, \’Hash\’: \’8ff243885e9017296aa2ef1a611ef5b3927ddce818cb7255a04ff3228c982c60\’, \’Nonce\’: 67644, \’PreviousHash\’: \’7532402844a1c130833a27600298d09a007d6124603cf44be9c05fcd5428c34a\’, \’TransactionData\’: \'{\”sender\”: \”kIqy1c8C\”, \”recipient\”: \”WSdK0EXh\”, \”amount\”: 9329}\’}
{\’Index\’: 1, \’Time\’: 1516268156.5981123, \’Difficulty\’: 3, \’Hash\’: \’ff9716bf9379e2ab7a8640419e7c7b7c7329a5e6e1bbf83a1249f49d070ca8b0\’, \’Nonce\’: 37336, \’PreviousHash\’: \’7532402844a1c130833a27600298d09a007d6124603cf44be9c05fcd5428c34a\’, \’TransactionData\’: \'{\”sender\”: \”vBwU0luH\”, \”recipient\”: \”d7o6cRCj\”, \”amount\”: 5628}\’}
{\’Index\’: 1, \’Time\’: 1516268156.5981123, \’Difficulty\’: 3, \’Hash\’: \’3410c70c31f9bacbfcbd74d63f25f69f27d36075e2d44bddaa60bd72fa042e60\’, \’Nonce\’: 34617, \’PreviousHash\’: \’7532402844a1c130833a27600298d09a007d6124603cf44be9c05fcd5428c34a\’, \’TransactionData\’: \'{\”sender\”: \”yzcNpBnh\”, \”recipient\”: \”vbIr7SKo\”, \”amount\”: 6387}\’}
{\’Index\’: 1, \’Time\’: 1516268156.5981123, \’Difficulty\’: 27, \’Hash\’: \’91e3dc3ef1a151557a1edd837528410b916362bcfb77dbb14dc54c8929f5a0d0\’, \’Nonce\’: 49121, \’PreviousHash\’: \’7532402844a1c130833a27600298d09a007d6124603cf44be9c05fcd5428c34a\’, \’TransactionData\’: \'{\”sender\”: \”p1MguhVz\”, \”recipient\”: \”gVSom4D3\”, \”amount\”: 7356}\’}

很明顯前兩個是最快的,爲了簡單,我在最快的裏面隨便選取一個,意思到了就行。大家可以看到,難度值,根據上文所說,這是反應一個區塊生成的難易程度的,難度高的,在我這裏會表示這個礦工爲了得到這個區塊進行了多少次嘗試。看到這裏也許你會問:爲什麼難度最大的時間並沒有明顯長呢?也就是用時並沒有按照難度的增加而增加。我猜想應該是因爲我的示例算法簡單,因此結果也不是十分精確,如果計算量達到一定的規模,應該會有明顯的差距。(如果有高人知道,可以回覆我,在此謝過!)第三到第六個的區塊創建結果格式是與之一樣的,就不刷屏了。

最後看下整個區塊鏈的結果:

{\’Index\’: 0, \’Time\’: 1516268156.5971138, \’Difficulty\’: 0, \’Hash\’: \’7532402844a1c130833a27600298d09a007d6124603cf44be9c05fcd5428c34a\’, \’Nonce\’: 87688, \’PreviousHash\’: \’0\’, \’TransactionData\’: \'{\”sender\”: \”OuVCmHbs\”, \”recipient\”: \”kFxbwSLc\”, \”amount\”: 503}\’}
{\’Index\’: 1, \’Time\’: 1516268156.5971138, \’Difficulty\’: 2, \’Hash\’: \’01f505a276e3f55a868d9ee18f70bcff75429e1de70f5ab59471a3551cc67a30\’, \’Nonce\’: 91554, \’PreviousHash\’: \’7532402844a1c130833a27600298d09a007d6124603cf44be9c05fcd5428c34a\’, \’TransactionData\’: \'{\”sender\”: \”OY8z0Rrx\”, \”recipient\”: \”iSGFJsEm\”, \”amount\”: 8723}\’}
{\’Index\’: 2, \’Time\’: 1516268156.5991132, \’Difficulty\’: 4, \’Hash\’: \’098544436793881e8041c0c903c96c0055e16396113d73c63bc55e7ba78ec130\’, \’Nonce\’: 12875, \’PreviousHash\’: \’01f505a276e3f55a868d9ee18f70bcff75429e1de70f5ab59471a3551cc67a30\’, \’TransactionData\’: \'{\”sender\”: \”HJZSX1hk\”, \”recipient\”: \”j82k51yY\”, \”amount\”: 3521}\’}
{\’Index\’: 3, \’Time\’: 1516268156.6001143, \’Difficulty\’: 27, \’Hash\’: \’7c10243223caf39bc5a6067de8d93f6ea46bad62c4a0fbcc0aa4e086585d8200\’, \’Nonce\’: 18663, \’PreviousHash\’: \’098544436793881e8041c0c903c96c0055e16396113d73c63bc55e7ba78ec130\’, \’TransactionData\’: \'{\”sender\”: \”cJrGxN5R\”, \”recipient\”: \”wkZI8QCv\”, \”amount\”: 1224}\’}
{\’Index\’: 4, \’Time\’: 1516268156.601114, \’Difficulty\’: 3, \’Hash\’: \’60a099d3fe53e031800669fcc1d9b5ab6df1f80a40354135310a799892f1c3d0\’, \’Nonce\’: 51446, \’PreviousHash\’: \’7c10243223caf39bc5a6067de8d93f6ea46bad62c4a0fbcc0aa4e086585d8200\’, \’TransactionData\’: \'{\”sender\”: \”nCNJoy52\”, \”recipient\”: \”kYBT9f65\”, \”amount\”: 3603}\’}
{\’Index\’: 5, \’Time\’: 1516268156.605163, \’Difficulty\’: 2, \’Hash\’: \’765f69163cf95584721015e3ce819c1980ce33752f8a4dea553d3bedd39f8920\’, \’Nonce\’: 31804, \’PreviousHash\’: \’60a099d3fe53e031800669fcc1d9b5ab6df1f80a40354135310a799892f1c3d0\’, \’TransactionData\’: \'{\”sender\”: \”FqOkiTEu\”, \”recipient\”: \”y9EDcSYA\”, \”amount\”: 4185}\’}

這就是由這 6 個礦工依次創建的六個區塊,根據 hash 值環環相扣。
到底我想說的基本就結束了,最後我想說區塊鏈是個神奇的技術,從聽到它就深深的吸引着我,期望未來區塊鏈可以真的帶來巨大的變革。要知道,隨着 AI 的興起,區塊鏈的問世,屬於程序員的數字時代會進一步昇華,互聯網時代只是一個開始!文章末尾附上完整代碼。

import hashlib
import random
import string
import json
import threading
from decimal import Decimal
from time import time
class MyThread(threading.Thread): def __init__(self\\, target\\, args=()):
super(MyThread\\, self).__init__()
self.func = target self.args = args def run(self):
self.result = self.func(*self.args)
_def_ get_result(self):
try:
return self.result
except Exception:
return None class BlockChain:
def __init__(self\\, initialHash):
# init block chain
self.chain = []
# init pitman
self.pitmen = []
for i in range(6):
self.pitmen.append(Pitman)
# collect mine results
self.results = []
# generate GenesisBlock
self.newblock(initialHash_)
@property
def last_block(self):
_if_ len(self.chain):
return self.chain[-1]
else:
return None def get_trans(self):
_return_ json.dumps({
\’sender\’: \’\’.join(random.sample(string.asciiletters + string.digits, 8)),
\’recipient\’: \’\’.join(random.sample(string.asciiletters + string.digits, 8)),
\’amount\’: random.randrange(1, 10000)
})
_def_ new_block(self\\, _initialHash_=_None_):
if initialHash:
# generate Genesis Block
block = Block()
block.index = 0
block.nonce = random.randrange(0, 99999)
block.previousHash = \’0\’
block.difficulty = 0
block.transactionData = self.get_trans()
guess = f\'{block.previousHash}{block.nonce}{block.transactionData}\’.encode()
block.hash = hashlib.sha256(guess).hexdigest()
block.time = time()
self.chain.append(block)
_else_:
_for_ i in range(len(self.pitmen)):
pm = MyThread(target=self.pitmen[i].mine,
args=(self.pitmen[i],
len(self.chain),
self.last_block.get_block()[\’Hash\’]\\,
self.gettrans()))
pm.start()
pm.join()
self.results.append(pm.getresult())
# show all blocks
print(\”All blocks generated by pitmen:\”)
for result in self.results:
print(result[0].get_block())
# get new block
firstblock = self.results[0][0]
mintime = Decimal(self.results[0][1])
for i in range(1, len(self.results)):
if Decimal(self.results[i][1]) < mintime:
firstblock = self.results[i][0]
else:
continue self.chain.append(firstblock)
self.results = []
_def_ show_chain(self):
print(\’This is mine first block chain!\’)
for block in self.chain:
print(block.get_block())
class Block:
def __init__(self):
self.index = None self.time = None self.difficulty = None self.nonce = None self.hash = None self.previousHash = None self.transactionData = None def get_block(self):
_return_ {
\’Index\’: self.index,
\’Time\’: self.time,
\’Difficulty\’: self.difficulty,
\’Hash\’: self.hash,
\’Nonce\’: self.nonce,
\’PreviousHash\’: self.previousHash,
\’TransactionData\’: self.transactionData
}
class Pitman: def mine(self, index, previousHash, transactionData):
beginTime = time()
block = Block() block.index = _index_ block.previousHash = _previousHash_ block.transactionData = _transactionData_ block.difficulty\\, block.hash\\, block.nonce = self.generate_hash(_previousHash_\\, _transactionData_) block.time = time() endTime = time() _return_ block\\, endTime \\- beginTime@staticmethod
def generatehash(previousHash_\\, _transactionData_):
difficulty = 0
nonce = random.randrange(0, 99999)
guess = f\'{previousHash}{nonce}{transactionData}\’.encode()
myhash = hashlib.sha256(guess).hexdigest()
_while_ myhash[-1] != \’0\’:
difficulty += 1
nonce += difficulty
guess = f\'{previousHash}{nonce}{transactionData}\’.encode()
myhash = hashlib.sha256(guess).hexdigest()
return difficulty\\, myhash\\, nonce
if __name__ == \’__main__\’:
chain = BlockChain(1)
length = 5
for i in range(length):
chain.newblock()
chain.showchain()

更多精彩內容,關注鏈聞 ChainNews 公衆號(id:chainnewscom),
或者來微博@ 鏈聞 ChainNews 與我們互動!
轉載請註明版權和原文鏈接!

來源鏈接:blog.csdn.net