python区块链简单模拟【03】

引入钱包,账户地址,公私钥

bash 复制代码
# 导入椭圆曲线算法
from ecdsa import SigningKey, SECP256k1, VerifyingKey, BadSignatureError
import binascii
import base64
from hashlib import sha256


class Wallet:
    """
        钱包
    """
    def __init__(self):
        """
            钱包初始化时基于椭圆曲线生成一个唯一的秘钥对,代表区块链上一个唯一的账户
        """
        self._private_key = SigningKey.generate(curve=SECP256k1)   #私钥  签名
        self._public_key = self._private_key.get_verifying_key()   #公钥  验证 

    @property    #通过 @property 装饰器,可以直接通过方法名来访问方法,不需要在方法名后添加一对"()"小括号。
    def address(self):
        """
            这里通过公钥生成地址
            base64.b64encode()将bytes类型数据进行base64编码,返回编码后的bytes类型
            base64.b64deocde()将base64编码的bytes类型进行解码,返回解码后的bytes类型、
            常见于网址url加密中
        """
        h = sha256(self._public_key.to_pem())
        return base64.b64encode(h.digest())  #返回16进制sha256哈希加密后的哈希值并对其进行编码

    @property
    def pubkey(self):
        """
            返回公钥字符串
        """
        return self._public_key.to_pem()

    def sign(self, message):
        """
            生成数字签名
        """
        h = sha256(message.encode('utf8'))
        return binascii.hexlify(self._private_key.sign(h.digest()))  #二进制输出

    
def verify_sign(pubkey, message, signature):
    """
        验证签名
    """
    verifier = VerifyingKey.from_pem(pubkey)
    h = sha256(message.encode('utf8'))
    return verifier.verify(binascii.unhexlify(signature), h.digest())
bash 复制代码
# 新建一个钱包

w = Wallet()
bash 复制代码
# 打印钱包地址  
w.address
bash 复制代码
# 打印钱包公钥

w.pubkey
bash 复制代码
# 测试数据

data = "交易数据"
bash 复制代码
# 生成签名

sig = w.sign(data)

# 打印签名
print(sig)
bash 复制代码
# 验证签名

