most of nym-node changes

This commit is contained in:
Jędrzej Stuczyński
2025-05-13 15:31:36 +01:00
parent 8bcbb69889
commit 61dd59ff9d
12 changed files with 106 additions and 42 deletions
+1 -1
View File
@@ -933,7 +933,7 @@ impl From<nym_node_requests::api::v1::node::models::HostKeys> for HostKeys {
fn from(value: nym_node_requests::api::v1::node::models::HostKeys) -> Self {
HostKeysDeHelper {
ed25519: value.ed25519_identity,
current_x25519_sphinx_key: value.current_x25519_sphinx_key.into(),
current_x25519_sphinx_key: value.primary_x25519_sphinx_key.into(),
pre_announced_x25519_sphinx_key: value.pre_announced_x25519_sphinx_key.map(Into::into),
x25519_noise: value.x25519_noise,
}
+8 -8
View File
@@ -136,7 +136,7 @@ mod tests {
hostname: Some("foomp.com".to_string()),
keys: crate::api::v1::node::models::HostKeys {
ed25519_identity: *ed22519.public_key(),
current_x25519_sphinx_key: SphinxKey {
primary_x25519_sphinx_key: SphinxKey {
rotation_id: current_rotation_id,
public_key: *x25519_sphinx.public_key(),
},
@@ -154,7 +154,7 @@ mod tests {
hostname: Some("foomp.com".to_string()),
keys: crate::api::v1::node::models::HostKeys {
ed25519_identity: *ed22519.public_key(),
current_x25519_sphinx_key: SphinxKey {
primary_x25519_sphinx_key: SphinxKey {
rotation_id: current_rotation_id,
public_key: *x25519_sphinx.public_key(),
},
@@ -174,7 +174,7 @@ mod tests {
hostname: Some("foomp.com".to_string()),
keys: crate::api::v1::node::models::HostKeys {
ed25519_identity: *ed22519.public_key(),
current_x25519_sphinx_key: SphinxKey {
primary_x25519_sphinx_key: SphinxKey {
rotation_id: current_rotation_id,
public_key: *x25519_sphinx.public_key(),
},
@@ -195,7 +195,7 @@ mod tests {
hostname: Some("foomp.com".to_string()),
keys: crate::api::v1::node::models::HostKeys {
ed25519_identity: *ed22519.public_key(),
current_x25519_sphinx_key: SphinxKey {
primary_x25519_sphinx_key: SphinxKey {
rotation_id: current_rotation_id,
public_key: *x25519_sphinx.public_key(),
},
@@ -236,7 +236,7 @@ mod tests {
hostname: Some("foomp.com".to_string()),
keys: HostKeys {
ed25519_identity: *ed22519.public_key(),
current_x25519_sphinx_key: SphinxKey {
primary_x25519_sphinx_key: SphinxKey {
rotation_id: u32::MAX,
public_key: *x25519_sphinx.public_key(),
},
@@ -293,7 +293,7 @@ mod tests {
hostname: legacy_info_no_noise.hostname.clone(),
keys: crate::api::v1::node::models::HostKeys {
ed25519_identity: legacy_info_no_noise.keys.ed25519_identity.parse().unwrap(),
current_x25519_sphinx_key: SphinxKey {
primary_x25519_sphinx_key: SphinxKey {
rotation_id: u32::MAX,
public_key: *x25519_sphinx.public_key(),
},
@@ -308,7 +308,7 @@ mod tests {
hostname: legacy_info_noise.hostname.clone(),
keys: crate::api::v1::node::models::HostKeys {
ed25519_identity: legacy_info_noise.keys.ed25519_identity.parse().unwrap(),
current_x25519_sphinx_key: SphinxKey {
primary_x25519_sphinx_key: SphinxKey {
rotation_id: u32::MAX,
public_key: *x25519_sphinx.public_key(),
},
@@ -365,7 +365,7 @@ mod tests {
hostname: legacy_info.hostname.clone(),
keys: crate::api::v1::node::models::HostKeys {
ed25519_identity: legacy_info.keys.ed25519.parse().unwrap(),
current_x25519_sphinx_key: SphinxKey {
primary_x25519_sphinx_key: SphinxKey {
rotation_id: u32::MAX,
public_key: *x25519_sphinx.public_key(),
},
@@ -131,12 +131,17 @@ pub struct HostKeys {
#[cfg_attr(feature = "openapi", schema(value_type = String))]
pub ed25519_identity: ed25519::PublicKey,
#[deprecated(note = "use explicit primary_x25519_sphinx_key instead")]
#[serde(alias = "x25519")]
#[serde(with = "bs58_x25519_pubkey")]
#[schemars(with = "String")]
#[cfg_attr(feature = "openapi", schema(value_type = String))]
pub x25519_sphinx: x25519::PublicKey,
/// Current, active, x25519 sphinx key clients are expected to use when constructing packets
/// with this node in the route.
#[serde(alias = "x25519")]
#[serde(alias = "x25519_sphinx")]
#[serde(deserialize_with = "de_sphinx_key")]
pub current_x25519_sphinx_key: SphinxKey,
pub primary_x25519_sphinx_key: SphinxKey,
/// Pre-announced x25519 sphinx key clients will use during the following key rotation
#[serde(default)]
@@ -223,7 +228,7 @@ impl From<HostKeys> for LegacyHostKeysV3 {
fn from(value: HostKeys) -> Self {
LegacyHostKeysV3 {
ed25519_identity: value.ed25519_identity,
x25519_sphinx: value.current_x25519_sphinx_key.public_key,
x25519_sphinx: value.primary_x25519_sphinx_key.public_key,
x25519_noise: value.x25519_noise,
}
}
+30
View File
@@ -529,6 +529,9 @@ pub struct Mixnet {
/// Settings for controlling replay detection
pub replay_protection: ReplayProtection,
#[serde(default)]
pub key_rotation: KeyRotation,
#[serde(default)]
pub debug: MixnetDebug,
}
@@ -717,6 +720,32 @@ impl Default for ReplayProtectionDebug {
}
}
#[derive(Debug, Default, Copy, Clone, Deserialize, PartialEq, Serialize)]
#[serde(default)]
pub struct KeyRotation {
pub debug: KeyRotationDebug,
}
#[derive(Debug, Copy, Clone, Deserialize, PartialEq, Serialize)]
#[serde(default)]
pub struct KeyRotationDebug {
/// Specifies how often the node should poll for any changes in the key rotation global state.
#[serde(with = "humantime_serde")]
pub rotation_state_poling_interval: Duration,
}
impl KeyRotationDebug {
pub const DEFAULT_ROTATION_STATE_POLLING_INTERVAL: Duration = Duration::from_secs(4 * 60 * 60);
}
impl Default for KeyRotationDebug {
fn default() -> Self {
KeyRotationDebug {
rotation_state_poling_interval: Self::DEFAULT_ROTATION_STATE_POLLING_INTERVAL,
}
}
}
impl MixnetDebug {
// given that genuine clients are using mean delay of 50ms,
// the probability of them delaying for over 10s is 10^-87
@@ -767,6 +796,7 @@ impl Mixnet {
nym_api_urls,
nyxd_urls,
replay_protection: ReplayProtection::new_default(data_dir),
key_rotation: Default::default(),
debug: Default::default(),
}
}
@@ -1403,6 +1403,7 @@ pub async fn try_upgrade_config_v9<P: AsRef<Path>>(
.bloomfilter_disk_flushing_rate,
},
},
key_rotation: Default::default(),
debug: MixnetDebug {
maximum_forward_packet_delay: old_cfg.mixnet.debug.maximum_forward_packet_delay,
packet_forwarding_initial_backoff: old_cfg
@@ -31,18 +31,29 @@ pub(crate) async fn host_information(
let pre_announced = match state.x25519_sphinx_keys.secondary() {
None => None,
Some(secondary_key) => {
todo!()
if secondary_key.rotation_id() == primary_key.rotation_id() + 1 {
Some(api_requests::v1::node::models::SphinxKey {
rotation_id: secondary_key.rotation_id(),
public_key: secondary_key.x25519_pubkey(),
})
} else {
None
}
}
};
let primary_pubkey = primary_key.x25519_pubkey();
#[allow(deprecated)]
let host_info = api_requests::v1::node::models::HostInformation {
ip_address: state.static_information.ip_addresses.clone(),
hostname: state.static_information.hostname.clone(),
keys: api_requests::v1::node::models::HostKeys {
ed25519_identity: *state.static_information.ed25519_identity_keys.public_key(),
current_x25519_sphinx_key: api_requests::v1::node::models::SphinxKey {
x25519_sphinx: primary_pubkey,
primary_x25519_sphinx_key: api_requests::v1::node::models::SphinxKey {
rotation_id: primary_key.rotation_id(),
public_key: primary_key.x25519_pubkey(),
public_key: primary_pubkey,
},
x25519_noise: state.static_information.x25519_noise_key,
pre_announced_x25519_sphinx_key: pre_announced,
@@ -35,13 +35,12 @@ impl ActiveSphinxKeys {
primary: SphinxPrivateKey,
secondary: Option<SphinxPrivateKey>,
) -> Self {
todo!()
// ActiveSphinxKeys {
// inner: Arc::new(ActiveSphinxKeysInner {
// primary_key: ArcSwap::from_pointee(primary),
// secondary_key: ArcSwapOption::from_pointee(secondary),
// }),
// }
ActiveSphinxKeys {
inner: Arc::new(ActiveSphinxKeysInner {
primary_key: ArcSwap::from_pointee(primary),
secondary_key: ArcSwapOption::from_pointee(secondary),
}),
}
}
pub(crate) fn even(&self) -> Option<SphinxKeyGuard> {
+15 -12
View File
@@ -6,7 +6,6 @@ use crate::node::key_rotation::manager::SphinxKeyManager;
use crate::node::nym_apis_client::NymApisClient;
use crate::node::replay_protection::manager::ReplayProtectionBloomfiltersManager;
use futures::pin_mut;
use nym_node_metrics::NymNodeMetrics;
use nym_task::ShutdownToken;
use nym_validator_client::models::{KeyRotationInfoResponse, KeyRotationState};
use std::time::Duration;
@@ -14,7 +13,7 @@ use time::OffsetDateTime;
use tokio::time::{interval, sleep, Instant};
use tracing::{error, info, trace, warn};
struct RotationConfig {
pub(crate) struct RotationConfig {
epoch_duration: Duration,
rotation_state: KeyRotationState,
}
@@ -78,20 +77,24 @@ enum KeyRotationActionState {
impl KeyRotationController {
pub(crate) fn new(
config: &Config,
rotation_config: RotationConfig,
client: NymApisClient,
replay_protection_manager: ReplayProtectionBloomfiltersManager,
metrics: NymNodeMetrics,
managed_keys: SphinxKeyManager,
shutdown_token: ShutdownToken,
) -> Self {
todo!()
// KeyRotationController {
// regular_polling_interval,
// replay_protection_manager,
// client,
// managed_keys,
// shutdown_token,
// }
KeyRotationController {
regular_polling_interval: config
.mixnet
.key_rotation
.debug
.rotation_state_poling_interval,
rotation_config,
replay_protection_manager,
client,
managed_keys,
shutdown_token,
}
}
async fn determine_next_action(&self) -> NextAction {
@@ -234,7 +237,7 @@ impl KeyRotationController {
polling_interval.reset();
let mut next_action = self.determine_next_action().await;
let mut state_update_future = sleep(next_action.until_deadline());
let state_update_future = sleep(next_action.until_deadline());
pin_mut!(state_update_future);
while !self.shutdown_token.is_cancelled() {
+1 -1
View File
@@ -180,7 +180,7 @@ impl SphinxKeyManager {
// immediately rotate keys (but leave 1h grace period for current primary, i.e. set it as secondary)
if primary.rotation_id() != current_rotation_id {
warn!("this node has been inactive for more than a key rotation duration. the current primary key was generated for rotation {} while the current rotation is {current_rotation_id}. new key will be generated now.", primary.rotation_id());
let mut this = SphinxKeyManager {
let this = SphinxKeyManager {
keys: ActiveSphinxKeys::new_loaded(primary, None),
primary_key_path: primary_key_path.as_ref().to_path_buf(),
secondary_key_path: secondary_key_path.as_ref().to_path_buf(),
+3 -1
View File
@@ -1003,11 +1003,13 @@ impl NymNode {
replay_protection_manager: ReplayProtectionBloomfiltersManager,
) -> Result<(), NymNodeError> {
let managed_keys = self.take_managed_sphinx_keys()?;
let rotation_state = nym_apis_client.get_key_rotation_info().await?;
let rotation_controller = KeyRotationController::new(
&self.config,
rotation_state.into(),
nym_apis_client,
replay_protection_manager,
self.metrics.clone(),
managed_keys,
self.shutdown_manager.clone_token("key-rotation-controller"),
);
@@ -210,7 +210,7 @@ impl ReplayProtectionBloomfilters {
})?;
let id = guard.primary.metadata.rotation_id;
let bytes = guard.primary.data.to_bytes();
let bytes = guard.primary.bytes();
Ok((bytes, id))
}
@@ -233,7 +233,7 @@ impl ReplayProtectionBloomfilters {
};
let id = secondary.metadata.rotation_id;
let bytes = secondary.data.to_bytes();
let bytes = secondary.bytes();
Ok(Some((bytes, id)))
}
}
+16 -3
View File
@@ -15,7 +15,7 @@ use nym_crypto::asymmetric::x25519;
use nym_sphinx_addressing::nodes::NymNodeRoutingAddress;
use nym_sphinx_framing::codec::{NymCodec, NymCodecError};
use nym_sphinx_framing::packet::FramedNymPacket;
use nym_sphinx_params::PacketSize;
use nym_sphinx_params::{PacketSize, SphinxKeyRotation};
use nym_sphinx_routing::generate_hop_delays;
use nym_sphinx_types::constants::{
EXPANDED_SHARED_SECRET_HKDF_INFO, EXPANDED_SHARED_SECRET_HKDF_SALT,
@@ -101,6 +101,7 @@ pub(crate) struct ThroughputTestingClient {
listener: TcpListener,
forward_connection: Framed<TcpStream, NymCodec>,
payload_key: PayloadKey,
key_rotation: SphinxKeyRotation,
}
fn rederive_lioness_payload_key(shared_secret: &[u8; 32]) -> PayloadKey {
@@ -195,6 +196,12 @@ impl ThroughputTestingClient {
}
};
let key_rotation = if loaded_private.is_even_rotation() {
SphinxKeyRotation::EvenRotation
} else {
SphinxKeyRotation::OddRotation
};
Ok(ThroughputTestingClient {
stats,
last_received_update: Instant::now(),
@@ -210,6 +217,7 @@ impl ThroughputTestingClient {
listener,
forward_connection: Framed::new(forward_connection, NymCodec),
payload_key,
key_rotation,
})
}
@@ -256,8 +264,13 @@ impl ThroughputTestingClient {
packet_bytes.append(&mut payload_bytes);
let forward_packet = NymPacket::sphinx_from_bytes(&packet_bytes)?;
todo!()
// Ok(FramedNymPacket::new(forward_packet, Default::default()))
// let key_rotation = if self.s
Ok(FramedNymPacket::new(
forward_packet,
Default::default(),
self.key_rotation,
))
}
async fn send_packets(&mut self) -> anyhow::Result<()> {