From b7d9386c26faa42d6980ea8ec061df79b156fa1b Mon Sep 17 00:00:00 2001 From: andrussal Date: Wed, 10 Dec 2025 09:22:47 +0100 Subject: [PATCH] Add cfgsync input validation module and thiserror dep --- Cargo.lock | 1 + testing-framework/tools/cfgsync/Cargo.toml | 1 + testing-framework/tools/cfgsync/src/config.rs | 33 ++++------ .../tools/cfgsync/src/config/validation.rs | 62 +++++++++++++++++++ 4 files changed, 76 insertions(+), 21 deletions(-) create mode 100644 testing-framework/tools/cfgsync/src/config/validation.rs diff --git a/Cargo.lock b/Cargo.lock index 7f971f8..c45d4c2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1008,6 +1008,7 @@ dependencies = [ "subnetworks-assignations", "testing-framework-config", "testing-framework-core", + "thiserror 2.0.17", "tokio", "tracing", ] diff --git a/testing-framework/tools/cfgsync/Cargo.toml b/testing-framework/tools/cfgsync/Cargo.toml index b68950e..1d68716 100644 --- a/testing-framework/tools/cfgsync/Cargo.toml +++ b/testing-framework/tools/cfgsync/Cargo.toml @@ -35,5 +35,6 @@ serde_yaml = "0.9" subnetworks-assignations = { workspace = true } testing-framework-config = { workspace = true } testing-framework-core = { path = "../../core" } +thiserror = { workspace = true } tokio = { default-features = false, features = ["macros", "net", "rt-multi-thread"], version = "1" } tracing = { workspace = true } diff --git a/testing-framework/tools/cfgsync/src/config.rs b/testing-framework/tools/cfgsync/src/config.rs index 729890a..2c991ff 100644 --- a/testing-framework/tools/cfgsync/src/config.rs +++ b/testing-framework/tools/cfgsync/src/config.rs @@ -26,9 +26,12 @@ use testing_framework_config::topology::configs::{ pub use crate::host::{Host, HostKind, PortOverrides}; use crate::{ - config::providers::create_providers, host::sort_hosts, network::rewrite_initial_peers, + config::{providers::create_providers, validation::validate_inputs}, + host::sort_hosts, + network::rewrite_initial_peers, }; mod providers; +mod validation; #[must_use] pub fn create_node_configs( @@ -43,11 +46,14 @@ pub fn create_node_configs( ) -> HashMap { let hosts = sort_hosts(hosts); - assert_eq!( - hosts.len(), - consensus_params.n_participants, - "host count must match consensus participants" - ); + validate_inputs( + &hosts, + consensus_params, + ids.as_ref(), + da_ports.as_ref(), + blend_ports.as_ref(), + ) + .expect("invalid cfgsync inputs"); let ids = ids.unwrap_or_else(|| { let mut generated = vec![[0; 32]; consensus_params.n_participants]; @@ -56,29 +62,14 @@ pub fn create_node_configs( } generated }); - assert_eq!( - ids.len(), - consensus_params.n_participants, - "pre-generated ids must match participant count" - ); let ports = da_ports.unwrap_or_else(|| { (0..consensus_params.n_participants) .map(|_| get_available_udp_port().unwrap()) .collect() }); - assert_eq!( - ports.len(), - consensus_params.n_participants, - "da port list must match participant count" - ); let blend_ports = blend_ports.unwrap_or_else(|| hosts.iter().map(|h| h.blend_port).collect()); - assert_eq!( - blend_ports.len(), - consensus_params.n_participants, - "blend port list must match participant count" - ); let mut consensus_configs = create_consensus_configs(&ids, consensus_params, wallet_config); let bootstrap_configs = create_bootstrap_configs(&ids, SHORT_PROLONGED_BOOTSTRAP_PERIOD); diff --git a/testing-framework/tools/cfgsync/src/config/validation.rs b/testing-framework/tools/cfgsync/src/config/validation.rs new file mode 100644 index 0000000..5e4b2d7 --- /dev/null +++ b/testing-framework/tools/cfgsync/src/config/validation.rs @@ -0,0 +1,62 @@ +use testing_framework_config::topology::configs::consensus::ConsensusParams; +use thiserror::Error; + +use crate::host::Host; + +#[derive(Debug, Error, PartialEq, Eq)] +pub enum ValidationError { + #[error("host count {actual} does not match participants {expected}")] + HostCountMismatch { actual: usize, expected: usize }, + #[error("id count {actual} does not match participants {expected}")] + IdCountMismatch { actual: usize, expected: usize }, + #[error("da port count {actual} does not match participants {expected}")] + DaPortCountMismatch { actual: usize, expected: usize }, + #[error("blend port count {actual} does not match participants {expected}")] + BlendPortCountMismatch { actual: usize, expected: usize }, +} + +pub fn validate_inputs( + hosts: &[Host], + consensus_params: &ConsensusParams, + ids: Option<&Vec<[u8; 32]>>, + da_ports: Option<&Vec>, + blend_ports: Option<&Vec>, +) -> Result<(), ValidationError> { + let expected = consensus_params.n_participants; + + if hosts.len() != expected { + return Err(ValidationError::HostCountMismatch { + actual: hosts.len(), + expected, + }); + } + + if let Some(ids) = ids { + if ids.len() != expected { + return Err(ValidationError::IdCountMismatch { + actual: ids.len(), + expected, + }); + } + } + + if let Some(ports) = da_ports { + if ports.len() != expected { + return Err(ValidationError::DaPortCountMismatch { + actual: ports.len(), + expected, + }); + } + } + + if let Some(ports) = blend_ports { + if ports.len() != expected { + return Err(ValidationError::BlendPortCountMismatch { + actual: ports.len(), + expected, + }); + } + } + + Ok(()) +}