Downstream the eVRF libraries from FCMP++

Also adds no-std support to secq256k1 and embedwards25519.
This commit is contained in:
Luke Parker
2025-01-29 22:29:40 -05:00
parent 19422de231
commit 2bc880e372
35 changed files with 456 additions and 340 deletions

View File

@@ -54,7 +54,7 @@ rand = { version = "0.8", default-features = false, features = ["std"] }
ciphersuite = { path = "../ciphersuite", default-features = false, features = ["ristretto"] }
generalized-bulletproofs = { path = "../evrf/generalized-bulletproofs", features = ["tests"] }
ec-divisors = { path = "../evrf/divisors", features = ["pasta"] }
pasta_curves = "0.5"
pasta_curves = { git = "https://github.com/kayabaNerve/pasta_curves", rev = "a46b5be95cacbff54d06aad8d3bbcba42e05d616" }
[features]
std = [

View File

@@ -85,7 +85,7 @@ use ciphersuite::{
};
use multiexp::multiexp_vartime;
use generalized_bulletproofs::arithmetic_circuit_proof::*;
use generalized_bulletproofs::{Generators, arithmetic_circuit_proof::*};
use ec_divisors::DivisorCurve;
use crate::{Participant, ThresholdParams, Interpolation, ThresholdCore, ThresholdKeys};
@@ -277,6 +277,7 @@ impl<C: EvrfCurve> EvrfDkg<C> {
if evrf_public_keys.iter().any(|key| bool::from(key.is_identity())) {
Err(EvrfError::PublicKeyWasIdentity)?;
};
// This also checks the private key is not 0
let evrf_public_key = <C::EmbeddedCurve as Ciphersuite>::generator() * evrf_private_key.deref();
if !evrf_public_keys.iter().any(|key| *key == evrf_public_key) {
Err(EvrfError::NotAParticipant)?;
@@ -359,7 +360,7 @@ impl<C: EvrfCurve> EvrfDkg<C> {
let transcript = Self::initial_transcript(context, evrf_public_keys, t);
let mut evrf_verifier = generators.0.batch_verifier();
let mut evrf_verifier = Generators::batch_verifier();
for (i, participation) in participations {
let evrf_public_key = evrf_public_keys[usize::from(u16::from(*i)) - 1];
@@ -395,7 +396,7 @@ impl<C: EvrfCurve> EvrfDkg<C> {
if faulty.contains(i) {
continue;
}
let mut evrf_verifier = generators.0.batch_verifier();
let mut evrf_verifier = Generators::batch_verifier();
Evrf::<C>::verify(
rng,
&generators.0,

View File

@@ -129,15 +129,11 @@ impl<C: EvrfCurve> Evrf<C> {
/// Read a Variable from a theoretical vector commitment tape
fn read_one_from_tape(generators_to_use: usize, start: &mut usize) -> Variable {
// Each commitment has twice as many variables as generators in use
let commitment = *start / (2 * generators_to_use);
let commitment = *start / generators_to_use;
// The index will be less than the amount of generators in use, as half are left and half are
// right
let index = *start % generators_to_use;
let res = if (*start / generators_to_use) % 2 == 0 {
Variable::CG { commitment, index }
} else {
Variable::CH { commitment, index }
};
let res = Variable::CG { commitment, index };
*start += 1;
res
}
@@ -202,8 +198,8 @@ impl<C: EvrfCurve> Evrf<C> {
padded_pow_of_2 <<= 1;
}
// This may as small as 16, which would create an excessive amount of vector commitments
// We set a floor of 1024 rows for bandwidth reasons
padded_pow_of_2.max(1024)
// We set a floor of 2048 rows for bandwidth reasons
padded_pow_of_2.max(2048)
};
(expected_muls, generators_to_use)
}
@@ -213,7 +209,7 @@ impl<C: EvrfCurve> Evrf<C> {
evrf_public_key: (C::F, C::F),
coefficients: usize,
ecdh_commitments: &[[(C::F, C::F); 2]],
generator_tables: &[GeneratorTable<C::F, C::EmbeddedCurveParameters>],
generator_tables: &[&GeneratorTable<C::F, C::EmbeddedCurveParameters>],
circuit: &mut Circuit<C>,
transcript: &mut impl Transcript,
) {
@@ -376,8 +372,10 @@ impl<C: EvrfCurve> Evrf<C> {
let evrf_public_key;
let mut actual_coefficients = Vec::with_capacity(coefficients);
{
// This is checked at a higher level
let dlog =
ScalarDecomposition::<<C::EmbeddedCurve as Ciphersuite>::F>::new(**evrf_private_key);
ScalarDecomposition::<<C::EmbeddedCurve as Ciphersuite>::F>::new(**evrf_private_key)
.expect("eVRF private key was zero");
let points = Self::transcript_to_points(transcript, coefficients);
// Start by pushing the discrete logarithm onto the tape
@@ -431,7 +429,8 @@ impl<C: EvrfCurve> Evrf<C> {
}
}
let dlog =
ScalarDecomposition::<<C::EmbeddedCurve as Ciphersuite>::F>::new(ecdh_private_key);
ScalarDecomposition::<<C::EmbeddedCurve as Ciphersuite>::F>::new(ecdh_private_key)
.expect("ECDH private key was zero");
let ecdh_commitment = <C::EmbeddedCurve as Ciphersuite>::generator() * ecdh_private_key;
ecdh_commitments.push(ecdh_commitment);
ecdh_commitments_xy.last_mut().unwrap()[j] =
@@ -471,15 +470,10 @@ impl<C: EvrfCurve> Evrf<C> {
Self::muls_and_generators_to_use(coefficients, ecdh_public_keys.len());
let mut vector_commitments =
Vec::with_capacity(vector_commitment_tape.len().div_ceil(2 * generators_to_use));
for chunk in vector_commitment_tape.chunks(2 * generators_to_use) {
Vec::with_capacity(vector_commitment_tape.len().div_ceil(generators_to_use));
for chunk in vector_commitment_tape.chunks(generators_to_use) {
let g_values = chunk[.. generators_to_use.min(chunk.len())].to_vec().into();
let h_values = chunk[generators_to_use.min(chunk.len()) ..].to_vec().into();
vector_commitments.push(PedersenVectorCommitment {
g_values,
h_values,
mask: C::F::random(&mut *rng),
});
vector_commitments.push(PedersenVectorCommitment { g_values, mask: C::F::random(&mut *rng) });
}
vector_commitment_tape.zeroize();
@@ -499,7 +493,7 @@ impl<C: EvrfCurve> Evrf<C> {
.iter()
.map(|commitment| {
commitment
.commit(generators.g_bold_slice(), generators.h_bold_slice(), generators.h())
.commit(generators.g_bold_slice(), generators.h())
.ok_or(AcError::NotEnoughGenerators)
})
.collect::<Result<_, _>>()?,
@@ -518,7 +512,7 @@ impl<C: EvrfCurve> Evrf<C> {
evrf_public_key,
coefficients,
&ecdh_commitments_xy,
&generator_tables,
&generator_tables.iter().collect::<Vec<_>>(),
&mut circuit,
&mut transcript,
);
@@ -543,7 +537,7 @@ impl<C: EvrfCurve> Evrf<C> {
let mut agg_weights = Vec::with_capacity(commitments.len());
agg_weights.push(C::F::ONE);
while agg_weights.len() < commitments.len() {
agg_weights.push(transcript.challenge::<C::F>());
agg_weights.push(transcript.challenge::<C>());
}
let mut x = commitments
.iter()
@@ -554,7 +548,7 @@ impl<C: EvrfCurve> Evrf<C> {
// Do a Schnorr PoK for the randomness of the aggregated Pedersen commitment
let mut r = C::F::random(&mut *rng);
transcript.push_point(generators.h() * r);
let c = transcript.challenge::<C::F>();
let c = transcript.challenge::<C>();
transcript.push_scalar(r + (c * x));
r.zeroize();
x.zeroize();
@@ -615,7 +609,7 @@ impl<C: EvrfCurve> Evrf<C> {
let coeffs_vc_variables = dlog_len + ((1 + (2 * coefficients)) * dlog_proof_len);
let ecdhs_vc_variables = ((2 * ecdh_public_keys.len()) * dlog_len) +
((2 * 2 * ecdh_public_keys.len()) * dlog_proof_len);
let vcs = (coeffs_vc_variables + ecdhs_vc_variables).div_ceil(2 * generators_to_use);
let vcs = (coeffs_vc_variables + ecdhs_vc_variables).div_ceil(generators_to_use);
let all_commitments =
transcript.read_commitments(vcs, coefficients + ecdh_public_keys.len()).map_err(|_| ())?;
@@ -642,7 +636,7 @@ impl<C: EvrfCurve> Evrf<C> {
<C::EmbeddedCurve as Ciphersuite>::G::to_xy(evrf_public_key).ok_or(())?,
coefficients,
&ecdh_keys_xy,
&generator_tables,
&generator_tables.iter().collect::<Vec<_>>(),
&mut circuit,
&mut transcript,
);
@@ -665,7 +659,7 @@ impl<C: EvrfCurve> Evrf<C> {
let mut agg_weights = Vec::with_capacity(commitments.len());
agg_weights.push(C::F::ONE);
while agg_weights.len() < commitments.len() {
agg_weights.push(transcript.challenge::<C::F>());
agg_weights.push(transcript.challenge::<C>());
}
let sum_points =
@@ -677,7 +671,7 @@ impl<C: EvrfCurve> Evrf<C> {
#[allow(non_snake_case)]
let R = transcript.read_point::<C>().map_err(|_| ())?;
let c = transcript.challenge::<C::F>();
let c = transcript.challenge::<C>();
let s = transcript.read_scalar::<C>().map_err(|_| ())?;
// Doesn't batch verify this as we can't access the internals of the GBP batch verifier

View File

@@ -15,7 +15,7 @@ use ciphersuite::{
};
use pasta_curves::{Ep, Eq, Fp, Fq};
use generalized_bulletproofs::tests::generators;
use generalized_bulletproofs::{Generators, tests::generators};
use generalized_bulletproofs_ec_gadgets::DiscreteLogParameters;
use crate::evrf::proof::*;
@@ -35,6 +35,9 @@ impl Ciphersuite for Pallas {
// This is solely test code so it's fine
Self::F::from_uniform_bytes(&Self::H::digest([dst, msg].concat()).into())
}
fn reduce_512(scalar: [u8; 64]) -> Self::F {
Self::F::from_uniform_bytes(&scalar)
}
}
#[derive(Clone, Copy, PartialEq, Eq, Debug, Zeroize)]
@@ -52,6 +55,9 @@ impl Ciphersuite for Vesta {
// This is solely test code so it's fine
Self::F::from_uniform_bytes(&Self::H::digest([dst, msg].concat()).into())
}
fn reduce_512(scalar: [u8; 64]) -> Self::F {
Self::F::from_uniform_bytes(&scalar)
}
}
pub struct VestaParams;
@@ -68,7 +74,7 @@ impl EvrfCurve for Pallas {
}
fn evrf_proof_test<C: EvrfCurve>() {
let generators = generators(1024);
let generators = generators(2048);
let vesta_private_key = Zeroizing::new(<C::EmbeddedCurve as Ciphersuite>::F::random(&mut OsRng));
let ecdh_public_keys = [
<C::EmbeddedCurve as Ciphersuite>::G::random(&mut OsRng),
@@ -81,7 +87,7 @@ fn evrf_proof_test<C: EvrfCurve>() {
println!("Proving time: {:?}", time.elapsed());
let time = Instant::now();
let mut verifier = generators.batch_verifier();
let mut verifier = Generators::batch_verifier();
Evrf::<C>::verify(
&mut OsRng,
&generators,

View File

@@ -28,6 +28,10 @@ impl<C: Ciphersuite> Ciphersuite for AltGenerator<C> {
C::G::generator() * <C as Ciphersuite>::hash_to_F(b"DKG Promotion Test", b"generator")
}
fn reduce_512(scalar: [u8; 64]) -> Self::F {
<C as Ciphersuite>::reduce_512(scalar)
}
fn hash_to_F(dst: &[u8], data: &[u8]) -> Self::F {
<C as Ciphersuite>::hash_to_F(dst, data)
}