11import time
22import hashlib
3- from typing import Optional
4- from collections .abc import Sequence
3+ from typing import Sequence , Optional
54
65from .transaction import Transaction
76from .receipt import Receipt
@@ -39,27 +38,27 @@ def __init__(
3938 self ,
4039 index : int ,
4140 previous_hash : str ,
42- transactions : Optional [ Sequence [ Transaction ]] = None ,
43- timestamp : Optional [ float ] = None ,
44- target : Optional [ int ] = None ,
41+ target : int ,
42+ transactions : Sequence [ Transaction ] = () ,
43+ timestamp : int = 0 ,
4544 state_root : Optional [str ] = None ,
4645 receipt_root : Optional [str ] = None ,
47- receipts : Optional [ Sequence [Receipt ]] = None ,
46+ receipts : Sequence [Receipt ] = () ,
4847 miner : Optional [str ] = None ,
4948 ):
5049 self .index = index
5150 self .previous_hash = previous_hash
5251 # Freeze transactions into an immutable tuple to prevent header/body mismatch
53- self .transactions = tuple (transactions ) if transactions else ()
54- self .receipts = tuple (receipts ) if receipts else ()
52+ self .transactions = tuple (transactions )
53+ self .receipts = tuple (receipts )
5554 self .miner = miner
5655 # Deterministic timestamp (ms)
5756 self .timestamp : int = (
5857 round (time .time () * 1000 )
59- if timestamp is None
58+ if timestamp == 0
6059 else int (timestamp )
6160 )
62- self .target : Optional [ int ] = target
61+ self .target : int = target
6362 self .nonce : int = 0
6463 self .hash : Optional [str ] = None
6564 self .state_root : Optional [str ] = state_root
@@ -83,7 +82,7 @@ def to_header_dict(self):
8382 "state_root" : self .state_root ,
8483 "receipt_root" : self .receipt_root ,
8584 "timestamp" : self .timestamp ,
86- "target" : hex (self .target ) if self . target is not None else None ,
85+ "target" : hex (self .target ),
8786 "nonce" : self .nonce ,
8887 }
8988 # Include miner in header only when present (optional field)
@@ -138,10 +137,10 @@ def from_dict(cls, payload: dict):
138137 if not isinstance (parsed_target , int ) or parsed_target <= 0 or parsed_target > MAX_TARGET :
139138 raise ValueError (f"invalid target in payload: { parsed_target } " )
140139 else :
141- parsed_target = None
140+ raise ValueError ( "missing target in payload" )
142141
143142 raw_ts = payload .get ("timestamp" )
144- parsed_ts = int (raw_ts ) if raw_ts is not None else None
143+ parsed_ts = int (raw_ts ) if raw_ts is not None else 0
145144 block = cls (
146145 index = int (payload ["index" ]),
147146 previous_hash = payload ["previous_hash" ],
@@ -153,18 +152,18 @@ def from_dict(cls, payload: dict):
153152 receipts = receipts ,
154153 miner = payload .get ("miner" ),
155154 )
156- block .nonce = int (payload .get ("nonce" , 0 ) )
155+ block .nonce = int (payload .get ("nonce" ) or 0 )
157156 block .hash = payload .get ("hash" )
158157
159158 # Verify the block hash
160159 expected_hash = block .compute_hash ()
161- if block .hash is not None and block .hash != expected_hash :
160+ if block .hash and block .hash != expected_hash :
162161 raise ValueError ("block hash does not match header" )
163162
164163 # Recalculate and verify the Merkle root!
165164 if "merkle_root" in payload and payload ["merkle_root" ] != block .merkle_root :
166165 raise ValueError ("merkle_root does not match transactions" )
167-
166+
168167 if "receipt_root" in payload :
169168 expected_receipt_root = calculate_receipt_root (block .receipts )
170169 if payload ["receipt_root" ] != expected_receipt_root :
@@ -176,7 +175,7 @@ def from_dict(cls, payload: dict):
176175 def canonical_payload (self ) -> bytes :
177176 """Returns the full block (header + body) as canonical bytes for networking."""
178177 # Sanity checks to prevent broadcasting invalid blocks
179- if self .hash is None :
178+ if not self .hash :
180179 raise ValueError ("block hash is missing" )
181180 if self .hash != self .compute_hash ():
182181 raise ValueError ("block hash does not match header" )
0 commit comments