nym_api_requests/models/described/
v1.rs1use crate::models::{
5 AuthenticatorDetailsV1, AuxiliaryDetailsV1, BinaryBuildInformationOwned, DeclaredRolesV1,
6 HostInformationV1, IpPacketRouterDetailsV1, NetworkRequesterDetailsV1,
7 OffsetDateTimeJsonSchemaWrapper, WebSocketsV1, WireguardDetailsV1,
8};
9use crate::nym_nodes::{BasicEntryInformation, NodeRole, SemiSkimmedNodeV1, SkimmedNodeV1};
10use nym_crypto::asymmetric::{ed25519, x25519};
11use nym_mixnet_contract_common::reward_params::Performance;
12use nym_mixnet_contract_common::NodeId;
13use nym_network_defaults::{DEFAULT_MIX_LISTENING_PORT, DEFAULT_VERLOC_LISTENING_PORT};
14use serde::{Deserialize, Serialize};
15use tracing::warn;
16use utoipa::ToSchema;
17
18#[derive(Clone, Debug, Serialize, Deserialize, schemars::JsonSchema, ToSchema)]
23pub struct NymNodeDescriptionV1 {
24 #[schema(value_type = u32)]
25 pub node_id: NodeId,
26 pub contract_node_type: DescribedNodeTypeV1,
27 pub description: NymNodeDataV1,
28}
29
30impl NymNodeDescriptionV1 {
31 pub fn version(&self) -> &str {
32 &self.description.build_information.build_version
33 }
34
35 pub fn entry_information(&self) -> BasicEntryInformation {
36 BasicEntryInformation {
37 hostname: self.description.host_information.hostname.clone(),
38 ws_port: self.description.mixnet_websockets.ws_port,
39 wss_port: self.description.mixnet_websockets.wss_port,
40 }
41 }
42
43 pub fn ed25519_identity_key(&self) -> ed25519::PublicKey {
44 self.description.host_information.keys.ed25519
45 }
46
47 pub fn current_sphinx_key(&self, current_rotation_id: u32) -> x25519::PublicKey {
48 let keys = &self.description.host_information.keys;
49
50 if keys.current_x25519_sphinx_key.rotation_id == u32::MAX {
51 return keys.current_x25519_sphinx_key.public_key;
53 }
54
55 if current_rotation_id == keys.current_x25519_sphinx_key.rotation_id {
56 return keys.current_x25519_sphinx_key.public_key;
58 }
59
60 if let Some(pre_announced) = &keys.pre_announced_x25519_sphinx_key {
61 if pre_announced.rotation_id == current_rotation_id {
62 return pre_announced.public_key;
63 }
64 }
65
66 warn!(
67 "unexpected key rotation {current_rotation_id} for node {}",
68 self.node_id
69 );
70 keys.current_x25519_sphinx_key.public_key
72 }
73
74 pub fn to_skimmed_node(
75 &self,
76 current_rotation_id: u32,
77 role: NodeRole,
78 performance: Performance,
79 ) -> SkimmedNodeV1 {
80 let keys = &self.description.host_information.keys;
81 let entry = if self.description.declared_role.entry {
82 Some(self.entry_information())
83 } else {
84 None
85 };
86
87 SkimmedNodeV1 {
88 node_id: self.node_id,
89 ed25519_identity_pubkey: keys.ed25519,
90 ip_addresses: self.description.host_information.ip_address.clone(),
91 mix_port: self.description.mix_port(),
92 x25519_sphinx_pubkey: self.current_sphinx_key(current_rotation_id),
93 role,
97 supported_roles: self.description.declared_role,
98 entry,
99 performance,
100 }
101 }
102
103 pub fn to_semi_skimmed_node(
104 &self,
105 current_rotation_id: u32,
106 role: NodeRole,
107 performance: Performance,
108 ) -> SemiSkimmedNodeV1 {
109 let skimmed_node = self.to_skimmed_node(current_rotation_id, role, performance);
110
111 SemiSkimmedNodeV1 {
112 basic: skimmed_node,
113 x25519_noise_versioned_key: self
114 .description
115 .host_information
116 .keys
117 .x25519_versioned_noise,
118 }
119 }
120}
121
122#[derive(Debug, Clone, Copy, PartialEq, Serialize, Deserialize, schemars::JsonSchema, ToSchema)]
127#[serde(rename_all = "snake_case")]
128#[cfg_attr(feature = "generate-ts", derive(ts_rs::TS))]
129#[cfg_attr(
130 feature = "generate-ts",
131 ts(
132 export,
133 export_to = "ts-packages/types/src/types/rust/DescribedNodeType.ts"
134 )
135)]
136pub enum DescribedNodeTypeV1 {
137 LegacyMixnode,
138 LegacyGateway,
139 NymNode,
140}
141
142impl DescribedNodeTypeV1 {
143 pub fn is_nym_node(&self) -> bool {
144 matches!(self, DescribedNodeTypeV1::NymNode)
145 }
146}
147
148#[derive(Clone, Debug, Serialize, Deserialize, schemars::JsonSchema, ToSchema)]
153pub struct NymNodeDataV1 {
154 #[serde(default)]
155 pub last_polled: OffsetDateTimeJsonSchemaWrapper,
156
157 pub host_information: HostInformationV1,
158
159 #[serde(default)]
160 pub declared_role: DeclaredRolesV1,
161
162 #[serde(default)]
163 pub auxiliary_details: AuxiliaryDetailsV1,
164
165 pub build_information: BinaryBuildInformationOwned,
167
168 #[serde(default)]
169 pub network_requester: Option<NetworkRequesterDetailsV1>,
170
171 #[serde(default)]
172 pub ip_packet_router: Option<IpPacketRouterDetailsV1>,
173
174 #[serde(default)]
175 pub authenticator: Option<AuthenticatorDetailsV1>,
176
177 #[serde(default)]
178 pub wireguard: Option<WireguardDetailsV1>,
179
180 pub mixnet_websockets: WebSocketsV1,
182}
183
184impl NymNodeDataV1 {
185 pub fn mix_port(&self) -> u16 {
186 self.auxiliary_details
187 .announce_ports
188 .mix_port
189 .unwrap_or(DEFAULT_MIX_LISTENING_PORT)
190 }
191
192 pub fn verloc_port(&self) -> u16 {
193 self.auxiliary_details
194 .announce_ports
195 .verloc_port
196 .unwrap_or(DEFAULT_VERLOC_LISTENING_PORT)
197 }
198}