mirror of
https://github.com/arnaucube/plonky2-ecdsa.git
synced 2026-01-12 00:51:31 +01:00
Fix build
This commit is contained in:
@@ -11,10 +11,10 @@ parallel = ["plonky2_maybe_rayon/parallel", "plonky2/parallel"]
|
|||||||
[dependencies]
|
[dependencies]
|
||||||
anyhow = { version = "1.0.40", default-features = false }
|
anyhow = { version = "1.0.40", default-features = false }
|
||||||
itertools = { version = "0.10.0", 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 }
|
num = { version = "0.4.0", default-features = false }
|
||||||
plonky2 = { version = "0.1.2", default-features = false }
|
plonky2 = { git = "https://github.com/0xPolygonZero/plonky2" }
|
||||||
plonky2_u32 = { version = "0.1.0", default-features = false }
|
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"] }
|
serde = { version = "1.0", default-features = false, features = ["derive"] }
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
|
|||||||
@@ -40,7 +40,7 @@ pub fn msm_precompute<C: Curve>(
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn precompute_single_generator<C: Curve>(g: ProjectivePoint<C>, w: usize) -> Vec<AffinePoint<C>> {
|
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);
|
let mut powers: Vec<ProjectivePoint<C>> = Vec::with_capacity(digits);
|
||||||
powers.push(g);
|
powers.push(g);
|
||||||
for i in 1..digits {
|
for i in 1..digits {
|
||||||
@@ -68,7 +68,7 @@ pub fn msm_execute<C: Curve>(
|
|||||||
) -> ProjectivePoint<C> {
|
) -> ProjectivePoint<C> {
|
||||||
assert_eq!(precomputation.powers_per_generator.len(), scalars.len());
|
assert_eq!(precomputation.powers_per_generator.len(), scalars.len());
|
||||||
let w = precomputation.w;
|
let w = precomputation.w;
|
||||||
let digits = (C::ScalarField::BITS + w - 1) / w;
|
let digits = C::ScalarField::BITS.div_ceil(w);
|
||||||
let base = 1 << w;
|
let base = 1 << w;
|
||||||
|
|
||||||
// This is a variant of Yao's method, adapted to the multi-scalar setting. Because we use
|
// This is a variant of Yao's method, adapted to the multi-scalar setting. Because we use
|
||||||
@@ -107,7 +107,7 @@ pub fn msm_execute_parallel<C: Curve>(
|
|||||||
) -> ProjectivePoint<C> {
|
) -> ProjectivePoint<C> {
|
||||||
assert_eq!(precomputation.powers_per_generator.len(), scalars.len());
|
assert_eq!(precomputation.powers_per_generator.len(), scalars.len());
|
||||||
let w = precomputation.w;
|
let w = precomputation.w;
|
||||||
let digits = (C::ScalarField::BITS + w - 1) / w;
|
let digits = C::ScalarField::BITS.div_ceil(w);
|
||||||
let base = 1 << w;
|
let base = 1 << w;
|
||||||
|
|
||||||
// This is a variant of Yao's method, adapted to the multi-scalar setting. Because we use
|
// This is a variant of Yao's method, adapted to the multi-scalar setting. Because we use
|
||||||
@@ -158,7 +158,7 @@ pub fn msm_execute_parallel<C: Curve>(
|
|||||||
|
|
||||||
pub(crate) fn to_digits<C: Curve>(x: &C::ScalarField, w: usize) -> Vec<usize> {
|
pub(crate) fn to_digits<C: Curve>(x: &C::ScalarField, w: usize) -> Vec<usize> {
|
||||||
let scalar_bits = C::ScalarField::BITS;
|
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.
|
// Convert x to a bool array.
|
||||||
let x_canonical: Vec<_> = x
|
let x_canonical: Vec<_> = x
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ const WINDOW_BITS: usize = 4;
|
|||||||
const BASE: usize = 1 << WINDOW_BITS;
|
const BASE: usize = 1 << WINDOW_BITS;
|
||||||
|
|
||||||
fn digits_per_scalar<C: Curve>() -> usize {
|
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,
|
/// Precomputed state used for scalar x ProjectivePoint multiplications,
|
||||||
|
|||||||
@@ -32,6 +32,7 @@ const A2: Secp256K1Scalar = Secp256K1Scalar([6323353552219852760, 14980988506747
|
|||||||
const B2: Secp256K1Scalar = Secp256K1Scalar([16747920425669159701, 3496713202691238861, 0, 0]);
|
const B2: Secp256K1Scalar = Secp256K1Scalar([16747920425669159701, 3496713202691238861, 0, 0]);
|
||||||
|
|
||||||
/// Algorithm 15.41 in Handbook of Elliptic and Hyperelliptic Curve Cryptography.
|
/// 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
|
/// Decompose a scalar `k` into two small scalars `k1, k2` with `|k1|, |k2| < √p` that satisfy
|
||||||
/// `k1 + s * k2 = k`.
|
/// `k1 + s * k2 = k`.
|
||||||
/// Returns `(|k1|, |k2|, k1 < 0, k2 < 0)`.
|
/// Returns `(|k1|, |k2|, k1 < 0, k2 < 0)`.
|
||||||
@@ -76,6 +77,7 @@ pub fn decompose_secp256k1_scalar(
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// See Section 15.2.1 in Handbook of Elliptic and Hyperelliptic Curve Cryptography.
|
/// 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
|
/// 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
|
/// 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`.
|
/// endomorphism `psi: (x, y) |-> (beta * x, y)` equivalent to scalar multiplication by `s`.
|
||||||
|
|||||||
@@ -1,6 +1,10 @@
|
|||||||
|
use alloc::string::String;
|
||||||
use alloc::vec;
|
use alloc::vec;
|
||||||
use alloc::vec::Vec;
|
use alloc::vec::Vec;
|
||||||
|
use anyhow::Result;
|
||||||
use core::marker::PhantomData;
|
use core::marker::PhantomData;
|
||||||
|
use plonky2::plonk::circuit_data::CommonCircuitData;
|
||||||
|
use plonky2::util::serialization::{IoResult, Read, Write};
|
||||||
|
|
||||||
use num::{BigUint, Integer, Zero};
|
use num::{BigUint, Integer, Zero};
|
||||||
use plonky2::field::extension::Extendable;
|
use plonky2::field::extension::Extendable;
|
||||||
@@ -27,6 +31,16 @@ impl BigUintTarget {
|
|||||||
pub fn get_limb(&self, i: usize) -> U32Target {
|
pub fn get_limb(&self, i: usize) -> U32Target {
|
||||||
self.limbs[i]
|
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(),
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait CircuitBuilderBiguint<F: RichField + Extendable<D>, const D: usize> {
|
pub trait CircuitBuilderBiguint<F: RichField + Extendable<D>, const D: usize> {
|
||||||
@@ -274,7 +288,7 @@ impl<F: RichField + Extendable<D>, const D: usize> CircuitBuilderBiguint<F, D>
|
|||||||
|
|
||||||
pub trait WitnessBigUint<F: PrimeField64>: Witness<F> {
|
pub trait WitnessBigUint<F: PrimeField64>: Witness<F> {
|
||||||
fn get_biguint_target(&self, target: BigUintTarget) -> BigUint;
|
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 {
|
impl<T: Witness<F>, F: PrimeField64> WitnessBigUint<F> for T {
|
||||||
@@ -288,28 +302,32 @@ impl<T: Witness<F>, F: PrimeField64> WitnessBigUint<F> for T {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
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();
|
let mut limbs = value.to_u32_digits();
|
||||||
assert!(target.num_limbs() >= limbs.len());
|
assert!(target.num_limbs() >= limbs.len());
|
||||||
limbs.resize(target.num_limbs(), 0);
|
limbs.resize(target.num_limbs(), 0);
|
||||||
for i in 0..target.num_limbs() {
|
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> {
|
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> {
|
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();
|
let mut limbs = value.to_u32_digits();
|
||||||
assert!(target.num_limbs() >= limbs.len());
|
assert!(target.num_limbs() >= limbs.len());
|
||||||
limbs.resize(target.num_limbs(), 0);
|
limbs.resize(target.num_limbs(), 0);
|
||||||
for i in 0..target.num_limbs() {
|
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 @@ struct BigUintDivRemGenerator<F: RichField + Extendable<D>, const D: usize> {
|
|||||||
_phantom: PhantomData<F>,
|
_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>
|
for BigUintDivRemGenerator<F, D>
|
||||||
{
|
{
|
||||||
|
fn id(&self) -> String {
|
||||||
|
"BigUintDivRemGenerator".into()
|
||||||
|
}
|
||||||
|
|
||||||
fn dependencies(&self) -> Vec<Target> {
|
fn dependencies(&self) -> Vec<Target> {
|
||||||
self.a
|
self.a
|
||||||
.limbs
|
.limbs
|
||||||
@@ -334,13 +356,46 @@ impl<F: RichField + Extendable<D>, const D: usize> SimpleGenerator<F>
|
|||||||
.collect()
|
.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 a = witness.get_biguint_target(self.a.clone());
|
||||||
let b = witness.get_biguint_target(self.b.clone());
|
let b = witness.get_biguint_target(self.b.clone());
|
||||||
let (div, rem) = a.div_rem(&b);
|
let (div, rem) = a.div_rem(&b);
|
||||||
|
|
||||||
out_buffer.set_biguint_target(&self.div, &div);
|
out_buffer.set_biguint_target(&self.div, &div)?;
|
||||||
out_buffer.set_biguint_target(&self.rem, &rem);
|
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 @@ mod tests {
|
|||||||
let expected_z = builder.add_virtual_biguint_target(expected_z_value.to_u32_digits().len());
|
let expected_z = builder.add_virtual_biguint_target(expected_z_value.to_u32_digits().len());
|
||||||
builder.connect_biguint(&z, &expected_z);
|
builder.connect_biguint(&z, &expected_z);
|
||||||
|
|
||||||
pw.set_biguint_target(&x, &x_value);
|
pw.set_biguint_target(&x, &x_value)?;
|
||||||
pw.set_biguint_target(&y, &y_value);
|
pw.set_biguint_target(&y, &y_value)?;
|
||||||
pw.set_biguint_target(&expected_z, &expected_z_value);
|
pw.set_biguint_target(&expected_z, &expected_z_value)?;
|
||||||
|
|
||||||
let data = builder.build::<C>();
|
let data = builder.build::<C>();
|
||||||
let proof = data.prove(pw).unwrap();
|
let proof = data.prove(pw).unwrap();
|
||||||
@@ -438,9 +493,9 @@ mod tests {
|
|||||||
let expected_z = builder.add_virtual_biguint_target(expected_z_value.to_u32_digits().len());
|
let expected_z = builder.add_virtual_biguint_target(expected_z_value.to_u32_digits().len());
|
||||||
builder.connect_biguint(&z, &expected_z);
|
builder.connect_biguint(&z, &expected_z);
|
||||||
|
|
||||||
pw.set_biguint_target(&x, &x_value);
|
pw.set_biguint_target(&x, &x_value)?;
|
||||||
pw.set_biguint_target(&y, &y_value);
|
pw.set_biguint_target(&y, &y_value)?;
|
||||||
pw.set_biguint_target(&expected_z, &expected_z_value);
|
pw.set_biguint_target(&expected_z, &expected_z_value)?;
|
||||||
|
|
||||||
let data = builder.build::<C>();
|
let data = builder.build::<C>();
|
||||||
let proof = data.prove(pw).unwrap();
|
let proof = data.prove(pw).unwrap();
|
||||||
|
|||||||
@@ -102,7 +102,7 @@ mod tests {
|
|||||||
builder.curve_assert_valid(&res_expected);
|
builder.curve_assert_valid(&res_expected);
|
||||||
|
|
||||||
let n_target = builder.add_virtual_nonnative_target::<Secp256K1Scalar>();
|
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);
|
let res_target = fixed_base_curve_mul_circuit(&mut builder, g, &n_target);
|
||||||
builder.curve_assert_valid(&res_target);
|
builder.curve_assert_valid(&res_target);
|
||||||
|
|||||||
@@ -1,5 +1,9 @@
|
|||||||
|
use alloc::string::String;
|
||||||
use alloc::vec::Vec;
|
use alloc::vec::Vec;
|
||||||
|
use anyhow::Result;
|
||||||
use core::marker::PhantomData;
|
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::extension::Extendable;
|
||||||
use plonky2::field::secp256k1_base::Secp256K1Base;
|
use plonky2::field::secp256k1_base::Secp256K1Base;
|
||||||
@@ -109,24 +113,60 @@ struct GLVDecompositionGenerator<F: RichField + Extendable<D>, const D: usize> {
|
|||||||
_phantom: PhantomData<F>,
|
_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>
|
for GLVDecompositionGenerator<F, D>
|
||||||
{
|
{
|
||||||
|
fn id(&self) -> String {
|
||||||
|
"GLVDecompositionGenerator".into()
|
||||||
|
}
|
||||||
|
|
||||||
fn dependencies(&self) -> Vec<Target> {
|
fn dependencies(&self) -> Vec<Target> {
|
||||||
self.k.value.limbs.iter().map(|l| l.0).collect()
|
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(
|
let k = Secp256K1Scalar::from_noncanonical_biguint(
|
||||||
witness.get_biguint_target(self.k.value.clone()),
|
witness.get_biguint_target(self.k.value.clone()),
|
||||||
);
|
);
|
||||||
|
|
||||||
let (k1, k2, k1_neg, k2_neg) = decompose_secp256k1_scalar(k);
|
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.k1.value, &k1.to_canonical_biguint())?;
|
||||||
out_buffer.set_biguint_target(&self.k2.value, &k2.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.k1_neg, k1_neg)?;
|
||||||
out_buffer.set_bool_target(self.k2_neg, k2_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,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,11 @@
|
|||||||
|
use alloc::string::String;
|
||||||
use alloc::vec;
|
use alloc::vec;
|
||||||
use alloc::vec::Vec;
|
use alloc::vec::Vec;
|
||||||
|
use anyhow::Result;
|
||||||
use core::marker::PhantomData;
|
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 num::{BigUint, Integer, One, Zero};
|
||||||
use plonky2::field::extension::Extendable;
|
use plonky2::field::extension::Extendable;
|
||||||
@@ -10,7 +15,6 @@ use plonky2::iop::generator::{GeneratedValues, SimpleGenerator};
|
|||||||
use plonky2::iop::target::{BoolTarget, Target};
|
use plonky2::iop::target::{BoolTarget, Target};
|
||||||
use plonky2::iop::witness::{PartitionWitness, WitnessWrite};
|
use plonky2::iop::witness::{PartitionWitness, WitnessWrite};
|
||||||
use plonky2::plonk::circuit_builder::CircuitBuilder;
|
use plonky2::plonk::circuit_builder::CircuitBuilder;
|
||||||
use plonky2::util::ceil_div_usize;
|
|
||||||
use plonky2_u32::gadgets::arithmetic_u32::{CircuitBuilderU32, U32Target};
|
use plonky2_u32::gadgets::arithmetic_u32::{CircuitBuilderU32, U32Target};
|
||||||
use plonky2_u32::gadgets::range_check::range_check_u32_circuit;
|
use plonky2_u32::gadgets::range_check::range_check_u32_circuit;
|
||||||
use plonky2_u32::witness::GeneratedValuesU32;
|
use plonky2_u32::witness::GeneratedValuesU32;
|
||||||
@@ -25,9 +29,22 @@ pub struct NonNativeTarget<FF: Field> {
|
|||||||
pub(crate) _phantom: PhantomData<FF>,
|
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> {
|
pub trait CircuitBuilderNonNative<F: RichField + Extendable<D>, const D: usize> {
|
||||||
fn num_nonnative_limbs<FF: Field>() -> 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>;
|
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>
|
for CircuitBuilder<F, D>
|
||||||
{
|
{
|
||||||
fn num_nonnative_limbs<FF: Field>() -> 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> {
|
fn biguint_to_nonnative<FF: Field>(&mut self, x: &BigUintTarget) -> NonNativeTarget<FF> {
|
||||||
@@ -454,9 +471,13 @@ struct NonNativeAdditionGenerator<F: RichField + Extendable<D>, const D: usize,
|
|||||||
_phantom: PhantomData<F>,
|
_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>
|
for NonNativeAdditionGenerator<F, D, FF>
|
||||||
{
|
{
|
||||||
|
fn id(&self) -> String {
|
||||||
|
"NonNativeAdditionGenerator".into()
|
||||||
|
}
|
||||||
|
|
||||||
fn dependencies(&self) -> Vec<Target> {
|
fn dependencies(&self) -> Vec<Target> {
|
||||||
self.a
|
self.a
|
||||||
.value
|
.value
|
||||||
@@ -468,7 +489,11 @@ impl<F: RichField + Extendable<D>, const D: usize, FF: PrimeField> SimpleGenerat
|
|||||||
.collect()
|
.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 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 b = FF::from_noncanonical_biguint(witness.get_biguint_target(self.b.value.clone()));
|
||||||
let a_biguint = a.to_canonical_biguint();
|
let a_biguint = a.to_canonical_biguint();
|
||||||
@@ -481,8 +506,33 @@ impl<F: RichField + Extendable<D>, const D: usize, FF: PrimeField> SimpleGenerat
|
|||||||
(false, sum_biguint)
|
(false, sum_biguint)
|
||||||
};
|
};
|
||||||
|
|
||||||
out_buffer.set_biguint_target(&self.sum.value, &sum_reduced);
|
out_buffer.set_biguint_target(&self.sum.value, &sum_reduced)?;
|
||||||
out_buffer.set_bool_target(self.overflow, overflow);
|
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 @@ struct NonNativeMultipleAddsGenerator<F: RichField + Extendable<D>, const D: usi
|
|||||||
_phantom: PhantomData<F>,
|
_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>
|
for NonNativeMultipleAddsGenerator<F, D, FF>
|
||||||
{
|
{
|
||||||
|
fn id(&self) -> String {
|
||||||
|
"NonNativeMultipleAddsGenerator".into()
|
||||||
|
}
|
||||||
|
|
||||||
fn dependencies(&self) -> Vec<Target> {
|
fn dependencies(&self) -> Vec<Target> {
|
||||||
self.summands
|
self.summands
|
||||||
.iter()
|
.iter()
|
||||||
@@ -505,7 +559,11 @@ impl<F: RichField + Extendable<D>, const D: usize, FF: PrimeField> SimpleGenerat
|
|||||||
.collect()
|
.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
|
let summands: Vec<_> = self
|
||||||
.summands
|
.summands
|
||||||
.iter()
|
.iter()
|
||||||
@@ -526,8 +584,42 @@ impl<F: RichField + Extendable<D>, const D: usize, FF: PrimeField> SimpleGenerat
|
|||||||
let (overflow_biguint, sum_reduced) = sum_biguint.div_rem(&modulus);
|
let (overflow_biguint, sum_reduced) = sum_biguint.div_rem(&modulus);
|
||||||
let overflow = overflow_biguint.to_u64_digits()[0] as u32;
|
let overflow = overflow_biguint.to_u64_digits()[0] as u32;
|
||||||
|
|
||||||
out_buffer.set_biguint_target(&self.sum.value, &sum_reduced);
|
out_buffer.set_biguint_target(&self.sum.value, &sum_reduced)?;
|
||||||
out_buffer.set_u32_target(self.overflow, overflow);
|
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 @@ struct NonNativeSubtractionGenerator<F: RichField + Extendable<D>, const D: usiz
|
|||||||
_phantom: PhantomData<F>,
|
_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>
|
for NonNativeSubtractionGenerator<F, D, FF>
|
||||||
{
|
{
|
||||||
|
fn id(&self) -> String {
|
||||||
|
"NonNativeSubtractionGenerator".into()
|
||||||
|
}
|
||||||
|
|
||||||
fn dependencies(&self) -> Vec<Target> {
|
fn dependencies(&self) -> Vec<Target> {
|
||||||
self.a
|
self.a
|
||||||
.value
|
.value
|
||||||
@@ -554,7 +650,11 @@ impl<F: RichField + Extendable<D>, const D: usize, FF: PrimeField> SimpleGenerat
|
|||||||
.collect()
|
.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 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 b = FF::from_noncanonical_biguint(witness.get_biguint_target(self.b.value.clone()));
|
||||||
let a_biguint = a.to_canonical_biguint();
|
let a_biguint = a.to_canonical_biguint();
|
||||||
@@ -567,8 +667,33 @@ impl<F: RichField + Extendable<D>, const D: usize, FF: PrimeField> SimpleGenerat
|
|||||||
(modulus + a_biguint - b_biguint, true)
|
(modulus + a_biguint - b_biguint, true)
|
||||||
};
|
};
|
||||||
|
|
||||||
out_buffer.set_biguint_target(&self.diff.value, &diff_biguint);
|
out_buffer.set_biguint_target(&self.diff.value, &diff_biguint)?;
|
||||||
out_buffer.set_bool_target(self.overflow, overflow);
|
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 @@ struct NonNativeMultiplicationGenerator<F: RichField + Extendable<D>, const D: u
|
|||||||
_phantom: PhantomData<F>,
|
_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>
|
for NonNativeMultiplicationGenerator<F, D, FF>
|
||||||
{
|
{
|
||||||
|
fn id(&self) -> String {
|
||||||
|
"NonNativeMultiplicationGenerator".into()
|
||||||
|
}
|
||||||
|
|
||||||
fn dependencies(&self) -> Vec<Target> {
|
fn dependencies(&self) -> Vec<Target> {
|
||||||
self.a
|
self.a
|
||||||
.value
|
.value
|
||||||
@@ -595,7 +724,11 @@ impl<F: RichField + Extendable<D>, const D: usize, FF: PrimeField> SimpleGenerat
|
|||||||
.collect()
|
.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 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 b = FF::from_noncanonical_biguint(witness.get_biguint_target(self.b.value.clone()));
|
||||||
let a_biguint = a.to_canonical_biguint();
|
let a_biguint = a.to_canonical_biguint();
|
||||||
@@ -606,8 +739,33 @@ impl<F: RichField + Extendable<D>, const D: usize, FF: PrimeField> SimpleGenerat
|
|||||||
let modulus = FF::order();
|
let modulus = FF::order();
|
||||||
let (overflow_biguint, prod_reduced) = prod_biguint.div_rem(&modulus);
|
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.prod.value, &prod_reduced)?;
|
||||||
out_buffer.set_biguint_target(&self.overflow, &overflow_biguint);
|
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 @@ struct NonNativeInverseGenerator<F: RichField + Extendable<D>, const D: usize, F
|
|||||||
_phantom: PhantomData<F>,
|
_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>
|
for NonNativeInverseGenerator<F, D, FF>
|
||||||
{
|
{
|
||||||
|
fn id(&self) -> String {
|
||||||
|
"NonNativeInverseGenerator".into()
|
||||||
|
}
|
||||||
|
|
||||||
fn dependencies(&self) -> Vec<Target> {
|
fn dependencies(&self) -> Vec<Target> {
|
||||||
self.x.value.limbs.iter().map(|&l| l.0).collect()
|
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 x = FF::from_noncanonical_biguint(witness.get_biguint_target(self.x.value.clone()));
|
||||||
let inv = x.inverse();
|
let inv = x.inverse();
|
||||||
|
|
||||||
@@ -636,8 +802,30 @@ impl<F: RichField + Extendable<D>, const D: usize, FF: PrimeField> SimpleGenerat
|
|||||||
let modulus = FF::order();
|
let modulus = FF::order();
|
||||||
let (div, _rem) = prod.div_rem(&modulus);
|
let (div, _rem) = prod.div_rem(&modulus);
|
||||||
|
|
||||||
out_buffer.set_biguint_target(&self.div, &div);
|
out_buffer.set_biguint_target(&self.div, &div)?;
|
||||||
out_buffer.set_biguint_target(&self.inv, &inv_biguint);
|
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,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user