feat(p2p): mesh stack, LoRa mock transport, and relay demo

Implement transport abstraction (TCP/iroh), announce and routing table,
multi-hop mesh router, truncated-address link layer, and LoRa mock
medium with fragmentation plus EU868-style duty-cycle accounting.
Add mesh_lora_relay_demo and scripts/mesh-demo.sh. Relax CBOR vs JSON
size assertion to match fixed-size cryptographic overhead. Extend
.gitignore for nested targets and node_modules.

Made-with: Cursor
This commit is contained in:
2026-03-30 21:19:12 +02:00
parent d469999c2a
commit f9ac921a0c
20 changed files with 4042 additions and 6 deletions

View File

@@ -12,11 +12,22 @@
//! └── QUIC/TLS ── Server ── QUIC/TLS ┘ (fallback: store-and-forward)
//! ```
pub mod address;
pub mod announce;
pub mod announce_protocol;
pub mod broadcast;
pub mod envelope;
pub mod identity;
pub mod link;
pub mod mesh_router;
pub mod routing;
pub mod routing_table;
pub mod store;
pub mod transport;
pub mod transport_iroh;
pub mod transport_manager;
pub mod transport_tcp;
pub mod transport_lora;
#[cfg(feature = "traffic-resistance")]
pub mod traffic_resistance;
@@ -204,7 +215,7 @@ impl P2pNode {
.ok_or_else(|| anyhow::anyhow!("mesh identity not configured"))?;
let envelope = MeshEnvelope::new(identity, recipient_key, payload, ttl_secs, 0);
let bytes = envelope.to_bytes();
let bytes = envelope.to_wire();
if let Some(addr) = peer_addr {
self.send(addr, &bytes).await?;
@@ -257,7 +268,7 @@ impl P2pNode {
for env in envelopes {
if env.can_forward() {
let fwd = env.forwarded();
let bytes = fwd.to_bytes();
let bytes = fwd.to_wire();
self.send(peer_addr.clone(), &bytes).await?;
forwarded += 1;
}
@@ -318,7 +329,7 @@ impl P2pNode {
// Create a broadcast envelope (empty recipient_key signals broadcast).
let envelope = MeshEnvelope::new(identity, &[], encrypted, 300, 0);
let bytes = envelope.to_bytes();
let bytes = envelope.to_wire();
// Store in the mesh store for flood-forwarding.
let mut store = self