python實現區塊鏈

區塊結構:

# 區塊結構
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個加密貨幣

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章