mirror of
https://github.com/logos-co/nomos-node.git
synced 2026-08-27 17:41:11 +00:00
chore: enforce non-zero redundancy parameter for Blend cover messages (#3364)
This commit is contained in:
+15
-4
@@ -1,12 +1,17 @@
|
||||
use std::num::NonZeroU64;
|
||||
|
||||
use lb_blend_proofs::quota::Quota;
|
||||
use lb_utils::math::NonNegativeF64;
|
||||
use lb_utils::math::PositiveF64;
|
||||
|
||||
/// `Q_C`: the messaging allowance of a single core node for one epoch.
|
||||
///
|
||||
/// The spec requires the parameters to satisfy `C * ß_c > 0`, which the
|
||||
/// argument types carry: `message_frequency_per_round` is positive and
|
||||
/// `num_blend_layers` is non-zero, so `Q_C >= 1` for every epoch.
|
||||
#[must_use]
|
||||
pub fn core_quota(
|
||||
rounds_per_epoch: NonZeroU64,
|
||||
message_frequency_per_round: NonNegativeF64,
|
||||
message_frequency_per_round: PositiveF64,
|
||||
num_blend_layers: NonZeroU64,
|
||||
membership_size: usize,
|
||||
) -> Quota {
|
||||
@@ -18,8 +23,14 @@ pub fn core_quota(
|
||||
// `Q_c`: Messaging allowance that can be used by a core node during a single
|
||||
// epoch. We assume `R_c` to be `0` for now, hence `Q_c = ceil(C * (ß_c
|
||||
// + 0 * ß_c)) / N = ceil(C * ß_c) / N`.
|
||||
(((expected_number_of_epoch_messages * num_blend_layers.get() as f64) / membership_size as f64)
|
||||
.ceil() as u64)
|
||||
let quota_integer = NonZeroU64::try_from(
|
||||
((expected_number_of_epoch_messages * num_blend_layers.get() as f64)
|
||||
/ membership_size as f64)
|
||||
.ceil() as u64,
|
||||
)
|
||||
.expect("Core Quota cannot be zero, if `message_frequency_per_round` is greater than zero and `num_blend_layers` is non-zero.");
|
||||
quota_integer
|
||||
.get()
|
||||
.try_into()
|
||||
.expect("Core Quota must fit within the width the `PoQ` circuit allows.")
|
||||
}
|
||||
|
||||
@@ -142,7 +142,7 @@ mod tests {
|
||||
use lb_core::sdp::{MinStake, ServiceParameters, ServiceType};
|
||||
use lb_cryptarchia_engine::EpochConfig;
|
||||
pub use lb_groth16::ModulusShift;
|
||||
use lb_utils::math::{NonNegativeF64, NonNegativeRatio};
|
||||
use lb_utils::math::{NonNegativeRatio, PositiveF64};
|
||||
|
||||
use crate::{
|
||||
config::{BlendPoWConfig, PoWConfig},
|
||||
@@ -181,7 +181,7 @@ mod tests {
|
||||
service_rewards_params: ServiceRewardsParameters {
|
||||
blend: RewardsParameters {
|
||||
rounds_per_epoch: epoch_length.try_into().unwrap(),
|
||||
message_frequency_per_round: NonNegativeF64::try_from(1.0).unwrap(),
|
||||
message_frequency_per_round: PositiveF64::try_from(1.0).unwrap(),
|
||||
num_blend_layers: NonZeroU64::new(3).unwrap(),
|
||||
minimum_network_size: NonZeroU64::new(1).unwrap(),
|
||||
data_replication_factor: 0,
|
||||
@@ -243,7 +243,7 @@ mod tests {
|
||||
service_rewards_params: ServiceRewardsParameters {
|
||||
blend: RewardsParameters {
|
||||
rounds_per_epoch: epoch_length.try_into().unwrap(),
|
||||
message_frequency_per_round: NonNegativeF64::try_from(1.0).unwrap(),
|
||||
message_frequency_per_round: PositiveF64::try_from(1.0).unwrap(),
|
||||
num_blend_layers: NonZeroU64::new(3).unwrap(),
|
||||
minimum_network_size: NonZeroU64::new(1).unwrap(),
|
||||
data_replication_factor: 0,
|
||||
@@ -314,7 +314,7 @@ mod tests {
|
||||
service_rewards_params: ServiceRewardsParameters {
|
||||
blend: RewardsParameters {
|
||||
rounds_per_epoch: epoch_length.try_into().unwrap(),
|
||||
message_frequency_per_round: NonNegativeF64::try_from(1.0).unwrap(),
|
||||
message_frequency_per_round: PositiveF64::try_from(1.0).unwrap(),
|
||||
num_blend_layers: NonZeroU64::new(3).unwrap(),
|
||||
minimum_network_size: NonZeroU64::new(1).unwrap(),
|
||||
data_replication_factor: 0,
|
||||
|
||||
@@ -864,7 +864,7 @@ pub mod tests {
|
||||
use lb_cryptarchia_engine::EpochConfig;
|
||||
use lb_groth16::{AdditiveGroup as _, ModulusShift};
|
||||
use lb_key_management_system_keys::keys::{Ed25519Key, Ed25519PublicKey, ZkKey, ZkSignature};
|
||||
use lb_utils::math::{NonNegativeF64, NonNegativeRatio};
|
||||
use lb_utils::math::{NonNegativeRatio, PositiveF64};
|
||||
use num_bigint::BigUint;
|
||||
use rand::{RngCore as _, thread_rng};
|
||||
|
||||
@@ -1074,7 +1074,7 @@ pub mod tests {
|
||||
service_rewards_params: ServiceRewardsParameters {
|
||||
blend: rewards::blend::RewardsParameters {
|
||||
rounds_per_epoch: epoch_length.try_into().unwrap(),
|
||||
message_frequency_per_round: NonNegativeF64::try_from(1.0).unwrap(),
|
||||
message_frequency_per_round: PositiveF64::try_from(1.0).unwrap(),
|
||||
num_blend_layers: NonZeroU64::new(3).unwrap(),
|
||||
minimum_network_size: NonZeroU64::new(1).unwrap(),
|
||||
data_replication_factor: 0,
|
||||
|
||||
@@ -642,7 +642,7 @@ mod tests {
|
||||
};
|
||||
use lb_groth16::{AdditiveGroup as _, Fr};
|
||||
use lb_key_management_system_keys::keys::{Ed25519Key, ZkKey};
|
||||
use lb_utils::math::NonNegativeF64;
|
||||
use lb_utils::math::PositiveF64;
|
||||
use num_bigint::BigUint;
|
||||
|
||||
use super::*;
|
||||
@@ -658,7 +658,7 @@ mod tests {
|
||||
service_rewards_params: ServiceRewardsParameters {
|
||||
blend: blend::RewardsParameters {
|
||||
rounds_per_epoch: NonZeroU64::new(10).unwrap(),
|
||||
message_frequency_per_round: NonNegativeF64::try_from(1.0).unwrap(),
|
||||
message_frequency_per_round: PositiveF64::try_from(1.0).unwrap(),
|
||||
num_blend_layers: NonZeroU64::new(3).unwrap(),
|
||||
minimum_network_size: NonZeroU64::new(1).unwrap(),
|
||||
data_replication_factor: 0,
|
||||
|
||||
@@ -15,7 +15,7 @@ use lb_core::{
|
||||
mantle::{Utxo, Value},
|
||||
sdp::{ActivityMetadata, ProviderId, ServiceParameters},
|
||||
};
|
||||
use lb_utils::math::NonNegativeF64;
|
||||
use lb_utils::math::PositiveF64;
|
||||
use tracing::debug;
|
||||
|
||||
use crate::{
|
||||
@@ -233,7 +233,7 @@ where
|
||||
#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
|
||||
pub struct RewardsParameters {
|
||||
pub rounds_per_epoch: NonZeroU64,
|
||||
pub message_frequency_per_round: NonNegativeF64,
|
||||
pub message_frequency_per_round: PositiveF64,
|
||||
pub num_blend_layers: NonZeroU64,
|
||||
pub data_replication_factor: u64,
|
||||
pub minimum_network_size: NonZeroU64,
|
||||
@@ -327,7 +327,7 @@ mod tests {
|
||||
) -> RewardsParameters {
|
||||
RewardsParameters {
|
||||
rounds_per_epoch: rounds_per_epoch.try_into().unwrap(),
|
||||
message_frequency_per_round: NonNegativeF64::try_from(1.0).unwrap(),
|
||||
message_frequency_per_round: PositiveF64::try_from(1.0).unwrap(),
|
||||
num_blend_layers: NonZeroU64::new(3).unwrap(),
|
||||
minimum_network_size: minimum_network_size.try_into().unwrap(),
|
||||
data_replication_factor: 0,
|
||||
|
||||
@@ -2,7 +2,7 @@ use core::{num::NonZeroU64, time::Duration};
|
||||
|
||||
use lb_ledger::mantle::sdp::rewards::blend::RewardsParameters;
|
||||
use lb_libp2p::protocol_name::StreamProtocol;
|
||||
use lb_utils::math::NonNegativeF64;
|
||||
use lb_utils::math::{NonNegativeF64, PositiveF64};
|
||||
use nutype::nutype;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
@@ -127,7 +127,7 @@ pub struct SchedulerSettings {
|
||||
#[derive(Serialize, Deserialize, Clone, Debug)]
|
||||
pub struct CoverTrafficSettings {
|
||||
/// `F_c`: frequency at which cover messages are generated per round.
|
||||
pub message_frequency_per_round: NonNegativeF64,
|
||||
pub message_frequency_per_round: PositiveF64,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Clone, Debug)]
|
||||
|
||||
@@ -4,7 +4,7 @@ use lb_core::blend::core_quota;
|
||||
use lb_key_management_system_service::{backend::preload::KeyId, keys::UnsecuredEd25519Key};
|
||||
use lb_poq::Quota;
|
||||
use lb_services_utils::overwatch::{RecoveryData, StorageRecoverySettings};
|
||||
use lb_utils::math::NonNegativeF64;
|
||||
use lb_utils::math::PositiveF64;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::settings::TimingSettings;
|
||||
@@ -103,7 +103,7 @@ pub struct SchedulerSettings {
|
||||
#[derive(Serialize, Deserialize, Clone, Debug)]
|
||||
pub struct CoverTrafficSettings {
|
||||
/// `F_c`: frequency at which cover messages are generated per round.
|
||||
pub message_frequency_per_round: NonNegativeF64,
|
||||
pub message_frequency_per_round: PositiveF64,
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
use core::time::Duration;
|
||||
use core::{num::NonZeroU64, time::Duration};
|
||||
use std::collections::VecDeque;
|
||||
|
||||
use futures::{StreamExt as _, stream::repeat};
|
||||
@@ -1854,8 +1854,14 @@ async fn a_transaction_awaiting_a_pow_solution_does_not_stall_the_event_loop() {
|
||||
0,
|
||||
);
|
||||
// No cover traffic, so every message the service sends is one this test put
|
||||
// in and the count below means what it says.
|
||||
settings.scheduler.cover.message_frequency_per_round = 0.0.try_into().unwrap();
|
||||
// in and the count below means what it says. The frequency itself must stay
|
||||
// positive (`C * ß_c > 0`), so the silence comes from the quota instead:
|
||||
// `Q_c = ceil(10 rounds * 0.05 * 2 layers / 2 nodes) = ceil(0.5) = 1`, and
|
||||
// the scheduler floors its cover count at `Q_c / num_blend_layers = 0`.
|
||||
// Anything in `(0, 0.1]` gives the same quota, so the halfway point keeps
|
||||
// float drift well clear of either rounding boundary.
|
||||
settings.num_blend_layers = NonZeroU64::try_from(2).unwrap();
|
||||
settings.scheduler.cover.message_frequency_per_round = 0.05.try_into().unwrap();
|
||||
|
||||
let (inbound_relay, inbound_message_sender) = new_stream();
|
||||
let (mut blend_message_stream, _blend_message_sender) = new_stream();
|
||||
|
||||
@@ -516,7 +516,7 @@ mod pol_tests {
|
||||
Config as SdpConfig, ServiceRewardsParameters, rewards::blend::RewardsParameters,
|
||||
},
|
||||
};
|
||||
use lb_utils::math::{NonNegativeF64, NonNegativeRatio};
|
||||
use lb_utils::math::{NonNegativeRatio, PositiveF64};
|
||||
use lb_wallet_service::{WalletMsg, WalletServiceSettings};
|
||||
use overwatch::services::{
|
||||
ServiceData,
|
||||
@@ -749,7 +749,7 @@ mod pol_tests {
|
||||
service_rewards_params: ServiceRewardsParameters {
|
||||
blend: RewardsParameters {
|
||||
rounds_per_epoch: NonZero::new(10u64).unwrap(),
|
||||
message_frequency_per_round: NonNegativeF64::try_from(1.0).unwrap(),
|
||||
message_frequency_per_round: PositiveF64::try_from(1.0).unwrap(),
|
||||
num_blend_layers: NonZero::new(3u64).unwrap(),
|
||||
minimum_network_size: NonZero::new(1u64).unwrap(),
|
||||
data_replication_factor: 0,
|
||||
|
||||
@@ -367,7 +367,7 @@ mod tests {
|
||||
mantle::sdp::{ServiceRewardsParameters, rewards},
|
||||
};
|
||||
use lb_network_service::{NetworkService, backends::NetworkBackend, message::ChainSyncEvent};
|
||||
use lb_utils::math::{NonNegativeF64, NonNegativeRatio};
|
||||
use lb_utils::math::{NonNegativeRatio, PositiveF64};
|
||||
use overwatch::{
|
||||
overwatch::OverwatchHandle,
|
||||
services::{ServiceData, relay::OutboundRelay},
|
||||
@@ -973,7 +973,7 @@ mod tests {
|
||||
service_rewards_params: ServiceRewardsParameters {
|
||||
blend: rewards::blend::RewardsParameters {
|
||||
rounds_per_epoch: epoch_length.try_into().unwrap(),
|
||||
message_frequency_per_round: NonNegativeF64::try_from(1.0).unwrap(),
|
||||
message_frequency_per_round: PositiveF64::try_from(1.0).unwrap(),
|
||||
num_blend_layers: NonZeroU64::new(3).unwrap(),
|
||||
minimum_network_size: NonZeroU64::new(1).unwrap(),
|
||||
data_replication_factor: 0,
|
||||
|
||||
@@ -136,7 +136,7 @@ mod tests {
|
||||
config::{BlendPoWConfig, ModulusShift, PoWConfig},
|
||||
mantle::sdp::{ServiceRewardsParameters, rewards},
|
||||
};
|
||||
use lb_utils::math::{NonNegativeF64, NonNegativeRatio};
|
||||
use lb_utils::math::{NonNegativeRatio, PositiveF64};
|
||||
|
||||
use super::*;
|
||||
|
||||
@@ -177,7 +177,7 @@ mod tests {
|
||||
service_rewards_params: ServiceRewardsParameters {
|
||||
blend: rewards::blend::RewardsParameters {
|
||||
rounds_per_epoch: epoch_length.try_into().unwrap(),
|
||||
message_frequency_per_round: NonNegativeF64::try_from(1.0).unwrap(),
|
||||
message_frequency_per_round: PositiveF64::try_from(1.0).unwrap(),
|
||||
num_blend_layers: NonZeroU64::new(3).unwrap(),
|
||||
minimum_network_size: NonZeroU64::new(1).unwrap(),
|
||||
data_replication_factor: 0,
|
||||
@@ -360,7 +360,7 @@ mod tests {
|
||||
service_rewards_params: ServiceRewardsParameters {
|
||||
blend: rewards::blend::RewardsParameters {
|
||||
rounds_per_epoch: epoch_length.try_into().unwrap(),
|
||||
message_frequency_per_round: NonNegativeF64::try_from(1.0).unwrap(),
|
||||
message_frequency_per_round: PositiveF64::try_from(1.0).unwrap(),
|
||||
num_blend_layers: NonZeroU64::new(3).unwrap(),
|
||||
minimum_network_size: NonZeroU64::new(1).unwrap(),
|
||||
data_replication_factor: 0,
|
||||
|
||||
@@ -24,7 +24,7 @@ use lb_node::config::{
|
||||
network::deployment::Settings as NetworkDeploymentSettings,
|
||||
time::deployment::Settings as TimeDeploymentSettings,
|
||||
};
|
||||
use lb_utils::math::{NonNegativeF64, NonNegativeRatio};
|
||||
use lb_utils::math::{NonNegativeRatio, PositiveF64};
|
||||
|
||||
use crate::{
|
||||
release::ProtocolIdentity,
|
||||
@@ -97,10 +97,10 @@ pub fn e2e_deployment_settings_with_genesis_block(
|
||||
.expect("Normalization constant cannot be negative."),
|
||||
scheduler: SchedulerSettings {
|
||||
cover: CoverTrafficSettings {
|
||||
message_frequency_per_round: NonNegativeF64::try_from(
|
||||
message_frequency_per_round: PositiveF64::try_from(
|
||||
COVER_MESSAGE_FREQUENCY_PER_ROUND,
|
||||
)
|
||||
.expect("Message frequency per round cannot be negative."),
|
||||
.expect("Message frequency per round must be positive."),
|
||||
},
|
||||
delayer: MessageDelayerSettings {
|
||||
maximum_release_delay_in_rounds: NonZeroU64::try_from(
|
||||
|
||||
+2
-2
@@ -898,7 +898,7 @@ mod tests {
|
||||
mantle::sdp::{ServiceRewardsParameters, rewards},
|
||||
};
|
||||
use lb_pol::LotteryConstants;
|
||||
use lb_utils::math::{NonNegativeF64, NonNegativeRatio};
|
||||
use lb_utils::math::{NonNegativeRatio, PositiveF64};
|
||||
use lb_utxotree::UtxoTree;
|
||||
use num_bigint::BigUint;
|
||||
use rpds::HashTrieSetSync;
|
||||
@@ -1882,7 +1882,7 @@ mod tests {
|
||||
service_rewards_params: ServiceRewardsParameters {
|
||||
blend: rewards::blend::RewardsParameters {
|
||||
rounds_per_epoch: epoch_length.try_into().unwrap(),
|
||||
message_frequency_per_round: NonNegativeF64::try_from(1.0).unwrap(),
|
||||
message_frequency_per_round: PositiveF64::try_from(1.0).unwrap(),
|
||||
num_blend_layers: NonZeroU64::new(3).unwrap(),
|
||||
minimum_network_size: NonZeroU64::new(1).unwrap(),
|
||||
data_replication_factor: 0,
|
||||
|
||||
Reference in New Issue
Block a user