Skip to content

Fix P2P message validation and host parameter#64

Open
quickquickcode wants to merge 2 commits intoStabilityNexus:mainfrom
quickquickcode:quickquickcode/fix_run_code
Open

Fix P2P message validation and host parameter#64
quickquickcode wants to merge 2 commits intoStabilityNexus:mainfrom
quickquickcode:quickquickcode/fix_run_code

Conversation

@quickquickcode
Copy link

@quickquickcode quickquickcode commented Mar 21, 2026

Problem

When starting a second MiniChain node and connecting to the first node, the following issues occurred:

  1. AttributeError: 'P2PNetwork' object has no attribute 'set_on_peer_connected'
  2. OSError: Missing host parameter in run_node function
  3. Invalid message schema warnings: The _validate_message method strictly checked for {"type", "data"} fields, but _listen_to_peer adds _peer_addr field, causing validation to fail

Solution

  1. Added missing host parameter to run_node function in main.py
  2. Changed network.set_on_peer_connected() to network._on_peer_connected = on_peer_connected
  3. Updated P2PNetwork.start() method to accept host parameter
  4. Modified _validate_message to allow _peer_addr field in addition to type and data

Testing

  • All 41 existing tests pass
  • Manual testing shows nodes can now connect without validation errors

Changes

  • main.py: Fixed function signature and method call
  • minichain/p2p.py: Added host parameter and fixed message validation logic

Summary by CodeRabbit

  • New Features

    • Nodes can bind to configurable host addresses (not limited to localhost).
    • Added a formal peer-connected callback registration so handlers can be attached more predictably.
  • Improvements

    • Centralized peer-connected notification and error handling for more consistent behavior.
    • Relaxed peer message validation to allow required fields plus controlled additional metadata while preserving protocol integrity.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Mar 21, 2026

Walkthrough

The PR adds configurable host binding for the P2P server, changes how peer-connected callbacks are registered, centralizes peer-connected notification handling, and relaxes message validation/peer-address attachment timing.

Changes

Cohort / File(s) Summary
Node startup
main.py
run_node signature now requires host: str; asyncio.run(...) is updated to pass args.host.
P2P network core
minichain/p2p.py
P2PNetwork.start gains host: str = "127.0.0.1" and binds that address. Added register_on_peer_connected(handler_callback) and centralized _notify_peer_connected(writer, error_message); connection handlers now call _notify_peer_connected(...). Message validation relaxed to require type and data and prohibits extra keys; peer address (_peer_addr) is attached after validation and duplicate checks.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

Suggested labels

Python Lang

Suggested reviewers

  • Zahnentferner

Poem

🐰 I hop to the node with a binding new beat,
Listening on hosts where peers come to meet,
Callbacks registered, notifications sing,
Messages kinder to metadata I bring,
A tiny chain hums — network paws tap the street.

