通過構建區塊鏈來學習區塊鏈-1-Transaction|Block|POW
原文連結:https://medium.com/@vanflymen/learn-blockchains-by-building-one-117428612f46
- 交易Transaction
- 區塊Block
- 工作量證明
你來這裡是因為,和我一樣,你對加密貨幣的崛起感到興奮。你想知道區塊鏈是如何工作的——它們背後的基本技術。
但理解區塊鏈並不容易——至少對我來說不是。我艱難地瀏覽了密集的視訊,學習了很多的教程,並處理了由於例子太少而產生的放大的挫折感。
我喜歡邊做邊學。如果您也這樣做,在本指南的最後,您將擁有一個功能良好的區塊鏈,並對它們的工作原理有一個堅實的瞭解。
在你開始之前…
請記住,區塊鏈是一個不可變的、連續的記錄鏈,稱為塊
如果你不確定雜湊是什麼,這裡有一個解釋。
-
這本指南是針對誰的? 您應該能夠輕鬆地閱讀和編寫一些基本的Python,並對HTTP請求的工作原理有一些瞭解,因為我們將通過HTTP與我們的區塊鏈通訊。
-
我需要什麼? 確保安裝了Python 3.6+(以及pip)。你還需要安裝Flask和wonderful Requests 庫:
pip install Flask==0.12.2 requests==2.18.4
您還需要一個HTTP客戶機,比如Postman 或cURL;但什麼都行。
- 最終程式碼在哪裡?
這裡提供了
###步驟1:構建一個區塊鏈
開啟您最喜歡的文字編輯器或IDE,我個人喜歡PyCharm。建立一個名為blockchain.py的新檔案。我們只使用一個檔案,但是如果您丟失了,您可以隨時查閱原始碼。
代表一個區塊鏈
我們將建立一個區塊鏈類,該類的建構函式建立一個初始空列表(用於儲存我們的區塊鏈),另一個用於儲存事務。這是我們班的藍圖:
class Blockchain(object): def __init__(self): self.chain = [] self.current_transactions = [] def new_block(self): # Creates a new Block and adds it to the chain pass def new_transaction(self): # Adds a new transaction to the list of transactions pass [@staticmethod](https://my.oschina.net/staticmethod) def hash(block): # Hashes a Block pass [@property](https://my.oschina.net/property) def last_block(self): # Returns the last Block in the chain pass
我們的區塊鏈類負責管理鏈。它將儲存事務,並具有一些用於向鏈新增新塊的輔助方法。讓我們開始充實一些方法。
Block是什麼樣子的?
每個塊都有以下內容:
- 一個索引、
- 一個時間戳(Unix時間)、
- 一個事務列表、
- 一個證明(稍後將詳細介紹)
- 前一個塊的雜湊。
下面是單個塊的例子:
block = {
'index': 1,
'timestamp': 1506057125.900785,
'transactions': [
{
'sender': "8527147fe1f5426f9dd545de4b27ee00",
'recipient': "a77f5cdfa2934df3954a5c7c7da5df1f",
'amount': 5,
}
],
'proof': 324984774000,
'previous_hash': "2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824”
}
此時,鏈的概念應該很明顯——每個新塊都包含前一個塊的雜湊(Hash)。這是至關重要的,因為它使區塊鏈具有不變性:如果攻擊者破壞了鏈中較早的一個區塊,那麼所有後續的區塊都將包含不正確的雜湊(Hash)。
這說得通嗎?如果沒有,花點時間讓它沉下去——這是區塊鏈背後的核心理念。
將事務新增到塊中
我們需要一種向塊新增事務的方法。我們的new_transaction()方法對此負責,它非常簡單:
class Blockchain(object):
...
def new_transaction(self, sender, recipient, amount):
"""
Creates a new transaction to go into the next mined Block
:param sender: <str> Address of the Sender
:param recipient: <str> Address of the Recipient
:param amount: <int> Amount
:return: <int> The index of the Block that will hold this transaction
"""
self.current_transactions.append({
'sender': sender,
'recipient': recipient,
'amount': amount,
})
return self.last_block['index'] + 1
new_transaction()將一個事務新增到列表後,它返回將事務新增到下一個要挖掘的塊的索引。這將在稍後對提交事務的使用者有用。
建立新的Block
當我們的區塊鏈被例項化時,我們需要用一個genesis塊來播種它——一個沒有前處理的塊。我們還需要向genesis塊新增一個“證明”,這是挖掘(或工作證明)的結果。稍後我們將更多地討論採礦。
除了在建構函式中建立genesis塊,我們還將充實new_block()、new_transaction()和hash()的方法:
import hashlib
import json
from time import time
class Blockchain(object):
def __init__(self):
self.current_transactions = []
self.chain = []
# Create the genesis block
self.new_block(previous_hash=1, proof=100)
def new_block(self, proof, previous_hash=None):
"""
Create a new Block in the Blockchain
:param proof: <int> The proof given by the Proof of Work algorithm
:param previous_hash: (Optional) <str> Hash of previous Block
:return: <dict> New Block
"""
block = {
'index': len(self.chain) + 1,
'timestamp': time(),
'transactions': self.current_transactions,
'proof': proof,
'previous_hash': previous_hash or self.hash(self.chain[-1]),
}
# Reset the current list of transactions
self.current_transactions = []
self.chain.append(block)
return block
def new_transaction(self, sender, recipient, amount):
"""
Creates a new transaction to go into the next mined Block
:param sender: <str> Address of the Sender
:param recipient: <str> Address of the Recipient
:param amount: <int> Amount
:return: <int> The index of the Block that will hold this transaction
"""
self.current_transactions.append({
'sender': sender,
'recipient': recipient,
'amount': amount,
})
return self.last_block['index'] + 1
[@property](https://my.oschina.net/property)
def last_block(self):
return self.chain[-1]
@staticmethod
def hash(block):
"""
Creates a SHA-256 hash of a Block
:param block: <dict> Block
:return: <str>
"""
# We must make sure that the Dictionary is Ordered, or we'll have inconsistent hashes
block_string = json.dumps(block, sort_keys=True).encode()
return hashlib.sha256(block_string).hexdigest()
上面的內容應該是直接了當的—我添加了一些註釋和文件字串來幫助保持清晰。我們幾乎完成了對區塊鏈的表示。但此時,您一定想知道如何建立、鍛造或挖掘新的塊。
工作證明
工作演算法(PoW)的一個證明是如何在區塊鏈上建立或挖掘新的塊。PoW的目標是發現一個可以解決問題的數。這個數字一定很難找到,但是很容易被網路上的任何人驗證——從計算的角度來說。這是工作證明背後的核心思想。
我們將看一個非常簡單的例子來幫助理解這一點。
讓我們決定某個整數x乘以另一個y的雜湊必須以0結尾。雜湊(x * y) = ac23dc…0。對於這個簡化的例子,我們令x = 5。用Python實現:
from hashlib import sha256
x = 5
y = 0 # We don't know what y should be yet...
while sha256(f'{x*y}'.encode()).hexdigest()[-1] != "0":
y += 1
print(f'The solution is y = {y}’)
解是y = 21。因為,生成的雜湊以0結尾:
hash(5 * 21) = 1253e9373e…5e3600155e860
在比特幣中,工作證明演算法被稱為Hashcash。它和上面的基本例子沒有太大的不同。它是礦工們為了建立一個新的塊而競相求解的演算法。通常,難度由字串中搜索的字元數量決定。然後,這些礦商會因為他們的解決方案而獲得一筆交易中的硬幣作為回報。
網路能夠很容易地驗證他們的解決方案。
實現基本的工作證明
讓我們為區塊鏈實現一個類似的演算法。我們的規則將類似於上面的例子:
找到一個數字p,當它與前一個塊的解進行雜湊時,會產生一個前導4個0的雜湊。
import hashlib
import json
from time import time
from uuid import uuid4
class Blockchain(object):
...
def proof_of_work(self, last_proof):
"""
Simple Proof of Work Algorithm:
- Find a number p' such that hash(pp') contains leading 4 zeroes, where p is the previous p'
- p is the previous proof, and p' is the new proof
:param last_proof: <int>
:return: <int>
"""
proof = 0
while self.valid_proof(last_proof, proof) is False:
proof += 1
return proof
@staticmethod
def valid_proof(last_proof, proof):
"""
Validates the Proof: Does hash(last_proof, proof) contain 4 leading zeroes?
:param last_proof: <int> Previous Proof
:param proof: <int> Current Proof
:return: <bool> True if correct, False if not.
"""
guess = f'{last_proof}{proof}'.encode()
guess_hash = hashlib.sha256(guess).hexdigest()
return guess_hash[:4] == “0000"
為了調整演算法的難度,可以修改前導零的個數。但是4就足夠了。您將發現,新增一個前導零會大大縮短找到解決方案所需的時間。
我們的類幾乎完成了,我們已經準備好開始使用HTTP請求與它進行互動。
本文由Rebase社群的River翻譯並整理;有問題請加微信syuukawa