區塊結構:
# 區塊結構
class Block:
'''
pre_hash:父區塊哈希值
transaction:交易列表
timestamp:區塊創建時間
hash:區塊哈希值
nonce:隨機值
'''
def __init__(self, transaction, pre_hash):
# 將傳入的父區塊的哈希值和數據保存到類變量中
self.pre_hash = pre_hash
self.transaction = transaction
# 獲取當前時間
self.timetamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
self.hash = None
self.nonce = None
# 計算區塊的哈希值
message = hashlib.sha256()
message.update(str(self.pre_hash).encode('utf-8'))
message.update(str(self.transaction).encode('utf-8'))
message.update(str(self.timetamp).encode('utf-8'))
self.hash = message.hexdigest()
def __repr__(self):
return "區塊內容:%s\n哈希值:%s" % (self.transaction, self.hash)
區塊鏈結構:
# 區塊鏈結構
class BlockChain:
'''
blocks:包含的區塊列表
'''
def __init__(self):
self.blocks = []
# 添加區塊
def addBlock(self, block):
self.blocks.append(block)
交易類:
在實際的區塊鏈中,數據不是簡單的字符串,而是一個個交易記錄, 包含交易的發送方、接收方、交易數量以及用來驗證交易的發送方公鑰和簽名,所以定義一個包含這幾個字段的交易類。
class Transaction:
# 初始化交易
def __init__(self, sender, recipient, amount):
if isinstance(sender, bytes):
sender = sender.decode('utf-8')
self.sender = sender # 發送方
if isinstance(recipient, bytes):
recipient = recipient.decode('utf-8')
self.recipient = recipient # 接收方
self.amount = amount # 交易數量
# 驗證交易可靠性,需要發送方的公鑰和簽名
def setSign(self, signature, pubkey):
self.signature = signature # 發送方
self.pubkey = pubkey # 公鑰
# 交易分爲:挖礦所得、轉賬交易
# 挖礦所得無發送方,以此進行區分顯示不同內容
def __repr__(self):
if self.sender:
s = "從%s轉到%s %d 個加密貨幣" % (self.sender, self.recipient, self.amount)
else:
s = "%s挖礦獲取 %d 個加密貨幣" % (self.recipient, self.amount)
return s
錢包:
存放賬戶(一對唯一的公鑰和私鑰),即錢包的本質是生成和管理密鑰對的工具。
# 錢包
class Wallet:
def __init__(self):
# 基於橢圓曲線生成一個唯一的密鑰對,代表區塊鏈上一個唯一的賬戶
self.__private_key = SigningKey.generate(curve=SECP256k1)
self.__public_key = self.__private_key.get_verifying_key()
# 生成簽名
# 通過公鑰生成地址(公鑰->hash->base64->地址)
@property
def address(self):
h = hashlib.sha256(self.__public_key.to_pem())
return base64.b64encode(h.digest())
@property
def pubkey(self):
# 返回公鑰字符串
return self.__public_key.to_pem()
def sign(self, message):
# 生成簽名(是一串二進制字符串)
h = hashlib.sha256(message.encode('utf8'))
# 將二進制字符串轉爲ASCII進行輸出
return binascii.hexlify(self.__private_key.sign(h.digest()))
# 驗證簽名是否正確
def verifySign(self, pubkey, message, signature):
verifier = VerifyingKey.from_pem(pubkey)
h = hashlib.sha256(message.encode('utf8'))
return verifier.verify(binascii.unhexlify(signature), h.digest())
測試錢包的功能:
# 測試錢包功能
wallet = Wallet()
print(wallet.address) # 錢包地址
print(wallet.pubkey) # 錢包公鑰
data = "交易數據"
sg = wallet.sign(data) # 生成簽名
print(sg)
# 判斷簽名是否正確
print(wallet.verifySign(wallet.pubkey, data, sg))
工作量證明:
引入共識機制,選擇最簡單的PoW(工作量證明機制)。其原理是通過不斷計算,找到一個隨機數(nonce),使得生成的哈希值滿足一定條件。
# 工作量證明
class ProofOfWork:
def __init__(self, block, miner, difficult=5):
self.miner = miner
self.block = block
# 工作量難度,默認爲5,表示有效的哈希值以5個0開頭
self.difficult = difficult
# 挖礦獎勵,美完成一個區塊可獲得1個加密數字貨幣
self.reward = 1
# 挖礦函數:尋找nonce的值
def mine(self):
i = 0
prefix = '0' * self.difficult
while True:
message = hashlib.sha256()
message.update(str(self.block.pre_hash).encode('utf-8'))
message.update(str(self.block.transaction).encode('utf-8'))
message.update(str(self.block.timetamp).encode('utf-8'))
message.update(str(i).encode('utf-8'))
digest = message.hexdigest()
if digest.startswith(prefix):
self.block.nonce = i
self.block.hash = digest
return self.block
i += 1
# 添加獎勵
t = Transaction(sender="", recipient=self.miner.address, amount=self.reward)
sig = self.miner.sign(json.dumps(t, cls=Transaction))
# sig = self.miner.sign(t)
t.setSign(sig, self.miner.pubkey)
self.block.transaction.append(t)
# 驗證區塊有效性
def validate(self):
message = hashlib.sha256()
message.update(str(self.block.pre_hash).encode('utf-8'))
message.update(str(self.block.transaction).encode('utf-8'))
message.update(str(self.block.timetamp).encode('utf-8'))
message.update(str(self.block.nonce).encode('utf-8'))
digest = message.hexdigest()
prefix = '0' * self.difficult
return digest.startswith(prefix)
getBalance()函數獲取區塊鏈中賬戶的加密數字貨幣信息
# 獲取區塊鏈中加密數字貨幣情況
def getBalance(user):
balance = 0
for block in bc.blocks:
for t in block.transaction:
if t.sender == user.address.decode(): # 如果用戶是發送方
balance -= t.amount
elif t.recipient == user.address.decode(): # 如果用戶是接收方
balance += t.amount
return balance
測試整個區塊鏈的交易情況:初始化一個區塊鏈和3個錢包,查看錢包餘額。
# 創建一個區塊鏈
bc = BlockChain()
# 測試交易功能
a = Wallet()
b = Wallet()
c = Wallet()
print("a:%d個加密貨幣" % (getBalance(a)))
print("b:%d個加密貨幣" % (getBalance(b)))
print("c:%d個加密貨幣" % (getBalance(c)))
運行結果:餘額均爲 0
a:0個加密貨幣
b:0個加密貨幣
c:0個加密貨幣