use crate::{CompressionFunction, EdwardsCurve, EdwardsPointExpression, Expression, Field, GadgetBuilder};
pub trait SignatureExpression<F: Field, C: EdwardsCurve<F>, CF> {
fn verify(
&self,
builder: &mut GadgetBuilder<F>,
message: &Expression<F>,
public_key: &EdwardsPointExpression<F, C>,
compress: &CF,
) where CF: CompressionFunction<F>;
}
pub struct SchnorrSignatureExpression<F: Field> {
pub s: Expression<F>,
pub e: Expression<F>,
}
impl<F: Field, C: EdwardsCurve<F>, CF> SignatureExpression<F, C, CF> for SchnorrSignatureExpression<F> {
fn verify(
&self,
builder: &mut GadgetBuilder<F>,
message: &Expression<F>,
public_key: &EdwardsPointExpression<F, C>,
compress: &CF,
) where CF: CompressionFunction<F> {
let generator = EdwardsPointExpression::from_elements(
C::subgroup_generator().0, C::subgroup_generator().1,
);
let gs = EdwardsPointExpression::scalar_mult(builder, &generator, &self.s);
let ye = EdwardsPointExpression::scalar_mult(builder, public_key, &self.e);
let gs_ye = EdwardsPointExpression::add(builder, &gs, &ye);
let hash_check = compress.compress(builder, gs_ye.compressed(), &message);
builder.assert_equal(&hash_check, &self.e);
}
}
#[cfg(test)]
mod tests {
use std::str::FromStr;
use crate::{EdwardsPointExpression, Expression, GadgetBuilder, WireValues, EdwardsPoint};
use crate::CompressionFunction;
use crate::curve::EdwardsCurve;
use crate::embedded_curve::JubJub;
use crate::field::{Bls12_381, Element, Field};
use crate::signature::{SchnorrSignatureExpression, SignatureExpression};
#[test]
fn verify() {
let generator = EdwardsPoint::<Bls12_381, JubJub>::from_elements(
JubJub::subgroup_generator().0, JubJub::subgroup_generator().1,
);
let private_key = Element::from_str("4372820819045374670962167435360035096875258").unwrap();
let mut builder = GadgetBuilder::<Bls12_381>::new();
let public_key = generator.scalar_mult_evaluate(&private_key);
let nonce = Element::from_str("5434290453746709621674353600312312").unwrap();
let r = generator.scalar_mult_evaluate(&nonce);
let compress = TestCompress {};
let message = Element::from_str("12345").unwrap();
let e = compress.compress_evaluate(&r.compressed(), &message);
let s = &nonce - &private_key * &e;
let signature = SchnorrSignatureExpression { s: Expression::from(s), e: Expression::from(e) };
let mut builder = GadgetBuilder::<Bls12_381>::new();
signature.verify(
&mut builder,
&Expression::from(message),
&EdwardsPointExpression::from_edwards_point(public_key),
&compress,
);
let gadget = builder.build();
let mut values = WireValues::new();
gadget.execute(&mut values);
}
struct TestCompress;
impl<F: Field> CompressionFunction<F> for TestCompress {
fn compress(&self, _builder: &mut GadgetBuilder<F>, x: &Expression<F>, y: &Expression<F>)
-> Expression<F> {
x * 2 + y
}
}
}