verify_sign(w.pubkey, data, sig)
bash 复制代码
import json

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 set_sign(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 TransactionEncoder(json.JSONEncoder):
    """
    定义Json的编码类,用来序列化Transaction
    """
    def default(self, obj):
        if isinstance(obj, Transaction):
            return obj.__dict__
        else:
            return json.JSONEncoder.default(self, obj)

`import hashlib

from datetime import datetime

class Block:

"""

区块结构

prev_hash: 父区块哈希值

transactions: 交易列表

timestamp: 区块创建时间

hash: 区块哈希值

Nonce: 随机数

"""

def init (self, transactions, prev_hash):

将传入的父哈希值和数据保存到类变量中

self.prev_hash = prev_hash

self.transactions = transactions

获取当前时间

self.timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S")

    # 设置Nonce和哈希的初始值为None
    self.nonce = None
    self.hash = None
    
def __repr__(self):
    return "区块内容:%s\n哈希值: %s" % (json.dumps(self.transactions), self.hash)`
bash 复制代码
class ProofOfWork:
    """
        工作量证明
        简化为一个挖矿者,只要挖矿就一定能挖到,只是时间问题
    """
    def __init__(self, block, miner, difficult=5):
        self.block = block
        
        # 定义工作量难度,默认为5,表示有效的哈希值以5个"0"开头
        self.difficulty = difficult

        self.miner = miner
        
        # 添加挖矿奖励
        self.reward_amount = 1  #奖励一个加密货币

    def mine(self):
        """
            挖矿函数
        """
        i = 0                            #初始化随机值
        prefix = '0' * self.difficulty   #设置难度
        
        
        # 添加奖励                    新建挖矿交易
        t = Transaction(
                sender="",
                recipient=self.miner.address,
                amount=self.reward_amount,
            )
        sig = self.miner.sign(json.dumps(t, cls=TransactionEncoder))    #钱包类中的账户使私钥签名
        t.set_sign(sig, self.miner.pubkey)                              #发送签名和公钥
        self.block.transactions.append(t)                               #将交易添加到区块链中交易列表中

        while True:
            message = hashlib.sha256()
            message.update(str(self.block.prev_hash).encode('utf-8'))
            # 更新区块中的交易数据
            # message.update(str(self.block.data).encode('utf-8'))
            message.update(str(self.block.transactions).encode('utf-8'))
            message.update(str(self.block.timestamp).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

    def validate(self):
        """
            验证有效性
        """
        message = hashlib.sha256()
        
        #四句话将区块各个参数进行哈希运算
        message.update(str(self.block.prev_hash).encode('utf-8'))
        # 更新区块中的交易数据
        # message.update(str(self.block.data).encode('utf-8'))
        message.update(json.dumps(self.block.transactions).encode('utf-8'))
        message.update(str(self.block.timestamp).encode('utf-8'))
        message.update(str(self.block.nonce).encode('utf-8'))
        
        digest = message.hexdigest()  #16进制输出hash值

        prefix = '0' * self.difficulty
        return digest.startswith(prefix)   #验证是否为符合难度的哈希值
bash 复制代码
class BlockChain:
    """
        区块链结构体
            blocks:        包含的区块列表
    """
    def __init__(self):
        self.blocks = []

    def add_block(self, block):
        """
        添加区块
        """
        self.blocks.append(block)
    
    def print_list(self):
        print("区块链包含区块个数: %d\n" % len(self.blocks))
        for block in self.blocks:
            print("上个区块哈希:%s" % block.prev_hash)
            print("区块内容:%s" % block.transactions)
            print("区块哈希:%s" % block.hash)
            print("\n") 
bash 复制代码
def get_balance(user):
    balance = 0
    for block in blockchain.blocks:
        for t in block.transactions:
            if t.sender == user.address.decode():
                balance -= t.amount
            elif t.recipient == user.address.decode():
                balance += t.amount
    return balance
bash 复制代码
# 初始化区块链
blockchain = BlockChain()

# 创建三个钱包,一个属于alice,一个属于tom,剩下一个属于bob
alice = Wallet()
tom = Wallet()
bob = Wallet()

# 打印当前钱包情况
print("alice: %d个加密货币" % (get_balance(alice)))
print("tom: %d个加密货币" % (get_balance(tom)))
print("bob: %d个加密货币" % (get_balance(bob)))
bash 复制代码
# alice生成创世区块,并添加到区块链中

new_block1 = Block(transactions=[], prev_hash="")
w1 = ProofOfWork(new_block1, alice)
genesis_block = w1.mine()
blockchain.add_block(genesis_block)
bash 复制代码
# 显示alice当前余额

print("alice: %d个加密货币" % (get_balance(alice)))
bash 复制代码
# alice 转账给 tom 0.3个加密货币
transactions = []
new_transaction = Transaction(
    sender=alice.address,
    recipient=tom.address,
    amount=0.3
)
sig = tom.sign(str(new_transaction))       #私钥签名
new_transaction.set_sign(sig, tom.pubkey)  #发送签名和公钥
bash 复制代码
# bob 在网络上接收到这笔交易,进行验证没问题后生成一个新的区块并添加到区块链中

if verify_sign(new_transaction.pubkey, 
                  str(new_transaction),
                   new_transaction.signature):    #验证者验证
    
    # 验证交易签名没问题,生成一个新的区块
    print("验证交易成功")
    new_block2 = Block(transactions=[new_transaction], prev_hash="")
    print("生成新的区块...")
    w2 = ProofOfWork(new_block2, bob)
    block = w2.mine()                              #bob挖矿,找到新的区块将其写入区块链
    print("将新区块添加到区块链中")
    blockchain.add_block(block)
else:
    print("交易验证失败!")

# 打印当前钱包情况 print("alice: %.1f个加密货币" % (get_balance(alice))) print("tom: %.1f个加密货币" % (get_balance(tom))) print("bob: %d个加密货币" % (get_balance(bob)))

相关推荐
无须logic ᭄4 分钟前
CrypTen项目实践
python·机器学习·密码学·同态加密
百流17 分钟前
scala文件编译相关理解
开发语言·学习·scala
Channing Lewis17 分钟前
flask常见问答题
后端·python·flask
Channing Lewis19 分钟前
如何保护 Flask API 的安全性?
后端·python·flask
水兵没月1 小时前
钉钉群机器人设置——python版本
python·机器人·钉钉
Evand J1 小时前
matlab绘图——彩色螺旋图
开发语言·matlab·信息可视化
我想学LINUX2 小时前
【2024年华为OD机试】 (A卷,100分)- 微服务的集成测试(JavaScript&Java & Python&C/C++)
java·c语言·javascript·python·华为od·微服务·集成测试
深度混淆2 小时前
C#,入门教程(04)——Visual Studio 2022 数据编程实例:随机数与组合
开发语言·c#
雁于飞2 小时前
c语言贪吃蛇(极简版,基本能玩)
c语言·开发语言·笔记·学习·其他·课程设计·大作业