arnaucube
arnaucube/plonky2-crypto-gadgetsPublic Self-hosted repository
plonky2-crypto-gadgets/ecgfp5/src/circuit.rs
ecgfp5/src/circuit.rsRaw
  1//! For LICENSE check out https://github.com/0xPARC/plonky2-crypto-gadgets/blob/main/LICENSE
  2
  3use plonky2::{
  4    field::extension::Extendable, hash::hash_types::RichField, iop::witness::PartialWitness,
  5    plonk::circuit_builder::CircuitBuilder,
  6};
  7use pod2::backends::plonky2::{
  8    basetypes::{D, F},
  9    primitives::ec::{
 10        bits::{BigUInt320Target, CircuitBuilderBits},
 11        curve::{CircuitBuilderElliptic, Point, PointTarget, WitnessWriteCurve},
 12    },
 13};
 14
 15use crate::ECGFP5SecretKey;
 16
 17/// EcGFp5 secret key target type
 18pub struct ECGFP5SecretKeyTarget(pub BigUInt320Target);
 19
 20/// EcGFp5 public key (point) type alias
 21pub type PublicKeyTarget = PointTarget;
 22
 23pub trait CircuitBuilderECGFP5PublicKey<F: RichField + Extendable<D>, const D: usize> {
 24    /// Adds secret key target
 25    fn add_secret_key(&mut self) -> ECGFP5SecretKeyTarget;
 26
 27    /// Derives public key from secret key
 28    fn public_key(&mut self, sk: &ECGFP5SecretKeyTarget) -> PublicKeyTarget;
 29}
 30
 31impl CircuitBuilderECGFP5PublicKey<F, D> for CircuitBuilder<F, D> {
 32    fn add_secret_key(&mut self) -> ECGFP5SecretKeyTarget {
 33        ECGFP5SecretKeyTarget(self.add_virtual_biguint320_target())
 34    }
 35
 36    fn public_key(&mut self, sk: &ECGFP5SecretKeyTarget) -> PublicKeyTarget {
 37        let generator = self.constant_point(Point::generator());
 38        self.multiply_point(&sk.0.bits, &generator)
 39    }
 40}
 41
 42pub trait PartialWitnessECGFP5PublicKey {
 43    /// Sets EcGFp5 secret key witnesses
 44    fn set_secret_key_target(
 45        &mut self,
 46        target: &ECGFP5SecretKeyTarget,
 47        value: &ECGFP5SecretKey,
 48    ) -> anyhow::Result<()>;
 49}
 50
 51impl PartialWitnessECGFP5PublicKey for PartialWitness<F> {
 52    fn set_secret_key_target(
 53        &mut self,
 54        target: &ECGFP5SecretKeyTarget,
 55        value: &ECGFP5SecretKey,
 56    ) -> anyhow::Result<()> {
 57        self.set_biguint320_target(&target.0, &value.0)
 58    }
 59}
 60
 61#[cfg(test)]
 62mod tests {
 63    use plonky2::{
 64        iop::witness::PartialWitness,
 65        plonk::{
 66            circuit_builder::CircuitBuilder, circuit_data::CircuitConfig,
 67            config::PoseidonGoldilocksConfig,
 68        },
 69    };
 70    use pod2::backends::plonky2::{
 71        basetypes::{D, F},
 72        primitives::ec::curve::WitnessWriteCurve,
 73    };
 74
 75    use crate::{
 76        ECGFP5SecretKey,
 77        circuit::{CircuitBuilderECGFP5PublicKey, PartialWitnessECGFP5PublicKey},
 78    };
 79
 80    #[test]
 81    fn public_key_calculation() -> anyhow::Result<()> {
 82        let config = CircuitConfig::standard_recursion_config();
 83        let mut builder = CircuitBuilder::<F, D>::new(config);
 84
 85        let sk_target = builder.add_secret_key();
 86        let pk_target = builder.public_key(&sk_target);
 87
 88        let data = builder.build::<PoseidonGoldilocksConfig>();
 89        (0..10).try_for_each(|_| {
 90            let sk = ECGFP5SecretKey::rand();
 91            let pk = sk.public_key();
 92
 93            let mut pw = PartialWitness::new();
 94            pw.set_secret_key_target(&sk_target, &sk)?;
 95            pw.set_point_target(&pk_target, &pk)?;
 96
 97            let proof = data.prove(pw)?;
 98            data.verify(proof)
 99        })
100    }
101}