From 3a2e5bea0de6d38ca416e9bc1a03239feeaef61e Mon Sep 17 00:00:00 2001 From: Luke Parker <lukeparker5132@gmail.com> Date: Wed, 25 May 2022 00:30:51 -0400 Subject: [PATCH] Move the CLSAG test to the newly modular FROST test setup --- coins/monero/src/tests/clsag.rs | 75 +++++++++++--------------- coins/monero/src/tests/frost.rs | 94 ++------------------------------- 2 files changed, 36 insertions(+), 133 deletions(-) diff --git a/coins/monero/src/tests/clsag.rs b/coins/monero/src/tests/clsag.rs index b3d6529c..20398117 100644 --- a/coins/monero/src/tests/clsag.rs +++ b/coins/monero/src/tests/clsag.rs @@ -1,5 +1,5 @@ #[cfg(feature = "multisig")] -use std::{cell::RefCell, rc::Rc, collections::HashMap}; +use std::{cell::RefCell, rc::Rc}; use rand::{RngCore, rngs::OsRng}; @@ -12,10 +12,10 @@ use crate::{ ringct::clsag::{ClsagInput, Clsag} }; #[cfg(feature = "multisig")] -use crate::{frost::{MultisigError, Transcript}, ringct::clsag::{ClsagDetails, ClsagMultisig}}; +use crate::{frost::{Ed25519, MultisigError, Transcript}, ringct::clsag::{ClsagDetails, ClsagMultisig}}; #[cfg(feature = "multisig")] -use crate::tests::frost::{THRESHOLD, generate_keys, sign}; +use frost::tests::{key_gen, algorithm_machines, sign}; const RING_LEN: u64 = 11; const AMOUNT: u64 = 1337; @@ -70,7 +70,7 @@ fn clsag() { #[cfg(feature = "multisig")] #[test] fn clsag_multisig() -> Result<(), MultisigError> { - let (keys, group_private) = generate_keys(); + let keys = key_gen::<_, Ed25519>(&mut OsRng); let randomness = random_scalar(&mut OsRng); let mut ring = vec![]; @@ -79,55 +79,42 @@ fn clsag_multisig() -> Result<(), MultisigError> { let mask; let amount; if i != u64::from(RING_INDEX) { - dest = random_scalar(&mut OsRng); + dest = &random_scalar(&mut OsRng) * &ED25519_BASEPOINT_TABLE; mask = random_scalar(&mut OsRng); amount = OsRng.next_u64(); } else { - dest = group_private.0; + dest = keys[&1].group_key().0; mask = randomness; amount = AMOUNT; } - ring.push([&dest * &ED25519_BASEPOINT_TABLE, Commitment::new(mask, amount).calculate()]); + ring.push([dest, Commitment::new(mask, amount).calculate()]); } let mask_sum = random_scalar(&mut OsRng); - let mut machines = HashMap::new(); - for i in 1 ..= THRESHOLD { - machines.insert( - i, - sign::AlgorithmMachine::new( - ClsagMultisig::new( - Transcript::new(b"Monero Serai CLSAG Test".to_vec()), - Rc::new(RefCell::new(Some( - ClsagDetails::new( - ClsagInput::new( - Commitment::new(randomness, AMOUNT), - Decoys { - i: RING_INDEX, - offsets: (1 ..= RING_LEN).into_iter().collect(), - ring: ring.clone() - } - ).unwrap(), - mask_sum - ) - ))) - ).unwrap(), - Rc::new(keys[&i].clone()), - &(1 ..= THRESHOLD).collect::<Vec<_>>() - ).unwrap() - ); - } - - let mut signatures = sign(&mut machines, &[1; 32]); - let signature = signatures.swap_remove(0); - for s in 0 .. usize::from(THRESHOLD - 1) { - // Verify the commitments and the non-decoy s scalar are identical to every other signature - // FROST will already have called verify on the produced signature, before checking individual - // key shares. For FROST Schnorr, it's cheaper. For CLSAG, it may be more expensive? Yet it - // ensures we have usable signatures, not just signatures we think are usable - assert_eq!(signatures[s].1, signature.1); - assert_eq!(signatures[s].0.s[RING_INDEX as usize], signature.0.s[RING_INDEX as usize]); - } + sign( + &mut OsRng, + algorithm_machines( + &mut OsRng, + ClsagMultisig::new( + Transcript::new(b"Monero Serai CLSAG Test".to_vec()), + Rc::new(RefCell::new(Some( + ClsagDetails::new( + ClsagInput::new( + Commitment::new(randomness, AMOUNT), + Decoys { + i: RING_INDEX, + offsets: (1 ..= RING_LEN).into_iter().collect(), + ring: ring.clone() + } + ).unwrap(), + mask_sum + ) + ))) + ).unwrap(), + &keys + ), + &[1; 32] + ); Ok(()) } diff --git a/coins/monero/src/tests/frost.rs b/coins/monero/src/tests/frost.rs index 6eca98e9..423d23d2 100644 --- a/coins/monero/src/tests/frost.rs +++ b/coins/monero/src/tests/frost.rs @@ -1,95 +1,11 @@ -#![cfg(feature = "multisig")] - -use std::collections::HashMap; - use rand::rngs::OsRng; -use ff::Field; -use dalek_ff_group::{ED25519_BASEPOINT_TABLE, Scalar}; - -pub use frost::{ - FrostError, MultisigParams, MultisigKeys, - lagrange, key_gen, algorithm::Algorithm, sign -}; +use frost::tests::{curve::test_curve, key_gen}; use crate::frost::Ed25519; -pub const THRESHOLD: u16 = 3; -pub const PARTICIPANTS: u16 = 5; - -fn clone_without<K: Clone + std::cmp::Eq + std::hash::Hash, V: Clone>( - map: &HashMap<K, V>, - without: &K -) -> HashMap<K, V> { - let mut res = map.clone(); - res.remove(without).unwrap(); - res -} - -pub fn generate_keys() -> (HashMap<u16, MultisigKeys<Ed25519>>, Scalar) { - let mut params = HashMap::new(); - let mut machines = HashMap::new(); - let mut commitments = HashMap::new(); - for i in 1 ..= PARTICIPANTS { - params.insert( - i, - MultisigParams::new(THRESHOLD, PARTICIPANTS, i).unwrap() - ); - machines.insert( - i, - key_gen::StateMachine::<Ed25519>::new( - params[&i], - "monero-sign-rs test suite".to_string() - ) - ); - commitments.insert(i, machines.get_mut(&i).unwrap().generate_coefficients(&mut OsRng).unwrap()); - } - - let mut secret_shares = HashMap::new(); - for (i, machine) in machines.iter_mut() { - secret_shares.insert( - *i, - machine.generate_secret_shares(&mut OsRng, clone_without(&commitments, i)).unwrap() - ); - } - - let mut keys = HashMap::new(); - for (i, machine) in machines.iter_mut() { - let mut our_secret_shares = HashMap::new(); - for (l, shares) in &secret_shares { - if i == l { - continue; - } - our_secret_shares.insert(*l, shares[&i].clone()); - } - keys.insert(*i, machine.complete(our_secret_shares).unwrap().clone()); - } - - let mut group_private = Scalar::zero(); - for i in 1 ..= THRESHOLD { - group_private += keys[&i].secret_share() * lagrange::<Scalar>(i, &(1 ..= THRESHOLD).collect::<Vec<_>>()); - } - assert_eq!(&ED25519_BASEPOINT_TABLE * group_private, keys[&1].group_key()); - - (keys, group_private) -} - -pub fn sign<S, M: sign::StateMachine<Signature = S>>(machines: &mut HashMap<u16, M>, msg: &[u8]) -> Vec<S> { - assert!(machines.len() >= THRESHOLD.into()); - - let mut commitments = HashMap::new(); - for (i, machine) in machines.iter_mut() { - commitments.insert(*i, machine.preprocess(&mut OsRng).unwrap()); - } - - let mut shares = HashMap::new(); - for (i, machine) in machines.iter_mut() { - shares.insert(*i, machine.sign(clone_without(&commitments, i), msg).unwrap()); - } - - let mut res = vec![]; - for (i, machine) in machines.iter_mut() { - res.push(machine.complete(clone_without(&shares, i)).unwrap()) - } - res +#[test] +fn frost_ed25519() { + test_curve::<_, Ed25519>(&mut OsRng); + key_gen::<_, Ed25519>(&mut OsRng); }