Tenzro Testnet is live. Get testnet TNZO

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:

TopicPurpose
tenzro/blocks/1.0.0Block propagation
tenzro/transactions/1.0.0Transaction propagation
tenzro/consensus/1.0.0Consensus messages (BFT consensus)
tenzro/attestations/1.0.0TEE attestations
tenzro/models/1.0.0Model registrations
tenzro/inference/1.0.0Inference requests/responses
tenzro/status/1.0.0Status 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

MetricValue
Max Connections1000
Messages per Second1000+ per topic
Message Propagation100-500ms (mesh size 8)
DHT Lookup~500ms (network size 1000)