Networking
Tenzro uses libp2p for peer-to-peer networking, providing decentralized communication via gossipsub pub/sub and Kademlia DHT for peer discovery.
libp2p Stack
- Transport: TCP with noise encryption
- Pub/Sub: Gossipsub for message propagation
- Discovery: Kademlia DHT + mDNS (local)
- Identify: Peer identification and capability exchange
- Ping: Keep-alive and latency measurement
Gossipsub Topics
Nodes subscribe to gossipsub topics for different message types:
| Topic | Purpose |
|---|
| tenzro/blocks/1.0.0 | Block propagation |
| tenzro/transactions/1.0.0 | Transaction propagation |
| tenzro/consensus/1.0.0 | Consensus messages (HotStuff-2) |
| tenzro/attestations/1.0.0 | TEE attestations |
| tenzro/models/1.0.0 | Model registrations |
| tenzro/inference/1.0.0 | Inference requests/responses |
| tenzro/status/1.0.0 | Status and discovery |
Peer Discovery
Bootstrap Nodes
Nodes connect to bootstrap nodes on startup for initial peer discovery:
# Start node with bootstrap nodes
tenzro-node \
--boot-nodes \
/ip4/bootstrap-node-1-ip/tcp/9000/p2p/12D3KooWABC... \
/ip4/bootstrap-node-2-ip/tcp/9000/p2p/12D3KooWDEF...
Kademlia DHT
Kademlia DHT enables decentralized peer discovery without central servers:
- Peers organized in XOR distance metric
- K-bucket routing table (k=20)
- Periodic table refreshes every 10 minutes
- Peer records published to DHT with TTL
mDNS (Local Discovery)
mDNS discovers local peers on the same network without bootstrap nodes:
# Enable mDNS for local development
tenzro-node --enable-mdns
Peer Management
use tenzro_network::PeerManager;
let peer_manager = PeerManager::new()?;
// Connect to peer
peer_manager.connect_peer(
"/ip4/bootstrap-node-ip/tcp/9000/p2p/12D3KooWABC..."
).await?;
// Get connected peers
let peers = peer_manager.get_connected_peers().await?;
for peer in peers {
println!("Peer: {}", peer.peer_id);
println!("Latency: {}ms", peer.latency_ms);
println!("Role: {:?}", peer.role);
}
// Disconnect peer
peer_manager.disconnect_peer(&peer_id).await?;
Message Deduplication
MessageDeduplicator prevents amplification attacks by tracking seen messages:
// Message deduplication with 60-second window
let dedup = MessageDeduplicator::new(Duration::from_secs(60));
if dedup.is_duplicate(&message_id) {
// Ignore duplicate message
return Ok(());
}
dedup.mark_seen(message_id);
// Process message...
Rate Limiting
Rate limiting prevents peers from flooding the network:
// Rate limit: 100 messages per second per peer
let rate_limiter = RateLimiter::new(100, Duration::from_secs(1));
if !rate_limiter.check_and_update(&peer_id) {
// Peer exceeded rate limit
peer_manager.disconnect_peer(&peer_id).await?;
return Err("Rate limit exceeded");
}
// Process message...
Peer Authentication
Peers authenticate using Ed25519 signatures on their peer ID:
// Verify peer identity
let verified = peer_manager.verify_peer_identity(
&peer_id,
&signature,
).await?;
if !verified {
peer_manager.ban_peer(&peer_id).await?;
return Err("Invalid peer signature");
}
Validator Authentication
The ValidatorRegistry trait provides validator-specific authentication for consensus and block messages, ensuring only registered validators can participate in consensus topics:
// ValidatorRegistry trait in peer_manager.rs
pub trait ValidatorRegistry: Send + Sync {
fn is_validator(&self, peer_id: &PeerId) -> bool;
fn validator_peer_ids(&self) -> Vec<PeerId>;
}
// NodeValidatorRegistry wraps consensus engine
// Validates peers by checking against active validator set
impl ValidatorRegistry for NodeValidatorRegistry {
fn is_validator(&self, peer_id: &PeerId) -> bool {
// Checks peer against consensus engine's active validator set
self.consensus.is_registered_validator(peer_id)
}
fn validator_peer_ids(&self) -> Vec<PeerId> {
// Returns all active validator peer IDs
self.consensus.get_validator_peer_ids()
}
}
// Wired at node startup in tenzro-node
let validator_registry = NodeValidatorRegistry::new(consensus_engine);
peer_manager.set_validator_registry(validator_registry);
// Topic-based authorization ENFORCED
// Consensus and block messages require validator authentication
peer_manager.authorize_peer_for_topic(&peer_id, "tenzro/consensus/1.0.0")?;
peer_manager.authorize_peer_for_topic(&peer_id, "tenzro/blocks/1.0.0")?;
// Non-validator peers can still participate as light clients
// - Subscribe to transactions (tenzro/transactions/1.0.0)
// - Subscribe to blocks (read-only)
// - Cannot publish to consensus topic (enforced by ValidatorRegistry)
This ensures that only registered validators can participate in consensus, while allowing light clients and non-validator nodes to observe the network and submit transactions. The ValidatorRegistry integration is production-ready and prevents Sybil attacks on consensus topics.
Network Metrics
// Get network metrics
let metrics = peer_manager.get_metrics().await?;
println!("Connected Peers: {}", metrics.connected_peers);
println!("Inbound Connections: {}", metrics.inbound_connections);
println!("Outbound Connections: {}", metrics.outbound_connections);
println!("Messages Sent: {}", metrics.messages_sent);
println!("Messages Received: {}", metrics.messages_received);
println!("Bytes Sent: {}", metrics.bytes_sent);
println!("Bytes Received: {}", metrics.bytes_received);
Gossipsub Configuration
// Gossipsub parameters
{
"mesh_size": 8, // Target mesh size (D in spec)
"mesh_low": 6, // Min mesh size before grafting
"mesh_high": 12, // Max mesh size before pruning
"fanout_ttl_seconds": 60, // Fanout cache TTL
"heartbeat_interval": 1, // Heartbeat interval (seconds)
"history_length": 5, // Message cache size
"history_gossip": 3 // Messages to gossip in IHAVE
}
NAT Traversal
Tenzro supports NAT traversal for nodes behind firewalls:
- UPnP: Automatic port mapping for home routers
- Relay: Circuit relay for unreachable peers
- Hole Punching: DCUtR protocol for direct connections
# Enable NAT traversal
tenzro-node --enable-upnp --enable-relay
Performance
| Metric | Value |
|---|
| Max Connections | 1000 |
| Messages per Second | 1000+ per topic |
| Message Propagation | 100-500ms (mesh size 8) |
| DHT Lookup | ~500ms (network size 1000) |