Skip to main content

nym_node_requests/api/v1/lewes_protocol/
models.rs

1// Copyright 2026 - Nym Technologies SA <contact@nymtech.net>
2// SPDX-License-Identifier: Apache-2.0
3
4use nym_crypto::asymmetric::x25519;
5use nym_crypto::asymmetric::x25519::serde_helpers::bs58_dh_public_key;
6use schemars::JsonSchema;
7use serde::{Deserialize, Serialize};
8use std::collections::BTreeMap;
9use strum_macros::{Display, EnumIter, EnumString};
10
11#[derive(Serialize, Deserialize, Debug, Clone, JsonSchema)]
12#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
13pub struct LewesProtocol {
14    /// Helper field that specifies whether the LP listener(s) is enabled on this node.
15    /// It is directly controlled by the node's role (i.e. it is enabled if it supports 'entry' mode)
16    pub enabled: bool,
17
18    /// LP TCP control address (default: 41264) for establishing LP sessions
19    pub control_port: u16,
20
21    /// LP UDP data address (default: 51264) for Sphinx packets wrapped in LP
22    pub data_port: u16,
23
24    #[serde(with = "bs58_dh_public_key")]
25    #[schemars(with = "String")]
26    #[cfg_attr(feature = "openapi", schema(value_type = String))]
27    /// LP public key
28    pub x25519: x25519::DHPublicKey,
29
30    /// Digests of the KEM keys available to this node alongside hashing algorithms used
31    /// for their computation.
32    /// note: digests are hex encoded
33    pub kem_keys: BTreeMap<LPKEM, BTreeMap<LPHashFunction, String>>,
34}
35
36impl LewesProtocol {
37    pub fn new(
38        enabled: bool,
39        control_port: u16,
40        data_port: u16,
41        x25519: x25519::DHPublicKey,
42        kem_keys: BTreeMap<LPKEM, BTreeMap<LPHashFunction, String>>,
43    ) -> Self {
44        LewesProtocol {
45            enabled,
46            control_port,
47            data_port,
48            x25519,
49            kem_keys,
50        }
51    }
52}
53
54// explicitly redefine available HashFunctions and KEMs so that we would not
55// accidentally remove some type and thus break backwards compatibility at deserialisation level
56// (the only thing that should break at that point would be conversion into proper nym-kkt types
57// which would return a concrete error variant)
58
59#[derive(
60    Serialize,
61    Deserialize,
62    Debug,
63    Clone,
64    Copy,
65    JsonSchema,
66    Hash,
67    PartialEq,
68    Eq,
69    PartialOrd,
70    Display,
71    EnumString,
72    Ord,
73)]
74#[serde(rename_all = "lowercase")]
75#[strum(serialize_all = "lowercase")]
76#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
77pub enum LPKEM {
78    #[serde(alias = "ml_kem768")]
79    MlKem768,
80
81    #[serde(alias = "mc_eliece")]
82    McEliece,
83}
84
85impl From<LPKEM> for nym_kkt_ciphersuite::KEM {
86    fn from(lpkem: LPKEM) -> Self {
87        match lpkem {
88            LPKEM::MlKem768 => nym_kkt_ciphersuite::KEM::MlKem768,
89            LPKEM::McEliece => nym_kkt_ciphersuite::KEM::McEliece,
90        }
91    }
92}
93
94impl From<nym_kkt_ciphersuite::KEM> for LPKEM {
95    fn from(kem: nym_kkt_ciphersuite::KEM) -> Self {
96        match kem {
97            nym_kkt_ciphersuite::KEM::MlKem768 => LPKEM::MlKem768,
98            nym_kkt_ciphersuite::KEM::McEliece => LPKEM::McEliece,
99        }
100    }
101}
102
103#[derive(
104    Serialize,
105    Deserialize,
106    Debug,
107    Clone,
108    Copy,
109    JsonSchema,
110    Hash,
111    PartialEq,
112    Eq,
113    PartialOrd,
114    Display,
115    EnumString,
116    EnumIter,
117    Ord,
118)]
119#[serde(rename_all = "lowercase")]
120#[strum(serialize_all = "lowercase")]
121#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
122pub enum LPHashFunction {
123    Blake3,
124    Shake128,
125    Shake256,
126    Sha256,
127}
128
129impl From<LPHashFunction> for nym_kkt_ciphersuite::HashFunction {
130    fn from(lp_hash_fnction: LPHashFunction) -> Self {
131        match lp_hash_fnction {
132            LPHashFunction::Blake3 => nym_kkt_ciphersuite::HashFunction::Blake3,
133            LPHashFunction::Shake128 => nym_kkt_ciphersuite::HashFunction::Shake128,
134            LPHashFunction::Shake256 => nym_kkt_ciphersuite::HashFunction::Shake256,
135            LPHashFunction::Sha256 => nym_kkt_ciphersuite::HashFunction::SHA256,
136        }
137    }
138}
139
140impl From<nym_kkt_ciphersuite::HashFunction> for LPHashFunction {
141    fn from(kem: nym_kkt_ciphersuite::HashFunction) -> Self {
142        match kem {
143            nym_kkt_ciphersuite::HashFunction::Blake3 => LPHashFunction::Blake3,
144            nym_kkt_ciphersuite::HashFunction::Shake128 => LPHashFunction::Shake128,
145            nym_kkt_ciphersuite::HashFunction::Shake256 => LPHashFunction::Shake256,
146            nym_kkt_ciphersuite::HashFunction::SHA256 => LPHashFunction::Sha256,
147        }
148    }
149}
150
151#[derive(
152    Serialize,
153    Deserialize,
154    Debug,
155    Clone,
156    Copy,
157    JsonSchema,
158    Hash,
159    PartialEq,
160    Eq,
161    PartialOrd,
162    Display,
163    EnumString,
164    EnumIter,
165)]
166#[serde(rename_all = "lowercase")]
167#[strum(serialize_all = "lowercase")]
168#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
169pub enum LPSignatureScheme {
170    Ed25519,
171}
172
173impl From<LPSignatureScheme> for nym_kkt_ciphersuite::SignatureScheme {
174    fn from(lp_hash_fnction: LPSignatureScheme) -> Self {
175        match lp_hash_fnction {
176            LPSignatureScheme::Ed25519 => nym_kkt_ciphersuite::SignatureScheme::Ed25519,
177        }
178    }
179}
180
181impl From<nym_kkt_ciphersuite::SignatureScheme> for LPSignatureScheme {
182    fn from(kem: nym_kkt_ciphersuite::SignatureScheme) -> Self {
183        match kem {
184            nym_kkt_ciphersuite::SignatureScheme::Ed25519 => LPSignatureScheme::Ed25519,
185        }
186    }
187}
188
189#[cfg(test)]
190mod tests {
191    use super::*;
192    use nym_kkt_ciphersuite::SignatureScheme;
193
194    #[test]
195    fn kem_display() {
196        assert_eq!(LPKEM::MlKem768.to_string(), "mlkem768");
197        assert_eq!(LPKEM::McEliece.to_string(), "mceliece");
198    }
199
200    #[test]
201    fn hash_function_display() {
202        assert_eq!(LPHashFunction::Blake3.to_string(), "blake3");
203        assert_eq!(LPHashFunction::Shake128.to_string(), "shake128");
204        assert_eq!(LPHashFunction::Shake256.to_string(), "shake256");
205        assert_eq!(LPHashFunction::Sha256.to_string(), "sha256");
206    }
207
208    #[test]
209    fn signature_scheme_display() {
210        assert_eq!(SignatureScheme::Ed25519.to_string(), "ed25519");
211    }
212}