arnaucube
arnaucube/plonky2-ecdsaPublic Self-hosted repository
Fix build
Ahmad root@ahmadafuni.com
Tue, 20 May 2025 16:03:22 +1000
commit

c37ab0cefa1b0052384c9f012cdcc25d08da7b5e

parent

bdb6504bca250db1548cdcce2407d4e334990c33

M Cargo.toml → Cargo.toml

@@ -11,10 +11,10 @@

[dependencies] anyhow = { version = "1.0.40", default-features = false } itertools = { version = "0.10.0", default-features = false } -plonky2_maybe_rayon = { version = "0.1.0", default-features = false } num = { version = "0.4.0", default-features = false } -plonky2 = { version = "0.1.2", default-features = false } -plonky2_u32 = { version = "0.1.0", default-features = false } +plonky2 = { git = "https://github.com/0xPolygonZero/plonky2" } +plonky2_maybe_rayon = { git = "https://github.com/0xPolygonZero/plonky2" } +plonky2_u32 = { git = "https://github.com/ax0/plonky2-u32" } serde = { version = "1.0", default-features = false, features = ["derive"] } [dev-dependencies]
M src/curve/curve_msm.rs → src/curve/curve_msm.rs

@@ -40,7 +40,7 @@ }

} fn precompute_single_generator<C: Curve>(g: ProjectivePoint<C>, w: usize) -> Vec<AffinePoint<C>> { - let digits = (C::ScalarField::BITS + w - 1) / w; + let digits = C::ScalarField::BITS.div_ceil(w); let mut powers: Vec<ProjectivePoint<C>> = Vec::with_capacity(digits); powers.push(g); for i in 1..digits {

@@ -68,7 +68,7 @@ scalars: &[C::ScalarField],

) -> ProjectivePoint<C> { assert_eq!(precomputation.powers_per_generator.len(), scalars.len()); let w = precomputation.w; - let digits = (C::ScalarField::BITS + w - 1) / w; + let digits = C::ScalarField::BITS.div_ceil(w); let base = 1 << w; // This is a variant of Yao's method, adapted to the multi-scalar setting. Because we use

@@ -107,7 +107,7 @@ scalars: &[C::ScalarField],

) -> ProjectivePoint<C> { assert_eq!(precomputation.powers_per_generator.len(), scalars.len()); let w = precomputation.w; - let digits = (C::ScalarField::BITS + w - 1) / w; + let digits = C::ScalarField::BITS.div_ceil(w); let base = 1 << w; // This is a variant of Yao's method, adapted to the multi-scalar setting. Because we use

@@ -158,7 +158,7 @@ }

pub(crate) fn to_digits<C: Curve>(x: &C::ScalarField, w: usize) -> Vec<usize> { let scalar_bits = C::ScalarField::BITS; - let num_digits = (scalar_bits + w - 1) / w; + let num_digits = scalar_bits.div_ceil(w); // Convert x to a bool array. let x_canonical: Vec<_> = x
M src/curve/curve_multiplication.rs → src/curve/curve_multiplication.rs

@@ -9,7 +9,7 @@ const WINDOW_BITS: usize = 4;

const BASE: usize = 1 << WINDOW_BITS; fn digits_per_scalar<C: Curve>() -> usize { - (C::ScalarField::BITS + WINDOW_BITS - 1) / WINDOW_BITS + C::ScalarField::BITS.div_ceil(WINDOW_BITS) } /// Precomputed state used for scalar x ProjectivePoint multiplications,
M src/curve/glv.rs → src/curve/glv.rs

@@ -32,6 +32,7 @@

const B2: Secp256K1Scalar = Secp256K1Scalar([16747920425669159701, 3496713202691238861, 0, 0]); /// Algorithm 15.41 in Handbook of Elliptic and Hyperelliptic Curve Cryptography. +/// /// Decompose a scalar `k` into two small scalars `k1, k2` with `|k1|, |k2| < √p` that satisfy /// `k1 + s * k2 = k`. /// Returns `(|k1|, |k2|, k1 < 0, k2 < 0)`.

@@ -76,6 +77,7 @@ (k1, k2, k1_neg, k2_neg)

} /// See Section 15.2.1 in Handbook of Elliptic and Hyperelliptic Curve Cryptography. +/// /// GLV scalar multiplication `k * P = k1 * P + k2 * psi(P)`, where `k = k1 + s * k2` is the /// decomposition computed in `decompose_secp256k1_scalar(k)` and `psi` is the Secp256k1 /// endomorphism `psi: (x, y) |-> (beta * x, y)` equivalent to scalar multiplication by `s`.
M src/gadgets/biguint.rs → src/gadgets/biguint.rs

@@ -1,6 +1,10 @@

+use alloc::string::String; use alloc::vec; use alloc::vec::Vec; +use anyhow::Result; use core::marker::PhantomData; +use plonky2::plonk::circuit_data::CommonCircuitData; +use plonky2::util::serialization::{IoResult, Read, Write}; use num::{BigUint, Integer, Zero}; use plonky2::field::extension::Extendable;

@@ -26,6 +30,16 @@ }