🚥 Pre-merge checks | ✅ 2
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the main changes: it addresses both the P2P message validation fix and the host parameter addition, which are the core issues resolved in this PR.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@main.py`:
- Line 329: Replace the direct assignment to the private attribute
network._on_peer_connected by adding a public registration method on the
P2PNetwork class (e.g., register_on_peer_connected or
add_peer_connected_handler) that accepts the callback and sets/updates the
internal handler, then call that method from main.py instead of writing to
network._on_peer_connected; modify P2PNetwork to store the handler and invoke it
where peers connect, and update main.py to call the new public method with
on_peer_connected.

In `@minichain/p2p.py`:
- Around line 209-215: The current validator is allowing `_peer_addr` in the
on‑wire schema; instead validate the raw envelope first by checking
required_fields = {"type","data"} against the incoming message (ensure issubset
of set(message)) and reject any extra fields immediately (i.e. ensure
set(message).issubset({"type","data"})) before attaching transport metadata;
remove `_peer_addr` from allowed_fields validation and only add `_peer_addr`
after the message passes validation (the place where `_listen_to_peer` attaches
`_peer_addr` should perform that attachment post‑validation).
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: 95a741f2-3b3e-41b0-8eba-b6f1edbbfcf3

📥 Commits

Reviewing files that changed from the base of the PR and between 1b61cae and 195f09d.

📒 Files selected for processing (2)
  • main.py
  • minichain/p2p.py

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
main.py (1)

334-339: ⚠️ Potential issue | 🟡 Minor

Variable shadowing: host is reassigned from bind address to peer address.

Line 336 reuses the host variable (originally the bind address) to store the peer's host from connect_to. While this doesn't cause a bug in the current code flow, it's confusing and error-prone for future maintenance. Consider using a distinct name like peer_host.

🔧 Proposed fix
     if connect_to:
         try:
-            host, peer_port = connect_to.rsplit(":", 1)
-            await network.connect_to_peer(host, int(peer_port))
+            peer_host, peer_port = connect_to.rsplit(":", 1)
+            await network.connect_to_peer(peer_host, int(peer_port))
         except ValueError:
             logger.error("Invalid --connect format. Use host:port")
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@main.py` around lines 334 - 339, The code reuses the variable name host
(originally the bind address) when parsing connect_to, which can be confusing;
change the parsing to use a distinct name (e.g., peer_host) so you do:
peer_host, peer_port = connect_to.rsplit(":", 1) and then call await
network.connect_to_peer(peer_host, int(peer_port)) (keep the existing try/except
ValueError unchanged).
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@minichain/p2p.py`:
- Around line 51-56: Add an explicit return type annotation to the helper method
_notify_peer_connected: change its signature to declare it returns None (i.e.,
async def _notify_peer_connected(self, writer, error_message) -> None). This
satisfies type checkers and clarifies intent while leaving the existing await
self._on_peer_connected(writer) and exception logging logic unchanged.
- Around line 213-217: Replace the two bidirectional subset checks with a single
equality check: ensure the validator uses required_fields = {"type", "data"} and
then return False if set(message) != required_fields; update the code around the
current checks (the variables required_fields and message in this scope) so the
logic is a single equality comparison and continues to exclude _peer_addr from
the wire-schema validation.

---

Outside diff comments:
In `@main.py`:
- Around line 334-339: The code reuses the variable name host (originally the
bind address) when parsing connect_to, which can be confusing; change the
parsing to use a distinct name (e.g., peer_host) so you do: peer_host, peer_port
= connect_to.rsplit(":", 1) and then call await
network.connect_to_peer(peer_host, int(peer_port)) (keep the existing try/except
ValueError unchanged).
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: 616067d3-7364-47f6-88b9-1337ce311b32

📥 Commits

Reviewing files that changed from the base of the PR and between 195f09d and 7b238b2.

📒 Files selected for processing (2)
  • main.py
  • minichain/p2p.py

Comment on lines +51 to +56
async def _notify_peer_connected(self, writer, error_message):
if self._on_peer_connected:
try:
await self._on_peer_connected(writer)
except Exception:
logger.exception(error_message)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick | 🔵 Trivial

Consider adding return type annotation.

The helper centralizes callback invocation nicely. Adding -> None would satisfy type checkers and improve clarity.

🔧 Proposed fix
-    async def _notify_peer_connected(self, writer, error_message):
+    async def _notify_peer_connected(self, writer, error_message) -> None:
🧰 Tools
🪛 Ruff (0.15.6)

[warning] 51-51: Missing return type annotation for private function _notify_peer_connected

Add return type annotation: None

(ANN202)

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@minichain/p2p.py` around lines 51 - 56, Add an explicit return type
annotation to the helper method _notify_peer_connected: change its signature to
declare it returns None (i.e., async def _notify_peer_connected(self, writer,
error_message) -> None). This satisfies type checkers and clarifies intent while
leaving the existing await self._on_peer_connected(writer) and exception logging
logic unchanged.

Comment on lines +213 to 217
required_fields = {"type", "data"}
if not required_fields.issubset(set(message)):
return False
if not set(message).issubset(required_fields):
return False
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick | 🔵 Trivial

Consider simplifying to a single equality check.

The bidirectional subset checks (required_fields.issubset(set(message)) AND set(message).issubset(required_fields)) are logically equivalent to set(message) == required_fields. A single equality check would be more direct.

This properly addresses the past review feedback to keep _peer_addr out of the wire-schema validator.

🔧 Proposed simplification
     def _validate_message(self, message):
         if not isinstance(message, dict):
             return False
-        required_fields = {"type", "data"}
-        if not required_fields.issubset(set(message)):
-            return False
-        if not set(message).issubset(required_fields):
+        if set(message) != {"type", "data"}:
             return False
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@minichain/p2p.py` around lines 213 - 217, Replace the two bidirectional
subset checks with a single equality check: ensure the validator uses
required_fields = {"type", "data"} and then return False if set(message) !=
required_fields; update the code around the current checks (the variables
required_fields and message in this scope) so the logic is a single equality
comparison and continues to exclude _peer_addr from the wire-schema validation.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant