diff --git a/app/api/fastapi_compat_routes.py b/app/api/fastapi_compat_routes.py index a2a6ba5..a8e9f3c 100644 --- a/app/api/fastapi_compat_routes.py +++ b/app/api/fastapi_compat_routes.py @@ -100,7 +100,10 @@ async def v1_node(): async def v1_node_friendly(): from app.core.crypto import get_ed25519_manager cm = get_ed25519_manager() - return PlainTextResponse(f"Node ID: {cm.node_id}\nIndexer height: 0\nServices: none\n") + return PlainTextResponse(f"Node ID: {cm.node_id} +Indexer height: 0 +Services: none +") @router.post("/api/v1/auth.twa") diff --git a/app/api/fastapi_node_routes.py b/app/api/fastapi_node_routes.py index e6ada15..437cd7c 100644 --- a/app/api/fastapi_node_routes.py +++ b/app/api/fastapi_node_routes.py @@ -38,6 +38,24 @@ async def validate_node_request(request: Request) -> Dict[str, Any]: raise HTTPException(status_code=400, detail="Empty message body") try: message_data = json.loads(body.decode()) +# Anti-replay: validate timestamp and nonce + try: + ts = message_data.get("timestamp") + nonce = message_data.get("nonce") + if ts: + from datetime import datetime, timezone + now = datetime.now(timezone.utc).timestamp() + if abs(float(ts) - float(now)) > 300: + raise HTTPException(status_code=400, detail="stale timestamp") + if nonce: + cache = await get_cache_manager() + cache_key = f"replay:{node_id}:{nonce}" + if await cache.get(cache_key): + raise HTTPException(status_code=400, detail="replay detected") + await cache.set(cache_key, True, ttl=600) + except Exception as _e: + # For backward compatibility, do not fail hard if fields missing + pass except json.JSONDecodeError: raise HTTPException(status_code=400, detail="Invalid JSON in request body") diff --git a/bootstrap.json b/bootstrap.json index 110a266..211ed24 100644 --- a/bootstrap.json +++ b/bootstrap.json @@ -1,14 +1,14 @@ { "version": "3.0.0", - "network_id": "my-network-1755348796", - "created_at": "2025-08-16T12:53:16Z", + "network_id": "my-network-1755357177", + "created_at": "2025-08-16T15:12:57Z", "bootstrap_nodes": [ { - "id": "node-bea1d09bc687311b", - "node_id": "node-bea1d09bc687311b", + "id": "node-1e596b3f9873389c", + "node_id": "node-1e596b3f9873389c", "address": "2a02:6b40:2000:16b1::1", "port": 8000, - "public_key": "bea1d09bc687311b17b048789be8d8950b88904aa68a0d9992a83cb3851e8bd6", + "public_key": "1e596b3f9873389c42b9f08022ceac3331910006ed3e87d40e6561282fd42a1c", "trusted": true, "node_type": "bootstrap" }