Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 36 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ members = [
"common/nym-common",
"common/config",
"common/cosmwasm-smart-contracts/coconut-dkg",
"contracts/performance",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

don't add it to the main workspace - all contracts have their own sub workspace

"common/cosmwasm-smart-contracts/contracts-common",
"common/cosmwasm-smart-contracts/contracts-common-testing",
"common/cosmwasm-smart-contracts/easy_addr",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ pub use nym_performance_contract_common::{
EpochMeasurementsPagedResponse, EpochNodePerformance, EpochPerformancePagedResponse,
FullHistoricalPerformancePagedResponse, HistoricalPerformance, LastSubmission,
NetworkMonitorInformation, NetworkMonitorsPagedResponse, NodeId, NodeMeasurement,
NodeMeasurementsResponse, NodePerformance, NodePerformancePagedResponse,
NodeMeasurementsPerKindResponse, NodePerformance, NodePerformancePagedResponse,
NodePerformanceResponse, RetiredNetworkMonitor, RetiredNetworkMonitorsPagedResponse,
};

Expand Down Expand Up @@ -60,7 +60,7 @@ pub trait PerformanceQueryClient {
&self,
epoch_id: EpochId,
node_id: NodeId,
) -> Result<NodeMeasurementsResponse, NyxdError> {
) -> Result<NodeMeasurementsPerKindResponse, NyxdError> {
self.query_performance_contract(PerformanceQueryMsg::NodeMeasurements { epoch_id, node_id })
.await
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ pub mod storage_keys {
pub const AUTHORISED_COUNT: &str = "authorised-count";
pub const AUTHORISED: &str = "authorised";
pub const RETIRED: &str = "retired";
pub const PERFORMANCE_RESULTS: &str = "performance-results";
pub const PERFORMANCE_RESULTS_PER_KIND: &str = "performance-results-per-kind";
pub const PERFORMANCE_DEFINED_KINDS: &str = "performance-defined-kinds";

pub const SUBMISSION_METADATA: &str = "submission-metadata";
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,12 @@ pub enum NymPerformanceContractError {
#[error("{address} is not an authorised network monitor")]
NotAuthorised { address: Addr },

#[error("{kind} not a valid measurement kind")]
UnsupportedMeasurementKind { kind: String },

#[error("Invalid input: {0}")]
InvalidInput(String),

#[error(
"attempted to submit performance data for epoch {epoch_id} and node {node_id} whilst last submitted was {last_epoch_id} for node {last_node_id}"
)]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ use cosmwasm_schema::cw_serde;
use crate::types::{
EpochMeasurementsPagedResponse, EpochPerformancePagedResponse,
FullHistoricalPerformancePagedResponse, LastSubmission, NetworkMonitorResponse,
NetworkMonitorsPagedResponse, NodeMeasurementsResponse, NodePerformancePagedResponse,
NetworkMonitorsPagedResponse, NodeMeasurementsPerKindResponse, NodePerformancePagedResponse,
NodePerformanceResponse, RetiredNetworkMonitorsPagedResponse,
};

Expand All @@ -35,6 +35,14 @@ pub enum ExecuteMsg {
data: Vec<NodePerformance>,
},

/// Measurement kind needs to be defined by the admin before measurements of
/// that kind can be submitted.
DefineMeasurementKind { measurement_kind: String },

/// After this action is done, measurements of this kind are erased.
/// New measurements of this kind cannot be submitted
RetireMeasurementKind { measurement_kind: String },

/// Attempt to authorise new network monitor for submitting performance data
AuthoriseNetworkMonitor { address: String },

Expand Down Expand Up @@ -69,9 +77,17 @@ pub enum QueryMsg {
limit: Option<u32>,
},

/// Returns all submitted measurements for the particular node
/// Returns all measurements of a specific kind for the particular node
#[cfg_attr(feature = "schema", returns(NodeMeasurementsResponse))]
NodeMeasurements {
epoch_id: EpochId,
node_id: NodeId,
kind: String,
},

// TODO dz add paged variant ?
#[cfg_attr(feature = "schema", returns(NodeMeasurementsResponse))]
NodeMeasurements { epoch_id: EpochId, node_id: NodeId },
AllNodeMeasurements { epoch_id: EpochId, node_id: NodeId },

/// Returns (paged) measurements for particular epoch
#[cfg_attr(feature = "schema", returns(EpochMeasurementsPagedResponse))]
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
// Copyright 2025 - Nym Technologies SA <[email protected]>
// SPDX-License-Identifier: Apache-2.0

use std::collections::HashMap;

use cosmwasm_schema::cw_serde;
use cosmwasm_std::{Addr, Env, Timestamp};
use nym_contracts_common::Percent;
Expand Down Expand Up @@ -49,11 +51,13 @@ pub struct RetiredNetworkMonitor {
}

#[cw_serde]
#[derive(Copy)]
pub struct NodePerformance {
#[serde(rename = "n")]
pub node_id: NodeId,

#[serde(rename = "m")]
pub measurement_kind: MeasurementKind,

// note: value is rounded to 2 decimal places.
#[serde(rename = "p")]
pub performance: Percent,
Expand Down Expand Up @@ -97,25 +101,35 @@ impl NodeResults {
}

pub fn inner(&self) -> &[Percent] {
&self.0
&self.0.as_slice()
}
}

pub type MeasurementKind = String;

/// maps measurement kind to the value of that measurement for a node
/// (present only if measured)
#[cw_serde]
pub struct NodePerformanceResponse {
pub performance: Option<Percent>,
pub performance: HashMap<MeasurementKind, Percent>,
}

#[cw_serde]
pub struct NodeMeasurementsResponse {
pub struct NodeMeasurementsPerKindResponse {
pub measurements: Option<NodeResults>,
}

#[cw_serde]
#[derive(Copy)]
pub struct AllNodeMeasurementsResponse {
// Option is used because if a measurement has been defined, that doesn't
// mean the node had actually been measured at the time of the query
pub measurements: HashMap<MeasurementKind, Option<NodeResults>>,
}

#[cw_serde]
pub struct EpochNodePerformance {
pub epoch: EpochId,
pub performance: Option<Percent>,
pub performance: HashMap<MeasurementKind, Percent>,
}

#[cw_serde]
Expand All @@ -133,24 +147,23 @@ pub struct EpochPerformancePagedResponse {
}

#[cw_serde]
pub struct NodeMeasurement {
pub struct NodeMeasurements {
pub node_id: NodeId,
pub measurements: NodeResults,
pub measurements_per_kind: HashMap<String, NodeResults>,
}

#[cw_serde]
pub struct EpochMeasurementsPagedResponse {
pub epoch_id: EpochId,
pub measurements: Vec<NodeMeasurement>,
pub measurements: Vec<NodeMeasurements>,
pub start_next_after: Option<NodeId>,
}

#[cw_serde]
#[derive(Copy)]
pub struct HistoricalPerformance {
pub epoch_id: EpochId,
pub node_id: NodeId,
pub performance: Percent,
pub performance: HashMap<MeasurementKind, Percent>,
}

#[cw_serde]
Expand Down Expand Up @@ -187,11 +200,14 @@ pub struct RemoveEpochMeasurementsResponse {
pub additional_entries_to_remove_remaining: bool,
}

/// return details about submissions: whether they were accepted, or why they
/// were rejected
#[cw_serde]
#[derive(Default)]
pub struct BatchSubmissionResult {
pub accepted_scores: u64,
pub non_existent_nodes: Vec<NodeId>,
pub non_existent_measurement_kind: Vec<String>,
}

#[cfg(test)]
Expand Down
35 changes: 26 additions & 9 deletions contracts/performance/src/contract.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,20 @@
// SPDX-License-Identifier: Apache-2.0

use crate::queries::{
query_admin, query_epoch_measurements_paged, query_epoch_performance_paged,
query_full_historical_performance_paged, query_last_submission, query_network_monitor_details,
query_network_monitors_paged, query_node_measurements, query_node_performance,
query_node_performance_paged, query_retired_network_monitors_paged,
query_admin, query_all_node_measurements, query_epoch_measurements_paged,
query_epoch_performance_paged, query_full_historical_performance_paged, query_last_submission,
query_network_monitor_details, query_network_monitors_paged, query_node_measurements_for_kind,
query_node_performance, query_node_performance_paged, query_retired_network_monitors_paged,
};
use crate::storage::NYM_PERFORMANCE_CONTRACT_STORAGE;
use crate::transactions::{
try_authorise_network_monitor, try_batch_submit_performance_results,
try_remove_epoch_measurements, try_remove_node_measurements, try_retire_network_monitor,
try_submit_performance_results, try_update_contract_admin,
try_define_measurement_kind, try_remove_epoch_measurements, try_remove_node_measurements,
try_retire_measurement_kind, try_retire_network_monitor, try_submit_performance_results,
try_update_contract_admin,
};
use cosmwasm_std::{
entry_point, to_json_binary, Binary, Deps, DepsMut, Env, MessageInfo, Response,
Binary, Deps, DepsMut, Env, MessageInfo, Response, entry_point, to_json_binary,
};
use nym_contracts_common::set_build_information;
use nym_performance_contract_common::{
Expand Down Expand Up @@ -62,12 +63,20 @@ pub fn execute(
ExecuteMsg::BatchSubmit { epoch, data } => {
try_batch_submit_performance_results(deps, env, info, epoch, data)
}
ExecuteMsg::DefineMeasurementKind { measurement_kind } => {
try_define_measurement_kind(deps, &info.sender, measurement_kind)
}
ExecuteMsg::RetireMeasurementKind { measurement_kind } => {
try_retire_measurement_kind(deps, &info.sender, measurement_kind)
}
ExecuteMsg::AuthoriseNetworkMonitor { address } => {
try_authorise_network_monitor(deps, env, info, address)
}
ExecuteMsg::RetireNetworkMonitor { address } => {
try_retire_network_monitor(deps, env, info, address)
}
// TODO dz removing measurement for only a certain node shouldn't be allowed
// remove this message and corresponding path
ExecuteMsg::RemoveNodeMeasurements { epoch_id, node_id } => {
try_remove_node_measurements(deps, info, epoch_id, node_id)
}
Expand Down Expand Up @@ -116,9 +125,17 @@ pub fn query(deps: Deps, _: Env, msg: QueryMsg) -> Result<Binary, NymPerformance
QueryMsg::RetiredNetworkMonitorsPaged { start_after, limit } => Ok(to_json_binary(
&query_retired_network_monitors_paged(deps, start_after, limit)?,
)?),
QueryMsg::NodeMeasurements { epoch_id, node_id } => Ok(to_json_binary(
&query_node_measurements(deps, epoch_id, node_id)?,
QueryMsg::NodeMeasurements {
epoch_id,
node_id,
kind,
} => Ok(to_json_binary(&query_node_measurements_for_kind(
deps, epoch_id, node_id, kind,
)?)?),
QueryMsg::AllNodeMeasurements { epoch_id, node_id } => Ok(to_json_binary(
&query_all_node_measurements(deps, epoch_id, node_id)?,
)?),

QueryMsg::EpochMeasurementsPaged {
epoch_id,
start_after,
Expand Down
2 changes: 1 addition & 1 deletion contracts/performance/src/helpers.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// Copyright 2025 - Nym Technologies SA <[email protected]>
// SPDX-License-Identifier: Apache-2.0

use cosmwasm_std::{from_json, Binary, CustomQuery, QuerierWrapper, StdError, StdResult};
use cosmwasm_std::{Binary, CustomQuery, QuerierWrapper, StdError, StdResult, from_json};
use cw_storage_plus::{Key, Namespace, Path, PrimaryKey};
use nym_mixnet_contract_common::{Interval, NymNodeBond};
use nym_performance_contract_common::{EpochId, NodeId};
Expand Down
Loading
Loading