diff --git a/rust/Cargo.toml b/rust/Cargo.toml index 768569c..a79693a 100644 --- a/rust/Cargo.toml +++ b/rust/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "freenet-stdlib" -version = "0.1.9" +version = "0.1.10" edition = "2021" rust-version = "1.71.1" publish = true diff --git a/rust/src/client_api/client_events.rs b/rust/src/client_api/client_events.rs index 30d8263..da1aa2b 100644 --- a/rust/src/client_api/client_events.rs +++ b/rust/src/client_api/client_events.rs @@ -259,14 +259,13 @@ pub enum ClientRequest<'a> { } #[derive(Serialize, Deserialize, Debug, Clone)] -pub enum NodeQuery { - ConnectedPeers, - SubscriptionInfo, -} +pub struct ConnectedPeers {} -// For backward compatibility #[derive(Serialize, Deserialize, Debug, Clone)] -pub struct ConnectedPeers {} +pub struct NodeDiagnostics { + /// Optional contract key to filter diagnostics for specific contract + pub contract_key: Option, +} impl ClientRequest<'_> { pub fn into_owned(self) -> ClientRequest<'static> { @@ -724,22 +723,153 @@ pub enum HostResponse { type Peer = String; #[derive(Serialize, Deserialize, Debug)] +pub enum QueryResponse { + ConnectedPeers { peers: Vec<(Peer, SocketAddr)> }, + NetworkDebug(NetworkDebugInfo), + NodeDiagnostics(NodeDiagnosticsResponse), +} + +#[derive(Serialize, Deserialize, Debug, Clone)] +pub struct NetworkDebugInfo { + pub subscriptions: Vec, + pub connected_peers: Vec<(String, SocketAddr)>, +} + +#[derive(Serialize, Deserialize, Debug, Clone)] +pub struct NodeDiagnosticsResponse { + /// Node information + pub node_info: Option, + + /// Network connectivity information + pub network_info: Option, + + /// Contract subscription information + pub subscriptions: Vec, + + /// Contract states for specific contracts + pub contract_states: std::collections::HashMap, + + /// System metrics + pub system_metrics: Option, + + /// Information about connected peers with detailed data + pub connected_peers_detailed: Vec, +} + +#[derive(Serialize, Deserialize, Debug, Clone)] +pub struct NodeInfo { + pub peer_id: String, + pub is_gateway: bool, + pub location: String, + pub uptime_seconds: u64, +} + +#[derive(Serialize, Deserialize, Debug, Clone)] +pub struct NetworkInfo { + pub connected_peers: Vec<(String, String)>, // (peer_id, address) + pub active_connections: usize, +} + +#[derive(Serialize, Deserialize, Debug, Clone)] +pub struct ContractState { + /// Number of nodes subscribed to this contract + pub subscribers: u32, + /// Peer IDs of nodes that are subscribed to this contract + pub subscriber_peer_ids: Vec, +} + +#[derive(Serialize, Deserialize, Debug, Clone)] +pub struct SystemMetrics { + pub active_connections: u32, + pub seeding_contracts: u32, +} + +#[derive(Serialize, Deserialize, Debug, Clone)] pub struct SubscriptionInfo { pub contract_key: ContractKey, pub client_id: usize, - pub last_update: Option, } -#[derive(Serialize, Deserialize, Debug)] -pub struct NetworkDebugInfo { - pub subscriptions: Vec, - pub connected_peers: Vec<(Peer, SocketAddr)>, +/// Basic information about a connected peer +#[derive(Serialize, Deserialize, Debug, Clone)] +pub struct ConnectedPeerInfo { + pub peer_id: String, + pub address: String, } -#[derive(Serialize, Deserialize, Debug)] -pub enum QueryResponse { - ConnectedPeers { peers: Vec<(Peer, SocketAddr)> }, - NetworkDebug(NetworkDebugInfo), +#[derive(Serialize, Deserialize, Debug, Clone)] +pub enum NodeQuery { + ConnectedPeers, + SubscriptionInfo, + NodeDiagnostics { + /// Diagnostic configuration specifying what information to collect + config: NodeDiagnosticsConfig, + }, +} + +#[derive(Serialize, Deserialize, Debug, Clone)] +pub struct NodeDiagnosticsConfig { + /// Include basic node information (ID, location, uptime, etc.) + pub include_node_info: bool, + + /// Include network connectivity information + pub include_network_info: bool, + + /// Include contract subscription information + pub include_subscriptions: bool, + + /// Include contract states for specific contracts (empty = all contracts) + pub contract_keys: Vec, + + /// Include memory and performance metrics + pub include_system_metrics: bool, + + /// Include detailed information about connected peers (vs basic peer list) + pub include_detailed_peer_info: bool, + + /// Include peer IDs of subscribers in contract state information + pub include_subscriber_peer_ids: bool, +} + +impl NodeDiagnosticsConfig { + /// Create a comprehensive diagnostic config for debugging update propagation issues + pub fn for_update_propagation_debugging(contract_key: ContractKey) -> Self { + Self { + include_node_info: true, + include_network_info: true, + include_subscriptions: true, + contract_keys: vec![contract_key], + include_system_metrics: true, + include_detailed_peer_info: true, + include_subscriber_peer_ids: true, + } + } + + /// Create a lightweight diagnostic config for basic node status + pub fn basic_status() -> Self { + Self { + include_node_info: true, + include_network_info: true, + include_subscriptions: false, + contract_keys: vec![], + include_system_metrics: false, + include_detailed_peer_info: false, + include_subscriber_peer_ids: false, + } + } + + /// Create a full diagnostic config (all information) + pub fn full() -> Self { + Self { + include_node_info: true, + include_network_info: true, + include_subscriptions: true, + contract_keys: vec![], // empty = all contracts + include_system_metrics: true, + include_detailed_peer_info: true, + include_subscriber_peer_ids: true, + } + } } impl HostResponse { diff --git a/rust/src/versioning.rs b/rust/src/versioning.rs index bc3838e..b92dc99 100644 --- a/rust/src/versioning.rs +++ b/rust/src/versioning.rs @@ -124,11 +124,14 @@ impl DelegateCode<'static> { mut contract_data: Cursor>, ) -> Result<(Self, APIVersion), std::io::Error> { // Get contract version - let version = contract_data - .read_u64::() - .map_err(|_| std::io::Error::new(std::io::ErrorKind::InvalidData, "Failed to read version"))?; + let version = contract_data.read_u64::().map_err(|_| { + std::io::Error::new(std::io::ErrorKind::InvalidData, "Failed to read version") + })?; let version = APIVersion::from_u64(version).map_err(|e| { - std::io::Error::new(std::io::ErrorKind::InvalidData, format!("Version error: {}", e)) + std::io::Error::new( + std::io::ErrorKind::InvalidData, + format!("Version error: {}", e), + ) })?; if version == APIVersion::Version0_0_1 { @@ -307,7 +310,10 @@ impl ContractCode<'static> { std::io::Error::new(std::io::ErrorKind::InvalidData, "Failed to read version") })?; let version = APIVersion::from_u64(version).map_err(|e| { - std::io::Error::new(std::io::ErrorKind::InvalidData, format!("Version error: {}", e)) + std::io::Error::new( + std::io::ErrorKind::InvalidData, + format!("Version error: {}", e), + ) })?; if version == APIVersion::Version0_0_1 {