diff --git a/Cargo.lock b/Cargo.lock index 6c1e9be8..41938230 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -8140,10 +8140,12 @@ dependencies = [ "ciphersuite", "dkg", "dockertest", + "embedwards25519", "hex", "parity-scale-codec", "rand_core", "schnorrkel", + "secq256k1", "serai-client", "serai-docker-tests", "serai-message-queue", @@ -8418,6 +8420,7 @@ name = "serai-primitives" version = "0.1.0" dependencies = [ "borsh", + "ciphersuite", "frame-support", "parity-scale-codec", "rand_core", diff --git a/crypto/dkg/src/evrf/mod.rs b/crypto/dkg/src/evrf/mod.rs index 1213fed3..3d043138 100644 --- a/crypto/dkg/src/evrf/mod.rs +++ b/crypto/dkg/src/evrf/mod.rs @@ -161,6 +161,7 @@ fn polynomial( share } +#[allow(clippy::type_complexity)] fn share_verification_statements( rng: &mut (impl RngCore + CryptoRng), commitments: &[C::G], @@ -234,6 +235,7 @@ pub struct EvrfDkg { evrf_public_keys: Vec<::G>, group_key: C::G, verification_shares: HashMap, + #[allow(clippy::type_complexity)] encrypted_secret_shares: HashMap::G; 2], C::F)>>, } diff --git a/crypto/dkg/src/musig.rs b/crypto/dkg/src/musig.rs index c0cdb852..82843272 100644 --- a/crypto/dkg/src/musig.rs +++ b/crypto/dkg/src/musig.rs @@ -65,6 +65,7 @@ pub fn musig_key(context: &[u8], keys: &[C::G]) -> Result(context, keys)?; let mut res = C::G::identity(); for i in 1 ..= keys_len { + // TODO: Calculate this with a multiexp res += keys[usize::from(i - 1)] * binding_factor::(transcript.clone(), i); } Ok(res) diff --git a/substrate/client/tests/common/validator_sets.rs b/substrate/client/tests/common/validator_sets.rs index 9bc8454f..ed428c16 100644 --- a/substrate/client/tests/common/validator_sets.rs +++ b/substrate/client/tests/common/validator_sets.rs @@ -5,6 +5,8 @@ use zeroize::Zeroizing; use rand_core::OsRng; use sp_core::{ + ConstU32, + bounded_vec::BoundedVec, sr25519::{Pair, Signature}, Pair as PairTrait, }; @@ -14,8 +16,9 @@ use frost::dkg::musig::musig; use schnorrkel::Schnorrkel; use serai_client::{ + primitives::EmbeddedEllipticCurve, validator_sets::{ - primitives::{ValidatorSet, KeyPair, musig_context, set_keys_message}, + primitives::{MAX_KEY_LEN, ValidatorSet, KeyPair, musig_context, set_keys_message}, ValidatorSetsEvent, }, Amount, Serai, SeraiValidatorSets, @@ -58,7 +61,7 @@ pub async fn set_keys( let sig = frost::tests::sign_without_caching( &mut OsRng, frost::tests::algorithm_machines(&mut OsRng, &Schnorrkel::new(b"substrate"), &musig_keys), - &set_keys_message(&set, &[], &key_pair), + &set_keys_message(&set, &key_pair), ); // Set the key pair @@ -66,8 +69,8 @@ pub async fn set_keys( serai, &SeraiValidatorSets::set_keys( set.network, - vec![].try_into().unwrap(), key_pair.clone(), + vec![1; musig_keys.len()].try_into().unwrap(), Signature(sig.to_bytes()), ), ) diff --git a/substrate/client/tests/validator_sets.rs b/substrate/client/tests/validator_sets.rs index 9b092afd..fee572dc 100644 --- a/substrate/client/tests/validator_sets.rs +++ b/substrate/client/tests/validator_sets.rs @@ -6,7 +6,7 @@ use sp_core::{ }; use serai_client::{ - primitives::{NETWORKS, NetworkId, BlockHash, insecure_pair_from_name}, + primitives::{NETWORKS, EmbeddedEllipticCurve, NetworkId, BlockHash, insecure_pair_from_name}, validator_sets::{ primitives::{Session, ValidatorSet, KeyPair}, ValidatorSetsEvent, @@ -21,7 +21,7 @@ use serai_client::{ mod common; use common::{ tx::publish_tx, - validator_sets::{allocate_stake, deallocate_stake, set_keys}, + validator_sets::{set_embedded_elliptic_curve_key, allocate_stake, deallocate_stake, set_keys}, }; fn get_random_key_pair() -> KeyPair { @@ -231,9 +231,9 @@ async fn validator_set_rotation() { { set_embedded_elliptic_curve_key( &serai, + &last_participant, embedded_elliptic_curve, vec![0; 32].try_into().unwrap(), - &last_participant, i.try_into().unwrap(), ) .await; diff --git a/substrate/node/src/chain_spec.rs b/substrate/node/src/chain_spec.rs index f7e83465..5836c371 100644 --- a/substrate/node/src/chain_spec.rs +++ b/substrate/node/src/chain_spec.rs @@ -4,10 +4,7 @@ use sp_core::Pair as PairTrait; use sc_service::ChainType; -use ciphersuite::{ - group::{ff::PrimeField, GroupEncoding}, - Ciphersuite, -}; +use ciphersuite::{group::GroupEncoding, Ciphersuite}; use embedwards25519::Embedwards25519; use secq256k1::Secq256k1; @@ -23,13 +20,9 @@ fn account_from_name(name: &'static str) -> PublicKey { insecure_pair_from_name(name).public() } -// Panics on names which are too long, or ciphersuites with weirdly encoded scalars -fn insecure_ciphersuite_key_from_name(name: &'static str) -> Vec { - let mut repr = ::Repr::default(); - let repr_len = repr.as_ref().len(); - let start = (repr_len / 2) - (name.len() / 2); - repr.as_mut()[start .. (start + name.len())].copy_from_slice(name.as_bytes()); - (C::generator() * C::F::from_repr(repr).unwrap()).to_bytes().as_ref().to_vec() +fn insecure_arbitrary_public_key_from_name(name: &'static str) -> Vec { + let key = insecure_arbitrary_key_from_name::(name); + (C::generator() * key).to_bytes().as_ref().to_vec() } fn wasm_binary() -> Vec { @@ -54,10 +47,10 @@ fn devnet_genesis( ( account_from_name(name), AllEmbeddedEllipticCurveKeysAtGenesis { - embedwards25519: insecure_ciphersuite_key_from_name::(name) + embedwards25519: insecure_arbitrary_public_key_from_name::(name) .try_into() .unwrap(), - secq256k1: insecure_ciphersuite_key_from_name::(name).try_into().unwrap(), + secq256k1: insecure_arbitrary_public_key_from_name::(name).try_into().unwrap(), }, ) }) diff --git a/substrate/primitives/Cargo.toml b/substrate/primitives/Cargo.toml index 0e1e8f38..4a495b53 100644 --- a/substrate/primitives/Cargo.toml +++ b/substrate/primitives/Cargo.toml @@ -18,6 +18,8 @@ workspace = true [dependencies] zeroize = { version = "^1.5", features = ["derive"], optional = true } +ciphersuite = { path = "../../crypto/ciphersuite", default-features = false, optional = true } + scale = { package = "parity-scale-codec", version = "3", default-features = false, features = ["derive"] } scale-info = { version = "2", default-features = false, features = ["derive"] } @@ -35,7 +37,7 @@ frame-support = { git = "https://github.com/serai-dex/substrate", default-featur rand_core = { version = "0.6", default-features = false, features = ["getrandom"] } [features] -std = ["zeroize", "scale/std", "borsh?/std", "serde?/std", "scale-info/std", "sp-core/std", "sp-runtime/std", "frame-support/std"] +std = ["zeroize", "ciphersuite/std", "scale/std", "borsh?/std", "serde?/std", "scale-info/std", "sp-core/std", "sp-runtime/std", "frame-support/std"] borsh = ["dep:borsh"] serde = ["dep:serde"] default = ["std"] diff --git a/substrate/primitives/src/account.rs b/substrate/primitives/src/account.rs index 77877a14..0fe63a28 100644 --- a/substrate/primitives/src/account.rs +++ b/substrate/primitives/src/account.rs @@ -95,6 +95,16 @@ pub fn insecure_pair_from_name(name: &str) -> Pair { Pair::from_string(&format!("//{name}"), None).unwrap() } +/// Create a private key for an arbitrary curve by a name. +/// +/// This key is not in any regards to be treated as an actual private key, as it is not private, +/// nor is it even collision-resistant (crafted names may collide). It's solely for testing +/// purposes. +#[cfg(feature = "std")] +pub fn insecure_arbitrary_key_from_name(name: &str) -> C::F { + C::hash_to_F(b"insecure arbitrary key", name.as_bytes()) +} + pub struct AccountLookup; impl Lookup for AccountLookup { type Source = SeraiAddress; diff --git a/substrate/validator-sets/pallet/src/lib.rs b/substrate/validator-sets/pallet/src/lib.rs index f97b3d13..f2f76544 100644 --- a/substrate/validator-sets/pallet/src/lib.rs +++ b/substrate/validator-sets/pallet/src/lib.rs @@ -1002,7 +1002,7 @@ pub mod pallet { EmbeddedEllipticCurve::Secq256k1 => 33, }; if key.len() != expected_len { - Err(Error::InvalidEmbeddedEllipticCurveKey)?; + Err(Error::::InvalidEmbeddedEllipticCurveKey)?; } // This does allow overwriting an existing key which... is unlikely to be done? diff --git a/tests/coordinator/Cargo.toml b/tests/coordinator/Cargo.toml index f5bc6426..78696fa8 100644 --- a/tests/coordinator/Cargo.toml +++ b/tests/coordinator/Cargo.toml @@ -24,7 +24,11 @@ zeroize = { version = "1", default-features = false } rand_core = { version = "0.6", default-features = false } blake2 = "0.10" + ciphersuite = { path = "../../crypto/ciphersuite", default-features = false, features = ["ristretto", "secp256k1"] } +embedwards25519 = { path = "../../crypto/evrf/embedwards25519" } +secq256k1 = { path = "../../crypto/evrf/secq256k1" } + schnorrkel = "0.11" dkg = { path = "../../crypto/dkg", default-features = false, features = ["tests"] } diff --git a/tests/coordinator/src/lib.rs b/tests/coordinator/src/lib.rs index c364128c..b686e8b9 100644 --- a/tests/coordinator/src/lib.rs +++ b/tests/coordinator/src/lib.rs @@ -18,6 +18,8 @@ use ciphersuite::{ group::{ff::PrimeField, GroupEncoding}, Ciphersuite, Ristretto, }; +use embedwards25519::Embedwards25519; +use secq256k1::Secq256k1; use serai_client::primitives::NetworkId; @@ -118,6 +120,8 @@ pub struct Processor { queue_for_sending: MessageQueue, abort_handle: Option>, + evrf_public_keys: ([u8; 32], Vec), + substrate_key: Arc::F>>>>, } @@ -131,7 +135,7 @@ impl Drop for Processor { impl Processor { pub async fn new( - raw_i: u8, + name: &'static str, network: NetworkId, ops: &DockerOperations, handles: Handles, @@ -168,6 +172,7 @@ impl Processor { let (msg_send, msg_recv) = mpsc::unbounded_channel(); + use serai_client::primitives::insecure_arbitrary_key_from_name; let substrate_key = Arc::new(AsyncMutex::new(None)); let mut res = Processor { network, @@ -183,6 +188,28 @@ impl Processor { msgs: msg_recv, abort_handle: None, + evrf_public_keys: ( + (Embedwards25519::generator() * insecure_arbitrary_key_from_name::(name)) + .to_bytes(), + match network { + NetworkId::Serai => panic!("mock processor for the serai network"), + NetworkId::Bitcoin | NetworkId::Ethereum => { + let key = (Secq256k1::generator() * + insecure_arbitrary_key_from_name::(name)) + .to_bytes(); + let key: &[u8] = key.as_ref(); + key.to_vec() + } + NetworkId::Monero => { + let key = (Embedwards25519::generator() * + insecure_arbitrary_key_from_name::(name)) + .to_bytes(); + let key: &[u8] = key.as_ref(); + key.to_vec() + } + }, + ), + substrate_key: substrate_key.clone(), }; @@ -256,10 +283,12 @@ impl Processor { if current_cosign.is_none() || (current_cosign.as_ref().unwrap().block != block) { *current_cosign = Some(new_cosign); } + let mut preprocess = [0; 64]; + preprocess[.. name.len()].copy_from_slice(name.as_ref()); send_message( messages::coordinator::ProcessorMessage::CosignPreprocess { id: id.clone(), - preprocesses: vec![[raw_i; 64]], + preprocesses: vec![preprocess], } .into(), ) @@ -270,12 +299,11 @@ impl Processor { ) => { // TODO: Assert the ID matches CURRENT_COSIGN // TODO: Verify the received preprocesses + let mut share = [0; 32]; + share[.. name.len()].copy_from_slice(name.as_bytes()); send_message( - messages::coordinator::ProcessorMessage::SubstrateShare { - id, - shares: vec![[raw_i; 32]], - } - .into(), + messages::coordinator::ProcessorMessage::SubstrateShare { id, shares: vec![share] } + .into(), ) .await; } @@ -327,6 +355,10 @@ impl Processor { res } + pub fn evrf_public_keys(&self) -> ([u8; 32], Vec) { + self.evrf_public_keys.clone() + } + pub async fn serai(&self) -> Serai { Serai::new(self.serai_rpc.clone()).await.unwrap() } diff --git a/tests/coordinator/src/tests/key_gen.rs b/tests/coordinator/src/tests/key_gen.rs index 8ea14cbc..55670bca 100644 --- a/tests/coordinator/src/tests/key_gen.rs +++ b/tests/coordinator/src/tests/key_gen.rs @@ -1,7 +1,4 @@ -use std::{ - time::{Duration, SystemTime}, - collections::HashMap, -}; +use std::time::{Duration, SystemTime}; use zeroize::Zeroizing; use rand_core::OsRng; @@ -10,14 +7,14 @@ use ciphersuite::{ group::{ff::Field, GroupEncoding}, Ciphersuite, Ristretto, Secp256k1, }; -use dkg::ThresholdParams; +use dkg::Participant; use serai_client::{ primitives::NetworkId, Public, validator_sets::primitives::{Session, ValidatorSet, KeyPair}, }; -use messages::{key_gen::KeyGenId, CoordinatorMessage}; +use messages::CoordinatorMessage; use crate::tests::*; @@ -29,16 +26,27 @@ pub async fn key_gen( let mut participant_is = vec![]; let set = ValidatorSet { session, network: NetworkId::Bitcoin }; - let id = KeyGenId { session: set.session, attempt: 0 }; + // This is distinct from the result of evrf_public_keys for each processor, as there'll have some + // ordering algorithm on-chain which won't match our ordering + let mut evrf_public_keys_as_on_chain = None; for (i, processor) in processors.iter_mut().enumerate() { let msg = processor.recv_message().await; match &msg { CoordinatorMessage::KeyGen(messages::key_gen::CoordinatorMessage::GenerateKey { - params, + evrf_public_keys, .. }) => { - participant_is.push(params.i()); + if evrf_public_keys_as_on_chain.is_none() { + evrf_public_keys_as_on_chain = Some(evrf_public_keys.clone()); + } + assert_eq!(evrf_public_keys_as_on_chain.as_ref().unwrap(), evrf_public_keys); + let i = evrf_public_keys + .iter() + .position(|public_keys| *public_keys == processor.evrf_public_keys()) + .unwrap(); + let i = Participant::new(1 + u16::try_from(i).unwrap()).unwrap(); + participant_is.push(i); } _ => panic!("unexpected message: {msg:?}"), } @@ -46,63 +54,39 @@ pub async fn key_gen( assert_eq!( msg, CoordinatorMessage::KeyGen(messages::key_gen::CoordinatorMessage::GenerateKey { - id, - params: ThresholdParams::new( - u16::try_from(((coordinators * 2) / 3) + 1).unwrap(), - u16::try_from(coordinators).unwrap(), - participant_is[i], - ) - .unwrap(), - shares: 1, + session, + threshold: u16::try_from(((coordinators * 2) / 3) + 1).unwrap(), + evrf_public_keys: evrf_public_keys_as_on_chain.clone().unwrap(), }) ); processor - .send_message(messages::key_gen::ProcessorMessage::Commitments { - id, - commitments: vec![vec![u8::try_from(u16::from(participant_is[i])).unwrap()]], + .send_message(messages::key_gen::ProcessorMessage::Participation { + session, + participation: vec![u8::try_from(u16::from(participant_is[i])).unwrap()], }) .await; + + // Sleep so this participation gets included, before moving to the next participation + wait_for_tributary().await; } wait_for_tributary().await; - for (i, processor) in processors.iter_mut().enumerate() { - let mut commitments = (0 .. u8::try_from(coordinators).unwrap()) - .map(|l| { - ( - participant_is[usize::from(l)], - vec![u8::try_from(u16::from(participant_is[usize::from(l)])).unwrap()], - ) - }) - .collect::>(); - commitments.remove(&participant_is[i]); - assert_eq!( - processor.recv_message().await, - CoordinatorMessage::KeyGen(messages::key_gen::CoordinatorMessage::Commitments { - id, - commitments, - }) - ); - - // Recipient it's for -> (Sender i, Recipient i) - let mut shares = (0 .. u8::try_from(coordinators).unwrap()) - .map(|l| { - ( - participant_is[usize::from(l)], - vec![ - u8::try_from(u16::from(participant_is[i])).unwrap(), - u8::try_from(u16::from(participant_is[usize::from(l)])).unwrap(), - ], - ) - }) - .collect::>(); - - shares.remove(&participant_is[i]); - processor - .send_message(messages::key_gen::ProcessorMessage::Shares { id, shares: vec![shares] }) - .await; + for processor in processors.iter_mut() { + #[allow(clippy::needless_range_loop)] // This wouldn't improve readability/clarity + for i in 0 .. coordinators { + assert_eq!( + processor.recv_message().await, + CoordinatorMessage::KeyGen(messages::key_gen::CoordinatorMessage::Participation { + session, + participant: participant_is[i], + participation: vec![u8::try_from(u16::from(participant_is[i])).unwrap()], + }) + ); + } } + // Now that we've received all participations, publish the key pair let substrate_priv_key = Zeroizing::new(::F::random(&mut OsRng)); let substrate_key = (::generator() * *substrate_priv_key).to_bytes(); @@ -112,40 +96,24 @@ pub async fn key_gen( let serai = processors[0].serai().await; let mut last_serai_block = serai.latest_finalized_block().await.unwrap().number(); - wait_for_tributary().await; - for (i, processor) in processors.iter_mut().enumerate() { - let i = participant_is[i]; - assert_eq!( - processor.recv_message().await, - CoordinatorMessage::KeyGen(messages::key_gen::CoordinatorMessage::Shares { - id, - shares: { - let mut shares = (0 .. u8::try_from(coordinators).unwrap()) - .map(|l| { - ( - participant_is[usize::from(l)], - vec![ - u8::try_from(u16::from(participant_is[usize::from(l)])).unwrap(), - u8::try_from(u16::from(i)).unwrap(), - ], - ) - }) - .collect::>(); - shares.remove(&i); - vec![shares] - }, - }) - ); + for processor in processors.iter_mut() { processor .send_message(messages::key_gen::ProcessorMessage::GeneratedKeyPair { - id, + session, substrate_key, network_key: network_key.clone(), }) .await; } - // Sleeps for longer since we need to wait for a Substrate block as well + // Wait for the Nonces TXs to go around + wait_for_tributary().await; + // Wait for the Share TXs to go around + wait_for_tributary().await; + + // And now we're waiting ro the TX to be published onto Serai + + // We need to wait for a finalized Substrate block as well, so this waites for up to 20 blocks 'outer: for _ in 0 .. 20 { tokio::time::sleep(Duration::from_secs(6)).await; if std::env::var("GITHUB_CI") == Ok("true".to_string()) { diff --git a/tests/coordinator/src/tests/mod.rs b/tests/coordinator/src/tests/mod.rs index ef67b0ac..0b46cd81 100644 --- a/tests/coordinator/src/tests/mod.rs +++ b/tests/coordinator/src/tests/mod.rs @@ -41,6 +41,18 @@ impl) -> F> Test } } +fn name(i: usize) -> &'static str { + match i { + 0 => "Alice", + 1 => "Bob", + 2 => "Charlie", + 3 => "Dave", + 4 => "Eve", + 5 => "Ferdie", + _ => panic!("needed a 7th name for a serai node"), + } +} + pub(crate) async fn new_test(test_body: impl TestBody, fast_epoch: bool) { let mut unique_id_lock = UNIQUE_ID.get_or_init(|| Mutex::new(0)).lock().await; @@ -50,15 +62,7 @@ pub(crate) async fn new_test(test_body: impl TestBody, fast_epoch: bool) { // Spawn one extra coordinator which isn't in-set #[allow(clippy::range_plus_one)] for i in 0 .. (COORDINATORS + 1) { - let name = match i { - 0 => "Alice", - 1 => "Bob", - 2 => "Charlie", - 3 => "Dave", - 4 => "Eve", - 5 => "Ferdie", - _ => panic!("needed a 7th name for a serai node"), - }; + let name = name(i); let serai_composition = serai_composition(name, fast_epoch); let (processor_key, message_queue_keys, message_queue_composition) = @@ -196,14 +200,7 @@ pub(crate) async fn new_test(test_body: impl TestBody, fast_epoch: bool) { let mut processors: Vec = vec![]; for (i, (handles, key)) in coordinators.iter().enumerate() { processors.push( - Processor::new( - i.try_into().unwrap(), - NetworkId::Bitcoin, - &outer_ops, - handles.clone(), - *key, - ) - .await, + Processor::new(name(i), NetworkId::Bitcoin, &outer_ops, handles.clone(), *key).await, ); } diff --git a/tests/full-stack/src/tests/mod.rs b/tests/full-stack/src/tests/mod.rs index 7d92070e..a288ff05 100644 --- a/tests/full-stack/src/tests/mod.rs +++ b/tests/full-stack/src/tests/mod.rs @@ -57,14 +57,24 @@ pub(crate) async fn new_test(test_body: impl TestBody) { let (coord_key, message_queue_keys, message_queue_composition) = message_queue_instance(); let (bitcoin_composition, bitcoin_port) = network_instance(NetworkId::Bitcoin); - let mut bitcoin_processor_composition = - processor_instance(NetworkId::Bitcoin, bitcoin_port, message_queue_keys[&NetworkId::Bitcoin]); + let mut bitcoin_processor_composition = processor_instance( + name, + NetworkId::Bitcoin, + bitcoin_port, + message_queue_keys[&NetworkId::Bitcoin], + ) + .0; assert_eq!(bitcoin_processor_composition.len(), 1); let bitcoin_processor_composition = bitcoin_processor_composition.swap_remove(0); let (monero_composition, monero_port) = network_instance(NetworkId::Monero); - let mut monero_processor_composition = - processor_instance(NetworkId::Monero, monero_port, message_queue_keys[&NetworkId::Monero]); + let mut monero_processor_composition = processor_instance( + name, + NetworkId::Monero, + monero_port, + message_queue_keys[&NetworkId::Monero], + ) + .0; assert_eq!(monero_processor_composition.len(), 1); let monero_processor_composition = monero_processor_composition.swap_remove(0); diff --git a/tests/processor/src/lib.rs b/tests/processor/src/lib.rs index a54f58ec..5b0c4216 100644 --- a/tests/processor/src/lib.rs +++ b/tests/processor/src/lib.rs @@ -3,18 +3,14 @@ use std::sync::{OnceLock, Mutex}; use zeroize::Zeroizing; -use rand_core::OsRng; use ciphersuite::{ - group::{ - ff::{Field, PrimeField}, - GroupEncoding, - }, + group::{ff::PrimeField, GroupEncoding}, Ciphersuite, Secp256k1, Ed25519, Ristretto, }; use dkg::evrf::*; -use serai_client::primitives::NetworkId; +use serai_client::primitives::{NetworkId, insecure_arbitrary_key_from_name}; use messages::{ProcessorMessage, CoordinatorMessage}; use serai_message_queue::{Service, Metadata, client::MessageQueue}; @@ -39,12 +35,13 @@ pub struct EvrfPublicKeys { } pub fn processor_instance( + name: &str, network: NetworkId, port: u32, message_queue_key: ::F, ) -> (Vec, EvrfPublicKeys) { let substrate_evrf_key = - <::EmbeddedCurve as Ciphersuite>::F::random(&mut OsRng); + insecure_arbitrary_key_from_name::<::EmbeddedCurve>(name); let substrate_evrf_pub_key = (::EmbeddedCurve::generator() * substrate_evrf_key).to_bytes(); let substrate_evrf_key = substrate_evrf_key.to_repr(); @@ -53,13 +50,14 @@ pub fn processor_instance( NetworkId::Serai => panic!("starting a processor for Serai"), NetworkId::Bitcoin | NetworkId::Ethereum => { let evrf_key = - <::EmbeddedCurve as Ciphersuite>::F::random(&mut OsRng); + insecure_arbitrary_key_from_name::<::EmbeddedCurve>(name); let pub_key = (::EmbeddedCurve::generator() * evrf_key).to_bytes().to_vec(); (evrf_key.to_repr(), pub_key) } NetworkId::Monero => { - let evrf_key = <::EmbeddedCurve as Ciphersuite>::F::random(&mut OsRng); + let evrf_key = + insecure_arbitrary_key_from_name::<::EmbeddedCurve>(name); let pub_key = (::EmbeddedCurve::generator() * evrf_key).to_bytes().to_vec(); (evrf_key.to_repr(), pub_key) @@ -120,6 +118,7 @@ pub struct ProcessorKeys { pub type Handles = (String, String, String, String); pub fn processor_stack( + name: &str, network: NetworkId, network_hostname_override: Option, ) -> (Handles, ProcessorKeys, Vec) { @@ -129,7 +128,7 @@ pub fn processor_stack( serai_message_queue_tests::instance(); let (mut processor_compositions, evrf_keys) = - processor_instance(network, network_rpc_port, message_queue_keys[&network]); + processor_instance(name, network, network_rpc_port, message_queue_keys[&network]); // Give every item in this stack a unique ID // Uses a Mutex as we can't generate a 8-byte random ID without hitting hostname length limits diff --git a/tests/processor/src/tests/batch.rs b/tests/processor/src/tests/batch.rs index 5d5d6475..b85f43cf 100644 --- a/tests/processor/src/tests/batch.rs +++ b/tests/processor/src/tests/batch.rs @@ -3,7 +3,7 @@ use std::{ time::{SystemTime, Duration}, }; -use rand_core::RngCore; +use rand_core::{RngCore, OsRng}; use dkg::{Participant, tests::clone_without}; diff --git a/tests/processor/src/tests/mod.rs b/tests/processor/src/tests/mod.rs index 62d22098..668506b1 100644 --- a/tests/processor/src/tests/mod.rs +++ b/tests/processor/src/tests/mod.rs @@ -19,8 +19,11 @@ fn new_test(network: NetworkId) -> (Vec<(Handles, ProcessorKeys)>, DockerTest) { let mut coordinators = vec![]; let mut test = DockerTest::new().with_network(dockertest::Network::Isolated); let mut eth_handle = None; - for _ in 0 .. COORDINATORS { - let (handles, keys, compositions) = processor_stack(network, eth_handle.clone()); + for i in 0 .. COORDINATORS { + // Uses the counter `i` as this has no relation to any other system, and while Substrate has + // hard-coded names for itself, these tests down't spawn any Substrate node + let (handles, keys, compositions) = + processor_stack(&i.to_string(), network, eth_handle.clone()); // TODO: Remove this once https://github.com/foundry-rs/foundry/issues/7955 // This has all processors share an Ethereum node until we can sync controlled nodes if network == NetworkId::Ethereum { diff --git a/tests/processor/src/tests/send.rs b/tests/processor/src/tests/send.rs index 93091a5e..8dfb5353 100644 --- a/tests/processor/src/tests/send.rs +++ b/tests/processor/src/tests/send.rs @@ -3,7 +3,7 @@ use std::{ time::{SystemTime, Duration}, }; -use rand_core::RngCore; +use rand_core::{RngCore, OsRng}; use dkg::{Participant, tests::clone_without};