pub fn get_limb(&self, i: usize) -> U32Target { self.limbs[i] + } + + pub fn to_target_vec(&self) -> Vec<Target> { + self.limbs.iter().map(|t| t.0).collect() + } + + pub fn from_target_vec(ts: &[Target]) -> Self { + Self { + limbs: ts.iter().map(|t| U32Target(*t)).collect(), + } } }

@@ -274,7 +288,7 @@ }

pub trait WitnessBigUint<F: PrimeField64>: Witness<F> { fn get_biguint_target(&self, target: BigUintTarget) -> BigUint; - fn set_biguint_target(&mut self, target: &BigUintTarget, value: &BigUint); + fn set_biguint_target(&mut self, target: &BigUintTarget, value: &BigUint) -> Result<()>; } impl<T: Witness<F>, F: PrimeField64> WitnessBigUint<F> for T {

@@ -288,28 +302,32 @@ (acc << 32) + self.get_target(limb.0).to_canonical_biguint()

}) } - fn set_biguint_target(&mut self, target: &BigUintTarget, value: &BigUint) { + fn set_biguint_target(&mut self, target: &BigUintTarget, value: &BigUint) -> Result<()> { let mut limbs = value.to_u32_digits(); assert!(target.num_limbs() >= limbs.len()); limbs.resize(target.num_limbs(), 0); for i in 0..target.num_limbs() { - self.set_u32_target(target.limbs[i], limbs[i]); + self.set_u32_target(target.limbs[i], limbs[i])?; } + + Ok(()) } } pub trait GeneratedValuesBigUint<F: PrimeField> { - fn set_biguint_target(&mut self, target: &BigUintTarget, value: &BigUint); + fn set_biguint_target(&mut self, target: &BigUintTarget, value: &BigUint) -> Result<()>; } impl<F: PrimeField> GeneratedValuesBigUint<F> for GeneratedValues<F> { - fn set_biguint_target(&mut self, target: &BigUintTarget, value: &BigUint) { + fn set_biguint_target(&mut self, target: &BigUintTarget, value: &BigUint) -> Result<()> { let mut limbs = value.to_u32_digits(); assert!(target.num_limbs() >= limbs.len()); limbs.resize(target.num_limbs(), 0); for i in 0..target.num_limbs() { - self.set_u32_target(target.get_limb(i), limbs[i]); + self.set_u32_target(target.get_limb(i), limbs[i])?; } + + Ok(()) } }

@@ -322,9 +340,13 @@ rem: BigUintTarget,

_phantom: PhantomData<F>, } -impl<F: RichField + Extendable<D>, const D: usize> SimpleGenerator<F> +impl<F: RichField + Extendable<D>, const D: usize> SimpleGenerator<F, D> for BigUintDivRemGenerator<F, D> { + fn id(&self) -> String { + "BigUintDivRemGenerator".into() + } + fn dependencies(&self) -> Vec<Target> { self.a .limbs

@@ -334,13 +356,46 @@ .map(|&l| l.0)

.collect() } - fn run_once(&self, witness: &PartitionWitness<F>, out_buffer: &mut GeneratedValues<F>) { + fn run_once( + &self, + witness: &PartitionWitness<F>, + out_buffer: &mut GeneratedValues<F>, + ) -> Result<()> { let a = witness.get_biguint_target(self.a.clone()); let b = witness.get_biguint_target(self.b.clone()); let (div, rem) = a.div_rem(&b); - out_buffer.set_biguint_target(&self.div, &div); - out_buffer.set_biguint_target(&self.rem, &rem); + out_buffer.set_biguint_target(&self.div, &div)?; + out_buffer.set_biguint_target(&self.rem, &rem) + } + + fn serialize(&self, dst: &mut Vec<u8>, _common_data: &CommonCircuitData<F, D>) -> IoResult<()> { + // Serialise each biguint target's limbs. + dst.write_target_vec(&self.a.to_target_vec())?; + dst.write_target_vec(&self.b.to_target_vec())?; + dst.write_target_vec(&self.div.to_target_vec())?; + dst.write_target_vec(&self.rem.to_target_vec()) + } + + fn deserialize( + src: &mut plonky2::util::serialization::Buffer, + _common_data: &CommonCircuitData<F, D>, + ) -> IoResult<Self> + where + Self: Sized, + { + let a = BigUintTarget::from_target_vec(&src.read_target_vec()?); + let b = BigUintTarget::from_target_vec(&src.read_target_vec()?); + let div = BigUintTarget::from_target_vec(&src.read_target_vec()?); + let rem = BigUintTarget::from_target_vec(&src.read_target_vec()?); + + Ok(Self { + a, + b, + div, + rem, + _phantom: PhantomData, + }) } }

@@ -378,9 +433,9 @@ let z = builder.add_biguint(&x, &y);

let expected_z = builder.add_virtual_biguint_target(expected_z_value.to_u32_digits().len()); builder.connect_biguint(&z, &expected_z); - pw.set_biguint_target(&x, &x_value); - pw.set_biguint_target(&y, &y_value); - pw.set_biguint_target(&expected_z, &expected_z_value); + pw.set_biguint_target(&x, &x_value)?; + pw.set_biguint_target(&y, &y_value)?; + pw.set_biguint_target(&expected_z, &expected_z_value)?; let data = builder.build::<C>(); let proof = data.prove(pw).unwrap();

@@ -438,9 +493,9 @@ let z = builder.mul_biguint(&x, &y);

let expected_z = builder.add_virtual_biguint_target(expected_z_value.to_u32_digits().len()); builder.connect_biguint(&z, &expected_z); - pw.set_biguint_target(&x, &x_value); - pw.set_biguint_target(&y, &y_value); - pw.set_biguint_target(&expected_z, &expected_z_value); + pw.set_biguint_target(&x, &x_value)?; + pw.set_biguint_target(&y, &y_value)?; + pw.set_biguint_target(&expected_z, &expected_z_value)?; let data = builder.build::<C>(); let proof = data.prove(pw).unwrap();
M src/gadgets/curve_fixed_base.rs → src/gadgets/curve_fixed_base.rs

@@ -102,7 +102,7 @@ let res_expected = builder.constant_affine_point(res);

builder.curve_assert_valid(&res_expected); let n_target = builder.add_virtual_nonnative_target::<Secp256K1Scalar>(); - pw.set_biguint_target(&n_target.value, &n.to_canonical_biguint()); + pw.set_biguint_target(&n_target.value, &n.to_canonical_biguint())?; let res_target = fixed_base_curve_mul_circuit(&mut builder, g, &n_target); builder.curve_assert_valid(&res_target);
M src/gadgets/glv.rs → src/gadgets/glv.rs

@@ -1,5 +1,9 @@

+use alloc::string::String; use alloc::vec::Vec; +use anyhow::Result; use core::marker::PhantomData; +use plonky2::plonk::circuit_data::CommonCircuitData; +use plonky2::util::serialization::{Buffer, IoResult, Read, Write}; use plonky2::field::extension::Extendable; use plonky2::field::secp256k1_base::Secp256K1Base;

@@ -109,24 +113,60 @@ k2_neg: BoolTarget,

_phantom: PhantomData<F>, } -impl<F: RichField + Extendable<D>, const D: usize> SimpleGenerator<F> +impl<F: RichField + Extendable<D>, const D: usize> SimpleGenerator<F, D> for GLVDecompositionGenerator<F, D> { + fn id(&self) -> String { + "GLVDecompositionGenerator".into() + } + fn dependencies(&self) -> Vec<Target> { self.k.value.limbs.iter().map(|l| l.0).collect() } - fn run_once(&self, witness: &PartitionWitness<F>, out_buffer: &mut GeneratedValues<F>) { + fn run_once( + &self, + witness: &PartitionWitness<F>, + out_buffer: &mut GeneratedValues<F>, + ) -> Result<()> { let k = Secp256K1Scalar::from_noncanonical_biguint( witness.get_biguint_target(self.k.value.clone()), ); let (k1, k2, k1_neg, k2_neg) = decompose_secp256k1_scalar(k); - out_buffer.set_biguint_target(&self.k1.value, &k1.to_canonical_biguint()); - out_buffer.set_biguint_target(&self.k2.value, &k2.to_canonical_biguint()); - out_buffer.set_bool_target(self.k1_neg, k1_neg); - out_buffer.set_bool_target(self.k2_neg, k2_neg); + out_buffer.set_biguint_target(&self.k1.value, &k1.to_canonical_biguint())?; + out_buffer.set_biguint_target(&self.k2.value, &k2.to_canonical_biguint())?; + out_buffer.set_bool_target(self.k1_neg, k1_neg)?; + out_buffer.set_bool_target(self.k2_neg, k2_neg) + } + + fn serialize(&self, dst: &mut Vec<u8>, _common_data: &CommonCircuitData<F, D>) -> IoResult<()> { + dst.write_target_vec(&self.k.to_target_vec())?; + dst.write_target_vec(&self.k1.to_target_vec())?; + dst.write_target_vec(&self.k2.to_target_vec())?; + dst.write_target_bool(self.k1_neg)?; + dst.write_target_bool(self.k2_neg) + } + + fn deserialize(src: &mut Buffer, _common_data: &CommonCircuitData<F, D>) -> IoResult<Self> + where + Self: Sized, + { + let k = NonNativeTarget::from_target_vec(&src.read_target_vec()?); + let k1 = NonNativeTarget::from_target_vec(&src.read_target_vec()?); + let k2 = NonNativeTarget::from_target_vec(&src.read_target_vec()?); + let k1_neg = src.read_target_bool()?; + let k2_neg = src.read_target_bool()?; + + Ok(Self { + k, + k1, + k2, + k1_neg, + k2_neg, + _phantom: PhantomData, + }) } }
M src/gadgets/nonnative.rs → src/gadgets/nonnative.rs

@@ -1,6 +1,11 @@

+use alloc::string::String; use alloc::vec; use alloc::vec::Vec; +use anyhow::Result; use core::marker::PhantomData; +use num::integer::div_ceil; +use plonky2::plonk::circuit_data::CommonCircuitData; +use plonky2::util::serialization::{Buffer, IoError, IoResult, Read, Write}; use num::{BigUint, Integer, One, Zero}; use plonky2::field::extension::Extendable;

@@ -10,7 +15,6 @@ use plonky2::iop::generator::{GeneratedValues, SimpleGenerator};

use plonky2::iop::target::{BoolTarget, Target}; use plonky2::iop::witness::{PartitionWitness, WitnessWrite}; use plonky2::plonk::circuit_builder::CircuitBuilder; -use plonky2::util::ceil_div_usize; use plonky2_u32::gadgets::arithmetic_u32::{CircuitBuilderU32, U32Target}; use plonky2_u32::gadgets::range_check::range_check_u32_circuit; use plonky2_u32::witness::GeneratedValuesU32;

@@ -25,9 +29,22 @@ pub(crate) value: BigUintTarget,

pub(crate) _phantom: PhantomData<FF>, } +impl<FF: Field> NonNativeTarget<FF> { + pub fn to_target_vec(&self) -> Vec<Target> { + self.value.to_target_vec() + } + + pub fn from_target_vec(ts: &[Target]) -> Self { + Self { + value: BigUintTarget::from_target_vec(ts), + _phantom: PhantomData, + } + } +} + pub trait CircuitBuilderNonNative<F: RichField + Extendable<D>, const D: usize> { fn num_nonnative_limbs<FF: Field>() -> usize { - ceil_div_usize(FF::BITS, 32) + div_ceil(FF::BITS, 32) } fn biguint_to_nonnative<FF: Field>(&mut self, x: &BigUintTarget) -> NonNativeTarget<FF>;

@@ -122,7 +139,7 @@ impl<F: RichField + Extendable<D>, const D: usize> CircuitBuilderNonNative<F, D>

for CircuitBuilder<F, D> { fn num_nonnative_limbs<FF: Field>() -> usize { - ceil_div_usize(FF::BITS, 32) + div_ceil(FF::BITS, 32) } fn biguint_to_nonnative<FF: Field>(&mut self, x: &BigUintTarget) -> NonNativeTarget<FF> {

@@ -454,9 +471,13 @@ overflow: BoolTarget,

_phantom: PhantomData<F>, } -impl<F: RichField + Extendable<D>, const D: usize, FF: PrimeField> SimpleGenerator<F> +impl<F: RichField + Extendable<D>, const D: usize, FF: PrimeField> SimpleGenerator<F, D> for NonNativeAdditionGenerator<F, D, FF> { + fn id(&self) -> String { + "NonNativeAdditionGenerator".into() + } + fn dependencies(&self) -> Vec<Target> { self.a .value

@@ -468,7 +489,11 @@ .map(|l| l.0)

.collect() } - fn run_once(&self, witness: &PartitionWitness<F>, out_buffer: &mut GeneratedValues<F>) { + fn run_once( + &self, + witness: &PartitionWitness<F>, + out_buffer: &mut GeneratedValues<F>, + ) -> Result<()> { let a = FF::from_noncanonical_biguint(witness.get_biguint_target(self.a.value.clone())); let b = FF::from_noncanonical_biguint(witness.get_biguint_target(self.b.value.clone())); let a_biguint = a.to_canonical_biguint();

@@ -481,8 +506,33 @@ } else {

(false, sum_biguint) }; - out_buffer.set_biguint_target(&self.sum.value, &sum_reduced); - out_buffer.set_bool_target(self.overflow, overflow); + out_buffer.set_biguint_target(&self.sum.value, &sum_reduced)?; + out_buffer.set_bool_target(self.overflow, overflow) + } + + fn serialize(&self, dst: &mut Vec<u8>, _common_data: &CommonCircuitData<F, D>) -> IoResult<()> { + dst.write_target_vec(&self.a.to_target_vec())?; + dst.write_target_vec(&self.b.to_target_vec())?; + dst.write_target_vec(&self.sum.to_target_vec())?; + dst.write_target_bool(self.overflow) + } + + fn deserialize(src: &mut Buffer, _common_data: &CommonCircuitData<F, D>) -> IoResult<Self> + where + Self: Sized, + { + let a = NonNativeTarget::from_target_vec(&src.read_target_vec()?); + let b = NonNativeTarget::from_target_vec(&src.read_target_vec()?); + let sum = NonNativeTarget::from_target_vec(&src.read_target_vec()?); + let overflow = src.read_target_bool()?; + + Ok(Self { + a, + b, + sum, + overflow, + _phantom: PhantomData, + }) } }

@@ -495,9 +545,13 @@ overflow: U32Target,

_phantom: PhantomData<F>, } -impl<F: RichField + Extendable<D>, const D: usize, FF: PrimeField> SimpleGenerator<F> +impl<F: RichField + Extendable<D>, const D: usize, FF: PrimeField> SimpleGenerator<F, D> for NonNativeMultipleAddsGenerator<F, D, FF> { + fn id(&self) -> String { + "NonNativeMultipleAddsGenerator".into() + } + fn dependencies(&self) -> Vec<Target> { self.summands .iter()

@@ -505,7 +559,11 @@ .flat_map(|summand| summand.value.limbs.iter().map(|limb| limb.0))

.collect() } - fn run_once(&self, witness: &PartitionWitness<F>, out_buffer: &mut GeneratedValues<F>) { + fn run_once( + &self, + witness: &PartitionWitness<F>, + out_buffer: &mut GeneratedValues<F>, + ) -> Result<()> { let summands: Vec<_> = self .summands .iter()

@@ -526,8 +584,42 @@ let modulus = FF::order();

let (overflow_biguint, sum_reduced) = sum_biguint.div_rem(&modulus); let overflow = overflow_biguint.to_u64_digits()[0] as u32; - out_buffer.set_biguint_target(&self.sum.value, &sum_reduced); - out_buffer.set_u32_target(self.overflow, overflow); + out_buffer.set_biguint_target(&self.sum.value, &sum_reduced)?; + out_buffer.set_u32_target(self.overflow, overflow) + } + + fn serialize(&self, dst: &mut Vec<u8>, _common_data: &CommonCircuitData<F, D>) -> IoResult<()> { + let summands_len = self.summands.len(); + dst.write_usize(summands_len)?; + self.summands + .iter() + .try_for_each(|summand| dst.write_target_vec(&summand.to_target_vec()))?; + + dst.write_target_vec(&self.sum.to_target_vec())?; + dst.write_target(self.overflow.0) + } + + fn deserialize(src: &mut Buffer, _common_data: &CommonCircuitData<F, D>) -> IoResult<Self> + where + Self: Sized, + { + let summands_len = src.read_usize()?; + let summands: Vec<_> = (0..summands_len) + .map(|_| { + Ok::<_, IoError>(NonNativeTarget::<FF>::from_target_vec( + &src.read_target_vec()?, + )) + }) + .collect::<IoResult<_>>()?; + let sum = NonNativeTarget::from_target_vec(&src.read_target_vec()?); + let overflow = U32Target(src.read_target()?); + + Ok(Self { + summands, + sum, + overflow, + _phantom: PhantomData, + }) } }

@@ -540,9 +632,13 @@ overflow: BoolTarget,

_phantom: PhantomData<F>, } -impl<F: RichField + Extendable<D>, const D: usize, FF: PrimeField> SimpleGenerator<F> +impl<F: RichField + Extendable<D>, const D: usize, FF: PrimeField> SimpleGenerator<F, D> for NonNativeSubtractionGenerator<F, D, FF> { + fn id(&self) -> String { + "NonNativeSubtractionGenerator".into() + } + fn dependencies(&self) -> Vec<Target> { self.a .value

@@ -554,7 +650,11 @@ .map(|l| l.0)

.collect() } - fn run_once(&self, witness: &PartitionWitness<F>, out_buffer: &mut GeneratedValues<F>) { + fn run_once( + &self, + witness: &PartitionWitness<F>, + out_buffer: &mut GeneratedValues<F>, + ) -> Result<()> { let a = FF::from_noncanonical_biguint(witness.get_biguint_target(self.a.value.clone())); let b = FF::from_noncanonical_biguint(witness.get_biguint_target(self.b.value.clone())); let a_biguint = a.to_canonical_biguint();

@@ -567,8 +667,33 @@ } else {

(modulus + a_biguint - b_biguint, true) }; - out_buffer.set_biguint_target(&self.diff.value, &diff_biguint); - out_buffer.set_bool_target(self.overflow, overflow); + out_buffer.set_biguint_target(&self.diff.value, &diff_biguint)?; + out_buffer.set_bool_target(self.overflow, overflow) + } + + fn serialize(&self, dst: &mut Vec<u8>, _common_data: &CommonCircuitData<F, D>) -> IoResult<()> { + dst.write_target_vec(&self.a.to_target_vec())?; + dst.write_target_vec(&self.b.to_target_vec())?; + dst.write_target_vec(&self.diff.to_target_vec())?; + dst.write_target_bool(self.overflow) + } + + fn deserialize(src: &mut Buffer, _common_data: &CommonCircuitData<F, D>) -> IoResult<Self> + where + Self: Sized, + { + let a = NonNativeTarget::from_target_vec(&src.read_target_vec()?); + let b = NonNativeTarget::from_target_vec(&src.read_target_vec()?); + let diff = NonNativeTarget::from_target_vec(&src.read_target_vec()?); + let overflow = src.read_target_bool()?; + + Ok(Self { + a, + b, + diff, + overflow, + _phantom: PhantomData, + }) } }

@@ -581,9 +706,13 @@ overflow: BigUintTarget,

_phantom: PhantomData<F>, } -impl<F: RichField + Extendable<D>, const D: usize, FF: PrimeField> SimpleGenerator<F> +impl<F: RichField + Extendable<D>, const D: usize, FF: PrimeField> SimpleGenerator<F, D> for NonNativeMultiplicationGenerator<F, D, FF> { + fn id(&self) -> String { + "NonNativeMultiplicationGenerator".into() + } + fn dependencies(&self) -> Vec<Target> { self.a .value

@@ -595,7 +724,11 @@ .map(|l| l.0)

.collect() } - fn run_once(&self, witness: &PartitionWitness<F>, out_buffer: &mut GeneratedValues<F>) { + fn run_once( + &self, + witness: &PartitionWitness<F>, + out_buffer: &mut GeneratedValues<F>, + ) -> Result<()> { let a = FF::from_noncanonical_biguint(witness.get_biguint_target(self.a.value.clone())); let b = FF::from_noncanonical_biguint(witness.get_biguint_target(self.b.value.clone())); let a_biguint = a.to_canonical_biguint();

@@ -606,8 +739,33 @@

let modulus = FF::order(); let (overflow_biguint, prod_reduced) = prod_biguint.div_rem(&modulus); - out_buffer.set_biguint_target(&self.prod.value, &prod_reduced); - out_buffer.set_biguint_target(&self.overflow, &overflow_biguint); + out_buffer.set_biguint_target(&self.prod.value, &prod_reduced)?; + out_buffer.set_biguint_target(&self.overflow, &overflow_biguint) + } + + fn serialize(&self, dst: &mut Vec<u8>, _common_data: &CommonCircuitData<F, D>) -> IoResult<()> { + dst.write_target_vec(&self.a.to_target_vec())?; + dst.write_target_vec(&self.b.to_target_vec())?; + dst.write_target_vec(&self.prod.to_target_vec())?; + dst.write_target_vec(&self.overflow.to_target_vec()) + } + + fn deserialize(src: &mut Buffer, _common_data: &CommonCircuitData<F, D>) -> IoResult<Self> + where + Self: Sized, + { + let a = NonNativeTarget::from_target_vec(&src.read_target_vec()?); + let b = NonNativeTarget::from_target_vec(&src.read_target_vec()?); + let prod = NonNativeTarget::from_target_vec(&src.read_target_vec()?); + let overflow = BigUintTarget::from_target_vec(&src.read_target_vec()?); + + Ok(Self { + a, + b, + prod, + overflow, + _phantom: PhantomData, + }) } }

@@ -619,14 +777,22 @@ div: BigUintTarget,

_phantom: PhantomData<F>, } -impl<F: RichField + Extendable<D>, const D: usize, FF: PrimeField> SimpleGenerator<F> +impl<F: RichField + Extendable<D>, const D: usize, FF: PrimeField> SimpleGenerator<F, D> for NonNativeInverseGenerator<F, D, FF> { + fn id(&self) -> String { + "NonNativeInverseGenerator".into() + } + fn dependencies(&self) -> Vec<Target> { self.x.value.limbs.iter().map(|&l| l.0).collect() } - fn run_once(&self, witness: &PartitionWitness<F>, out_buffer: &mut GeneratedValues<F>) { + fn run_once( + &self, + witness: &PartitionWitness<F>, + out_buffer: &mut GeneratedValues<F>, + ) -> Result<()> { let x = FF::from_noncanonical_biguint(witness.get_biguint_target(self.x.value.clone())); let inv = x.inverse();

@@ -636,8 +802,30 @@ let prod = x_biguint * &inv_biguint;

let modulus = FF::order(); let (div, _rem) = prod.div_rem(&modulus); - out_buffer.set_biguint_target(&self.div, &div); - out_buffer.set_biguint_target(&self.inv, &inv_biguint); + out_buffer.set_biguint_target(&self.div, &div)?; + out_buffer.set_biguint_target(&self.inv, &inv_biguint) + } + + fn serialize(&self, dst: &mut Vec<u8>, _common_data: &CommonCircuitData<F, D>) -> IoResult<()> { + dst.write_target_vec(&self.x.to_target_vec())?; + dst.write_target_vec(&self.inv.to_target_vec())?; + dst.write_target_vec(&self.div.to_target_vec()) + } + + fn deserialize(src: &mut Buffer, _common_data: &CommonCircuitData<F, D>) -> IoResult<Self> + where + Self: Sized, + { + let x = NonNativeTarget::from_target_vec(&src.read_target_vec()?); + let inv = BigUintTarget::from_target_vec(&src.read_target_vec()?); + let div = BigUintTarget::from_target_vec(&src.read_target_vec()?); + + Ok(Self { + x, + inv, + div, + _phantom: PhantomData, + }) } }