Skip to content
This repository has been archived by the owner on Oct 31, 2024. It is now read-only.

Commit

Permalink
chore: split spammer into multiple files (#270)
Browse files Browse the repository at this point in the history
  • Loading branch information
Freyskeyd authored Aug 2, 2023
1 parent 2963509 commit 226fc90
Show file tree
Hide file tree
Showing 4 changed files with 102 additions and 91 deletions.
11 changes: 11 additions & 0 deletions crates/topos-certificate-spammer/src/config.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
#[derive(Debug)]
pub struct CertificateSpammerConfig {
pub target_nodes: Option<Vec<String>>,
pub target_nodes_path: Option<String>,
pub local_key_seed: u64,
pub cert_per_batch: u64,
pub nb_subnets: u8,
pub nb_batches: Option<u64>,
pub batch_interval: u64,
pub target_subnets: Option<Vec<String>>,
}
19 changes: 19 additions & 0 deletions crates/topos-certificate-spammer/src/error.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
#[derive(Debug, thiserror::Error)]
pub enum Error {
#[error("target nodes are not specified")]
TargetNodesNotSpecified,
#[error("error reading target nodes json file:{0}")]
ReadingTargetNodesJsonFile(String),
#[error("error parsing target nodes json file:{0}")]
InvalidTargetNodesJsonFile(String),
#[error("invalid subnet id error: {0}")]
InvalidSubnetId(String),
#[error("hex conversion error {0}")]
HexConversion(hex::FromHexError),
#[error("invalid signing key: {0}")]
InvalidSigningKey(String),
#[error("Tce node connection error {0}")]
TCENodeConnection(topos_tce_proxy::Error),
#[error("Certificate signing error: {0}")]
CertificateSigning(topos_core::uci::Error),
}
101 changes: 10 additions & 91 deletions crates/topos-certificate-spammer/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,47 +13,17 @@ use topos_tce_proxy::client::{TceClient, TceClientBuilder};
use tracing::{debug, error, info, info_span, Instrument, Span};
use tracing_opentelemetry::OpenTelemetrySpanExt;

#[derive(Debug, thiserror::Error)]
pub enum Error {
#[error("target nodes are not specified")]
TargetNodesNotSpecified,
#[error("error reading target nodes json file:{0}")]
ErrorReadingTargetNodesJsonFile(String),
#[error("error parsing target nodes json file:{0}")]
InvalidTargetNodesJsonFile(String),
#[error("invalid subnet id error: {0}")]
InvalidSubnetId(String),
#[error("hex conversion error {0}")]
HexConversionError(hex::FromHexError),
#[error("invalid signing key: {0}")]
InvalidSigningKey(String),
#[error("Tce node connection error {0}")]
TCENodeConnectionError(topos_tce_proxy::Error),
#[error("Certificate signing error: {0}")]
CertificateSigningError(topos_core::uci::Error),
}
mod config;
mod error;
mod utils;

#[derive(Debug)]
pub struct CertificateSpammerConfig {
pub target_nodes: Option<Vec<String>>,
pub target_nodes_path: Option<String>,
pub local_key_seed: u64,
pub cert_per_batch: u64,
pub nb_subnets: u8,
pub nb_batches: Option<u64>,
pub batch_interval: u64,
pub target_subnets: Option<Vec<String>>,
}
use error::Error;

fn generate_random_32b_array() -> [u8; 32] {
(0..32)
.map(|_| rand::random::<u8>())
.collect::<Vec<u8>>()
.try_into()
.expect("Valid 32 byte array")
}
use crate::utils::{generate_source_subnets, generate_test_certificate};
pub use config::CertificateSpammerConfig;

type NodeApiAddress = String;

#[derive(Deserialize)]
struct FileNodes {
nodes: Vec<String>,
Expand Down Expand Up @@ -86,28 +56,6 @@ impl TargetNodeConnection {
}
}

/// Generate test certificate
pub fn generate_test_certificate(
source_subnet: &mut SourceSubnet,
target_subnet_ids: &[SubnetId],
) -> Result<Certificate, Box<dyn std::error::Error>> {
let mut new_cert = Certificate::new(
source_subnet.last_certificate_id,
source_subnet.source_subnet_id,
generate_random_32b_array(),
generate_random_32b_array(),
target_subnet_ids,
0,
Vec::new(),
)?;
new_cert
.update_signature(&source_subnet.signing_key)
.map_err(Error::CertificateSigningError)?;

source_subnet.last_certificate_id = new_cert.id;
Ok(new_cert)
}

async fn open_target_node_connection(
nodes: &[String],
source_subnet: &SourceSubnet,
Expand All @@ -134,7 +82,7 @@ async fn open_target_node_connection(
"Unable to create TCE client for node {}, error details: {}",
&tce_address, e
);
return Err(Error::TCENodeConnectionError(e));
return Err(Error::TCENodeConnection(e));
}
};

