#![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(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 }