This commit is contained in:
Jędrzej Stuczyński
2025-05-19 11:58:53 +01:00
parent 4bff5631b6
commit 729f455e80
13 changed files with 165 additions and 12 deletions
@@ -22,8 +22,7 @@ pub struct KeyRotationState {
impl KeyRotationState {
pub fn key_rotation_id(&self, current_epoch_id: EpochId) -> KeyRotationId {
let diff = current_epoch_id.saturating_sub(self.initial_epoch_id);
let full_rots = diff / self.validity_epochs;
full_rots
diff / self.validity_epochs
}
pub fn next_rotation_starting_epoch_id(&self, current_epoch_id: EpochId) -> EpochId {
+3
View File
@@ -606,6 +606,9 @@ impl Client {
Client {
base_url: new_url,
reqwest_client: self.reqwest_client.clone(),
#[cfg(target_arch = "wasm32")]
request_timeout: self.request_timeout,
}
}
@@ -10,8 +10,8 @@ use thiserror::Error;
// - packet_version (starting with v1.1.0)
// - packet_size indicator
// - packet_type
// - sphinx key rotation (starting with v1.11.0)
const TODO: &str = "update the ^ version number when this PR is almost ready";
// - sphinx key rotation (starting with v1.12.0/v1.13.0 - either Cheddar or Dolcelatte release)
// it also just so happens that the only valid values for packet_size indicator include values 1-6
// therefore if we receive byte `7` (or larger than that) we'll know we received a versioned packet,
// otherwise we should treat it as legacy
+9 -2
View File
@@ -5,7 +5,7 @@
#![allow(clippy::empty_docs)]
use crate::node::{EntryDetails, RoutingNode, RoutingNodeError, SupportedRoles};
use crate::{CachedEpochRewardedSet, NymTopology};
use crate::{CachedEpochRewardedSet, NymTopology, NymTopologyMetadata};
use serde::{Deserialize, Serialize};
use std::collections::HashMap;
use std::net::SocketAddr;
@@ -38,6 +38,8 @@ impl From<SerializableTopologyError> for JsValue {
#[serde(rename_all = "camelCase")]
#[serde(deny_unknown_fields)]
pub struct WasmFriendlyNymTopology {
pub metadata: NymTopologyMetadata,
pub rewarded_set: CachedEpochRewardedSet,
pub node_details: HashMap<u32, WasmFriendlyRoutingNode>,
@@ -53,13 +55,18 @@ impl TryFrom<WasmFriendlyNymTopology> for NymTopology {
.map(|details| details.try_into())
.collect::<Result<_, _>>()?;
Ok(NymTopology::new(value.rewarded_set, node_details))
Ok(NymTopology::new(
value.metadata,
value.rewarded_set,
node_details,
))
}
}
impl From<NymTopology> for WasmFriendlyNymTopology {
fn from(value: NymTopology) -> Self {
WasmFriendlyNymTopology {
metadata: value.metadata,
rewarded_set: value.rewarded_set,
node_details: value
.node_details
@@ -3440,6 +3440,34 @@
}
},
"additionalProperties": false
},
{
"description": "Gets the current state config of the key rotation (i.e. starting epoch id and validity duration)",
"type": "object",
"required": [
"get_key_rotation_state"
],
"properties": {
"get_key_rotation_state": {
"type": "object",
"additionalProperties": false
}
},
"additionalProperties": false
},
{
"description": "Gets the current key rotation id",
"type": "object",
"required": [
"get_key_rotation_id"
],
"properties": {
"get_key_rotation_id": {
"type": "object",
"additionalProperties": false
}
},
"additionalProperties": false
}
],
"definitions": {
@@ -5116,6 +5144,46 @@
}
}
},
"get_key_rotation_id": {
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "KeyRotationIdResponse",
"type": "object",
"required": [
"rotation_id"
],
"properties": {
"rotation_id": {
"type": "integer",
"format": "uint32",
"minimum": 0.0
}
},
"additionalProperties": false
},
"get_key_rotation_state": {
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "KeyRotationState",
"type": "object",
"required": [
"initial_epoch_id",
"validity_epochs"
],
"properties": {
"initial_epoch_id": {
"description": "Records the initial epoch_id when the key rotation has been introduced (0 for fresh contracts). It is used for determining when rotation is meant to advance.",
"type": "integer",
"format": "uint32",
"minimum": 0.0
},
"validity_epochs": {
"description": "Defines how long each key rotation is valid for (in terms of epochs)",
"type": "integer",
"format": "uint32",
"minimum": 0.0
}
},
"additionalProperties": false
},
"get_mix_node_bonds": {
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "PagedMixnodeBondsResponse",
+28
View File
@@ -1486,6 +1486,34 @@
}
},
"additionalProperties": false
},
{
"description": "Gets the current state config of the key rotation (i.e. starting epoch id and validity duration)",
"type": "object",
"required": [
"get_key_rotation_state"
],
"properties": {
"get_key_rotation_state": {
"type": "object",
"additionalProperties": false
}
},
"additionalProperties": false
},
{
"description": "Gets the current key rotation id",
"type": "object",
"required": [
"get_key_rotation_id"
],
"properties": {
"get_key_rotation_id": {
"type": "object",
"additionalProperties": false
}
},
"additionalProperties": false
}
],
"definitions": {
@@ -0,0 +1,16 @@
{
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "KeyRotationIdResponse",
"type": "object",
"required": [
"rotation_id"
],
"properties": {
"rotation_id": {
"type": "integer",
"format": "uint32",
"minimum": 0.0
}
},
"additionalProperties": false
}
@@ -0,0 +1,24 @@
{
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "KeyRotationState",
"type": "object",
"required": [
"initial_epoch_id",
"validity_epochs"
],
"properties": {
"initial_epoch_id": {
"description": "Records the initial epoch_id when the key rotation has been introduced (0 for fresh contracts). It is used for determining when rotation is meant to advance.",
"type": "integer",
"format": "uint32",
"minimum": 0.0
},
"validity_epochs": {
"description": "Defines how long each key rotation is valid for (in terms of epochs)",
"type": "integer",
"format": "uint32",
"minimum": 0.0
}
},
"additionalProperties": false
}
@@ -313,6 +313,8 @@ pub(crate) fn try_update_rewarding_params(
}
}
#[allow(clippy::panic)]
#[allow(clippy::unreachable)]
#[cfg(test)]
pub mod tests {
use super::*;
@@ -1,6 +1,11 @@
// Copyright 2021-2023 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
// fine in test code
#![allow(clippy::panic)]
#![allow(clippy::unreachable)]
#![allow(clippy::unimplemented)]
#[cfg(test)]
pub mod fixtures;
pub(crate) mod legacy;
@@ -212,6 +212,7 @@ pub(crate) fn try_migrate_vested_delegation(
)?))
}
#[allow(clippy::panic)]
#[cfg(test)]
mod tests {
use super::*;
@@ -198,7 +198,6 @@ impl KeyRotationController {
{
// mutex poisoning - we have to exit
self.shutdown_token.cancel();
return;
}
// no need to send the information explicitly to nym-apis, as they're scheduled to refresh
@@ -217,7 +216,6 @@ impl KeyRotationController {
{
// mutex poisoning - we have to exit
self.shutdown_token.cancel();
return;
}
}
@@ -229,7 +227,6 @@ impl KeyRotationController {
if self.replay_protection_manager.purge_secondary().is_err() {
// mutex poisoning - we have to exit
self.shutdown_token.cancel();
return;
}
}
@@ -238,18 +238,21 @@ impl ReplayProtectionBloomfilters {
}
}
// map from particular rotation id to vector of results, based on the order of requests received
type BatchCheckResult = HashMap<u32, Vec<bool>>;
impl ReplayProtectionBloomfilters {
pub(crate) fn batch_try_check_and_set(
&self,
reply_tags: &HashMap<u32, Vec<&[u8; REPLAY_TAG_SIZE]>>,
) -> Option<Result<HashMap<u32, Vec<bool>>, PoisonError<()>>> {
) -> Option<Result<BatchCheckResult, PoisonError<()>>> {
let mut guard = match self.inner.try_lock() {
Ok(guard) => guard,
Err(TryLockError::Poisoned(_)) => return Some(Err(PoisonError::new(()))),
Err(TryLockError::WouldBlock) => return None,
};
Some(Ok(guard.batch_check_and_set(&reply_tags)))
Some(Ok(guard.batch_check_and_set(reply_tags)))
}
pub(crate) fn batch_check_and_set(
@@ -260,7 +263,7 @@ impl ReplayProtectionBloomfilters {
return Err(PoisonError::new(()));
};
Ok(guard.batch_check_and_set(&reply_tags))
Ok(guard.batch_check_and_set(reply_tags))
}
}