Corium
Batteries-included adaptive mesh networking
Corium is a high-performance, secure, and adaptive mesh networking library written in Rust. It provides a robust foundation for building decentralized applications, scale-out fabrics, and distributed services with built-in NAT traversal, efficient PubSub, and a cryptographic identity system.
Why Corium?
| Feature | Description |
|---|---|
| Zero-Config NAT Traversal | SmartSock automatically punches holes through NATs and relays traffic when necessary |
| Adaptive DHT | Kademlia-based DHT with adaptive k and α parameters that adjust to network churn |
| Efficient PubSub | PlumTree protocol for scalable message propagation with automatic tree repair |
| Secure by Default | Ed25519 identities + QUIC/TLS 1.3 encryption with mutual authentication |
| Simple API | High-level async API for bootstrapping, messaging, and peer discovery |
Quick Start
Add corium to your Cargo.toml:
[]
= "0.3"
= { = "1", = ["full"] }
Create a Node
use Node;
use Result;
async
PubSub Messaging
// Subscribe to a topic
node.subscribe.await?;
// Publish a message
node.publish.await?;
// Receive messages
let mut messages = node.messages.await?;
while let Some = messages.recv.await
Direct Messaging
// Send a direct message to a peer by identity
node.send_direct.await?;
// Receive direct messages
let mut dms = node.direct_messages.await?;
while let Some = dms.recv.await
Peer Discovery
// Connect to a peer by identity (DHT lookup + SmartConnect)
let conn = node.connect_peer.await?;
// Find peers close to a target identity
let peers = node.find_peers.await?;
// Resolve a peer's endpoint record from DHT
let record = node.resolve_peer.await?;
Architecture
┌─────────────────────────────────────────────────────────────────┐
│ Node │
│ (Public API: bind, bootstrap, publish, subscribe, connect) │
├─────────────────────────────────────────────────────────────────┤
│ │
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────────────┐ │
│ │ PlumTree │ │ HyParView │ │ DhtNode │ │
│ │ (PubSub) │ │ (Overlay) │ │ (Peer Discovery) │ │
│ └──────┬───────┘ └──────┬───────┘ └──────────┬───────────┘ │
│ │ │ │ │
│ └─────────────────┼──────────────────────┘ │
│ │ │
│ ┌──────▼───────┐ │
│ │ RpcNode │ │
│ │ (RPC Layer) │ │
│ └──────┬───────┘ │
│ │ │
│ ┌─────────────────┼─────────────────┐ │
│ │ │ │ │
│ ┌──────▼───────┐ ┌──────▼───────┐ ┌──────▼───────┐ │
│ │ SmartSock │ │ QUIC │ │ UdpRelay │ │
│ │ (Path Mgmt) │ │ (Endpoint) │ │ Server │ │
│ └──────────────┘ └──────────────┘ └──────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────┘
Module Overview
| Module | Lines | Purpose |
|---|---|---|
node.rs |
~370 | Public API facade, orchestrates all subsystems |
transport.rs |
~2260 | SmartSock, path probing, relay tunneling, virtual addressing |
rpc.rs |
~1190 | Connection caching, RPC dispatch, SmartConnect logic |
dht.rs |
~2560 | Kademlia DHT with adaptive parameters, iterative lookups |
plumtree.rs |
~1570 | Epidemic broadcast trees for PubSub |
hyparview.rs |
~770 | Hybrid partial view membership protocol |
routing.rs |
~610 | K-bucket routing table with rate limiting |
identity.rs |
~880 | Ed25519 keypairs, endpoint records, signatures |
messages.rs |
~630 | RPC message types and serialization |
crypto.rs |
~400 | TLS certificates, Ed25519 verification |
Core Concepts
Identity (Zero-Hash Architecture)
Node identities are Ed25519 public keys (32 bytes, displayed as 64 hex characters). This "Zero-Hash" approach means the node ID is the public key—no separate hash mapping required.
let keypair = generate;
let identity: Identity = keypair.identity; // [u8; 32]
println!; // 64 hex chars
Contact
A Contact represents a reachable peer: identity + network addresses.
SmartAddr (Virtual Addressing)
SmartSock maps identities to virtual IPv6 addresses in the fd00:c0f1::/48 prefix, enabling identity-based routing through QUIC.
SmartConnect
When connecting to a peer, Corium uses a multi-stage approach:
- Direct Connection: Try connecting directly to peer's addresses
- DHT Path Nodes: Nodes contacted during DHT lookup become relay candidates
- Relay Fallback: If direct fails, negotiate relay through path nodes
- Path Probing: Continuously probe for better paths after connection
NAT Traversal
How SmartSock Works
┌────────┐ ┌────────┐ ┌────────┐
│ Node A │ │ Relay │ │ Node B │
│ (NAT) │ │ │ │ (NAT) │
└───┬────┘ └───┬────┘ └───┬────┘
│ │ │
│ 1. Try direct connect │ │
│─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─│─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─▶│
│ │ │
│ 2. If failed, request relay │ │
│────────────────────────────▶│ │
│ │ 3. Notify target │
│ │────────────────────────────▶│
│ │ │
│ │◀────────────────────────────│
│◀────────────────────────────│ 4. Relay established │
│ │ │
│ 5. CRLY-framed packets │ │
│════════════════════════════▶│════════════════════════════▶│
│◀════════════════════════════│◀════════════════════════════│
│ │ │
│ 6. Path probing (SMPR) │ │
│─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─│─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─▶│
│ │ │
│ 7. Upgrade to direct if possible │
│──────────────────────────────────────────────────────────▶│
Protocol Headers
| Protocol | Magic | Description |
|---|---|---|
| Relay Tunnel | CRLY |
4-byte magic + 16-byte session ID + payload |
| Path Probe | SMPR |
Request (0x01) / Response (0x02) with RTT measurement |
Path Selection
SmartSock maintains a PeerPathState for each peer with:
- Direct candidates: Known IP addresses
- Relay candidates: Available relay tunnels
- Active path: Currently selected path
- RTT measurements: Exponential moving average (α=0.2)
Direct paths are preferred unless relay is significantly faster (>50ms advantage).
DHT (Distributed Hash Table)
Kademlia Implementation
- XOR Distance Metric: Peers organized by XOR distance from target
- K-Buckets: 256 buckets for 256-bit key space
- Iterative Lookups: Parallel queries with configurable α
- Adaptive Parameters:
kandαadjust based on churn rate
Key Operations
// Store a value
dht.store.await?;
// Retrieve a value
let value = dht.get.await?;
// Find nodes close to a key
let nodes = dht.find_node.await?;
Latency Tiering
Peers are clustered by RTT into tiers:
- Tier 0: Fastest peers (used for lookups)
- Tier 1-N: Progressively slower peers (used for storage offloading)
PlumTree (PubSub)
Epidemic Broadcast Trees
PlumTree combines gossip reliability with tree efficiency:
- Eager Push: Forward full messages to
eager_peers(default: 4) - Lazy Push: Send
IHavetolazy_peers(default: 6) - IWant: Request missing messages
- Graft/Prune: Dynamically repair the broadcast tree
Message Flow
Publisher ──▶ Eager Peers ──▶ Their Eager Peers ──▶ ...
│ │
└── IHave ────▶ Lazy Peers (request via IWant if needed)
Message Authentication
All PubSub messages are signed with the sender's Ed25519 key:
HyParView (Membership)
Maintains a robust overlay network with:
- Active View: Small set of direct connections (default: 5)
- Passive View: Larger pool of known peers (default: 30)
- Shuffle Protocol: Periodically exchanges peers to improve connectivity
- Forward Join: New nodes propagate through the network
Security
Defense Layers
| Layer | Protection |
|---|---|
| Transport | TLS 1.3 via QUIC (mutual authentication) |
| Identity | Ed25519 key pairs, certificates embed public key |
| Messages | Signed PubSub, bounded deserialization |
| Resources | Rate limiting, bounded collections, timeouts |
Security Constants
const MAX_VALUE_SIZE: usize = 1024 * 1024; // 1 MB max DHT value
const MAX_MESSAGE_SIZE: usize = 64 * 1024; // 64 KB max PubSub message
const MAX_CONTACTS_PER_RESPONSE: usize = 100; // Limit DHT response size
const CONNECTION_STALE_TIMEOUT: Duration = 60s; // Connection cache TTL
const RPC_STREAM_TIMEOUT: Duration = 30s; // RPC timeout
CLI Usage
Running a Node
# Start a node on a random port
# Start with specific bind address
# Bootstrap from existing peer
Chatroom Example
# Start first node
# Join from another terminal (copy bootstrap string from first node)
Commands in chatroom:
- Type message and press Enter to broadcast
/dm <identity> <message>- Send direct message/peers- List known peers/quit- Exit
Testing
# Run all tests
# Run with logging
RUST_LOG=debug
# Run specific test
# Run integration tests
# Spawn local cluster
Dependencies
| Crate | Purpose |
|---|---|
quinn |
QUIC implementation |
tokio |
Async runtime |
ed25519-dalek |
Ed25519 signatures |
blake3 |
Fast cryptographic hashing |
rustls |
TLS implementation |
bincode |
Binary serialization |
lru |
LRU caches |
tracing |
Structured logging |
References
NAT Traversal with QUIC
-
Liang, J., et al. (2024). Implementing NAT Hole Punching with QUIC. VTC2024-Fall. arXiv:2408.01791
Demonstrates QUIC hole punching advantages and connection migration saving 2 RTTs.
Distributed Hash Tables
-
Freedman, M. J., et al. (2004). Democratizing Content Publication with Coral. NSDI '04. PDF
Introduced "sloppy" DHT with latency-based clustering—inspiration for Corium's tiering system.
PlumTree
-
Leitão, J., Pereira, J., & Rodrigues, L. (2007). Epidemic Broadcast Trees. SRDS '07.
The original PlumTree paper combining gossip reliability with tree efficiency.
HyParView
-
Leitão, J., Pereira, J., & Rodrigues, L. (2007). HyParView: A Membership Protocol for Reliable Gossip-Based Broadcast. DSN '07.
Hybrid partial view membership protocol for robust overlay maintenance.
License
MIT License - see LICENSE for details.