python实现区块链

鞠凌龙
2023-12-01

区块结构:

# 区块结构
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个加密货币

 

 类似资料: