diff --git a/node/rustchain_p2p_sync.py b/node/rustchain_p2p_sync.py index 01d7cec50..5d6bc6c17 100644 --- a/node/rustchain_p2p_sync.py +++ b/node/rustchain_p2p_sync.py @@ -404,11 +404,15 @@ def stop_health_checks(self): def add_p2p_endpoints(app, peer_manager, block_sync, tx_gossip): """Add P2P endpoints to Flask app""" + from flask import jsonify, request @app.route('/p2p/announce', methods=['POST']) def announce_peer(): """Endpoint for peer nodes to announce themselves""" - data = request.get_json() + data = request.get_json(silent=True) + if not isinstance(data, dict): + return jsonify({"ok": False, "error": "JSON object required"}), 400 + peer_url = data.get('peer_url') if peer_url: diff --git a/node/tests/test_p2p_sync_routes.py b/node/tests/test_p2p_sync_routes.py new file mode 100644 index 000000000..d676c38ad --- /dev/null +++ b/node/tests/test_p2p_sync_routes.py @@ -0,0 +1,54 @@ +# SPDX-License-Identifier: MIT + +from flask import Flask + +from node.rustchain_p2p_sync import add_p2p_endpoints + + +class StubPeerManager: + db_path = ":memory:" + + def __init__(self): + self.peers = [] + + def add_peer(self, peer_url): + self.peers.append(peer_url) + return True + + def get_active_peers(self): + return list(self.peers) + + +def build_client(): + app = Flask(__name__) + peer_manager = StubPeerManager() + add_p2p_endpoints(app, peer_manager, block_sync=None, tx_gossip=None) + return app.test_client(), peer_manager + + +def test_p2p_announce_accepts_valid_peer_url(): + client, peer_manager = build_client() + + response = client.post("/p2p/announce", json={"peer_url": "http://peer.example:8088"}) + + assert response.status_code == 200 + assert response.get_json() == {"ok": True, "peers": 1} + assert peer_manager.peers == ["http://peer.example:8088"] + + +def test_p2p_announce_rejects_non_object_json(): + client, _ = build_client() + + response = client.post("/p2p/announce", json=["peer_url", "http://peer.example:8088"]) + + assert response.status_code == 400 + assert response.get_json() == {"ok": False, "error": "JSON object required"} + + +def test_p2p_announce_rejects_missing_peer_url(): + client, _ = build_client() + + response = client.post("/p2p/announce", json={}) + + assert response.status_code == 400 + assert response.get_json() == {"ok": False, "error": "peer_url required"}