Fill computed fields during validation
This commit is contained in:
@@ -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):
|
||||
|
||||
Reference in New Issue
Block a user