From 9821aabf0b50d2487b07502d3d2cd89e7d62bdbe Mon Sep 17 00:00:00 2001 From: murilo ijanc Date: Tue, 24 Mar 2026 15:04:03 -0300 Subject: Initial commit NAT-aware Kademlia DHT library for peer-to-peer networks. Features: - Distributed key-value storage (iterative FIND_NODE, FIND_VALUE, STORE) - NAT traversal via DTUN hole-punching and proxy relay - Reliable Datagram Protocol (RDP) with 7-state connection machine - Datagram transport with automatic fragmentation/reassembly - Ed25519 packet authentication - 256-bit node IDs (Ed25519 public keys) - Rate limiting, ban list, and eclipse attack mitigation - Persistence and metrics - OpenBSD and Linux support --- src/persist.rs | 84 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 84 insertions(+) create mode 100644 src/persist.rs (limited to 'src/persist.rs') diff --git a/src/persist.rs b/src/persist.rs new file mode 100644 index 0000000..8e733b0 --- /dev/null +++ b/src/persist.rs @@ -0,0 +1,84 @@ +//! Persistence traits for data and routing table. +//! +//! The library defines the traits; applications +//! implement backends (SQLite, file, etc). + +use crate::error::Error; +use crate::id::NodeId; +use std::net::SocketAddr; + +/// Stored value record for persistence. +#[derive(Debug, Clone)] +pub struct StoredRecord { + pub key: Vec, + pub value: Vec, + pub target_id: NodeId, + pub source: NodeId, + pub ttl: u16, + pub is_unique: bool, +} + +/// Contact record for routing table persistence. +#[derive(Debug, Clone)] +pub struct ContactRecord { + pub id: NodeId, + pub addr: SocketAddr, +} + +/// Trait for persisting DHT stored values. +/// +/// Implement this to survive restarts. The library +/// calls `save` periodically and `load` on startup. +pub trait DataPersistence { + /// Save all stored values. + fn save(&self, records: &[StoredRecord]) -> Result<(), Error>; + + /// Load previously saved values. + fn load(&self) -> Result, Error>; +} + +/// Trait for persisting the routing table. +/// +/// Implement this for fast re-bootstrap after restart. +pub trait RoutingPersistence { + /// Save known contacts. + fn save_contacts(&self, contacts: &[ContactRecord]) -> Result<(), Error>; + + /// Load previously saved contacts. + fn load_contacts(&self) -> Result, Error>; +} + +/// No-op persistence (default — no persistence). +pub struct NoPersistence; + +impl DataPersistence for NoPersistence { + fn save(&self, _records: &[StoredRecord]) -> Result<(), Error> { + Ok(()) + } + fn load(&self) -> Result, Error> { + Ok(Vec::new()) + } +} + +impl RoutingPersistence for NoPersistence { + fn save_contacts(&self, _contacts: &[ContactRecord]) -> Result<(), Error> { + Ok(()) + } + fn load_contacts(&self) -> Result, Error> { + Ok(Vec::new()) + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn no_persistence_save_load() { + let p = NoPersistence; + assert!(p.save(&[]).is_ok()); + assert!(p.load().unwrap().is_empty()); + assert!(p.save_contacts(&[]).is_ok()); + assert!(p.load_contacts().unwrap().is_empty()); + } +} -- cgit v1.2.3