Have modular-frost compile again

This commit is contained in:
Luke Parker
2025-08-18 01:54:52 -04:00
parent 9f84adf8b3
commit e87bbcda64
6 changed files with 71 additions and 20 deletions

View File

@@ -40,12 +40,14 @@ multiexp = { path = "../multiexp", version = "0.4", default-features = false, fe
schnorr = { package = "schnorr-signatures", path = "../schnorr", version = "^0.5.1", default-features = false, features = ["std"] }
dkg = { path = "../dkg", version = "0.6", default-features = false, features = ["std"] }
dkg-recovery = { path = "../dkg/recovery", default-features = false, features = ["std"], optional = true }
[dev-dependencies]
hex = "0.4"
serde_json = { version = "1", default-features = false, features = ["std"] }
dkg = { path = "../dkg" }
dkg = { path = "../dkg", default-features = false, features = ["std"] }
dkg-recovery = { path = "../dkg/recovery", default-features = false, features = ["std"] }
[features]
ed25519 = ["dalek-ff-group", "ciphersuite/ed25519"]
@@ -56,4 +58,4 @@ p256 = ["ciphersuite/p256"]
ed448 = ["minimal-ed448", "ciphersuite/ed448"]
tests = ["hex", "rand_core/getrandom"]
tests = ["hex", "rand_core/getrandom", "dkg-recovery"]

View File

@@ -7,7 +7,7 @@ use std::collections::HashMap;
use thiserror::Error;
/// Distributed key generation protocol.
pub use dkg::{self, Participant, ThresholdParams, ThresholdCore, ThresholdKeys, ThresholdView};
pub use dkg::{self, Participant, ThresholdParams, ThresholdKeys, ThresholdView};
/// Curve trait and provided curves/HRAMs, forming various ciphersuites.
pub mod curve;

View File

@@ -1,11 +1,18 @@
use core::ops::Deref;
use std::collections::HashMap;
use zeroize::{Zeroize, Zeroizing};
use rand_core::{RngCore, CryptoRng};
pub use dkg::tests::{key_gen, musig_key_gen, recover_key};
use ciphersuite::{
group::ff::{Field, PrimeField},
Ciphersuite,
};
use dkg::Interpolation;
pub use dkg_recovery::recover_key;
use crate::{
Curve, Participant, ThresholdKeys, FrostError,
Curve, Participant, ThresholdParams, ThresholdKeys, FrostError,
algorithm::{Algorithm, Hram, IetfSchnorr},
sign::{Writable, PreprocessMachine, SignMachine, SignatureMachine, AlgorithmMachine},
};
@@ -26,6 +33,56 @@ pub const PARTICIPANTS: u16 = 5;
/// Constant threshold of participants to use when signing.
pub const THRESHOLD: u16 = ((PARTICIPANTS * 2) / 3) + 1;
/// Create a key, for testing purposes.
pub fn key_gen<R: RngCore + CryptoRng, C: Ciphersuite>(
rng: &mut R,
) -> HashMap<Participant, ThresholdKeys<C>> {
let coefficients: [_; THRESHOLD as usize] =
core::array::from_fn(|_| Zeroizing::new(C::F::random(&mut *rng)));
fn polynomial<F: PrimeField + Zeroize>(
coefficients: &[Zeroizing<F>],
l: Participant,
) -> Zeroizing<F> {
let l = F::from(u64::from(u16::from(l)));
// This should never be reached since Participant is explicitly non-zero
assert!(l != F::ZERO, "zero participant passed to polynomial");
let mut share = Zeroizing::new(F::ZERO);
for (idx, coefficient) in coefficients.iter().rev().enumerate() {
*share += coefficient.deref();
if idx != (coefficients.len() - 1) {
*share *= l;
}
}
share
}
let group_key = C::generator() * *coefficients[0];
let mut secret_shares = HashMap::with_capacity(PARTICIPANTS as usize);
let mut verification_shares = HashMap::with_capacity(PARTICIPANTS as usize);
for i in 1 ..= PARTICIPANTS {
let i = Participant::new(i).unwrap();
let secret_share = polynomial(&coefficients, i);
secret_shares.insert(i, secret_share.clone());
verification_shares.insert(i, C::generator() * *secret_share);
}
let mut res = HashMap::with_capacity(PARTICIPANTS as usize);
for i in 1 ..= PARTICIPANTS {
let i = Participant::new(i).unwrap();
let keys = ThresholdKeys::new(
ThresholdParams::new(THRESHOLD, PARTICIPANTS, i).unwrap(),
Interpolation::Lagrange,
secret_shares.remove(&i).unwrap(),
verification_shares.clone(),
)
.unwrap();
assert_eq!(keys.group_key(), group_key);
res.insert(i, keys);
}
res
}
/// Clone a map without a specific value.
pub fn clone_without<K: Clone + core::cmp::Eq + core::hash::Hash, V: Clone>(
map: &HashMap<K, V>,
@@ -238,12 +295,6 @@ pub fn test_schnorr<R: RngCore + CryptoRng, C: Curve, H: Hram<C>>(rng: &mut R) {
test_schnorr_with_keys::<_, _, H>(&mut *rng, &keys)
}
/// Test a basic Schnorr signature, yet with MuSig.
pub fn test_musig_schnorr<R: RngCore + CryptoRng, C: Curve, H: Hram<C>>(rng: &mut R) {
let keys = musig_key_gen(&mut *rng);
test_schnorr_with_keys::<_, _, H>(&mut *rng, &keys)
}
/// Test an offset Schnorr signature.
pub fn test_offset_schnorr<R: RngCore + CryptoRng, C: Curve, H: Hram<C>>(rng: &mut R) {
const MSG: &[u8] = b"Hello, World!";
@@ -290,7 +341,6 @@ pub fn test_schnorr_blame<R: RngCore + CryptoRng, C: Curve, H: Hram<C>>(rng: &mu
/// Run a variety of tests against a ciphersuite.
pub fn test_ciphersuite<R: RngCore + CryptoRng, C: Curve, H: Hram<C>>(rng: &mut R) {
test_schnorr::<R, C, H>(rng);
test_musig_schnorr::<R, C, H>(rng);
test_offset_schnorr::<R, C, H>(rng);
test_schnorr_blame::<R, C, H>(rng);

View File

@@ -9,12 +9,10 @@ use transcript::{Transcript, RecommendedTranscript};
use ciphersuite::group::{ff::Field, Group, GroupEncoding};
pub use dkg::tests::{key_gen, recover_key};
use crate::{
Curve, Participant, ThresholdView, ThresholdKeys, FrostError,
algorithm::Algorithm,
tests::{algorithm_machines, sign},
tests::{key_gen, algorithm_machines, sign},
};
#[derive(Clone)]

View File

@@ -13,7 +13,7 @@ use ciphersuite::group::{ff::PrimeField, GroupEncoding};
use crate::{
curve::Curve,
Participant, ThresholdCore, ThresholdKeys,
Participant, ThresholdKeys,
algorithm::{Hram, IetfSchnorr},
sign::{
Writable, Nonce, GeneratorCommitments, NonceCommitments, Commitments, Preprocess,
@@ -115,7 +115,7 @@ fn vectors_to_multisig_keys<C: Curve>(vectors: &Vectors) -> HashMap<Participant,
let mut keys = HashMap::new();
for i in 1 ..= u16::try_from(shares.len()).unwrap() {
// Manually re-implement the serialization for ThresholdCore to import this data
// Manually re-implement the serialization for ThresholdKeys to import this data
let mut serialized = vec![];
serialized.extend(u32::try_from(C::ID.len()).unwrap().to_le_bytes());
serialized.extend(C::ID);
@@ -128,14 +128,14 @@ fn vectors_to_multisig_keys<C: Curve>(vectors: &Vectors) -> HashMap<Participant,
serialized.extend(share.to_bytes().as_ref());
}
let these_keys = ThresholdCore::<C>::read::<&[u8]>(&mut serialized.as_ref()).unwrap();
let these_keys = ThresholdKeys::<C>::read::<&[u8]>(&mut serialized.as_ref()).unwrap();
assert_eq!(these_keys.params().t(), vectors.threshold);
assert_eq!(usize::from(these_keys.params().n()), shares.len());
let participant = Participant::new(i).unwrap();
assert_eq!(these_keys.params().i(), participant);
assert_eq!(these_keys.secret_share().deref(), &shares[usize::from(i - 1)]);
assert_eq!(hex::encode(these_keys.group_key().to_bytes().as_ref()), vectors.group_key);
keys.insert(participant, ThresholdKeys::new(these_keys));
keys.insert(participant, these_keys);
}
keys
@@ -157,7 +157,7 @@ pub fn test_with_vectors<R: RngCore + CryptoRng, C: Curve, H: Hram<C>>(
let secret =
C::read_F::<&[u8]>(&mut hex::decode(&vectors.group_secret).unwrap().as_ref()).unwrap();
assert_eq!(C::generator() * secret, group_key);
assert_eq!(recover_key(&keys), secret);
assert_eq!(*recover_key(&keys.values().cloned().collect::<Vec<_>>()).unwrap(), secret);
let mut machines = vec![];
for i in &vectors.included {