Skip to main content

tenzro_types/
network.rs

1//! Network types for Tenzro Network
2//!
3//! This module defines network topology, peer discovery, and node
4//! information structures.
5
6use crate::primitives::{Address, Timestamp};
7use serde::{Deserialize, Serialize};
8use std::net::SocketAddr;
9
10/// The role of a node in the Tenzro Network
11#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
12pub enum NetworkRole {
13    /// Full validator node
14    Validator,
15    /// Full node (non-validating)
16    FullNode,
17    /// Light client
18    LightClient,
19    /// TEE provider node
20    TeeProvider,
21    /// Model inference provider node
22    ModelProvider,
23    /// Storage provider node
24    StorageProvider,
25    /// Archive node (stores full history)
26    Archive,
27    /// Bootstrap/seed node
28    Bootstrap,
29    /// Micro node / participant — ultra-lightweight, no P2P required.
30    /// Humans or AI agents joining via MCP server, Claude, ClawBot,
31    /// or other agentic frameworks. Auto-provisioned DID + MPC wallet.
32    MicroNode,
33}
34
35impl NetworkRole {
36    /// Checks if this role can validate blocks
37    pub fn is_validator(&self) -> bool {
38        matches!(self, Self::Validator)
39    }
40
41    /// Checks if this role is a provider
42    pub fn is_provider(&self) -> bool {
43        matches!(
44            self,
45            Self::TeeProvider | Self::ModelProvider | Self::StorageProvider
46        )
47    }
48
49    /// Checks if this role maintains full state
50    pub fn is_full_node(&self) -> bool {
51        matches!(
52            self,
53            Self::Validator | Self::FullNode | Self::Archive | Self::Bootstrap
54        )
55    }
56
57    /// Checks if this role is a micro node (zero-install participant)
58    pub fn is_micro_node(&self) -> bool {
59        matches!(self, Self::MicroNode)
60    }
61}
62
63/// Information about a peer in the network
64#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
65pub struct PeerInfo {
66    /// Peer's unique identifier
67    pub peer_id: String,
68    /// Peer's network addresses
69    pub addresses: Vec<SocketAddr>,
70    /// Peer's role in the network
71    pub role: NetworkRole,
72    /// Protocol version
73    pub protocol_version: u32,
74    /// User agent string
75    pub user_agent: String,
76    /// Last seen timestamp
77    pub last_seen: Timestamp,
78    /// Peer reputation score
79    pub reputation: i64,
80    /// Connection status
81    pub status: PeerStatus,
82}
83
84impl PeerInfo {
85    /// Creates a new PeerInfo
86    pub fn new(peer_id: String, addresses: Vec<SocketAddr>, role: NetworkRole) -> Self {
87        Self {
88            peer_id,
89            addresses,
90            role,
91            protocol_version: 1,
92            user_agent: "tenzro/1.0".to_string(),
93            last_seen: Timestamp::now(),
94            reputation: 0,
95            status: PeerStatus::Disconnected,
96        }
97    }
98
99    /// Updates the last seen timestamp
100    pub fn update_last_seen(&mut self) {
101        self.last_seen = Timestamp::now();
102    }
103
104    /// Increases the reputation score
105    pub fn increase_reputation(&mut self, amount: i64) {
106        self.reputation = self.reputation.saturating_add(amount);
107    }
108
109    /// Decreases the reputation score
110    pub fn decrease_reputation(&mut self, amount: i64) {
111        self.reputation = self.reputation.saturating_sub(amount);
112    }
113}
114
115/// Peer connection status
116#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
117pub enum PeerStatus {
118    /// Not connected
119    Disconnected,
120    /// Attempting to connect
121    Connecting,
122    /// Successfully connected
123    Connected,
124    /// Connection failed
125    Failed,
126    /// Peer is banned
127    Banned,
128}
129
130/// Information about the local node
131#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
132pub struct NodeInfo {
133    /// Node's unique identifier
134    pub node_id: String,
135    /// Node's account address (if applicable)
136    pub address: Option<Address>,
137    /// Node's role in the network
138    pub role: NetworkRole,
139    /// Listen addresses
140    pub listen_addresses: Vec<SocketAddr>,
141    /// Public addresses (for NAT traversal)
142    pub public_addresses: Vec<SocketAddr>,
143    /// Protocol version
144    pub protocol_version: u32,
145    /// User agent string
146    pub user_agent: String,
147    /// Node start time
148    pub start_time: Timestamp,
149    /// Node configuration
150    pub config: NodeConfiguration,
151}
152
153impl NodeInfo {
154    /// Creates a new NodeInfo
155    pub fn new(node_id: String, role: NetworkRole) -> Self {
156        Self {
157            node_id,
158            address: None,
159            role,
160            listen_addresses: Vec::new(),
161            public_addresses: Vec::new(),
162            protocol_version: 1,
163            user_agent: "tenzro/1.0".to_string(),
164            start_time: Timestamp::now(),
165            config: NodeConfiguration::default(),
166        }
167    }
168
169    /// Sets the node's account address
170    pub fn with_address(mut self, address: Address) -> Self {
171        self.address = Some(address);
172        self
173    }
174
175    /// Adds a listen address
176    pub fn add_listen_address(&mut self, addr: SocketAddr) {
177        if !self.listen_addresses.contains(&addr) {
178            self.listen_addresses.push(addr);
179        }
180    }
181
182    /// Adds a public address
183    pub fn add_public_address(&mut self, addr: SocketAddr) {
184        if !self.public_addresses.contains(&addr) {
185            self.public_addresses.push(addr);
186        }
187    }
188
189    /// Returns the node uptime in milliseconds
190    pub fn uptime(&self) -> i64 {
191        Timestamp::now().as_millis() - self.start_time.as_millis()
192    }
193}
194
195/// Node configuration parameters
196#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
197pub struct NodeConfiguration {
198    /// Maximum number of inbound peers
199    pub max_inbound_peers: u32,
200    /// Maximum number of outbound peers
201    pub max_outbound_peers: u32,
202    /// Enable peer discovery
203    pub enable_discovery: bool,
204    /// Enable metrics collection
205    pub enable_metrics: bool,
206    /// Enable RPC server
207    pub enable_rpc: bool,
208    /// RPC listen address
209    pub rpc_address: Option<SocketAddr>,
210}
211
212impl Default for NodeConfiguration {
213    fn default() -> Self {
214        Self {
215            max_inbound_peers: 50,
216            max_outbound_peers: 25,
217            enable_discovery: true,
218            enable_metrics: true,
219            enable_rpc: true,
220            rpc_address: None,
221        }
222    }
223}
224
225/// Network statistics
226#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
227pub struct NetworkStats {
228    /// Total number of connected peers
229    pub connected_peers: u32,
230    /// Total bytes sent
231    pub bytes_sent: u64,
232    /// Total bytes received
233    pub bytes_received: u64,
234    /// Total messages sent
235    pub messages_sent: u64,
236    /// Total messages received
237    pub messages_received: u64,
238}
239
240impl NetworkStats {
241    /// Records a sent message
242    pub fn record_sent(&mut self, bytes: u64) {
243        self.messages_sent += 1;
244        self.bytes_sent = self.bytes_sent.saturating_add(bytes);
245    }
246
247    /// Records a received message
248    pub fn record_received(&mut self, bytes: u64) {
249        self.messages_received += 1;
250        self.bytes_received = self.bytes_received.saturating_add(bytes);
251    }
252}
253
254/// Full capabilities available to a micro node participant.
255///
256/// MicroNodes are zero-install full participants — they access everything
257/// via JSON-RPC, MCP tools, A2A protocol, or agentic frameworks.
258/// All capabilities default to `true` (full participant).
259#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
260pub struct MicroNodeCapabilities {
261    /// AI model inference from network providers
262    pub inference: bool,
263    /// TNZO payments (send, receive, escrow)
264    pub payments: bool,
265    /// A2A agent-to-agent collaboration
266    pub agent_collaboration: bool,
267    /// MCP tool access (24 tools)
268    pub mcp_tools: bool,
269    /// Task marketplace — request tasks and complete tasks for others
270    pub task_execution: bool,
271    /// Chain state queries (blocks, transactions, balances)
272    pub chain_query: bool,
273    /// Smart contract interaction (EVM/SVM/DAML)
274    pub smart_contracts: bool,
275    /// TEE confidential compute and key management
276    pub tee_services: bool,
277    /// Cross-chain bridge (Ethereum, Solana, Canton)
278    pub bridge: bool,
279    /// Governance — proposals and voting
280    pub governance: bool,
281}
282
283impl Default for MicroNodeCapabilities {
284    fn default() -> Self {
285        // All capabilities enabled — full participant by default
286        Self {
287            inference: true,
288            payments: true,
289            agent_collaboration: true,
290            mcp_tools: true,
291            task_execution: true,
292            chain_query: true,
293            smart_contracts: true,
294            tee_services: true,
295            bridge: true,
296            governance: true,
297        }
298    }
299}
300
301/// Information about a registered micro node participant
302#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
303pub struct MicroNodeInfo {
304    /// TDIP decentralized identifier (did:tenzro:...)
305    pub did: String,
306    /// Auto-provisioned MPC wallet address
307    pub wallet_address: String,
308    /// Human-readable display name (optional)
309    pub display_name: String,
310    /// Timestamp when the micro node joined
311    pub joined_at: Timestamp,
312    /// Entry point: "mcp", "claude", "clawbot", "a2a", "sdk", "api", "cli", "app"
313    pub origin: String,
314    /// What kind of participant joined
315    pub participant_type: MicroNodeParticipantType,
316    /// Capabilities available to this micro node
317    pub capabilities: MicroNodeCapabilities,
318}
319
320impl MicroNodeInfo {
321    /// Creates a new MicroNodeInfo with full capabilities
322    pub fn new(
323        did: String,
324        wallet_address: String,
325        display_name: String,
326        origin: String,
327        participant_type: MicroNodeParticipantType,
328    ) -> Self {
329        Self {
330            did,
331            wallet_address,
332            display_name,
333            joined_at: Timestamp::now(),
334            origin,
335            participant_type,
336            capabilities: MicroNodeCapabilities::default(),
337        }
338    }
339}
340
341/// The type of participant joining as a micro node
342#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
343pub enum MicroNodeParticipantType {
344    /// A human user (via Claude, ClawBot, CLI, desktop, SDK)
345    Human,
346    /// An AI agent (via A2A protocol, MCP, agentic framework)
347    Agent,
348    /// An automated bot or service
349    Bot,
350}