|
9 | 9 | import json |
10 | 10 | import logging |
11 | 11 |
|
12 | | -from .serialization import canonical_json_hash |
| 12 | +from .serialization import canonical_json_hash, canonical_json_dumps |
13 | 13 | from .validators import is_valid_receiver |
14 | 14 |
|
15 | 15 | logger = logging.getLogger(__name__) |
@@ -46,10 +46,8 @@ def register_handler(self, handler_callback): |
46 | 46 | async def start(self, port: int = 9000): |
47 | 47 | """Start listening for incoming peer connections on the given port.""" |
48 | 48 | self._port = port |
49 | | - self._server = await asyncio.start_server( |
50 | | - self._handle_incoming, host, port |
51 | | - ) |
52 | | - logger.info("Network: Listening on %s:%d", host, port) |
| 49 | + self._server = await asyncio.start_server(self._handle_incoming, "0.0.0.0", port) |
| 50 | + logger.info("Network: Listening on 0.0.0.0:%d", port) |
53 | 51 |
|
54 | 52 | async def stop(self): |
55 | 53 | """Gracefully shut down the server and disconnect all peers.""" |
@@ -204,9 +202,7 @@ def _validate_block_payload(self, payload): |
204 | 202 | ) |
205 | 203 |
|
206 | 204 | def _validate_message(self, message): |
207 | | - if not isinstance(message, dict): |
208 | | - return False |
209 | | - if set(message) != {"type", "data"}: |
| 205 | + if not {"type", "data"}.issubset(set(message)): |
210 | 206 | return False |
211 | 207 |
|
212 | 208 | msg_type = message.get("type") |
@@ -303,6 +299,7 @@ async def _listen_to_peer( |
303 | 299 | async def _broadcast_raw(self, payload: dict): |
304 | 300 | """Send a JSON message to every connected peer.""" |
305 | 301 | line = (json.dumps(payload) + "\n").encode() |
| 302 | + line = (canonical_json_dumps(payload) + "\n").encode() |
306 | 303 | disconnected = [] |
307 | 304 | for reader, writer in self._peers: |
308 | 305 | try: |
@@ -333,10 +330,16 @@ async def broadcast_transaction(self, tx): |
333 | 330 |
|
334 | 331 | async def broadcast_block(self, block, miner=None): |
335 | 332 | logger.info("Network: Broadcasting Block #%d", block.index) |
336 | | - block_payload = block.to_dict() |
337 | | - if miner is not None: |
338 | | - block_payload["miner"] = miner |
339 | | - payload = {"type": "block", "data": block_payload} |
| 333 | + |
| 334 | + # 1. Convert block to a dict (deterministic via serialization.py) |
| 335 | + block_data = json.loads(block.canonical_payload.decode('utf-8')) |
| 336 | + |
| 337 | + # 2. Wrap it in an envelope where 'miner' is OUTSIDE the 'data' |
| 338 | + payload = { |
| 339 | + "type": "block", |
| 340 | + "data": block_data, |
| 341 | + "miner": miner |
| 342 | + } |
340 | 343 | self._mark_seen("block", payload["data"]) |
341 | 344 | await self._broadcast_raw(payload) |
342 | 345 |
|
|
0 commit comments