pub struct P2PNode {
pub security_dashboard: Option<Arc<SecurityDashboard>>,
/* private fields */
}Expand description
Main P2P network node that manages connections, routing, and communication
This struct represents a complete P2P network participant that can:
- Connect to other peers via QUIC transport
- Participate in distributed hash table (DHT) operations
- Send and receive messages through various protocols
- Handle network events and peer lifecycle
Transport concerns (connections, messaging, events) are delegated to
TransportHandle.
Fields§
§security_dashboard: Option<Arc<SecurityDashboard>>Security dashboard for monitoring
Implementations§
Source§impl P2PNode
impl P2PNode
Sourcepub async fn new(config: NodeConfig) -> Result<Self>
pub async fn new(config: NodeConfig) -> Result<Self>
Create a new P2P node with the given configuration
Sourcepub fn builder() -> NodeBuilder
pub fn builder() -> NodeBuilder
Create a new node builder
Sourcepub fn transport(&self) -> &Arc<TransportHandle>
pub fn transport(&self) -> &Arc<TransportHandle>
Get the transport handle for sharing with other components.
Sourcepub fn transport_peer_id(&self) -> Option<String>
pub fn transport_peer_id(&self) -> Option<String>
Get the hex-encoded transport-level peer ID.
pub fn local_addr(&self) -> Option<String>
Sourcepub fn is_bootstrapped(&self) -> bool
pub fn is_bootstrapped(&self) -> bool
Check if the node has completed the initial bootstrap process
Returns true if the node has successfully connected to at least one
bootstrap peer and performed peer discovery (FIND_NODE).
Sourcepub async fn re_bootstrap(&self) -> Result<()>
pub async fn re_bootstrap(&self) -> Result<()>
Manually trigger re-bootstrap (useful for recovery or network rejoin)
This clears the bootstrapped state and attempts to reconnect to bootstrap peers and discover new peers.
Sourcepub fn trust_engine(&self) -> Option<Arc<EigenTrustEngine>>
pub fn trust_engine(&self) -> Option<Arc<EigenTrustEngine>>
Get the EigenTrust engine for direct trust operations
This provides access to the underlying trust engine for advanced use cases.
For simple success/failure reporting, prefer report_peer_success() and
report_peer_failure().
§Example
if let Some(engine) = node.trust_engine() {
// Update node statistics directly
engine.update_node_stats(&peer_id, NodeStatisticsUpdate::StorageContributed(1024)).await;
// Get global trust scores
let scores = engine.compute_global_trust().await;
}Sourcepub async fn report_peer_success(&self, peer_id: &str) -> Result<()>
pub async fn report_peer_success(&self, peer_id: &str) -> Result<()>
Report a successful interaction with a peer
Call this after successful data operations to increase the peer’s trust score. This is the primary method for saorsa-node to report positive outcomes.
§Arguments
peer_id- The peer ID (as a string) of the node that performed well
§Example
// After successfully retrieving a chunk from a peer
if let Ok(chunk) = fetch_chunk_from(&peer_id).await {
node.report_peer_success(&peer_id).await?;
}Sourcepub async fn report_peer_failure(&self, peer_id: &str) -> Result<()>
pub async fn report_peer_failure(&self, peer_id: &str) -> Result<()>
Report a failed interaction with a peer
Call this after failed data operations to decrease the peer’s trust score. This includes timeouts, corrupted data, or refused connections.
§Arguments
peer_id- The peer ID (as a string) of the node that failed
§Example
// After a chunk retrieval fails
match fetch_chunk_from(&peer_id).await {
Ok(chunk) => node.report_peer_success(&peer_id).await?,
Err(_) => node.report_peer_failure(&peer_id).await?,
}Sourcepub async fn report_peer_failure_with_reason(
&self,
peer_id: &str,
reason: PeerFailureReason,
) -> Result<()>
pub async fn report_peer_failure_with_reason( &self, peer_id: &str, reason: PeerFailureReason, ) -> Result<()>
Report a failed interaction with a peer, providing a specific failure reason.
This is the enriched version of P2PNode::report_peer_failure that maps the failure
reason to the appropriate trust penalty. Use this when you know why the
interaction failed to give the trust engine more accurate data.
- Transport-level failures (
Timeout,ConnectionFailed) map toFailedResponse DataUnavailablemaps toDataUnavailableCorruptedDatamaps toCorruptedData(counts as 2 failures)ProtocolErrormaps toProtocolViolation(counts as 2 failures)Refusedmaps toFailedResponse
Requires the adaptive-ml feature to be enabled.
§Arguments
peer_id- The peer ID of the node that failedreason- Why the interaction failed
§Example
use saorsa_core::error::PeerFailureReason;
// After a chunk retrieval returns corrupted data
node.report_peer_failure_with_reason(&peer_id, PeerFailureReason::CorruptedData).await?;Sourcepub fn peer_trust(&self, peer_id: &str) -> f64
pub fn peer_trust(&self, peer_id: &str) -> f64
Get the current trust score for a peer
Returns a value between 0.0 (untrusted) and 1.0 (fully trusted). Unknown peers return 0.0 by default.
§Arguments
peer_id- The peer ID (as a string) to query
§Example
let trust = node.peer_trust(&peer_id);
if trust < 0.3 {
tracing::warn!("Low trust peer: {}", peer_id);
}Sourcepub async fn send_request(
&self,
peer_id: &PeerId,
protocol: &str,
data: Vec<u8>,
timeout: Duration,
) -> Result<PeerResponse>
pub async fn send_request( &self, peer_id: &PeerId, protocol: &str, data: Vec<u8>, timeout: Duration, ) -> Result<PeerResponse>
Send a request to a peer and wait for a response with automatic trust reporting.
Unlike fire-and-forget send_message(), this method:
- Wraps the payload in a
RequestResponseEnvelopewith a unique message ID - Sends it on the
/rr/<protocol>protocol prefix - Waits for a matching response (or timeout)
- Automatically reports success or failure to the trust engine
The remote peer’s handler should call send_response() with the
incoming message ID to route the response back.
§Arguments
peer_id- Target peerprotocol- Application protocol name (e.g."chunk_fetch")data- Request payload bytestimeout- Maximum time to wait for a response
§Returns
A PeerResponse on success, or an error on timeout / connection failure.
§Example
let response = node.send_request(&peer_id, "chunk_fetch", chunk_id.to_vec(), Duration::from_secs(10)).await?;
println!("Got {} bytes from {}", response.data.len(), response.peer_id);pub async fn send_response( &self, peer_id: &PeerId, protocol: &str, message_id: &str, data: Vec<u8>, ) -> Result<()>
pub fn parse_request_envelope(data: &[u8]) -> Option<(String, bool, Vec<u8>)>
pub async fn subscribe(&self, topic: &str) -> Result<()>
pub async fn publish(&self, topic: &str, data: &[u8]) -> Result<()>
Sourcepub fn config(&self) -> &NodeConfig
pub fn config(&self) -> &NodeConfig
Get the node configuration
Sourcepub fn is_running(&self) -> bool
pub fn is_running(&self) -> bool
Check if the node is running
Sourcepub async fn listen_addrs(&self) -> Vec<SocketAddr>
pub async fn listen_addrs(&self) -> Vec<SocketAddr>
Get the current listen addresses
Sourcepub async fn connected_peers(&self) -> Vec<PeerId> ⓘ
pub async fn connected_peers(&self) -> Vec<PeerId> ⓘ
Get connected peers
Sourcepub async fn peer_count(&self) -> usize
pub async fn peer_count(&self) -> usize
Get peer count
Sourcepub async fn get_peer_id_by_address(&self, addr: &str) -> Option<PeerId>
pub async fn get_peer_id_by_address(&self, addr: &str) -> Option<PeerId>
Get the peer ID for a given socket address, if connected
Sourcepub async fn list_active_connections(&self) -> Vec<(PeerId, Vec<String>)>
pub async fn list_active_connections(&self) -> Vec<(PeerId, Vec<String>)>
List all active connections with their peer IDs and addresses
Sourcepub async fn remove_peer(&self, peer_id: &PeerId) -> bool
pub async fn remove_peer(&self, peer_id: &PeerId) -> bool
Remove a peer from the peers map
Sourcepub async fn is_peer_connected(&self, peer_id: &PeerId) -> bool
pub async fn is_peer_connected(&self, peer_id: &PeerId) -> bool
Check if a peer is connected
Sourcepub async fn connect_peer(&self, address: &str) -> Result<PeerId>
pub async fn connect_peer(&self, address: &str) -> Result<PeerId>
Connect to a peer
Sourcepub async fn disconnect_peer(&self, peer_id: &PeerId) -> Result<()>
pub async fn disconnect_peer(&self, peer_id: &PeerId) -> Result<()>
Disconnect from a peer
Sourcepub async fn is_connection_active(&self, peer_id: &str) -> bool
pub async fn is_connection_active(&self, peer_id: &str) -> bool
Check if a connection to a peer is active
Source§impl P2PNode
impl P2PNode
Sourcepub fn subscribe_events(&self) -> Receiver<P2PEvent>
pub fn subscribe_events(&self) -> Receiver<P2PEvent>
Subscribe to network events
Sourcepub async fn resource_metrics(&self) -> Result<ResourceMetrics>
pub async fn resource_metrics(&self) -> Result<ResourceMetrics>
Get production resource metrics
Sourcepub async fn health_check(&self) -> Result<()>
pub async fn health_check(&self) -> Result<()>
Check system health
Sourcepub fn production_config(&self) -> Option<&ProductionConfig>
pub fn production_config(&self) -> Option<&ProductionConfig>
Get production configuration (if enabled)
Sourcepub fn is_production_mode(&self) -> bool
pub fn is_production_mode(&self) -> bool
Check if production hardening is enabled
Sourcepub fn dht_manager(&self) -> &Arc<DhtNetworkManager>
pub fn dht_manager(&self) -> &Arc<DhtNetworkManager>
Get the attached DHT manager.
Sourcepub fn dht(&self) -> &Arc<DhtNetworkManager>
pub fn dht(&self) -> &Arc<DhtNetworkManager>
Backwards-compatible alias for dht_manager().
Sourcepub async fn dht_put(&self, key: Key, value: Vec<u8>) -> Result<()>
pub async fn dht_put(&self, key: Key, value: Vec<u8>) -> Result<()>
Store a value in the local DHT
This method stores data in the local DHT core through the attached manager.
For network-wide replication across multiple nodes, use DhtNetworkManager::put.
Sourcepub async fn dht_get(&self, key: Key) -> Result<Option<Vec<u8>>>
pub async fn dht_get(&self, key: Key) -> Result<Option<Vec<u8>>>
Retrieve a value from the local DHT
This method retrieves data from the local DHT core through the attached manager.
For network-wide lookups across multiple nodes, use DhtNetworkManager::get.
Sourcepub async fn add_discovered_peer(
&self,
peer_id: PeerId,
addresses: Vec<String>,
) -> Result<()>
pub async fn add_discovered_peer( &self, peer_id: PeerId, addresses: Vec<String>, ) -> Result<()>
Add a discovered peer to the bootstrap cache
Sourcepub async fn update_peer_metrics(
&self,
peer_id: &PeerId,
success: bool,
latency_ms: Option<u64>,
_error: Option<String>,
) -> Result<()>
pub async fn update_peer_metrics( &self, peer_id: &PeerId, success: bool, latency_ms: Option<u64>, _error: Option<String>, ) -> Result<()>
Update connection metrics for a peer in the bootstrap cache
Sourcepub async fn get_bootstrap_cache_stats(&self) -> Result<Option<CacheStats>>
pub async fn get_bootstrap_cache_stats(&self) -> Result<Option<CacheStats>>
Get bootstrap cache statistics
Sourcepub async fn cached_peer_count(&self) -> usize
pub async fn cached_peer_count(&self) -> usize
Get the number of cached bootstrap peers
Auto Trait Implementations§
impl Freeze for P2PNode
impl !RefUnwindSafe for P2PNode
impl Send for P2PNode
impl Sync for P2PNode
impl Unpin for P2PNode
impl UnsafeUnpin for P2PNode
impl !UnwindSafe for P2PNode
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> Instrument for T
impl<T> Instrument for T
Source§fn instrument(self, span: Span) -> Instrumented<Self>
fn instrument(self, span: Span) -> Instrumented<Self>
Source§fn in_current_span(self) -> Instrumented<Self>
fn in_current_span(self) -> Instrumented<Self>
Source§impl<T> PolicyExt for Twhere
T: ?Sized,
impl<T> PolicyExt for Twhere
T: ?Sized,
Source§impl<SS, SP> SupersetOf<SS> for SPwhere
SS: SubsetOf<SP>,
impl<SS, SP> SupersetOf<SS> for SPwhere
SS: SubsetOf<SP>,
Source§fn to_subset(&self) -> Option<SS>
fn to_subset(&self) -> Option<SS>
self from the equivalent element of its
superset. Read moreSource§fn is_in_subset(&self) -> bool
fn is_in_subset(&self) -> bool
self is actually part of its subset T (and can be converted to it).Source§fn to_subset_unchecked(&self) -> SS
fn to_subset_unchecked(&self) -> SS
self.to_subset but without any property checks. Always succeeds.Source§fn from_subset(element: &SS) -> SP
fn from_subset(element: &SS) -> SP
self to the equivalent element of its superset.