From b34df464f40c31efed1d84dfe191a589973fe730 Mon Sep 17 00:00:00 2001 From: shantanushok <159703391+shantanushok@users.noreply.github.com> Date: Wed, 12 Aug 2026 05:39:15 +0000 Subject: [PATCH 1/3] docs: update coverage badge --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 4c41e20..05bb524 100644 --- a/README.md +++ b/README.md @@ -42,7 +42,7 @@

-Coverage
Coverage Report
FileStmtsMissCoverMissing
minichain
   block.py921683%10, 14, 17–23, 72, 138–140, 165, 170, 179, 181
   chain.py2276372%17, 22, 28, 32, 34, 37, 41, 68–73, 81–82, 89–90, 98–99, 104–105, 126–129, 182–185, 195–196, 205–206, 209–210, 214–215, 234, 258, 266–274, 283–284, 286–287, 310–313, 316–325, 335–336
   contract.py1548147%11–12, 15–20, 36–89, 124, 128, 136, 192–195, 215–216, 225–227, 234–235, 239–241, 249–250, 252–253, 258–259, 261–262, 264–265, 267–268, 270–271
   mempool.py651675%17–18, 32–34, 39–40, 42–43, 49–50, 56, 59–60, 67–69
   mpt.py14379%18–20
   p2p.py26319625%30–31, 71, 74, 77, 80, 83–90, 93–94, 97–98, 103, 118, 121, 124–126, 129–131, 134, 137, 140, 144–145, 155–157, 168–182, 189–195, 204–258, 263–373
   persistence.py1713977%84, 90, 92, 133, 143–144, 223–224, 244, 247–248, 270, 282–293, 296–297, 303–307, 310–313, 316–320
   pow.py431467%33, 42, 52–54, 58–60, 70, 75–79
   rpc.py822668%41–42, 45, 61, 64, 68, 73–76, 78–91, 96–98
   state.py2141792%35, 56–57, 90, 109–110, 156, 169, 217, 277, 302, 332, 335–340
   validators.py9189%13
TOTAL144547267% 
+Coverage
Coverage Report
FileStmtsMissCoverMissing
minichain
   block.py921683%10, 14, 17–23, 72, 138–140, 165, 170, 179, 181
   chain.py2276372%17, 22, 28, 32, 34, 37, 41, 68–73, 81–82, 89–90, 98–99, 104–105, 126–129, 182–185, 195–196, 205–206, 209–210, 214–215, 234, 258, 266–274, 283–284, 286–287, 310–313, 316–325, 335–336
   contract.py1548147%11–12, 15–20, 36–89, 124, 128, 136, 192–195, 215–216, 225–227, 234–235, 239–241, 249–250, 252–253, 258–259, 261–262, 264–265, 267–268, 270–271
   mempool.py651675%17–18, 32–34, 39–40, 42–43, 49–50, 56, 59–60, 67–69
   mpt.py14379%18–20
   p2p.py26319625%30–31, 71, 74, 77, 80, 83–90, 93–94, 97–98, 103, 118, 121, 124–126, 129–131, 134, 137, 140, 144–145, 155–157, 168–182, 189–195, 204–258, 263–373
   persistence.py1713977%84, 90, 92, 133, 143–144, 223–224, 244, 247–248, 270, 282–293, 296–297, 303–307, 310–313, 316–320
   pow.py431467%33, 42, 52–54, 58–60, 70, 75–79
   rpc.py822668%41–42, 45, 61, 64, 68, 73–76, 78–91, 96–98
   state.py2141792%35, 56–57, 90, 109–110, 156, 169, 217, 277, 302, 332, 335–340
   validators.py9189%13
TOTAL144547267% 
From 41fb80eeef2a74a9770d8c47063d07536820bee4 Mon Sep 17 00:00:00 2001 From: Shantanu Date: Fri, 14 Aug 2026 21:22:40 +0530 Subject: [PATCH 2/3] fix(p2p): guard against non-dict hello payload --- main.py | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/main.py b/main.py index b37fce4..e202f9a 100644 --- a/main.py +++ b/main.py @@ -197,6 +197,14 @@ async def handler(data): return if msg_type == "hello": + if not isinstance(payload, dict): + logger.warning( + "Malformed hello from %s: payload is not a dict (got %s). Disconnecting.", + peer_addr, type(payload).__name__ + ) + asyncio.create_task(network.disconnect_peer(peer_addr)) + return ValidationStatus.MALFORMED + peer_chain_id = payload.get("chain_id") peer_gen_hash = payload.get("genesis_hash") if peer_chain_id != chain.chain_id: From 949b4d84632781bd7dc7883bc106e1aae8a43257 Mon Sep 17 00:00:00 2001 From: Shantanu Date: Sat, 15 Aug 2026 14:23:35 +0530 Subject: [PATCH 3/3] coderabbit changes addressed (hardening of the malformed 'hello' messages) --- main.py | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/main.py b/main.py index e202f9a..4c868b7 100644 --- a/main.py +++ b/main.py @@ -193,8 +193,11 @@ async def handler(data): payload = data.get("data") peer_addr = data.get("_peer_addr", "unknown") - if payload is None and msg_type in ("hello", "chain_request", "chain_response"): + if payload is None and msg_type in ("chain_request", "chain_response"): return + + # Note: a null payload in a hello message deliberately falls through + # to the isinstance(payload, dict) guard below, which disconnects the peer. if msg_type == "hello": if not isinstance(payload, dict): @@ -218,6 +221,14 @@ async def handler(data): logger.info("🔄 Handshake successful with %s", peer_addr) peer_tip = payload.get("latest_block_index", 0) + + if not isinstance(peer_tip, int) or isinstance(peer_tip, bool): + logger.warning( + "Malformed hello from %s: latest_block_index is not an integer (got %s). Disconnecting.", + peer_addr, type(peer_tip).__name__ + ) + asyncio.create_task(network.disconnect_peer(peer_addr)) + return ValidationStatus.MALFORMED if peer_tip > chain.last_block.index: logger.info("📡 Peer %s is ahead (%d > %d). Initiating chunked sync...", peer_addr, peer_tip, chain.last_block.index) request_chain(network, chain.last_block.index + 1, 500)