arnaucube
arnaucube/plonky2-ecdsaPublic Self-hosted repository
plonky2-ecdsa/src/gadgets/ecdsa.rs
src/gadgets/ecdsa.rsRaw
  1use core::marker::PhantomData;
  2
  3use plonky2::field::extension::Extendable;
  4use plonky2::field::secp256k1_scalar::Secp256K1Scalar;
  5use plonky2::hash::hash_types::RichField;
  6use plonky2::plonk::circuit_builder::CircuitBuilder;
  7
  8use crate::curve::curve_types::Curve;
  9use crate::curve::secp256k1::Secp256K1;
 10use crate::gadgets::curve::{AffinePointTarget, CircuitBuilderCurve};
 11use crate::gadgets::curve_fixed_base::fixed_base_curve_mul_circuit;
 12use crate::gadgets::glv::CircuitBuilderGlv;
 13use crate::gadgets::nonnative::{CircuitBuilderNonNative, NonNativeTarget};
 14
 15#[derive(Clone, Debug)]
 16pub struct ECDSASecretKeyTarget<C: Curve>(pub NonNativeTarget<C::ScalarField>);
 17
 18#[derive(Clone, Debug)]
 19pub struct ECDSAPublicKeyTarget<C: Curve>(pub AffinePointTarget<C>);
 20
 21#[derive(Clone, Debug)]
 22pub struct ECDSASignatureTarget<C: Curve> {
 23    pub r: NonNativeTarget<C::ScalarField>,
 24    pub s: NonNativeTarget<C::ScalarField>,
 25}
 26
 27pub fn verify_message_circuit<F: RichField + Extendable<D>, const D: usize>(
 28    builder: &mut CircuitBuilder<F, D>,
 29    msg: NonNativeTarget<Secp256K1Scalar>,
 30    sig: ECDSASignatureTarget<Secp256K1>,
 31    pk: ECDSAPublicKeyTarget<Secp256K1>,
 32) {
 33    let ECDSASignatureTarget { r, s } = sig;
 34
 35    builder.curve_assert_valid(&pk.0);
 36
 37    let c = builder.inv_nonnative(&s);
 38    let u1 = builder.mul_nonnative(&msg, &c);
 39    let u2 = builder.mul_nonnative(&r, &c);
 40
 41    let point1 = fixed_base_curve_mul_circuit(builder, Secp256K1::GENERATOR_AFFINE, &u1);
 42    let point2 = builder.glv_mul(&pk.0, &u2);
 43    let point = builder.curve_add(&point1, &point2);
 44
 45    let x = NonNativeTarget::<Secp256K1Scalar> {
 46        value: point.x.value,
 47        _phantom: PhantomData,
 48    };
 49    builder.connect_nonnative(&r, &x);
 50}
 51
 52#[cfg(test)]
 53mod tests {
 54    use anyhow::Result;
 55    use plonky2::field::types::Sample;
 56    use plonky2::iop::witness::PartialWitness;
 57    use plonky2::plonk::circuit_data::CircuitConfig;
 58    use plonky2::plonk::config::{GenericConfig, PoseidonGoldilocksConfig};
 59
 60    use super::*;
 61    use crate::curve::curve_types::CurveScalar;
 62    use crate::curve::ecdsa::{sign_message, ECDSAPublicKey, ECDSASecretKey, ECDSASignature};
 63
 64    fn test_ecdsa_circuit_with_config(config: CircuitConfig) -> Result<()> {
 65        const D: usize = 2;
 66        type C = PoseidonGoldilocksConfig;
 67        type F = <C as GenericConfig<D>>::F;
 68
 69        type Curve = Secp256K1;
 70
 71        let pw = PartialWitness::new();
 72        let mut builder = CircuitBuilder::<F, D>::new(config);
 73
 74        let msg = Secp256K1Scalar::rand();
 75        let msg_target = builder.constant_nonnative(msg);
 76
 77        let sk = ECDSASecretKey::<Curve>(Secp256K1Scalar::rand());
 78        let pk = ECDSAPublicKey((CurveScalar(sk.0) * Curve::GENERATOR_PROJECTIVE).to_affine());
 79
 80        let pk_target = ECDSAPublicKeyTarget(builder.constant_affine_point(pk.0));
 81
 82        let sig = sign_message(msg, sk);
 83
 84        let ECDSASignature { r, s } = sig;
 85        let r_target = builder.constant_nonnative(r);
 86        let s_target = builder.constant_nonnative(s);
 87        let sig_target = ECDSASignatureTarget {
 88            r: r_target,
 89            s: s_target,
 90        };
 91
 92        verify_message_circuit(&mut builder, msg_target, sig_target, pk_target);
 93
 94        dbg!(builder.num_gates());
 95        let data = builder.build::<C>();
 96        let proof = data.prove(pw).unwrap();
 97        data.verify(proof)
 98    }
 99
100    #[test]
101    #[ignore]
102    fn test_ecdsa_circuit_narrow() -> Result<()> {
103        test_ecdsa_circuit_with_config(CircuitConfig::standard_ecc_config())
104    }
105
106    #[test]
107    #[ignore]
108    fn test_ecdsa_circuit_wide() -> Result<()> {
109        test_ecdsa_circuit_with_config(CircuitConfig::wide_ecc_config())
110    }
111}