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