Expand All @@ -145,7 +93,7 @@ async fn open_target_node_connection(
"Unable to connect to node {}, error details: {}",
&tce_address, e
);
return Err(Error::TCENodeConnectionError(e));
return Err(Error::TCENodeConnection(e));
}
}

Expand Down Expand Up @@ -242,35 +190,6 @@ async fn dispatch(cert: Certificate, target_node: &TargetNodeConnection) {
submit_cert_to_tce(target_node, cert).await
}

pub fn generate_source_subnets(
local_key_seed: u64,
number_of_subnets: u8,
) -> Result<Vec<SourceSubnet>, Error> {
let mut subnets = Vec::new();

let mut signing_key = [0u8; 32];
let (_, right) = signing_key.split_at_mut(24);
right.copy_from_slice(local_key_seed.to_be_bytes().as_slice());
for _ in 0..number_of_subnets {
signing_key = tiny_keccak::keccak256(&signing_key);

// Subnet id of the source subnet which will be used for every generated certificate
let source_subnet_id: SubnetId = topos_crypto::keys::derive_public_key(&signing_key)
.map_err(|e| Error::InvalidSigningKey(e.to_string()))?
.as_slice()[1..33]
.try_into()
.map_err(|_| Error::InvalidSubnetId("Unable to parse subnet id".to_string()))?;

subnets.push(SourceSubnet {
signing_key,
source_subnet_id,
last_certificate_id: Default::default(),
});
}

Ok(subnets)
}

pub async fn run(
args: CertificateSpammerConfig,
mut shutdown: mpsc::Receiver<oneshot::Sender<()>>,
Expand All @@ -286,7 +205,7 @@ pub async fn run(
nodes
} else if let Some(target_nodes_path) = args.target_nodes_path {
let json_str = std::fs::read_to_string(target_nodes_path)
.map_err(|e| Error::ErrorReadingTargetNodesJsonFile(e.to_string()))?;
.map_err(|e| Error::ReadingTargetNodesJsonFile(e.to_string()))?;

let json: FileNodes = serde_json::from_str(&json_str)
.map_err(|e| Error::InvalidTargetNodesJsonFile(e.to_string()))?;
Expand Down
62 changes: 62 additions & 0 deletions crates/topos-certificate-spammer/src/utils.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
use topos_core::uci::{Certificate, SubnetId};

use crate::{error::Error, SourceSubnet};

pub fn generate_random_32b_array() -> [u8; 32] {
(0..32)
.map(|_| rand::random::<u8>())
.collect::<Vec<u8>>()
.try_into()
.expect("Valid 32 byte array")
}

/// Generate test certificate
pub fn generate_test_certificate(
source_subnet: &mut SourceSubnet,
target_subnet_ids: &[SubnetId],
) -> Result<Certificate, Box<dyn std::error::Error>> {
let mut new_cert = Certificate::new(
source_subnet.last_certificate_id,
source_subnet.source_subnet_id,
generate_random_32b_array(),
generate_random_32b_array(),
target_subnet_ids,
0,
Vec::new(),
)?;
new_cert
.update_signature(&source_subnet.signing_key)
.map_err(Error::CertificateSigning)?;

source_subnet.last_certificate_id = new_cert.id;
Ok(new_cert)
}

pub fn generate_source_subnets(
local_key_seed: u64,
number_of_subnets: u8,
) -> Result<Vec<SourceSubnet>, Error> {
let mut subnets = Vec::new();

let mut signing_key = [0u8; 32];
let (_, right) = signing_key.split_at_mut(24);
right.copy_from_slice(local_key_seed.to_be_bytes().as_slice());
for _ in 0..number_of_subnets {
signing_key = tiny_keccak::keccak256(&signing_key);

// Subnet id of the source subnet which will be used for every generated certificate
let source_subnet_id: SubnetId = topos_crypto::keys::derive_public_key(&signing_key)
.map_err(|e| Error::InvalidSigningKey(e.to_string()))?
.as_slice()[1..33]
.try_into()
.map_err(|_| Error::InvalidSubnetId("Unable to parse subnet id".to_string()))?;

subnets.push(SourceSubnet {
signing_key,
source_subnet_id,
last_certificate_id: Default::default(),
});
}

Ok(subnets)
}

0 comments on commit 226fc90

Please sign in to comment.