From bfa15283f50f91fda493feac915ddcb562f86555 Mon Sep 17 00:00:00 2001 From: Luke Parker Date: Mon, 30 May 2022 16:37:51 -0400 Subject: [PATCH] Remove Monero's test FROST file in favor of FROST"s exposed test files Moves private key recovery for given keys into FROST. --- coins/monero/tests/frost.rs | 95 ----------------------------------- coins/monero/tests/send.rs | 17 +++---- crypto/frost/src/tests/mod.rs | 16 ++++++ 3 files changed, 23 insertions(+), 105 deletions(-) delete mode 100644 coins/monero/tests/frost.rs diff --git a/coins/monero/tests/frost.rs b/coins/monero/tests/frost.rs deleted file mode 100644 index 46dce9cc..00000000 --- a/coins/monero/tests/frost.rs +++ /dev/null @@ -1,95 +0,0 @@ -#![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 monero_serai::frost::Ed25519; - -pub const THRESHOLD: u16 = 3; -pub const PARTICIPANTS: u16 = 5; - -fn clone_without( - map: &HashMap, - without: &K -) -> HashMap { - let mut res = map.clone(); - res.remove(without).unwrap(); - res -} - -pub fn generate_keys() -> (HashMap>, 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::::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(&mut OsRng, our_secret_shares).unwrap().clone()); - } - - let mut group_private = Scalar::zero(); - for i in 1 ..= THRESHOLD { - group_private += keys[&i].secret_share() * lagrange::(i, &(1 ..= THRESHOLD).collect::>()); - } - assert_eq!(&ED25519_BASEPOINT_TABLE * group_private, keys[&1].group_key()); - - (keys, group_private) -} - -pub fn sign>(machines: &mut HashMap, msg: &[u8]) -> Vec { - 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 -} diff --git a/coins/monero/tests/send.rs b/coins/monero/tests/send.rs index 7eaa6194..cb7a2b4f 100644 --- a/coins/monero/tests/send.rs +++ b/coins/monero/tests/send.rs @@ -8,8 +8,11 @@ use rand::rngs::OsRng; use blake2::{digest::Update, Digest, Blake2b512}; use curve25519_dalek::constants::ED25519_BASEPOINT_TABLE; + #[cfg(feature = "multisig")] use dalek_ff_group::Scalar; +#[cfg(feature = "multisig")] +use frost::tests::{THRESHOLD, key_gen, sign}; use monero::{ network::Network, @@ -22,9 +25,7 @@ mod rpc; use crate::rpc::{rpc, mine_block}; #[cfg(feature = "multisig")] -mod frost; -#[cfg(feature = "multisig")] -use crate::frost::{THRESHOLD, generate_keys, sign}; +use monero_serai::frost::Ed25519; lazy_static! { static ref SEQUENTIAL: Mutex<()> = Mutex::new(()); @@ -59,7 +60,7 @@ async fn send_core(test: usize, multisig: bool) { let mut spend_pub = &spend * &ED25519_BASEPOINT_TABLE; #[cfg(feature = "multisig")] - let (keys, _) = generate_keys(); + let keys = key_gen::<_, Ed25519>(&mut OsRng); if multisig { #[cfg(not(feature = "multisig"))] @@ -148,17 +149,13 @@ async fn send_core(test: usize, multisig: bool) { &mut OsRng, &rpc, rpc.get_height().await.unwrap() - 10, - keys[&i].clone(), + (*keys[&i]).clone(), (1 ..= THRESHOLD).collect::>() ).await.unwrap() ); } - let mut txs = sign(&mut machines, &vec![]); - for s in 1 .. THRESHOLD { - assert_eq!(txs[usize::from(s)].hash(), txs[0].hash()); - } - tx = Some(txs.swap_remove(0)); + tx = Some(sign(&mut OsRng, machines, &vec![])); } } diff --git a/crypto/frost/src/tests/mod.rs b/crypto/frost/src/tests/mod.rs index 4c74034d..f87ce812 100644 --- a/crypto/frost/src/tests/mod.rs +++ b/crypto/frost/src/tests/mod.rs @@ -2,9 +2,12 @@ use std::{rc::Rc, collections::HashMap}; use rand_core::{RngCore, CryptoRng}; +use ff::Field; + use crate::{ Curve, MultisigParams, MultisigKeys, + lagrange, key_gen, algorithm::Algorithm, sign::{StateMachine, AlgorithmMachine} @@ -102,6 +105,19 @@ pub fn key_gen( keys } +pub fn recover(keys: &HashMap>) -> C::F { + let first = keys.values().next().expect("no keys provided"); + assert!(keys.len() >= first.params().t().into(), "not enough keys provided"); + let included = keys.keys().cloned().collect::>(); + + let group_private = keys.iter().fold( + C::F::zero(), + |accum, (i, keys)| accum + (keys.secret_share() * lagrange::(*i, &included)) + ); + assert_eq!(C::generator_table() * group_private, first.group_key(), "failed to recover keys"); + group_private +} + pub fn algorithm_machines>( rng: &mut R, algorithm: A,