nym_api_requests/models/described/
v2.rs1use crate::models::described::type_translation::{
5 AnnouncePortsV1, AuthenticatorDetailsV1, DeclaredRolesV1, HostInformationV1, HostKeysV1,
6 IpPacketRouterDetailsV1, LewesProtocolDetailsV1, NetworkRequesterDetailsV1,
7 NymNodeAuxiliaryDetailsV1, SphinxKeyV1, WebSocketsV1, WireguardDetailsV1,
8};
9use crate::models::described::v1::{DescribedNodeTypeV1, NymNodeDataV1, NymNodeDescriptionV1};
10use crate::models::{BinaryBuildInformationOwned, OffsetDateTimeJsonSchemaWrapper};
11use crate::nym_nodes::{BasicEntryInformation, NodeRole, SkimmedNodeV1};
12use nym_crypto::asymmetric::{ed25519, x25519};
13use nym_mixnet_contract_common::reward_params::Performance;
14use nym_mixnet_contract_common::NodeId;
15use nym_network_defaults::{DEFAULT_MIX_LISTENING_PORT, DEFAULT_VERLOC_LISTENING_PORT};
16use nym_noise_keys::VersionedNoiseKeyV1;
17use serde::{Deserialize, Serialize};
18use tracing::warn;
19use utoipa::ToSchema;
20
21pub type HostInformationV2 = HostInformationV1;
23pub type DeclaredRolesV2 = DeclaredRolesV1;
24pub type AnnouncePortsV2 = AnnouncePortsV1;
25pub type NymNodeAuxiliaryDetailsV2 = NymNodeAuxiliaryDetailsV1;
26pub type NetworkRequesterDetailsV2 = NetworkRequesterDetailsV1;
27pub type IpPacketRouterDetailsV2 = IpPacketRouterDetailsV1;
28pub type AuthenticatorDetailsV2 = AuthenticatorDetailsV1;
29pub type WireguardDetailsV2 = WireguardDetailsV1;
30pub type WebSocketsV2 = WebSocketsV1;
31pub type DescribedNodeTypeV2 = DescribedNodeTypeV1;
32pub type HostKeysV2 = HostKeysV1;
33pub type SphinxKeyV2 = SphinxKeyV1;
34pub type VersionedNoiseKeyV2 = VersionedNoiseKeyV1;
35
36#[derive(Clone, Debug, Serialize, Deserialize, schemars::JsonSchema, ToSchema)]
41pub struct NymNodeDescriptionV2 {
42 #[schema(value_type = u32)]
43 pub node_id: NodeId,
44 pub contract_node_type: DescribedNodeTypeV2,
45 pub description: NymNodeDataV2,
46}
47
48impl NymNodeDescriptionV2 {
49 pub fn version(&self) -> &str {
50 &self.description.build_information.build_version
51 }
52
53 pub fn entry_information(&self) -> BasicEntryInformation {
54 BasicEntryInformation {
55 hostname: self.description.host_information.hostname.clone(),
56 ws_port: self.description.mixnet_websockets.ws_port,
57 wss_port: self.description.mixnet_websockets.wss_port,
58 }
59 }
60
61 pub fn ed25519_identity_key(&self) -> ed25519::PublicKey {
62 self.description.host_information.keys.ed25519
63 }
64
65 pub fn current_sphinx_key(&self, current_rotation_id: u32) -> x25519::PublicKey {
66 let keys = &self.description.host_information.keys;
67
68 if keys.current_x25519_sphinx_key.rotation_id == u32::MAX {
69 return keys.current_x25519_sphinx_key.public_key;
71 }
72
73 if current_rotation_id == keys.current_x25519_sphinx_key.rotation_id {
74 return keys.current_x25519_sphinx_key.public_key;
76 }
77
78 if let Some(pre_announced) = &keys.pre_announced_x25519_sphinx_key {
79 if pre_announced.rotation_id == current_rotation_id {
80 return pre_announced.public_key;
81 }
82 }
83
84 warn!(
85 "unexpected key rotation {current_rotation_id} for node {}",
86 self.node_id
87 );
88 keys.current_x25519_sphinx_key.public_key
90 }
91
92 pub fn to_skimmed_node(
93 &self,
94 current_rotation_id: u32,
95 role: NodeRole,
96 performance: Performance,
97 ) -> SkimmedNodeV1 {
98 let keys = &self.description.host_information.keys;
99 let entry = if self.description.declared_role.entry {
100 Some(self.entry_information())
101 } else {
102 None
103 };
104
105 SkimmedNodeV1 {
106 node_id: self.node_id,
107 ed25519_identity_pubkey: keys.ed25519,
108 ip_addresses: self.description.host_information.ip_address.clone(),
109 mix_port: self.description.mix_port(),
110 x25519_sphinx_pubkey: self.current_sphinx_key(current_rotation_id),
111 role,
115 supported_roles: self.description.declared_role,
116 entry,
117 performance,
118 }
119 }
120}
121
122#[derive(Clone, Debug, Serialize, Deserialize, schemars::JsonSchema, ToSchema)]
127pub struct NymNodeDataV2 {
128 #[serde(default)]
129 pub last_polled: OffsetDateTimeJsonSchemaWrapper,
130
131 pub host_information: HostInformationV2,
132
133 #[serde(default)]
134 pub declared_role: DeclaredRolesV2,
135
136 #[serde(default)]
137 pub auxiliary_details: NymNodeAuxiliaryDetailsV2,
138
139 pub build_information: BinaryBuildInformationOwned,
141
142 #[serde(default)]
143 pub network_requester: Option<NetworkRequesterDetailsV2>,
144
145 #[serde(default)]
146 pub ip_packet_router: Option<IpPacketRouterDetailsV2>,
147
148 #[serde(default)]
149 pub authenticator: Option<AuthenticatorDetailsV2>,
150
151 #[serde(default)]
152 pub wireguard: Option<WireguardDetailsV2>,
153
154 pub mixnet_websockets: WebSocketsV2,
156
157 #[serde(default)]
158 pub lewes_protocol: Option<LewesProtocolDetailsV1>,
159}
160
161impl NymNodeDataV2 {
162 pub fn mix_port(&self) -> u16 {
163 self.auxiliary_details
164 .announce_ports
165 .mix_port
166 .unwrap_or(DEFAULT_MIX_LISTENING_PORT)
167 }
168
169 pub fn verloc_port(&self) -> u16 {
170 self.auxiliary_details
171 .announce_ports
172 .verloc_port
173 .unwrap_or(DEFAULT_VERLOC_LISTENING_PORT)
174 }
175}
176
177impl From<NymNodeDataV2> for NymNodeDataV1 {
178 fn from(data: NymNodeDataV2) -> Self {
179 NymNodeDataV1 {
180 last_polled: data.last_polled,
181 host_information: data.host_information,
182 declared_role: data.declared_role,
183 auxiliary_details: data.auxiliary_details,
184 build_information: data.build_information,
185 network_requester: data.network_requester,
186 ip_packet_router: data.ip_packet_router,
187 authenticator: data.authenticator,
188 wireguard: data.wireguard,
189 mixnet_websockets: data.mixnet_websockets,
190 }
191 }
192}
193
194impl From<NymNodeDataV1> for NymNodeDataV2 {
195 fn from(data: NymNodeDataV1) -> Self {
196 NymNodeDataV2 {
197 last_polled: data.last_polled,
198 host_information: data.host_information,
199 declared_role: data.declared_role,
200 auxiliary_details: data.auxiliary_details,
201 build_information: data.build_information,
202 network_requester: data.network_requester,
203 ip_packet_router: data.ip_packet_router,
204 authenticator: data.authenticator,
205 wireguard: data.wireguard,
206 mixnet_websockets: data.mixnet_websockets,
207 lewes_protocol: Default::default(),
208 }
209 }
210}
211
212impl From<NymNodeDescriptionV2> for NymNodeDescriptionV1 {
213 fn from(value: NymNodeDescriptionV2) -> Self {
214 NymNodeDescriptionV1 {
215 node_id: value.node_id,
216 contract_node_type: value.contract_node_type,
217 description: value.description.into(),
218 }
219 }
220}
221
222impl From<NymNodeDescriptionV1> for NymNodeDescriptionV2 {
223 fn from(value: NymNodeDescriptionV1) -> Self {
224 NymNodeDescriptionV2 {
225 node_id: value.node_id,
226 contract_node_type: value.contract_node_type,
227 description: value.description.into(),
228 }
229 }
230}