From 53e659fc9d8fa1b060936245c1f2749c1d217b75 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lukas=20F=C3=BCrderer?= Date: Sat, 16 Mar 2024 15:20:46 +0100 Subject: [PATCH] Fill computed fields during validation --- blockchain.py | 88 +++++++++++++++++++++++++++++---------------------- 1 file changed, 51 insertions(+), 37 deletions(-) diff --git a/blockchain.py b/blockchain.py index 807c560..26c8a7c 100644 --- a/blockchain.py +++ b/blockchain.py @@ -32,9 +32,16 @@ class Transaction: if balance is None: return False return balance >= self.amount + self.transaction_fee + def get_transaction_raw(self): + return self.id.to_bytes(4, "big") + \ + self.sender + \ + self.receiver + \ + self.amount.to_bytes(8, "big") + \ + self.transaction_fee.to_bytes(8, "big") + \ + self.signature @dataclass -class FullBlock: +class Block: nonce: int timestamp: int previous_hash: bytes @@ -45,14 +52,15 @@ class FullBlock: balances: dict # (sender_pubkey, id) tuples used_transaction_ids: set + valid: bool - def is_valid(self, blockchain): + def validate(self, blockchain): if self.transaction is not None: if not self.transaction.is_valid(): return False if self.previous_hash != 32 * b"\0": prev_block = blockchain.get_block(self.previous_hash) - if type(prev_block) is not FullBlock: + if not prev_block.valid: return False if self.timestamp <= prev_block.timestamp: return False @@ -72,7 +80,35 @@ class FullBlock: return False block_raw = self.get_block_raw() block_hash = hashlib.sha256(block_raw).digest() - return int.from_bytes(block_hash, "big") * block_difficulty < 2**256 + self.valid = int.from_bytes(block_hash, "big") * block_difficulty < 2**256 + if self.valid: + self.calculate_balances(prev_block) + self.calculate_used_transaction_ids(prev_block) + return self.valid + def calculate_balances(self, prev_block): + if prev_block is None: + self.balances = { + self.miner_pubkey: 100, + } + return + balances = prev_block.balances.copy() + balances.setdefault(self.miner_pubkey, 0) + balances[miner_pubkey] += 100 + t = self.transaction + if t is not None: + balances[miner_pubkey] += t.transaction_fee + balances[t.sender] -= (t.amount + t.transaction_fee) + balances[t.receiver] += t.amount + self.balances = balances + def calculate_used_transaction_ids(self, prev_block): + if prev_block is None: + self.used_transaction_ids = set() + return + used_transaction_ids = prev_block.used_transaction_ids.copy() + t = self.transaction + if t is not None: + used_transaction_ids.add((t.sender, t.id)) + self.used_transaction_ids = used_transaction_ids def get_difficulty_info(self, steps, blockchain): if steps == 0: return self.difficulty_sum, self.timestamp @@ -83,40 +119,18 @@ class FullBlock: else: previous_block = blockchain.get_block(self.previous_hash) return previous_block.get_difficulty_info(steps-1, blockchain) - -@dataclass -class Datastructure: - nonce:int - timestamp: int - previous_hash: bytes - message: bytes - difficulty_sum: int - miner_pubkey: bytes - transaction: int - - def get_block_raw(self): - sender_pubkey_raw = Ed25519PublicKey.from_public_bytes(self.sender) - msg_raw = self.nonce.to_bytes(8, "big") + \ - self.timestamp.to_bytes(8, "big") + \ - self.previous_hash + \ - self.message + \ - self.difficulty_sum.to_bytes(32, "big") + \ - self.miner_pubkey +\ - self.transaction.to_bytes(148, "big") - try: - sender_pubkey_raw.verify(self.previous_hash,msg_raw) - except InvalidSignature: - return False - return self.transaction >=1 - def is_valid_after_transaction(self.tansaction): - if(self.transaction is None): - return False - - - - - + if self.transaction is None: + transaction = 148 * b"\0" + else: + transaction = self.transaction.get_transaction_raw() + return self.nonce.to_bytes(8, "big") + \ + self.timestamp.to_bytes(8, "big") + \ + self.previous_hash + \ + self.message + \ + self.difficulty_sum.to_bytes(32, "big") + \ + self.miner_pubkey + \ + transaction class Blockchain: def __init__(self):