""" Quick prototype of Betanet layers L1, L2, L3 and L5 in an asyncio simulation. Disclaimer: This is a simplified educational prototype. Cryptography is simulated using hash/HMAC placeholders (not real Ed25519/X25519). Replace placeholders with real crypto libraries (PyNaCl / cryptography) for production-quality code. Mapping to spec: - L1: Path and AS-hop validation (simple path object + signature checks) - L2: HTX session with outer 'fingerprint' mirroring and inner Noise-like handshake - L3: Overlay mesh with simple peerstore and content exchange (bitswap-like) - L5: Self-certifying IDs and a tiny alias ledger with finality simulation """ import asyncio import time from src.alias_ledger import AliasLedger from src.ashop import ASHop from src.betanet_cryptography import KeyPair from src.htx_frame import FT_CLOSE, FT_KEY_UPDATE, FT_PING, FT_STREAM from src.htx_session import HTXSession from src.overlay_node import OverlayNode from src.path import L1Path, PathSegment async def demo(): # Create AS keys for L1 hop validation as_keys = { "AS1": KeyPair(), "AS2": KeyPair(), "AS3": KeyPair(), } # Create overlay nodes (L3) with keys (these also act as service endpoints L5) nodeA = OverlayNode("Alice", KeyPair()) nodeB = OverlayNode("Bob", KeyPair()) nodeC = OverlayNode("Carol", KeyPair()) # Connect peers (mesh) nodeA.add_peer(nodeB) nodeB.add_peer(nodeC) nodeA.add_peer(nodeC) # L5: register an alias for Carol ledger = AliasLedger() ledger.register_alias("carol.service", nodeC.kp, seq=1, exp=int(time.time()) + 3600) # L1: Build a SCION-like path A -> AS1 -> AS2 -> C hop1_sig = as_keys["AS1"].sign(b"AS1") hop2_sig = as_keys["AS2"].sign(b"AS2") segment = PathSegment([ASHop("AS1", hop1_sig), ASHop("AS2", hop2_sig)]) path = L1Path([segment]) assert path.validate(as_keys), "L1 path validation failed" print("[L1] Path validated") # L2: Setup HTX session between A and C (outer fingerprint mirrored) fingerprint = "origin:example.com:ja3hash" # placeholder sessionAC_local = HTXSession(nodeA.kp, nodeC.kp.pub, fingerprint) sessionAC_remote = HTXSession(nodeC.kp, nodeA.kp.pub, fingerprint) # link peers sessionAC_local.peer = sessionAC_remote sessionAC_remote.peer = sessionAC_local await asyncio.gather( sessionAC_local.perform_handshake(), sessionAC_remote.perform_handshake() ) # Start receive loops async def handler_a(ftype, sid, plain): print( f"[L2][A] Received frame type={ftype} sid={sid} payload={plain.decode(errors='ignore')}" ) async def handler_c(ftype, sid, plain): print( f"[L2][C] Received frame type={ftype} sid={sid} payload={plain.decode(errors='ignore')}" ) asyncio.create_task(sessionAC_local.recv_loop(handler_a)) asyncio.create_task(sessionAC_remote.recv_loop(handler_c)) # L3: publish content from Carol cid = nodeC.publish(b"Hello from Carol's content!") print(f"[L3] Carol published CID {cid[:16]}...") # A resolves 'carol.service' via L5 resolved_pk_hex = ledger.resolve("carol.service") if not resolved_pk_hex: print("[L5] Alias resolution failed") return print(f"[L5] Resolved carol.service -> {resolved_pk_hex[:16]}...") # A asks overlay for CID (bitswap) content = await nodeA.bitswap_get(cid) if content: print("[L3] Alice retrieved content via overlay:", content.data) else: print("[L3] Alice failed to retrieve content from overlay") # A sends a message to C over HTX inner frames (L2) await sessionAC_local.send_frame( FT_STREAM, 1, b"GET /resource HTTP/1.1\r\nHost: carol.service\r\n\r\n" ) await asyncio.sleep(0.2) # Simulate KEY_UPDATE await sessionAC_local.send_frame(FT_KEY_UPDATE, None, b"KEY_UPDATE") await asyncio.sleep(0.2) # Send a ping await sessionAC_local.send_frame(FT_PING, None, b"PING") await asyncio.sleep(0.2) # Close await sessionAC_local.send_frame(FT_CLOSE, None, b"GOODBYE") await asyncio.sleep(0.2) print("\nDemo complete.") if __name__ == "__main__": asyncio.run(demo())