From d83df4f0b749c6c425e2e508fa21e2e19bc25caa Mon Sep 17 00:00:00 2001 From: Chris T Date: Fri, 22 Mar 2024 17:41:04 -0700 Subject: [PATCH] refactor: generic size limbs for curve precompiles (#417) Signed-off-by: 0xkanekiken <100861945+0xKanekiKen@users.noreply.github.com> Co-authored-by: 0xkanekiken <100861945+0xKanekiKen@users.noreply.github.com> --- Cargo.lock | 21 +- core/Cargo.toml | 2 + core/src/lib.rs | 4 +- core/src/operations/field/field_den.rs | 78 ++++---- .../operations/field/field_inner_product.rs | 76 ++++---- core/src/operations/field/field_op.rs | 85 +++++---- core/src/operations/field/field_sqrt.rs | 50 +++-- core/src/operations/field/params.rs | 42 ++-- .../src/syscall/precompiles/edwards/ed_add.rs | 74 +++----- .../precompiles/edwards/ed_decompress.rs | 80 ++++---- .../syscall/precompiles/k256/decompress.rs | 63 +++--- core/src/syscall/precompiles/mod.rs | 14 +- .../weierstrass/weierstrass_add.rs | 170 ++++++++--------- .../weierstrass/weierstrass_double.rs | 179 ++++++++---------- core/src/utils/ec/edwards/ed25519.rs | 25 ++- core/src/utils/ec/edwards/mod.rs | 13 +- core/src/utils/ec/field.rs | 94 ++++++--- core/src/utils/ec/mod.rs | 12 +- core/src/utils/ec/utils.rs | 13 +- core/src/utils/ec/weierstrass/bn254.rs | 28 +-- core/src/utils/ec/weierstrass/mod.rs | 20 +- core/src/utils/ec/weierstrass/secp256k1.rs | 31 +-- core/src/utils/mod.rs | 7 +- derive/src/lib.rs | 78 ++++---- examples/chess/script/Cargo.lock | 121 ++++++------ .../program/elf/riscv32im-succinct-zkvm-elf | Bin 197188 -> 197196 bytes examples/ed25519/script/Cargo.lock | 21 +- .../program/elf/riscv32im-succinct-zkvm-elf | Bin 102932 -> 102976 bytes examples/fibonacci-io/script/Cargo.lock | 21 +- .../program/elf/riscv32im-succinct-zkvm-elf | Bin 83444 -> 83472 bytes examples/fibonacci/script/Cargo.lock | 21 +- .../program/elf/riscv32im-succinct-zkvm-elf | Bin 167844 -> 167896 bytes examples/io/script/Cargo.lock | 21 +- examples/json/script/Cargo.lock | 21 +- examples/regex/script/Cargo.lock | 21 +- .../program/elf/riscv32im-succinct-zkvm-elf | Bin 315312 -> 315260 bytes examples/rsa/script/Cargo.lock | 21 +- examples/ssz-withdrawals/script/Cargo.lock | 21 +- examples/tendermint/script/Cargo.lock | 25 ++- 39 files changed, 865 insertions(+), 708 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index b659ee11f1..4bdfd30469 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -240,7 +240,7 @@ version = "0.10.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" dependencies = [ - "generic-array", + "generic-array 0.14.7", ] [[package]] @@ -527,7 +527,7 @@ version = "0.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0dc92fb57ca44df6db8059111ab3af99a63d5d0f8375d9972e319a379c6bab76" dependencies = [ - "generic-array", + "generic-array 0.14.7", "rand_core", "subtle", "zeroize", @@ -539,7 +539,7 @@ version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" dependencies = [ - "generic-array", + "generic-array 0.14.7", "typenum", ] @@ -746,7 +746,7 @@ dependencies = [ "crypto-bigint", "digest", "ff", - "generic-array", + "generic-array 0.14.7", "group", "pkcs8", "rand_core", @@ -959,6 +959,15 @@ dependencies = [ "zeroize", ] +[[package]] +name = "generic-array" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fe739944a5406424e080edccb6add95685130b9f160d5407c639c7df0c5836b0" +dependencies = [ + "typenum", +] + [[package]] name = "getrandom" version = "0.2.12" @@ -2287,7 +2296,7 @@ checksum = "d3e97a565f76233a6003f9f5c54be1d9c5bdfa3eccfb189469f11ec4901c47dc" dependencies = [ "base16ct", "der", - "generic-array", + "generic-array 0.14.7", "pkcs8", "subtle", "zeroize", @@ -2511,6 +2520,7 @@ dependencies = [ "elf", "elliptic-curve", "flate2", + "generic-array 1.0.0", "hashbrown 0.14.3", "hex", "itertools 0.12.1", @@ -2557,6 +2567,7 @@ dependencies = [ "tracing-forest", "tracing-log", "tracing-subscriber", + "typenum", ] [[package]] diff --git a/core/Cargo.toml b/core/Cargo.toml index 758a159205..8e45968ec0 100644 --- a/core/Cargo.toml +++ b/core/Cargo.toml @@ -39,6 +39,8 @@ anyhow = "1.0.79" blake3 = "1.5" blake3-zkvm = { git = "https://github.com/sp1-patches/BLAKE3.git", branch = "patch-blake3_zkvm/v.1.0.0" } cfg-if = "1.0.0" +generic-array = { version = "1.0.0", features = ["alloc"] } +typenum = "1.17.0" clap = { version = "4.4.0", features = ["derive"] } curve25519-dalek = { version = "=4.0.0" } elliptic-curve = "0.13.8" diff --git a/core/src/lib.rs b/core/src/lib.rs index 1fbedfc582..23ae115f9c 100644 --- a/core/src/lib.rs +++ b/core/src/lib.rs @@ -8,8 +8,10 @@ clippy::type_complexity, clippy::unnecessary_unwrap, clippy::default_constructed_unit_structs, - clippy::box_default + clippy::box_default, + incomplete_features )] +#![feature(generic_const_exprs)] extern crate alloc; diff --git a/core/src/operations/field/field_den.rs b/core/src/operations/field/field_den.rs index b2fd3e4e57..6d48de4275 100644 --- a/core/src/operations/field/field_den.rs +++ b/core/src/operations/field/field_den.rs @@ -1,10 +1,10 @@ use super::params::Limbs; -use super::params::NUM_WITNESS_LIMBS; use super::util::{compute_root_quotient_and_shift, split_u16_limbs_to_u8_limbs}; use super::util_air::eval_field_operation; use crate::air::Polynomial; use crate::air::SP1AirBuilder; use crate::utils::ec::field::FieldParameters; + use num::BigUint; use p3_field::PrimeField32; use sp1_derive::AlignedBorrow; @@ -19,21 +19,16 @@ use std::fmt::Debug; /// or made generic in the future. #[derive(Debug, Clone, AlignedBorrow)] #[repr(C)] -pub struct FieldDenCols { +pub struct FieldDenCols { /// The result of `a den b`, where a, b are field elements - pub result: Limbs, - pub(crate) carry: Limbs, - pub(crate) witness_low: [T; NUM_WITNESS_LIMBS], - pub(crate) witness_high: [T; NUM_WITNESS_LIMBS], + pub result: Limbs, + pub(crate) carry: Limbs, + pub(crate) witness_low: Limbs, + pub(crate) witness_high: Limbs, } -impl FieldDenCols { - pub fn populate( - &mut self, - a: &BigUint, - b: &BigUint, - sign: bool, - ) -> BigUint { +impl FieldDenCols { + pub fn populate(&mut self, a: &BigUint, b: &BigUint, sign: bool) -> BigUint { let p = P::modulus(); let minus_b_int = &p - b; let b_signed = if sign { b.clone() } else { minus_b_int }; @@ -53,11 +48,11 @@ impl FieldDenCols { debug_assert!(carry < p); debug_assert_eq!(&carry * &p, &equation_lhs - &equation_rhs); - let p_a: Polynomial = P::to_limbs_field::(a).into(); - let p_b: Polynomial = P::to_limbs_field::(b).into(); - let p_p: Polynomial = P::to_limbs_field::(&p).into(); - let p_result: Polynomial = P::to_limbs_field::(&result).into(); - let p_carry: Polynomial = P::to_limbs_field::(&carry).into(); + let p_a: Polynomial = P::to_limbs_field::(a).into(); + let p_b: Polynomial = P::to_limbs_field::(b).into(); + let p_p: Polynomial = P::to_limbs_field::(&p).into(); + let p_result: Polynomial = P::to_limbs_field::(&result).into(); + let p_carry: Polynomial = P::to_limbs_field::(&carry).into(); // Compute the vanishing polynomial. let vanishing_poly = if sign { @@ -76,20 +71,23 @@ impl FieldDenCols { self.result = p_result.into(); self.carry = p_carry.into(); - self.witness_low = p_witness_low.try_into().unwrap(); - self.witness_high = p_witness_high.try_into().unwrap(); + self.witness_low = Limbs(p_witness_low.try_into().unwrap()); + self.witness_high = Limbs(p_witness_high.try_into().unwrap()); result } } -impl FieldDenCols { +impl FieldDenCols +where + Limbs: Copy, +{ #[allow(unused_variables)] - pub fn eval, P: FieldParameters>( + pub fn eval>( &self, builder: &mut AB, - a: &Limbs, - b: &Limbs, + a: &Limbs, + b: &Limbs, sign: bool, ) where V: Into, @@ -115,8 +113,8 @@ impl FieldDenCols { let p_vanishing = p_lhs_minus_rhs - &p_carry * &p_limbs; - let p_witness_low = self.witness_low.iter().into(); - let p_witness_high = self.witness_high.iter().into(); + let p_witness_low = self.witness_low.0.iter().into(); + let p_witness_high = self.witness_high.0.iter().into(); eval_field_operation::(builder, &p_vanishing, &p_witness_low, &p_witness_high); } @@ -147,14 +145,15 @@ mod tests { use p3_matrix::MatrixRowSlices; use rand::thread_rng; use sp1_derive::AlignedBorrow; - #[derive(AlignedBorrow, Debug, Clone)] - pub struct TestCols { - pub a: Limbs, - pub b: Limbs, - pub a_den_b: FieldDenCols, + + #[derive(Debug, Clone, AlignedBorrow)] + pub struct TestCols { + pub a: Limbs, + pub b: Limbs, + pub a_den_b: FieldDenCols, } - pub const NUM_TEST_COLS: usize = size_of::>(); + pub const NUM_TEST_COLS: usize = size_of::>(); struct FieldDenChip { pub sign: bool, @@ -206,10 +205,10 @@ mod tests { .iter() .map(|(a, b)| { let mut row = [F::zero(); NUM_TEST_COLS]; - let cols: &mut TestCols = row.as_mut_slice().borrow_mut(); - cols.a = P::to_limbs_field::(a); - cols.b = P::to_limbs_field::(b); - cols.a_den_b.populate::

(a, b, self.sign); + let cols: &mut TestCols = row.as_mut_slice().borrow_mut(); + cols.a = P::to_limbs_field::(a); + cols.b = P::to_limbs_field::(b); + cols.a_den_b.populate(a, b, self.sign); row }) .collect::>(); @@ -237,13 +236,14 @@ mod tests { impl Air for FieldDenChip

where AB: SP1AirBuilder, + Limbs: Copy, { fn eval(&self, builder: &mut AB) { let main = builder.main(); - let local: &TestCols = main.row_slice(0).borrow(); + let local: &TestCols = main.row_slice(0).borrow(); local .a_den_b - .eval::(builder, &local.a, &local.b, self.sign); + .eval::(builder, &local.a, &local.b, self.sign); // A dummy constraint to keep the degree 3. builder.assert_zero( @@ -262,7 +262,7 @@ mod tests { } #[test] - fn prove_babybear() { + fn prove_field() { let config = BabyBearPoseidon2::new(); let mut challenger = config.challenger(); diff --git a/core/src/operations/field/field_inner_product.rs b/core/src/operations/field/field_inner_product.rs index 080ebbf945..14b33eb18e 100644 --- a/core/src/operations/field/field_inner_product.rs +++ b/core/src/operations/field/field_inner_product.rs @@ -1,10 +1,10 @@ use super::params::Limbs; -use super::params::NUM_WITNESS_LIMBS; use super::util::{compute_root_quotient_and_shift, split_u16_limbs_to_u8_limbs}; use super::util_air::eval_field_operation; use crate::air::Polynomial; use crate::air::SP1AirBuilder; use crate::utils::ec::field::FieldParameters; + use num::BigUint; use num::Zero; use p3_field::{AbstractField, PrimeField32}; @@ -16,20 +16,24 @@ use std::fmt::Debug; /// or made generic in the future. #[derive(Debug, Clone, AlignedBorrow)] #[repr(C)] -pub struct FieldInnerProductCols { +pub struct FieldInnerProductCols { /// The result of `a inner product b`, where a, b are field elements - pub result: Limbs, - pub(crate) carry: Limbs, - pub(crate) witness_low: [T; NUM_WITNESS_LIMBS], - pub(crate) witness_high: [T; NUM_WITNESS_LIMBS], + pub result: Limbs, + pub(crate) carry: Limbs, + pub(crate) witness_low: Limbs, + pub(crate) witness_high: Limbs, } -impl FieldInnerProductCols { - pub fn populate(&mut self, a: &[BigUint], b: &[BigUint]) -> BigUint { - let p_a_vec: Vec> = - a.iter().map(|x| P::to_limbs_field::(x).into()).collect(); - let p_b_vec: Vec> = - b.iter().map(|x| P::to_limbs_field::(x).into()).collect(); +impl FieldInnerProductCols { + pub fn populate(&mut self, a: &[BigUint], b: &[BigUint]) -> BigUint { + let p_a_vec: Vec> = a + .iter() + .map(|x| P::to_limbs_field::(x).into()) + .collect(); + let p_b_vec: Vec> = b + .iter() + .map(|x| P::to_limbs_field::(x).into()) + .collect(); let modulus = &P::modulus(); let inner_product = a @@ -43,9 +47,9 @@ impl FieldInnerProductCols { assert!(carry < &(2u32 * modulus)); assert_eq!(carry * modulus, inner_product - result); - let p_modulus: Polynomial = P::to_limbs_field::(modulus).into(); - let p_result: Polynomial = P::to_limbs_field::(result).into(); - let p_carry: Polynomial = P::to_limbs_field::(carry).into(); + let p_modulus: Polynomial = P::to_limbs_field::(modulus).into(); + let p_result: Polynomial = P::to_limbs_field::(result).into(); + let p_carry: Polynomial = P::to_limbs_field::(carry).into(); // Compute the vanishing polynomial. let p_inner_product = p_a_vec @@ -66,20 +70,23 @@ impl FieldInnerProductCols { self.result = p_result.into(); self.carry = p_carry.into(); - self.witness_low = p_witness_low.try_into().unwrap(); - self.witness_high = p_witness_high.try_into().unwrap(); + self.witness_low = Limbs(p_witness_low.try_into().unwrap()); + self.witness_high = Limbs(p_witness_high.try_into().unwrap()); result.clone() } } -impl FieldInnerProductCols { +impl FieldInnerProductCols +where + Limbs: Copy, +{ #[allow(unused_variables)] - pub fn eval, P: FieldParameters>( + pub fn eval>( &self, builder: &mut AB, - a: &[Limbs], - b: &[Limbs], + a: &[Limbs], + b: &[Limbs], ) where V: Into, { @@ -103,8 +110,8 @@ impl FieldInnerProductCols { let p_carry_mul_modulus = &p_carry * &p_limbs; let p_vanishing = &p_inner_product_minus_result - &(&p_carry * &p_limbs); - let p_witness_low = self.witness_low.iter().into(); - let p_witness_high = self.witness_high.iter().into(); + let p_witness_low = self.witness_low.0.iter().into(); + let p_witness_high = self.witness_high.0.iter().into(); eval_field_operation::(builder, &p_vanishing, &p_witness_low, &p_witness_high); } @@ -137,13 +144,13 @@ mod tests { use sp1_derive::AlignedBorrow; #[derive(AlignedBorrow, Debug, Clone)] - pub struct TestCols { - pub a: [Limbs; 1], - pub b: [Limbs; 1], - pub a_ip_b: FieldInnerProductCols, + pub struct TestCols { + pub a: [Limbs; 1], + pub b: [Limbs; 1], + pub a_ip_b: FieldInnerProductCols, } - pub const NUM_TEST_COLS: usize = size_of::>(); + pub const NUM_TEST_COLS: usize = size_of::>(); struct FieldIpChip { pub _phantom: std::marker::PhantomData

, @@ -189,10 +196,10 @@ mod tests { .iter() .map(|(a, b)| { let mut row = [F::zero(); NUM_TEST_COLS]; - let cols: &mut TestCols = row.as_mut_slice().borrow_mut(); - cols.a[0] = P::to_limbs_field::(&a[0]); - cols.b[0] = P::to_limbs_field::(&b[0]); - cols.a_ip_b.populate::

(a, b); + let cols: &mut TestCols = row.as_mut_slice().borrow_mut(); + cols.a[0] = P::to_limbs_field::(&a[0]); + cols.b[0] = P::to_limbs_field::(&b[0]); + cols.a_ip_b.populate(a, b); row }) .collect::>(); @@ -222,11 +229,12 @@ mod tests { impl Air for FieldIpChip

where AB: SP1AirBuilder, + Limbs: Copy, { fn eval(&self, builder: &mut AB) { let main = builder.main(); - let local: &TestCols = main.row_slice(0).borrow(); - local.a_ip_b.eval::(builder, &local.a, &local.b); + let local: &TestCols = main.row_slice(0).borrow(); + local.a_ip_b.eval::(builder, &local.a, &local.b); // A dummy constraint to keep the degree 3. builder.assert_zero( diff --git a/core/src/operations/field/field_op.rs b/core/src/operations/field/field_op.rs index 35a3cf87e9..2ce6047584 100644 --- a/core/src/operations/field/field_op.rs +++ b/core/src/operations/field/field_op.rs @@ -1,10 +1,10 @@ use super::params::Limbs; -use super::params::NUM_WITNESS_LIMBS; use super::util::{compute_root_quotient_and_shift, split_u16_limbs_to_u8_limbs}; use super::util_air::eval_field_operation; use crate::air::Polynomial; use crate::air::SP1AirBuilder; use crate::utils::ec::field::FieldParameters; + use num::{BigUint, Zero}; use p3_air::AirBuilder; use p3_field::PrimeField32; @@ -24,21 +24,16 @@ pub enum FieldOperation { /// or made generic in the future. #[derive(Debug, Clone, AlignedBorrow)] #[repr(C)] -pub struct FieldOpCols { +pub struct FieldOpCols { /// The result of `a op b`, where a, b are field elements - pub result: Limbs, - pub(crate) carry: Limbs, - pub(crate) witness_low: [T; NUM_WITNESS_LIMBS], - pub(crate) witness_high: [T; NUM_WITNESS_LIMBS], + pub result: Limbs, + pub(crate) carry: Limbs, + pub(crate) witness_low: Limbs, + pub(crate) witness_high: Limbs, } -impl FieldOpCols { - pub fn populate( - &mut self, - a: &BigUint, - b: &BigUint, - op: FieldOperation, - ) -> BigUint { +impl FieldOpCols { + pub fn populate(&mut self, a: &BigUint, b: &BigUint, op: FieldOperation) -> BigUint { if b == &BigUint::zero() && op == FieldOperation::Div { // Division by 0 is allowed only when dividing 0 so that padded rows can be all 0. assert_eq!( @@ -58,8 +53,8 @@ impl FieldOpCols { // to contain the result by the user. // Note that this reversal means we have to flip result, a correspondingly in // the `eval` function. - self.populate::

(&result, b, FieldOperation::Add); - self.result = P::to_limbs_field::(&result); + self.populate(&result, b, FieldOperation::Add); + self.result = P::to_limbs_field::(&result); return result; } @@ -75,13 +70,13 @@ impl FieldOpCols { // multiplication because those columns are expected to contain the result by the user. // Note that this reversal means we have to flip result, a correspondingly in the `eval` // function. - self.populate::

(&result, b, FieldOperation::Mul); - self.result = P::to_limbs_field::(&result); + self.populate(&result, b, FieldOperation::Mul); + self.result = P::to_limbs_field::(&result); return result; } - let p_a: Polynomial = P::to_limbs_field::(a).into(); - let p_b: Polynomial = P::to_limbs_field::(b).into(); + let p_a: Polynomial = P::to_limbs_field::(a).into(); + let p_b: Polynomial = P::to_limbs_field::(b).into(); // Compute field addition in the integers. let modulus = &P::modulus(); @@ -99,9 +94,9 @@ impl FieldOpCols { } // Make little endian polynomial limbs. - let p_modulus: Polynomial = P::to_limbs_field::(modulus).into(); - let p_result: Polynomial = P::to_limbs_field::(&result).into(); - let p_carry: Polynomial = P::to_limbs_field::(&carry).into(); + let p_modulus: Polynomial = P::to_limbs_field::(modulus).into(); + let p_result: Polynomial = P::to_limbs_field::(&result).into(); + let p_carry: Polynomial = P::to_limbs_field::(&carry).into(); // Compute the vanishing polynomial. let p_op = match op { @@ -121,18 +116,18 @@ impl FieldOpCols { self.result = p_result.into(); self.carry = p_carry.into(); - self.witness_low = p_witness_low.try_into().unwrap(); - self.witness_high = p_witness_high.try_into().unwrap(); + + self.witness_low = Limbs(p_witness_low.try_into().unwrap()); + self.witness_high = Limbs(p_witness_high.try_into().unwrap()); result } } -impl FieldOpCols { +impl FieldOpCols { #[allow(unused_variables)] pub fn eval< AB: SP1AirBuilder, - P: FieldParameters, A: Into> + Clone, B: Into> + Clone, >( @@ -143,6 +138,7 @@ impl FieldOpCols { op: FieldOperation, ) where V: Into, + Limbs: Copy, { let p_a_param: Polynomial = (*a).clone().into(); let p_b: Polynomial = (*b).clone().into(); @@ -159,8 +155,8 @@ impl FieldOpCols { let p_op_minus_result: Polynomial = p_op - p_result; let p_limbs = Polynomial::from_iter(P::modulus_field_iter::().map(AB::Expr::from)); let p_vanishing = p_op_minus_result - &(&p_carry * &p_limbs); - let p_witness_low = self.witness_low.iter().into(); - let p_witness_high = self.witness_high.iter().into(); + let p_witness_low = self.witness_low.0.iter().into(); + let p_witness_high = self.witness_high.0.iter().into(); eval_field_operation::(builder, &p_vanishing, &p_witness_low, &p_witness_high); } } @@ -178,11 +174,13 @@ mod tests { use crate::stark::StarkGenericConfig; use crate::utils::ec::edwards::ed25519::Ed25519BaseField; use crate::utils::ec::field::FieldParameters; - use crate::utils::{pad_to_power_of_two, BabyBearPoseidon2}; - use crate::utils::{uni_stark_prove as prove, uni_stark_verify as verify}; + use crate::utils::ec::weierstrass::secp256k1::Secp256k1BaseField; + use crate::utils::{ + pad_to_power_of_two, uni_stark_prove as prove, uni_stark_verify as verify, + BabyBearPoseidon2, + }; use crate::{air::SP1AirBuilder, runtime::ExecutionRecord}; use core::borrow::{Borrow, BorrowMut}; - use core::mem::size_of; use num::bigint::RandBigInt; use p3_air::Air; use p3_baby_bear::BabyBear; @@ -190,15 +188,16 @@ mod tests { use p3_matrix::MatrixRowSlices; use rand::thread_rng; use sp1_derive::AlignedBorrow; + use std::mem::size_of; #[derive(AlignedBorrow, Debug, Clone)] - pub struct TestCols { - pub a: Limbs, - pub b: Limbs, - pub a_op_b: FieldOpCols, + pub struct TestCols { + pub a: Limbs, + pub b: Limbs, + pub a_op_b: FieldOpCols, } - pub const NUM_TEST_COLS: usize = size_of::>(); + pub const NUM_TEST_COLS: usize = size_of::>(); struct FieldOpChip { pub operation: FieldOperation, @@ -250,10 +249,10 @@ mod tests { .iter() .map(|(a, b)| { let mut row = [F::zero(); NUM_TEST_COLS]; - let cols: &mut TestCols = row.as_mut_slice().borrow_mut(); - cols.a = P::to_limbs_field::(a); - cols.b = P::to_limbs_field::(b); - cols.a_op_b.populate::

(a, b, self.operation); + let cols: &mut TestCols = row.as_mut_slice().borrow_mut(); + cols.a = P::to_limbs_field::(a); + cols.b = P::to_limbs_field::(b); + cols.a_op_b.populate(a, b, self.operation); row }) .collect::>(); @@ -283,13 +282,14 @@ mod tests { impl Air for FieldOpChip

where AB: SP1AirBuilder, + Limbs: Copy, { fn eval(&self, builder: &mut AB) { let main = builder.main(); - let local: &TestCols = main.row_slice(0).borrow(); + let local: &TestCols = main.row_slice(0).borrow(); local .a_op_b - .eval::(builder, &local.a, &local.b, self.operation); + .eval::(builder, &local.a, &local.b, self.operation); // A dummy constraint to keep the degree 3. builder.assert_zero( @@ -332,6 +332,7 @@ mod tests { let mut challenger = config.challenger(); + // TODO: test with other fields let chip: FieldOpChip = FieldOpChip::new(*op); let shard = ExecutionRecord::default(); let trace: RowMajorMatrix = diff --git a/core/src/operations/field/field_sqrt.rs b/core/src/operations/field/field_sqrt.rs index 234befdb5f..2442f078a5 100644 --- a/core/src/operations/field/field_sqrt.rs +++ b/core/src/operations/field/field_sqrt.rs @@ -11,48 +11,44 @@ use std::fmt::Debug; /// limb lives. #[derive(Debug, Clone, AlignedBorrow)] #[repr(C)] -pub struct FieldSqrtCols { +pub struct FieldSqrtCols { /// The multiplication operation to verify that the sqrt and the input match. /// /// In order to save space, we actually store the sqrt of the input in `multiplication.result` /// since we'll receive the input again in the `eval` function. - pub multiplication: FieldOpCols, + pub multiplication: FieldOpCols, } -impl FieldSqrtCols { +impl FieldSqrtCols { /// Populates the trace. /// /// `P` is the parameter of the field that each limb lives in. - pub fn populate( - &mut self, - a: &BigUint, - sqrt_fn: impl Fn(&BigUint) -> BigUint, - ) -> BigUint { + pub fn populate(&mut self, a: &BigUint, sqrt_fn: impl Fn(&BigUint) -> BigUint) -> BigUint { let sqrt = sqrt_fn(a); // Use FieldOpCols to compute result * result. let sqrt_squared = self.multiplication - .populate::

(&sqrt, &sqrt, super::field_op::FieldOperation::Mul); + .populate(&sqrt, &sqrt, super::field_op::FieldOperation::Mul); // If the result is indeed the square root of a, then result * result = a. assert_eq!(sqrt_squared, a.clone()); // This is a hack to save a column in FieldSqrtCols. We will receive the value a again in the // eval function, so we'll overwrite it with the sqrt. - self.multiplication.result = P::to_limbs_field::(&sqrt); + self.multiplication.result = P::to_limbs_field::(&sqrt); sqrt } } -impl FieldSqrtCols { +impl FieldSqrtCols +where + Limbs: Copy, +{ /// Calculates the square root of `a`. - pub fn eval, P: FieldParameters>( - &self, - builder: &mut AB, - a: &Limbs, - ) where + pub fn eval>(&self, builder: &mut AB, a: &Limbs) + where V: Into, { // As a space-saving hack, we store the sqrt of the input in `self.multiplication.result` @@ -63,7 +59,7 @@ impl FieldSqrtCols { multiplication.result = *a; // Compute sqrt * sqrt. We pass in P since we want its BaseField to be the mod. - multiplication.eval::, Limbs>( + multiplication.eval::, Limbs>( builder, &sqrt, &sqrt, @@ -97,13 +93,14 @@ mod tests { use p3_matrix::MatrixRowSlices; use rand::thread_rng; use sp1_derive::AlignedBorrow; + #[derive(AlignedBorrow, Debug, Clone)] - pub struct TestCols { - pub a: Limbs, - pub sqrt: FieldSqrtCols, + pub struct TestCols { + pub a: Limbs, + pub sqrt: FieldSqrtCols, } - pub const NUM_TEST_COLS: usize = size_of::>(); + pub const NUM_TEST_COLS: usize = size_of::>(); struct EdSqrtChip { pub _phantom: std::marker::PhantomData

, @@ -148,9 +145,9 @@ mod tests { .iter() .map(|a| { let mut row = [F::zero(); NUM_TEST_COLS]; - let cols: &mut TestCols = row.as_mut_slice().borrow_mut(); - cols.a = P::to_limbs_field::(a); - cols.sqrt.populate::

(a, ed25519_sqrt); + let cols: &mut TestCols = row.as_mut_slice().borrow_mut(); + cols.a = P::to_limbs_field::(a); + cols.sqrt.populate(a, ed25519_sqrt); row }) .collect::>(); @@ -180,13 +177,14 @@ mod tests { impl Air for EdSqrtChip

where AB: SP1AirBuilder, + Limbs: Copy, { fn eval(&self, builder: &mut AB) { let main = builder.main(); - let local: &TestCols = main.row_slice(0).borrow(); + let local: &TestCols = main.row_slice(0).borrow(); // eval verifies that local.sqrt.result is indeed the square root of local.a. - local.sqrt.eval::(builder, &local.a); + local.sqrt.eval::(builder, &local.a); // A dummy constraint to keep the degree 3. builder.assert_zero( diff --git a/core/src/operations/field/params.rs b/core/src/operations/field/params.rs index 605a9a0869..020e42f26b 100644 --- a/core/src/operations/field/params.rs +++ b/core/src/operations/field/params.rs @@ -1,16 +1,32 @@ use crate::air::Polynomial; +use generic_array::{ArrayLength, GenericArray}; use std::fmt::Debug; use std::ops::Index; use std::slice::Iter; +use std::usize; -pub const NUM_LIMBS: usize = 32; pub const NB_BITS_PER_LIMB: usize = 8; -pub const NUM_WITNESS_LIMBS: usize = 2 * NUM_LIMBS - 2; -#[derive(Default, Debug, Clone, Copy)] -pub struct Limbs(pub [T; NUM_LIMBS]); +#[derive(Debug, Clone)] +/// An array representing N limbs of T. +/// +/// GenericArray allows us to constrain the correct array lengths so we can have # of limbs and # of +/// witness limbs associated in NumLimbs / FieldParameters. +/// See: https://github.com/RustCrypto/traits/issues/1481 +pub struct Limbs(pub GenericArray); + +impl Copy for Limbs where N::ArrayType: Copy {} + +impl Default for Limbs +where + T: Default + Copy, +{ + fn default() -> Self { + Self(GenericArray::default()) + } +} -impl Index for Limbs { +impl Index for Limbs { type Output = T; fn index(&self, index: usize) -> &Self::Output { @@ -18,17 +34,19 @@ impl Index for Limbs { } } -impl IntoIterator for Limbs { +impl IntoIterator for Limbs { type Item = T; - type IntoIter = std::array::IntoIter; + type IntoIter = as IntoIterator>::IntoIter; fn into_iter(self) -> Self::IntoIter { self.0.into_iter() } } -impl + Clone, Expr: Clone> From> for Polynomial { - fn from(value: Limbs) -> Self { +impl + Clone, N: ArrayLength, Expr: Clone> From> + for Polynomial +{ + fn from(value: Limbs) -> Self { Polynomial::from_coefficients(&value.0.into_iter().map(|x| x.into()).collect::>()) } } @@ -39,14 +57,14 @@ impl<'a, Var: Into + Clone, Expr: Clone> From> for Polynomia } } -impl From> for Limbs { +impl From> for Limbs { fn from(value: Polynomial) -> Self { let inner = value.as_coefficients().try_into().unwrap(); Self(inner) } } -impl<'a, T: Debug + Default + Clone> From> for Limbs { +impl<'a, T: Debug + Default + Clone, N: ArrayLength> From> for Limbs { fn from(value: Iter<'a, T>) -> Self { let vec: Vec = value.cloned().collect(); let inner = vec.try_into().unwrap(); @@ -63,7 +81,7 @@ mod tests { #[test] fn test_modulus() { // Convert the MODULUS array to BigUint - let array_modulus = BigUint::from_bytes_le(&Ed25519BaseField::MODULUS); + let array_modulus = BigUint::from_bytes_le(Ed25519BaseField::MODULUS); // Get the modulus from the function let func_modulus = Ed25519BaseField::modulus(); diff --git a/core/src/syscall/precompiles/edwards/ed_add.rs b/core/src/syscall/precompiles/edwards/ed_add.rs index 577560f716..8bd76b0bfe 100644 --- a/core/src/syscall/precompiles/edwards/ed_add.rs +++ b/core/src/syscall/precompiles/edwards/ed_add.rs @@ -8,13 +8,12 @@ use crate::operations::field::field_den::FieldDenCols; use crate::operations::field::field_inner_product::FieldInnerProductCols; use crate::operations::field::field_op::FieldOpCols; use crate::operations::field::field_op::FieldOperation; -use crate::operations::field::params::Limbs; -use crate::operations::field::params::NUM_LIMBS; use crate::runtime::ExecutionRecord; use crate::runtime::Syscall; use crate::runtime::SyscallCode; use crate::syscall::precompiles::create_ec_add_event; use crate::syscall::precompiles::SyscallContext; +use crate::utils::ec::edwards::ed25519::Ed25519BaseField; use crate::utils::ec::edwards::EdwardsParameters; use crate::utils::ec::field::FieldParameters; use crate::utils::ec::AffinePoint; @@ -51,16 +50,16 @@ pub struct EdAddAssignCols { pub clk: T, pub p_ptr: T, pub q_ptr: T, - pub p_access: [MemoryWriteCols; 16], - pub q_access: [MemoryReadCols; 16], - pub(crate) x3_numerator: FieldInnerProductCols, - pub(crate) y3_numerator: FieldInnerProductCols, - pub(crate) x1_mul_y1: FieldOpCols, - pub(crate) x2_mul_y2: FieldOpCols, - pub(crate) f: FieldOpCols, - pub(crate) d_mul_f: FieldOpCols, - pub(crate) x3_ins: FieldDenCols, - pub(crate) y3_ins: FieldDenCols, + pub p_access: [MemoryWriteCols; Ed25519BaseField::NB_LIMBS], + pub q_access: [MemoryReadCols; Ed25519BaseField::NB_LIMBS], + pub(crate) x3_numerator: FieldInnerProductCols, + pub(crate) y3_numerator: FieldInnerProductCols, + pub(crate) x1_mul_y1: FieldOpCols, + pub(crate) x2_mul_y2: FieldOpCols, + pub(crate) f: FieldOpCols, + pub(crate) d_mul_f: FieldOpCols, + pub(crate) x3_ins: FieldDenCols, + pub(crate) y3_ins: FieldDenCols, } #[derive(Default)] @@ -83,29 +82,19 @@ impl EdAddAssignChip { ) { let x3_numerator = cols .x3_numerator - .populate::(&[p_x.clone(), q_x.clone()], &[q_y.clone(), p_y.clone()]); + .populate(&[p_x.clone(), q_x.clone()], &[q_y.clone(), p_y.clone()]); let y3_numerator = cols .y3_numerator - .populate::(&[p_y.clone(), p_x.clone()], &[q_y.clone(), q_x.clone()]); - let x1_mul_y1 = cols - .x1_mul_y1 - .populate::(&p_x, &p_y, FieldOperation::Mul); - let x2_mul_y2 = cols - .x2_mul_y2 - .populate::(&q_x, &q_y, FieldOperation::Mul); - let f = cols - .f - .populate::(&x1_mul_y1, &x2_mul_y2, FieldOperation::Mul); + .populate(&[p_y.clone(), p_x.clone()], &[q_y.clone(), q_x.clone()]); + let x1_mul_y1 = cols.x1_mul_y1.populate(&p_x, &p_y, FieldOperation::Mul); + let x2_mul_y2 = cols.x2_mul_y2.populate(&q_x, &q_y, FieldOperation::Mul); + let f = cols.f.populate(&x1_mul_y1, &x2_mul_y2, FieldOperation::Mul); let d = E::d_biguint(); - let d_mul_f = cols - .d_mul_f - .populate::(&f, &d, FieldOperation::Mul); - - cols.x3_ins - .populate::(&x3_numerator, &d_mul_f, true); - cols.y3_ins - .populate::(&y3_numerator, &d_mul_f, false); + let d_mul_f = cols.d_mul_f.populate(&f, &d, FieldOperation::Mul); + + cols.x3_ins.populate(&x3_numerator, &d_mul_f, true); + cols.y3_ins.populate(&y3_numerator, &d_mul_f, false); } } @@ -220,45 +209,42 @@ where let y2 = limbs_from_prev_access(&row.q_access[8..16]); // x3_numerator = x1 * y2 + x2 * y1. - row.x3_numerator - .eval::(builder, &[x1, x2], &[y2, y1]); + row.x3_numerator.eval::(builder, &[x1, x2], &[y2, y1]); // y3_numerator = y1 * y2 + x1 * x2. - row.y3_numerator - .eval::(builder, &[y1, x1], &[y2, x2]); + row.y3_numerator.eval::(builder, &[y1, x1], &[y2, x2]); // f = x1 * x2 * y1 * y2. row.x1_mul_y1 - .eval::(builder, &x1, &y1, FieldOperation::Mul); + .eval::(builder, &x1, &y1, FieldOperation::Mul); row.x2_mul_y2 - .eval::(builder, &x2, &y2, FieldOperation::Mul); + .eval::(builder, &x2, &y2, FieldOperation::Mul); let x1_mul_y1 = row.x1_mul_y1.result; let x2_mul_y2 = row.x2_mul_y2.result; row.f - .eval::(builder, &x1_mul_y1, &x2_mul_y2, FieldOperation::Mul); + .eval::(builder, &x1_mul_y1, &x2_mul_y2, FieldOperation::Mul); // d * f. let f = row.f.result; let d_biguint = E::d_biguint(); - let d_const = E::BaseField::to_limbs_field::(&d_biguint); - let d_const_expr = Limbs::(d_const.0.map(|x| x.into())); + let d_const = E::BaseField::to_limbs_field::(&d_biguint); row.d_mul_f - .eval::(builder, &f, &d_const_expr, FieldOperation::Mul); + .eval::(builder, &f, &d_const, FieldOperation::Mul); let d_mul_f = row.d_mul_f.result; // x3 = x3_numerator / (1 + d * f). row.x3_ins - .eval::(builder, &row.x3_numerator.result, &d_mul_f, true); + .eval::(builder, &row.x3_numerator.result, &d_mul_f, true); // y3 = y3_numerator / (1 - d * f). row.y3_ins - .eval::(builder, &row.y3_numerator.result, &d_mul_f, false); + .eval::(builder, &row.y3_numerator.result, &d_mul_f, false); // Constraint self.p_access.value = [self.x3_ins.result, self.y3_ins.result] // This is to ensure that p_access is updated with the new value. - for i in 0..NUM_LIMBS { + for i in 0..E::BaseField::NB_LIMBS { builder .when(row.is_real) .assert_eq(row.x3_ins.result[i], row.p_access[i / 4].value()[i % 4]); diff --git a/core/src/syscall/precompiles/edwards/ed_decompress.rs b/core/src/syscall/precompiles/edwards/ed_decompress.rs index cf07865c93..c4da5fccbf 100644 --- a/core/src/syscall/precompiles/edwards/ed_decompress.rs +++ b/core/src/syscall/precompiles/edwards/ed_decompress.rs @@ -6,6 +6,7 @@ use crate::memory::MemoryWriteCols; use crate::operations::field::field_op::FieldOpCols; use crate::operations::field::field_op::FieldOperation; use crate::operations::field::field_sqrt::FieldSqrtCols; +use crate::operations::field::params::Limbs; use crate::runtime::ExecutionRecord; use crate::runtime::MemoryReadRecord; use crate::runtime::MemoryWriteRecord; @@ -15,8 +16,10 @@ use crate::syscall::precompiles::SyscallContext; use crate::utils::bytes_to_words_le; use crate::utils::ec::edwards::ed25519::decompress; use crate::utils::ec::edwards::ed25519::ed25519_sqrt; +use crate::utils::ec::edwards::ed25519::Ed25519BaseField; use crate::utils::ec::edwards::EdwardsParameters; use crate::utils::ec::field::FieldParameters; +use crate::utils::ec::field::NumWords; use crate::utils::ec::COMPRESSED_POINT_BYTES; use crate::utils::ec::NUM_BYTES_FIELD_ELEMENT; use crate::utils::ec::NUM_WORDS_FIELD_ELEMENT; @@ -27,6 +30,7 @@ use crate::utils::words_to_bytes_le; use core::borrow::{Borrow, BorrowMut}; use core::mem::size_of; use curve25519_dalek::edwards::CompressedEdwardsY; +use generic_array::GenericArray; use num::BigUint; use num::One; use num::Zero; @@ -37,6 +41,8 @@ use p3_matrix::MatrixRowSlices; use serde::Deserialize; use serde::Serialize; use std::marker::PhantomData; +use typenum::Unsigned; +use typenum::U32; use p3_matrix::dense::RowMajorMatrix; use sp1_derive::AlignedBorrow; @@ -50,8 +56,10 @@ pub struct EdDecompressEvent { pub sign: bool, pub y_bytes: [u8; COMPRESSED_POINT_BYTES], pub decompressed_x_bytes: [u8; NUM_BYTES_FIELD_ELEMENT], - pub x_memory_records: [MemoryWriteRecord; NUM_WORDS_FIELD_ELEMENT], - pub y_memory_records: [MemoryReadRecord; NUM_WORDS_FIELD_ELEMENT], + pub x_memory_records: + [MemoryWriteRecord; <::WordsFieldElement as Unsigned>::USIZE], + pub y_memory_records: + [MemoryReadRecord; <::WordsFieldElement as Unsigned>::USIZE], } pub const NUM_ED_DECOMPRESS_COLS: usize = size_of::>(); @@ -69,15 +77,17 @@ pub struct EdDecompressCols { pub clk: T, pub ptr: T, pub sign: T, - pub x_access: [MemoryWriteCols; NUM_WORDS_FIELD_ELEMENT], - pub y_access: [MemoryReadCols; NUM_WORDS_FIELD_ELEMENT], - pub(crate) yy: FieldOpCols, - pub(crate) u: FieldOpCols, - pub(crate) dyy: FieldOpCols, - pub(crate) v: FieldOpCols, - pub(crate) u_div_v: FieldOpCols, - pub(crate) x: FieldSqrtCols, - pub(crate) neg_x: FieldOpCols, + pub x_access: + GenericArray, ::WordsFieldElement>, + pub y_access: + GenericArray, ::WordsFieldElement>, + pub(crate) yy: FieldOpCols, + pub(crate) u: FieldOpCols, + pub(crate) dyy: FieldOpCols, + pub(crate) v: FieldOpCols, + pub(crate) u_div_v: FieldOpCols, + pub(crate) x: FieldSqrtCols, + pub(crate) neg_x: FieldOpCols, } impl EdDecompressCols { @@ -98,23 +108,21 @@ impl EdDecompressCols { } let y = &BigUint::from_bytes_le(&event.y_bytes); - self.populate_field_ops::(y); + self.populate_field_ops::(y); record.add_byte_lookup_events(new_byte_lookup_events); } - fn populate_field_ops(&mut self, y: &BigUint) { + fn populate_field_ops(&mut self, y: &BigUint) { let one = BigUint::one(); - let yy = self.yy.populate::

(y, y, FieldOperation::Mul); - let u = self.u.populate::

(&yy, &one, FieldOperation::Sub); - let dyy = self - .dyy - .populate::

(&E::d_biguint(), &yy, FieldOperation::Mul); - let v = self.v.populate::

(&one, &dyy, FieldOperation::Add); - let u_div_v = self.u_div_v.populate::

(&u, &v, FieldOperation::Div); - let x = self.x.populate::

(&u_div_v, ed25519_sqrt); + let yy = self.yy.populate(y, y, FieldOperation::Mul); + let u = self.u.populate(&yy, &one, FieldOperation::Sub); + let dyy = self.dyy.populate(&E::d_biguint(), &yy, FieldOperation::Mul); + let v = self.v.populate(&one, &dyy, FieldOperation::Add); + let u_div_v = self.u_div_v.populate(&u, &v, FieldOperation::Div); + let x = self.x.populate(&u_div_v, ed25519_sqrt); self.neg_x - .populate::

(&BigUint::zero(), &x, FieldOperation::Sub); + .populate(&BigUint::zero(), &x, FieldOperation::Sub); } } @@ -127,33 +135,29 @@ impl EdDecompressCols { { builder.assert_bool(self.sign); - let y = limbs_from_prev_access(&self.y_access); + let y: Limbs = limbs_from_prev_access(&self.y_access); self.yy - .eval::(builder, &y, &y, FieldOperation::Mul); - self.u.eval::( + .eval::(builder, &y, &y, FieldOperation::Mul); + self.u.eval::( builder, &self.yy.result, &[AB::Expr::one()].iter(), FieldOperation::Sub, ); let d_biguint = E::d_biguint(); - let d_const = E::BaseField::to_limbs_field::(&d_biguint); + let d_const = E::BaseField::to_limbs_field::(&d_biguint); self.dyy - .eval::(builder, &d_const, &self.yy.result, FieldOperation::Mul); - self.v.eval::( + .eval::(builder, &d_const, &self.yy.result, FieldOperation::Mul); + self.v.eval::( builder, &[AB::Expr::one()].iter(), &self.dyy.result, FieldOperation::Add, ); - self.u_div_v.eval::( - builder, - &self.u.result, - &self.v.result, - FieldOperation::Div, - ); - self.x.eval::(builder, &self.u_div_v.result); - self.neg_x.eval::( + self.u_div_v + .eval::(builder, &self.u.result, &self.v.result, FieldOperation::Div); + self.x.eval::(builder, &self.u_div_v.result); + self.neg_x.eval::( builder, &[AB::Expr::zero()].iter(), &self.x.multiplication.result, @@ -179,7 +183,7 @@ impl EdDecompressCols { ); } - let x_limbs = limbs_from_access(&self.x_access); + let x_limbs: Limbs = limbs_from_access(&self.x_access); builder .when(self.is_real) .when(self.sign) @@ -298,7 +302,7 @@ impl MachineAir for EdDecompressChip = row.as_mut_slice().borrow_mut(); let zero = BigUint::zero(); - cols.populate_field_ops::(&zero); + cols.populate_field_ops::(&zero); row }); diff --git a/core/src/syscall/precompiles/k256/decompress.rs b/core/src/syscall/precompiles/k256/decompress.rs index 50fde52d62..9e8395d3e5 100644 --- a/core/src/syscall/precompiles/k256/decompress.rs +++ b/core/src/syscall/precompiles/k256/decompress.rs @@ -7,6 +7,7 @@ use crate::memory::MemoryReadWriteCols; use crate::operations::field::field_op::FieldOpCols; use crate::operations::field::field_op::FieldOperation; use crate::operations::field::field_sqrt::FieldSqrtCols; +use crate::operations::field::params::Limbs; use crate::runtime::ExecutionRecord; use crate::runtime::MemoryReadRecord; use crate::runtime::MemoryWriteRecord; @@ -14,6 +15,7 @@ use crate::runtime::Syscall; use crate::runtime::SyscallCode; use crate::syscall::precompiles::SyscallContext; use crate::utils::bytes_to_words_le; + use crate::utils::ec::field::FieldParameters; use crate::utils::ec::weierstrass::secp256k1::secp256k1_sqrt; use crate::utils::ec::weierstrass::secp256k1::Secp256k1BaseField; @@ -40,6 +42,7 @@ use p3_field::PrimeField32; use p3_matrix::MatrixRowSlices; use serde::{Deserialize, Serialize}; use std::str::FromStr; +use typenum::U32; use p3_matrix::dense::RowMajorMatrix; use sp1_derive::AlignedBorrow; @@ -136,11 +139,11 @@ pub struct K256DecompressCols { pub is_odd: T, pub x_access: [MemoryReadCols; NUM_WORDS_FIELD_ELEMENT], pub y_access: [MemoryReadWriteCols; NUM_WORDS_FIELD_ELEMENT], - pub(crate) x_2: FieldOpCols, - pub(crate) x_3: FieldOpCols, - pub(crate) x_3_plus_b: FieldOpCols, - pub(crate) y: FieldSqrtCols, - pub(crate) neg_y: FieldOpCols, + pub(crate) x_2: FieldOpCols, + pub(crate) x_3: FieldOpCols, + pub(crate) x_3_plus_b: FieldOpCols, + pub(crate) y: FieldSqrtCols, + pub(crate) neg_y: FieldOpCols, pub(crate) y_least_bits: [T; 8], } @@ -165,22 +168,15 @@ impl K256DecompressCols { fn populate_field_ops(&mut self, x: &BigUint) { // Y = sqrt(x^3 + b) - let x_2 = - self.x_2 - .populate::(&x.clone(), &x.clone(), FieldOperation::Mul); - let x_3 = self - .x_3 - .populate::(&x_2, x, FieldOperation::Mul); + let x_2 = self + .x_2 + .populate(&x.clone(), &x.clone(), FieldOperation::Mul); + let x_3 = self.x_3.populate(&x_2, x, FieldOperation::Mul); let b = Secp256k1Parameters::b_int(); - let x_3_plus_b = - self.x_3_plus_b - .populate::(&x_3, &b, FieldOperation::Add); - let y = self - .y - .populate::(&x_3_plus_b, secp256k1_sqrt); + let x_3_plus_b = self.x_3_plus_b.populate(&x_3, &b, FieldOperation::Add); + let y = self.y.populate(&x_3_plus_b, secp256k1_sqrt); let zero = BigUint::zero(); - self.neg_y - .populate::(&zero, &y, FieldOperation::Sub); + self.neg_y.populate(&zero, &y, FieldOperation::Sub); // Decompose bits of least significant Y byte let y_bytes = y.to_bytes_le(); let y_lsb = if y_bytes.is_empty() { 0 } else { y_bytes[0] }; @@ -197,26 +193,17 @@ impl K256DecompressCols { { builder.assert_bool(self.is_odd); - let x = limbs_from_prev_access(&self.x_access); + let x: Limbs = limbs_from_prev_access(&self.x_access); self.x_2 - .eval::(builder, &x, &x, FieldOperation::Mul); - self.x_3.eval::( - builder, - &self.x_2.result, - &x, - FieldOperation::Mul, - ); + .eval::(builder, &x, &x, FieldOperation::Mul); + self.x_3 + .eval::(builder, &self.x_2.result, &x, FieldOperation::Mul); let b = Secp256k1Parameters::b_int(); - let b_const = Secp256k1BaseField::to_limbs_field::(&b); - self.x_3_plus_b.eval::( - builder, - &self.x_3.result, - &b_const, - FieldOperation::Add, - ); - self.y - .eval::(builder, &self.x_3_plus_b.result); - self.neg_y.eval::( + let b_const = Secp256k1BaseField::to_limbs_field::(&b); + self.x_3_plus_b + .eval::(builder, &self.x_3.result, &b_const, FieldOperation::Add); + self.y.eval::(builder, &self.x_3_plus_b.result); + self.neg_y.eval::( builder, &[AB::Expr::zero()].iter(), &self.y.multiplication.result, @@ -244,7 +231,7 @@ impl K256DecompressCols { // When y_is_odd == should_be_odd, result is y // (Equivalent: y_is_odd != !should_be_odd) - let y_limbs = limbs_from_access(&self.y_access); + let y_limbs: Limbs = limbs_from_access(&self.y_access); builder .when(self.is_real) .when_ne(y_is_odd.into(), AB::Expr::one() - self.is_odd) diff --git a/core/src/syscall/precompiles/mod.rs b/core/src/syscall/precompiles/mod.rs index d0fd5f059a..bc2cbca9c1 100644 --- a/core/src/syscall/precompiles/mod.rs +++ b/core/src/syscall/precompiles/mod.rs @@ -5,13 +5,10 @@ pub mod keccak256; pub mod sha256; pub mod weierstrass; -use num::BigUint; use serde::{Deserialize, Serialize}; -use crate::air::SP1AirBuilder; -use crate::operations::field::params::Limbs; use crate::runtime::SyscallContext; -use crate::utils::ec::field::FieldParameters; + use crate::utils::ec::{AffinePoint, EllipticCurve}; use crate::{runtime::MemoryReadRecord, runtime::MemoryWriteRecord}; @@ -54,6 +51,7 @@ pub fn create_ec_add_event( let q_affine = AffinePoint::::from_words_le(&q); let result_affine = p_affine + q_affine; let result_words = result_affine.to_words_le(); + let p_memory_records = rt.mw_slice(p_ptr, &result_words).try_into().unwrap(); ECAddEvent { @@ -103,11 +101,3 @@ pub fn create_ec_double_event( p_memory_records, } } - -pub fn limbs_from_biguint(value: &BigUint) -> Limbs -where - AB: SP1AirBuilder, -{ - let a_const = F::to_limbs_field::(value); - Limbs::(a_const.0.map(|x| x.into())) -} diff --git a/core/src/syscall/precompiles/weierstrass/weierstrass_add.rs b/core/src/syscall/precompiles/weierstrass/weierstrass_add.rs index a119ae474a..76dda57c32 100644 --- a/core/src/syscall/precompiles/weierstrass/weierstrass_add.rs +++ b/core/src/syscall/precompiles/weierstrass/weierstrass_add.rs @@ -5,21 +5,23 @@ use crate::memory::MemoryReadCols; use crate::memory::MemoryWriteCols; use crate::operations::field::field_op::FieldOpCols; use crate::operations::field::field_op::FieldOperation; -use crate::operations::field::params::NUM_LIMBS; +use crate::operations::field::params::Limbs; use crate::runtime::ExecutionRecord; use crate::runtime::Syscall; use crate::runtime::SyscallCode; use crate::syscall::precompiles::create_ec_add_event; use crate::syscall::precompiles::SyscallContext; +use crate::utils::ec::field::FieldParameters; +use crate::utils::ec::field::NumLimbs; +use crate::utils::ec::field::NumWords; use crate::utils::ec::weierstrass::WeierstrassParameters; use crate::utils::ec::AffinePoint; use crate::utils::ec::EllipticCurve; -use crate::utils::ec::NUM_WORDS_EC_POINT; -use crate::utils::ec::NUM_WORDS_FIELD_ELEMENT; use crate::utils::limbs_from_prev_access; use crate::utils::pad_rows; use core::borrow::{Borrow, BorrowMut}; use core::mem::size_of; +use generic_array::GenericArray; use num::BigUint; use num::Zero; use p3_air::AirBuilder; @@ -31,8 +33,11 @@ use p3_matrix::MatrixRowSlices; use sp1_derive::AlignedBorrow; use std::fmt::Debug; use std::marker::PhantomData; +use typenum::Unsigned; -pub const NUM_WEIERSTRASS_ADD_COLS: usize = size_of::>(); +pub const fn num_weierstrass_add_cols() -> usize { + size_of::>() +} /// A set of columns to compute `WeierstrassAdd` that add two points on a Weierstrass curve. /// @@ -40,23 +45,23 @@ pub const NUM_WEIERSTRASS_ADD_COLS: usize = size_of:: { +pub struct WeierstrassAddAssignCols { pub is_real: T, pub shard: T, pub clk: T, pub p_ptr: T, pub q_ptr: T, - pub p_access: [MemoryWriteCols; NUM_WORDS_EC_POINT], - pub q_access: [MemoryReadCols; NUM_WORDS_EC_POINT], - pub(crate) slope_denominator: FieldOpCols, - pub(crate) slope_numerator: FieldOpCols, - pub(crate) slope: FieldOpCols, - pub(crate) slope_squared: FieldOpCols, - pub(crate) p_x_plus_q_x: FieldOpCols, - pub(crate) x3_ins: FieldOpCols, - pub(crate) p_x_minus_x: FieldOpCols, - pub(crate) y3_ins: FieldOpCols, - pub(crate) slope_times_p_x_minus_x: FieldOpCols, + pub p_access: GenericArray, P::WordsCurvePoint>, + pub q_access: GenericArray, P::WordsCurvePoint>, + pub(crate) slope_denominator: FieldOpCols, + pub(crate) slope_numerator: FieldOpCols, + pub(crate) slope: FieldOpCols, + pub(crate) slope_squared: FieldOpCols, + pub(crate) p_x_plus_q_x: FieldOpCols, + pub(crate) x3_ins: FieldOpCols, + pub(crate) p_x_minus_x: FieldOpCols, + pub(crate) y3_ins: FieldOpCols, + pub(crate) slope_times_p_x_minus_x: FieldOpCols, } #[derive(Default)] @@ -84,7 +89,7 @@ impl WeierstrassAddAssignChip { } fn populate_field_ops( - cols: &mut WeierstrassAddAssignCols, + cols: &mut WeierstrassAddAssignCols, p_x: BigUint, p_y: BigUint, q_x: BigUint, @@ -95,54 +100,44 @@ impl WeierstrassAddAssignChip { // slope = (q.y - p.y) / (q.x - p.x). let slope = { - let slope_numerator = - cols.slope_numerator - .populate::(&q_y, &p_y, FieldOperation::Sub); + let slope_numerator = cols + .slope_numerator + .populate(&q_y, &p_y, FieldOperation::Sub); let slope_denominator = cols.slope_denominator - .populate::(&q_x, &p_x, FieldOperation::Sub); + .populate(&q_x, &p_x, FieldOperation::Sub); - cols.slope.populate::( - &slope_numerator, - &slope_denominator, - FieldOperation::Div, - ) + cols.slope + .populate(&slope_numerator, &slope_denominator, FieldOperation::Div) }; // x = slope * slope - (p.x + q.x). let x = { - let slope_squared = - cols.slope_squared - .populate::(&slope, &slope, FieldOperation::Mul); - let p_x_plus_q_x = - cols.p_x_plus_q_x - .populate::(&p_x, &q_x, FieldOperation::Add); + let slope_squared = cols + .slope_squared + .populate(&slope, &slope, FieldOperation::Mul); + let p_x_plus_q_x = cols.p_x_plus_q_x.populate(&p_x, &q_x, FieldOperation::Add); cols.x3_ins - .populate::(&slope_squared, &p_x_plus_q_x, FieldOperation::Sub) + .populate(&slope_squared, &p_x_plus_q_x, FieldOperation::Sub) }; // y = slope * (p.x - x_3n) - p.y. { - let p_x_minus_x = - cols.p_x_minus_x - .populate::(&p_x, &x, FieldOperation::Sub); - let slope_times_p_x_minus_x = cols.slope_times_p_x_minus_x.populate::( - &slope, - &p_x_minus_x, - FieldOperation::Mul, - ); - cols.y3_ins.populate::( - &slope_times_p_x_minus_x, - &p_y, - FieldOperation::Sub, - ); + let p_x_minus_x = cols.p_x_minus_x.populate(&p_x, &x, FieldOperation::Sub); + let slope_times_p_x_minus_x = + cols.slope_times_p_x_minus_x + .populate(&slope, &p_x_minus_x, FieldOperation::Mul); + cols.y3_ins + .populate(&slope_times_p_x_minus_x, &p_y, FieldOperation::Sub); } } } impl MachineAir for WeierstrassAddAssignChip +where + [(); num_weierstrass_add_cols::()]:, { type Record = ExecutionRecord; @@ -160,9 +155,10 @@ impl MachineAir let mut new_byte_lookup_events = Vec::new(); for i in 0..input.weierstrass_add_events.len() { - let event = input.weierstrass_add_events[i].clone(); - let mut row = [F::zero(); NUM_WEIERSTRASS_ADD_COLS]; - let cols: &mut WeierstrassAddAssignCols = row.as_mut_slice().borrow_mut(); + let event = &input.weierstrass_add_events[i]; + let mut row = [F::zero(); num_weierstrass_add_cols::()]; + let cols: &mut WeierstrassAddAssignCols = + row.as_mut_slice().borrow_mut(); // Decode affine points. let p = &event.p; @@ -182,10 +178,10 @@ impl MachineAir Self::populate_field_ops(cols, p_x, p_y, q_x, q_y); // Populate the memory access columns. - for i in 0..NUM_WORDS_EC_POINT { + for i in 0..cols.q_access.len() { cols.q_access[i].populate(event.q_memory_records[i], &mut new_byte_lookup_events); } - for i in 0..NUM_WORDS_EC_POINT { + for i in 0..cols.p_access.len() { cols.p_access[i].populate(event.p_memory_records[i], &mut new_byte_lookup_events); } @@ -194,8 +190,9 @@ impl MachineAir output.add_byte_lookup_events(new_byte_lookup_events); pad_rows(&mut rows, || { - let mut row = [F::zero(); NUM_WEIERSTRASS_ADD_COLS]; - let cols: &mut WeierstrassAddAssignCols = row.as_mut_slice().borrow_mut(); + let mut row = [F::zero(); num_weierstrass_add_cols::()]; + let cols: &mut WeierstrassAddAssignCols = + row.as_mut_slice().borrow_mut(); let zero = BigUint::zero(); Self::populate_field_ops(cols, zero.clone(), zero.clone(), zero.clone(), zero); row @@ -204,7 +201,7 @@ impl MachineAir // Convert the trace to a row major matrix. RowMajorMatrix::new( rows.into_iter().flatten().collect::>(), - NUM_WEIERSTRASS_ADD_COLS, + num_weierstrass_add_cols::(), ) } @@ -215,89 +212,76 @@ impl MachineAir impl BaseAir for WeierstrassAddAssignChip { fn width(&self) -> usize { - NUM_WEIERSTRASS_ADD_COLS + num_weierstrass_add_cols::() } } impl Air for WeierstrassAddAssignChip where AB: SP1AirBuilder, + Limbs::Limbs>: Copy, { fn eval(&self, builder: &mut AB) { let main = builder.main(); - let row: &WeierstrassAddAssignCols = main.row_slice(0).borrow(); + let row: &WeierstrassAddAssignCols = main.row_slice(0).borrow(); + + let num_words_field_element = ::Limbs::USIZE / 4; - let p_x = limbs_from_prev_access(&row.p_access[0..NUM_WORDS_FIELD_ELEMENT]); - let p_y = limbs_from_prev_access(&row.p_access[NUM_WORDS_FIELD_ELEMENT..]); + let p_x = limbs_from_prev_access(&row.p_access[0..num_words_field_element]); + let p_y = limbs_from_prev_access(&row.p_access[num_words_field_element..]); - let q_x = limbs_from_prev_access(&row.q_access[0..NUM_WORDS_FIELD_ELEMENT]); - let q_y = limbs_from_prev_access(&row.q_access[NUM_WORDS_FIELD_ELEMENT..]); + let q_x = limbs_from_prev_access(&row.q_access[0..num_words_field_element]); + let q_y = limbs_from_prev_access(&row.q_access[num_words_field_element..]); // slope = (q.y - p.y) / (q.x - p.x). let slope = { - row.slope_numerator.eval::( - builder, - &q_y, - &p_y, - FieldOperation::Sub, - ); + row.slope_numerator + .eval::(builder, &q_y, &p_y, FieldOperation::Sub); - row.slope_denominator.eval::( - builder, - &q_x, - &p_x, - FieldOperation::Sub, - ); + row.slope_denominator + .eval::(builder, &q_x, &p_x, FieldOperation::Sub); - row.slope.eval::( + row.slope.eval::( builder, &row.slope_numerator.result, &row.slope_denominator.result, FieldOperation::Div, ); - row.slope.result + &row.slope.result }; // x = slope * slope - self.x - other.x. let x = { - row.slope_squared.eval::( - builder, - &slope, - &slope, - FieldOperation::Mul, - ); + row.slope_squared + .eval::(builder, slope, slope, FieldOperation::Mul); - row.p_x_plus_q_x.eval::( - builder, - &p_x, - &q_x, - FieldOperation::Add, - ); + row.p_x_plus_q_x + .eval::(builder, &p_x, &q_x, FieldOperation::Add); - row.x3_ins.eval::( + row.x3_ins.eval::( builder, &row.slope_squared.result, &row.p_x_plus_q_x.result, FieldOperation::Sub, ); - row.x3_ins.result + &row.x3_ins.result }; // y = slope * (p.x - x_3n) - q.y. { row.p_x_minus_x - .eval::(builder, &p_x, &x, FieldOperation::Sub); + .eval::(builder, &p_x, x, FieldOperation::Sub); - row.slope_times_p_x_minus_x.eval::( + row.slope_times_p_x_minus_x.eval::( builder, - &slope, + slope, &row.p_x_minus_x.result, FieldOperation::Mul, ); - row.y3_ins.eval::( + row.y3_ins.eval::( builder, &row.slope_times_p_x_minus_x.result, &p_y, @@ -307,7 +291,7 @@ where // Constraint self.p_access.value = [self.x3_ins.result, self.y3_ins.result]. This is to // ensure that p_access is updated with the new value. - for i in 0..NUM_LIMBS { + for i in 0..E::BaseField::NB_LIMBS { builder .when(row.is_real) .assert_eq(row.x3_ins.result[i], row.p_access[i / 4].value()[i % 4]); diff --git a/core/src/syscall/precompiles/weierstrass/weierstrass_double.rs b/core/src/syscall/precompiles/weierstrass/weierstrass_double.rs index 07025c881c..9281dfa76f 100644 --- a/core/src/syscall/precompiles/weierstrass/weierstrass_double.rs +++ b/core/src/syscall/precompiles/weierstrass/weierstrass_double.rs @@ -4,23 +4,25 @@ use crate::memory::MemoryCols; use crate::memory::MemoryWriteCols; use crate::operations::field::field_op::FieldOpCols; use crate::operations::field::field_op::FieldOperation; -use crate::operations::field::params::NUM_LIMBS; +use crate::operations::field::params::Limbs; use crate::runtime::ExecutionRecord; use crate::runtime::Syscall; use crate::runtime::SyscallCode; use crate::stark::MachineRecord; use crate::syscall::precompiles::create_ec_double_event; -use crate::syscall::precompiles::limbs_from_biguint; use crate::syscall::precompiles::SyscallContext; +use crate::utils::ec::field::FieldParameters; +use crate::utils::ec::field::NumLimbs; +use crate::utils::ec::field::NumWords; use crate::utils::ec::weierstrass::WeierstrassParameters; use crate::utils::ec::AffinePoint; use crate::utils::ec::EllipticCurve; -use crate::utils::ec::NUM_WORDS_EC_POINT; use crate::utils::ec::NUM_WORDS_FIELD_ELEMENT; use crate::utils::limbs_from_prev_access; use crate::utils::pad_rows; use core::borrow::{Borrow, BorrowMut}; use core::mem::size_of; +use generic_array::GenericArray; use num::BigUint; use num::Zero; use p3_air::AirBuilder; @@ -36,7 +38,9 @@ use std::fmt::Debug; use std::marker::PhantomData; use tracing::instrument; -pub const NUM_WEIERSTRASS_DOUBLE_COLS: usize = size_of::>(); +pub const fn num_weierstrass_double_cols() -> usize { + size_of::>() +} /// A set of columns to double a point on a Weierstrass curve. /// @@ -44,23 +48,23 @@ pub const NUM_WEIERSTRASS_DOUBLE_COLS: usize = size_of:: { +pub struct WeierstrassDoubleAssignCols { pub is_real: T, pub shard: T, pub clk: T, pub p_ptr: T, - pub p_access: [MemoryWriteCols; NUM_WORDS_EC_POINT], - pub(crate) slope_denominator: FieldOpCols, - pub(crate) slope_numerator: FieldOpCols, - pub(crate) slope: FieldOpCols, - pub(crate) p_x_squared: FieldOpCols, - pub(crate) p_x_squared_times_3: FieldOpCols, - pub(crate) slope_squared: FieldOpCols, - pub(crate) p_x_plus_p_x: FieldOpCols, - pub(crate) x3_ins: FieldOpCols, - pub(crate) p_x_minus_x: FieldOpCols, - pub(crate) y3_ins: FieldOpCols, - pub(crate) slope_times_p_x_minus_x: FieldOpCols, + pub p_access: GenericArray, P::WordsCurvePoint>, + pub(crate) slope_denominator: FieldOpCols, + pub(crate) slope_numerator: FieldOpCols, + pub(crate) slope: FieldOpCols, + pub(crate) p_x_squared: FieldOpCols, + pub(crate) p_x_squared_times_3: FieldOpCols, + pub(crate) slope_squared: FieldOpCols, + pub(crate) p_x_plus_p_x: FieldOpCols, + pub(crate) x3_ins: FieldOpCols, + pub(crate) p_x_minus_x: FieldOpCols, + pub(crate) y3_ins: FieldOpCols, + pub(crate) slope_times_p_x_minus_x: FieldOpCols, } #[derive(Default)] @@ -88,7 +92,7 @@ impl WeierstrassDoubleAssignChip { } fn populate_field_ops( - cols: &mut WeierstrassDoubleAssignCols, + cols: &mut WeierstrassDoubleAssignCols, p_x: BigUint, p_y: BigUint, ) { @@ -100,68 +104,51 @@ impl WeierstrassDoubleAssignChip { let slope = { // slope_numerator = a + (p.x * p.x) * 3. let slope_numerator = { - let p_x_squared = - cols.p_x_squared - .populate::(&p_x, &p_x, FieldOperation::Mul); - let p_x_squared_times_3 = cols.p_x_squared_times_3.populate::( + let p_x_squared = cols.p_x_squared.populate(&p_x, &p_x, FieldOperation::Mul); + let p_x_squared_times_3 = cols.p_x_squared_times_3.populate( &p_x_squared, &BigUint::from(3u32), FieldOperation::Mul, ); - cols.slope_numerator.populate::( - &a, - &p_x_squared_times_3, - FieldOperation::Add, - ) + cols.slope_numerator + .populate(&a, &p_x_squared_times_3, FieldOperation::Add) }; // slope_denominator = 2 * y. - let slope_denominator = cols.slope_denominator.populate::( - &BigUint::from(2u32), - &p_y, - FieldOperation::Mul, - ); + let slope_denominator = + cols.slope_denominator + .populate(&BigUint::from(2u32), &p_y, FieldOperation::Mul); - cols.slope.populate::( - &slope_numerator, - &slope_denominator, - FieldOperation::Div, - ) + cols.slope + .populate(&slope_numerator, &slope_denominator, FieldOperation::Div) }; // x = slope * slope - (p.x + p.x). let x = { - let slope_squared = - cols.slope_squared - .populate::(&slope, &slope, FieldOperation::Mul); - let p_x_plus_p_x = - cols.p_x_plus_p_x - .populate::(&p_x, &p_x, FieldOperation::Add); + let slope_squared = cols + .slope_squared + .populate(&slope, &slope, FieldOperation::Mul); + let p_x_plus_p_x = cols.p_x_plus_p_x.populate(&p_x, &p_x, FieldOperation::Add); cols.x3_ins - .populate::(&slope_squared, &p_x_plus_p_x, FieldOperation::Sub) + .populate(&slope_squared, &p_x_plus_p_x, FieldOperation::Sub) }; // y = slope * (p.x - x) - p.y. { - let p_x_minus_x = - cols.p_x_minus_x - .populate::(&p_x, &x, FieldOperation::Sub); - let slope_times_p_x_minus_x = cols.slope_times_p_x_minus_x.populate::( - &slope, - &p_x_minus_x, - FieldOperation::Mul, - ); - cols.y3_ins.populate::( - &slope_times_p_x_minus_x, - &p_y, - FieldOperation::Sub, - ); + let p_x_minus_x = cols.p_x_minus_x.populate(&p_x, &x, FieldOperation::Sub); + let slope_times_p_x_minus_x = + cols.slope_times_p_x_minus_x + .populate(&slope, &p_x_minus_x, FieldOperation::Mul); + cols.y3_ins + .populate(&slope_times_p_x_minus_x, &p_y, FieldOperation::Sub); } } } impl MachineAir for WeierstrassDoubleAssignChip +where + [(); num_weierstrass_double_cols::()]:, { type Record = ExecutionRecord; @@ -192,8 +179,8 @@ impl MachineAir let rows = events .iter() .map(|event| { - let mut row = [F::zero(); NUM_WEIERSTRASS_DOUBLE_COLS]; - let cols: &mut WeierstrassDoubleAssignCols = + let mut row = [F::zero(); num_weierstrass_double_cols::()]; + let cols: &mut WeierstrassDoubleAssignCols = row.as_mut_slice().borrow_mut(); // Decode affine points. @@ -210,7 +197,7 @@ impl MachineAir Self::populate_field_ops(cols, p_x, p_y); // Populate the memory access columns. - for i in 0..NUM_WORDS_EC_POINT { + for i in 0..cols.p_access.len() { cols.p_access[i] .populate(event.p_memory_records[i], &mut new_byte_lookup_events); } @@ -230,8 +217,9 @@ impl MachineAir } pad_rows(&mut rows, || { - let mut row = [F::zero(); NUM_WEIERSTRASS_DOUBLE_COLS]; - let cols: &mut WeierstrassDoubleAssignCols = row.as_mut_slice().borrow_mut(); + let mut row = [F::zero(); num_weierstrass_double_cols::()]; + let cols: &mut WeierstrassDoubleAssignCols = + row.as_mut_slice().borrow_mut(); let zero = BigUint::zero(); Self::populate_field_ops(cols, zero.clone(), zero.clone()); row @@ -240,7 +228,7 @@ impl MachineAir // Convert the trace to a row major matrix. RowMajorMatrix::new( rows.into_iter().flatten().collect::>(), - NUM_WEIERSTRASS_DOUBLE_COLS, + num_weierstrass_double_cols::(), ) } @@ -251,43 +239,42 @@ impl MachineAir impl BaseAir for WeierstrassDoubleAssignChip { fn width(&self) -> usize { - NUM_WEIERSTRASS_DOUBLE_COLS + num_weierstrass_double_cols::() } } impl Air for WeierstrassDoubleAssignChip where AB: SP1AirBuilder, + Limbs::Limbs>: Copy, { fn eval(&self, builder: &mut AB) { let main = builder.main(); - let row: &WeierstrassDoubleAssignCols = main.row_slice(0).borrow(); + let row: &WeierstrassDoubleAssignCols = main.row_slice(0).borrow(); - let p_x = limbs_from_prev_access(&row.p_access[0..NUM_WORDS_FIELD_ELEMENT]); - let p_y = limbs_from_prev_access(&row.p_access[NUM_WORDS_FIELD_ELEMENT..]); + let num_words_field_element = E::BaseField::NB_LIMBS / 4; + let p_x = limbs_from_prev_access(&row.p_access[0..num_words_field_element]); + let p_y = limbs_from_prev_access(&row.p_access[num_words_field_element..]); // a in the Weierstrass form: y^2 = x^3 + a * x + b. - let a = limbs_from_biguint::(&E::a_int()); + // TODO: U32 can't be hardcoded here? + let a = E::BaseField::to_limbs_field::(&E::a_int()); // slope = slope_numerator / slope_denominator. let slope = { // slope_numerator = a + (p.x * p.x) * 3. { - row.p_x_squared.eval::( - builder, - &p_x, - &p_x, - FieldOperation::Mul, - ); + row.p_x_squared + .eval::(builder, &p_x, &p_x, FieldOperation::Mul); - row.p_x_squared_times_3.eval::( + row.p_x_squared_times_3.eval::( builder, &row.p_x_squared.result, - &limbs_from_biguint::(&BigUint::from(3u32)), + &E::BaseField::to_limbs_field::(&BigUint::from(3u32)), FieldOperation::Mul, ); - row.slope_numerator.eval::( + row.slope_numerator.eval::( builder, &a, &row.p_x_squared_times_3.result, @@ -296,57 +283,49 @@ where }; // slope_denominator = 2 * y. - row.slope_denominator.eval::( + row.slope_denominator.eval::( builder, - &limbs_from_biguint::(&BigUint::from(2u32)), + &E::BaseField::to_limbs_field::(&BigUint::from(2u32)), &p_y, FieldOperation::Mul, ); - row.slope.eval::( + row.slope.eval::( builder, &row.slope_numerator.result, &row.slope_denominator.result, FieldOperation::Div, ); - row.slope.result + &row.slope.result }; // x = slope * slope - (p.x + p.x). let x = { - row.slope_squared.eval::( - builder, - &slope, - &slope, - FieldOperation::Mul, - ); - row.p_x_plus_p_x.eval::( - builder, - &p_x, - &p_x, - FieldOperation::Add, - ); - row.x3_ins.eval::( + row.slope_squared + .eval::(builder, slope, slope, FieldOperation::Mul); + row.p_x_plus_p_x + .eval::(builder, &p_x, &p_x, FieldOperation::Add); + row.x3_ins.eval::( builder, &row.slope_squared.result, &row.p_x_plus_p_x.result, FieldOperation::Sub, ); - row.x3_ins.result + &row.x3_ins.result }; // y = slope * (p.x - x) - p.y. { row.p_x_minus_x - .eval::(builder, &p_x, &x, FieldOperation::Sub); - row.slope_times_p_x_minus_x.eval::( + .eval::(builder, &p_x, x, FieldOperation::Sub); + row.slope_times_p_x_minus_x.eval::( builder, - &slope, + slope, &row.p_x_minus_x.result, FieldOperation::Mul, ); - row.y3_ins.eval::( + row.y3_ins.eval::( builder, &row.slope_times_p_x_minus_x.result, &p_y, @@ -356,7 +335,7 @@ where // Constraint self.p_access.value = [self.x3_ins.result, self.y3_ins.result]. This is to // ensure that p_access is updated with the new value. - for i in 0..NUM_LIMBS { + for i in 0..E::BaseField::NB_LIMBS { builder .when(row.is_real) .assert_eq(row.x3_ins.result[i], row.p_access[i / 4].value()[i % 4]); diff --git a/core/src/utils/ec/edwards/ed25519.rs b/core/src/utils/ec/edwards/ed25519.rs index 01f99e3b58..0a794304bd 100644 --- a/core/src/utils/ec/edwards/ed25519.rs +++ b/core/src/utils/ec/edwards/ed25519.rs @@ -1,11 +1,13 @@ use curve25519_dalek::edwards::CompressedEdwardsY; +use generic_array::GenericArray; use num::{BigUint, Num, One}; use serde::{Deserialize, Serialize}; use std::str::FromStr; +use typenum::{U32, U62}; -use crate::operations::field::params::{NB_BITS_PER_LIMB, NUM_LIMBS}; use crate::utils::ec::edwards::{EdwardsCurve, EdwardsParameters}; -use crate::utils::ec::field::{FieldParameters, MAX_NB_LIMBS}; +use crate::utils::ec::field::FieldParameters; +use crate::utils::ec::field::NumLimbs; use crate::utils::ec::{AffinePoint, EllipticCurveParameters}; pub type Ed25519 = EdwardsCurve; @@ -17,13 +19,11 @@ pub struct Ed25519Parameters; pub struct Ed25519BaseField; impl FieldParameters for Ed25519BaseField { - const NB_BITS_PER_LIMB: usize = NB_BITS_PER_LIMB; - const NB_LIMBS: usize = NUM_LIMBS; - const NB_WITNESS_LIMBS: usize = 2 * Self::NB_LIMBS - 2; - const MODULUS: [u8; NUM_LIMBS] = [ + const MODULUS: &'static [u8] = &[ 237, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 127, ]; + const WITNESS_OFFSET: usize = 1usize << 13; fn modulus() -> BigUint { @@ -31,15 +31,20 @@ impl FieldParameters for Ed25519BaseField { } } +impl NumLimbs for Ed25519BaseField { + type Limbs = U32; + type Witness = U62; +} + impl EllipticCurveParameters for Ed25519Parameters { type BaseField = Ed25519BaseField; } impl EdwardsParameters for Ed25519Parameters { - const D: [u16; MAX_NB_LIMBS] = [ - 30883, 4953, 19914, 30187, 55467, 16705, 2637, 112, 59544, 30585, 16505, 36039, 65139, - 11119, 27886, 20995, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - ]; + const D: GenericArray = GenericArray::from_array([ + 163, 120, 89, 19, 202, 77, 235, 117, 171, 216, 65, 65, 77, 10, 112, 0, 152, 232, 121, 119, + 121, 64, 199, 140, 115, 254, 111, 43, 238, 108, 3, 82, + ]); fn prime_group_order() -> BigUint { BigUint::from(2u32).pow(252) + BigUint::from(27742317777372353535851937790883648493u128) diff --git a/core/src/utils/ec/edwards/mod.rs b/core/src/utils/ec/edwards/mod.rs index b608231d3d..391b0f07db 100644 --- a/core/src/utils/ec/edwards/mod.rs +++ b/core/src/utils/ec/edwards/mod.rs @@ -1,13 +1,16 @@ pub mod ed25519; +use generic_array::GenericArray; use num::{BigUint, Zero}; use serde::{Deserialize, Serialize}; -use crate::utils::ec::field::{FieldParameters, MAX_NB_LIMBS}; +use crate::utils::ec::field::FieldParameters; use crate::utils::ec::{AffinePoint, EllipticCurve, EllipticCurveParameters}; +use super::field::NumLimbs; + pub trait EdwardsParameters: EllipticCurveParameters { - const D: [u16; MAX_NB_LIMBS]; + const D: GenericArray::Limbs>; fn generator() -> (BigUint, BigUint); @@ -16,7 +19,7 @@ pub trait EdwardsParameters: EllipticCurveParameters { fn d_biguint() -> BigUint { let mut modulus = BigUint::zero(); for (i, limb) in Self::D.iter().enumerate() { - modulus += BigUint::from(*limb) << (16 * i); + modulus += BigUint::from(*limb) << (8 * i); } modulus } @@ -31,7 +34,7 @@ pub trait EdwardsParameters: EllipticCurveParameters { pub struct EdwardsCurve(pub E); impl EdwardsParameters for EdwardsCurve { - const D: [u16; MAX_NB_LIMBS] = E::D; + const D: GenericArray::Limbs> = E::D; fn generator() -> (BigUint, BigUint) { E::generator() @@ -94,7 +97,7 @@ impl AffinePoint> { &self, other: &AffinePoint>, ) -> AffinePoint> { - let p = E::BaseField::modulus(); + let p = ::BaseField::modulus(); let x_3n = (&self.x * &other.y + &self.y * &other.x) % &p; let y_3n = (&self.y * &other.y + &self.x * &other.x) % &p; diff --git a/core/src/utils/ec/field.rs b/core/src/utils/ec/field.rs index 2cff8134b9..f1920cbcba 100644 --- a/core/src/utils/ec/field.rs +++ b/core/src/utils/ec/field.rs @@ -1,25 +1,26 @@ use super::utils::biguint_from_limbs; -use crate::operations::field::params::Limbs; -use crate::operations::field::params::NB_BITS_PER_LIMB; -use crate::operations::field::params::NUM_LIMBS; +use crate::operations::field::params::{Limbs, NB_BITS_PER_LIMB}; +use generic_array::sequence::GenericSequence; +use generic_array::{ArrayLength, GenericArray}; use num::BigUint; use p3_field::Field; use serde::{de::DeserializeOwned, Serialize}; use std::fmt::Debug; - -pub const MAX_NB_LIMBS: usize = 32; +use std::ops::Div; +use typenum::Unsigned; +use typenum::{U2, U4}; pub trait FieldParameters: - Send + Sync + Copy + 'static + Debug + Serialize + DeserializeOwned + Send + Sync + Copy + 'static + Debug + Serialize + DeserializeOwned + NumLimbs { const NB_BITS_PER_LIMB: usize = NB_BITS_PER_LIMB; - const NB_LIMBS: usize = NUM_LIMBS; + const NB_LIMBS: usize = Self::Limbs::USIZE; const NB_WITNESS_LIMBS: usize = 2 * Self::NB_LIMBS - 2; const WITNESS_OFFSET: usize = 1usize << 13; - const MODULUS: [u8; NUM_LIMBS]; + const MODULUS: &'static [u8]; fn modulus() -> BigUint { - biguint_from_limbs(&Self::MODULUS) + biguint_from_limbs(Self::MODULUS) } fn nb_bits() -> usize { @@ -28,28 +29,69 @@ pub trait FieldParameters: fn modulus_field_iter() -> impl Iterator { Self::MODULUS - .into_iter() - .map(|x| F::from_canonical_u8(x)) + .iter() + .map(|x| F::from_canonical_u8(*x)) .take(Self::NB_LIMBS) } - fn to_limbs(x: &BigUint) -> Limbs { + /// Convert a BigUint to a Vec of u8 limbs (with len NB_LIMBS). + fn to_limbs(x: &BigUint) -> Vec { let mut bytes = x.to_bytes_le(); - bytes.resize(NUM_LIMBS, 0u8); - let mut limbs = [0u8; NUM_LIMBS]; - limbs.copy_from_slice(&bytes); - Limbs(limbs) + bytes.resize(Self::NB_LIMBS, 0u8); + bytes + } + + /// Convert a BigUint to a Vec of F limbs (with len NB_LIMBS). + fn to_limbs_field_vec, F: Field>(x: &BigUint) -> Vec { + Self::to_limbs(x) + .into_iter() + .map(|x| F::from_canonical_u8(x).into()) + .collect::>() + } + + /// Convert a BigUint to Limbs. + fn to_limbs_field, F: Field>(x: &BigUint) -> Limbs { + limbs_from_vec(Self::to_limbs_field_vec(x)) } +} - fn to_limbs_field(x: &BigUint) -> Limbs { - Limbs( - Self::to_limbs(x) - .0 - .into_iter() - .map(|x| F::from_canonical_u8(x)) - .collect::>() - .try_into() - .unwrap(), - ) +/// Convert a vec of u8 limbs to a Limbs of N length. +pub fn limbs_from_vec, N: ArrayLength, F: Field>(limbs: Vec) -> Limbs { + debug_assert_eq!(limbs.len(), N::USIZE); + let mut result = GenericArray::::generate(|_i| F::zero().into()); + for (i, limb) in limbs.into_iter().enumerate() { + result[i] = limb; } + Limbs(result) +} + +/// Trait that holds the typenum values for # of limbs and # of witness limbs. +pub trait NumLimbs: Clone + Debug { + type Limbs: ArrayLength + Debug; + type Witness: ArrayLength + Debug; +} + +/// Trait that holds number of words needed to represent a field element and a curve point. +pub trait NumWords: Clone + Debug { + /// The number of words needed to represent a field element. + type WordsFieldElement: ArrayLength + Debug; + /// The number of words needed to represent a curve point (two field elements). + type WordsCurvePoint: ArrayLength + Debug; +} + +/// Implement NumWords for NumLimbs where # Limbs is divisible by 4. +/// +/// Using typenum we can do N/4 and N/2 in type-level arithmetic. Having it as a separate trait +/// avoids needing the Div where clauses everywhere. +impl NumWords for N +where + N::Limbs: Div, + N::Limbs: Div, + >::Output: ArrayLength + Debug, + >::Output: ArrayLength + Debug, +{ + /// Each word has 4 limbs so we divide by 4. + type WordsFieldElement = >::Output; + /// Curve point has 2 field elements so we divide by 2. + type WordsCurvePoint = >::Output; } diff --git a/core/src/utils/ec/mod.rs b/core/src/utils/ec/mod.rs index 55bae646ec..a6449393ce 100644 --- a/core/src/utils/ec/mod.rs +++ b/core/src/utils/ec/mod.rs @@ -11,7 +11,8 @@ use std::fmt::Debug; use std::ops::{Add, Neg}; use crate::air::WORD_SIZE; -use crate::operations::field::params::NUM_LIMBS; + +use self::field::NumWords; pub const NUM_WORDS_FIELD_ELEMENT: usize = 8; pub const NUM_BYTES_FIELD_ELEMENT: usize = NUM_WORDS_FIELD_ELEMENT * WORD_SIZE; @@ -58,9 +59,9 @@ impl AffinePoint { pub fn to_words_le(&self) -> [u32; 16] { let mut x_bytes = self.x.to_bytes_le(); - x_bytes.resize(NUM_LIMBS, 0u8); + x_bytes.resize(32, 0u8); let mut y_bytes = self.y.to_bytes_le(); - y_bytes.resize(NUM_LIMBS, 0u8); + y_bytes.resize(32, 0u8); let mut words = [0u32; 16]; for i in 0..8 { @@ -84,11 +85,14 @@ impl AffinePoint { pub trait EllipticCurveParameters: Debug + Send + Sync + Copy + Serialize + DeserializeOwned + 'static { - type BaseField: FieldParameters; + type BaseField: FieldParameters + NumWords; } /// An interface for elliptic curve groups. pub trait EllipticCurve: EllipticCurveParameters { + const NB_LIMBS: usize = Self::BaseField::NB_LIMBS; + + const NB_WITNESS_LIMBS: usize = Self::BaseField::NB_WITNESS_LIMBS; /// Adds two different points on the curve. /// /// Warning: This method assumes that the two points are different. diff --git a/core/src/utils/ec/utils.rs b/core/src/utils/ec/utils.rs index 834e112fdb..523fa8b10b 100644 --- a/core/src/utils/ec/utils.rs +++ b/core/src/utils/ec/utils.rs @@ -1,7 +1,5 @@ use num::BigUint; -use crate::operations::field::params::NUM_LIMBS; - pub fn biguint_to_bits_le(integer: &BigUint, num_bits: usize) -> Vec { let byte_vec = integer.to_bytes_le(); let mut bits = Vec::new(); @@ -18,14 +16,11 @@ pub fn biguint_to_bits_le(integer: &BigUint, num_bits: usize) -> Vec { bits } -pub fn biguint_to_limbs(integer: &BigUint) -> [u8; NUM_LIMBS] { +pub fn biguint_to_limbs(integer: &BigUint) -> [u8; N] { let mut bytes = integer.to_bytes_le(); - debug_assert!( - bytes.len() <= NUM_LIMBS, - "Number too large to fit in {NUM_LIMBS} limbs" - ); - bytes.resize(NUM_LIMBS, 0u8); - let mut limbs = [0u8; NUM_LIMBS]; + debug_assert!(bytes.len() <= N, "Number too large to fit in {N} limbs"); + bytes.resize(N, 0u8); + let mut limbs = [0u8; N]; limbs.copy_from_slice(&bytes); limbs } diff --git a/core/src/utils/ec/weierstrass/bn254.rs b/core/src/utils/ec/weierstrass/bn254.rs index a84c172672..4ab5ac5756 100644 --- a/core/src/utils/ec/weierstrass/bn254.rs +++ b/core/src/utils/ec/weierstrass/bn254.rs @@ -1,8 +1,11 @@ +use generic_array::GenericArray; use num::{BigUint, Num, Zero}; use serde::{Deserialize, Serialize}; +use typenum::{U32, U62}; use super::{SwCurve, WeierstrassParameters}; -use crate::utils::ec::field::{FieldParameters, MAX_NB_LIMBS}; +use crate::utils::ec::field::FieldParameters; +use crate::utils::ec::field::NumLimbs; use crate::utils::ec::EllipticCurveParameters; #[derive(Debug, Clone, Copy, PartialEq, Serialize, Deserialize)] @@ -16,13 +19,7 @@ pub type Bn254 = SwCurve; pub struct Bn254BaseField; impl FieldParameters for Bn254BaseField { - const NB_BITS_PER_LIMB: usize = 16; - - const NB_LIMBS: usize = 16; - - const NB_WITNESS_LIMBS: usize = 2 * Self::NB_LIMBS - 2; - - const MODULUS: [u8; MAX_NB_LIMBS] = [ + const MODULUS: &'static [u8] = &[ 71, 253, 124, 216, 22, 140, 32, 60, 141, 202, 113, 104, 145, 106, 129, 151, 93, 88, 129, 129, 182, 69, 80, 184, 41, 160, 49, 225, 114, 78, 100, 48, ]; @@ -38,20 +35,25 @@ impl FieldParameters for Bn254BaseField { } } +impl NumLimbs for Bn254BaseField { + type Limbs = U32; + type Witness = U62; +} + impl EllipticCurveParameters for Bn254Parameters { type BaseField = Bn254BaseField; } impl WeierstrassParameters for Bn254Parameters { - const A: [u16; MAX_NB_LIMBS] = [ + const A: GenericArray = GenericArray::from_array([ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - ]; + ]); - const B: [u16; MAX_NB_LIMBS] = [ + const B: GenericArray = GenericArray::from_array([ 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - ]; + ]); fn generator() -> (BigUint, BigUint) { let x = BigUint::from(1u32); let y = BigUint::from(2u32); @@ -84,7 +86,7 @@ mod tests { #[test] fn test_weierstrass_biguint_scalar_mul() { assert_eq!( - biguint_from_limbs(&Bn254BaseField::MODULUS), + biguint_from_limbs(Bn254BaseField::MODULUS), Bn254BaseField::modulus() ); } diff --git a/core/src/utils/ec/weierstrass/mod.rs b/core/src/utils/ec/weierstrass/mod.rs index 17f2a97ed4..84ebe130d2 100644 --- a/core/src/utils/ec/weierstrass/mod.rs +++ b/core/src/utils/ec/weierstrass/mod.rs @@ -1,17 +1,20 @@ +use generic_array::GenericArray; use num::{BigUint, Zero}; use serde::{Deserialize, Serialize}; -use crate::utils::ec::field::{FieldParameters, MAX_NB_LIMBS}; +use crate::utils::ec::field::FieldParameters; use crate::utils::ec::utils::biguint_to_bits_le; use crate::utils::ec::{AffinePoint, EllipticCurve, EllipticCurveParameters}; +use super::field::NumLimbs; + pub mod bn254; pub mod secp256k1; /// Parameters that specify a short Weierstrass curve : y^2 = x^3 + ax + b. pub trait WeierstrassParameters: EllipticCurveParameters { - const A: [u16; MAX_NB_LIMBS]; - const B: [u16; MAX_NB_LIMBS]; + const A: GenericArray::Limbs>; + const B: GenericArray::Limbs>; fn generator() -> (BigUint, BigUint); @@ -20,7 +23,7 @@ pub trait WeierstrassParameters: EllipticCurveParameters { fn a_int() -> BigUint { let mut modulus = BigUint::zero(); for (i, limb) in Self::A.iter().enumerate() { - modulus += BigUint::from(*limb) << (16 * i); + modulus += BigUint::from(*limb) << (8 * i); } modulus } @@ -28,7 +31,7 @@ pub trait WeierstrassParameters: EllipticCurveParameters { fn b_int() -> BigUint { let mut modulus = BigUint::zero(); for (i, limb) in Self::B.iter().enumerate() { - modulus += BigUint::from(*limb) << (16 * i); + modulus += BigUint::from(*limb) << (8 * i); } modulus } @@ -42,8 +45,8 @@ pub trait WeierstrassParameters: EllipticCurveParameters { pub struct SwCurve(pub E); impl WeierstrassParameters for SwCurve { - const A: [u16; MAX_NB_LIMBS] = E::A; - const B: [u16; MAX_NB_LIMBS] = E::B; + const A: GenericArray::Limbs> = E::A; + const B: GenericArray::Limbs> = E::B; fn a_int() -> BigUint { E::a_int() @@ -71,6 +74,9 @@ impl EllipticCurveParameters for SwCurve { } impl EllipticCurve for SwCurve { + const NB_LIMBS: usize = Self::BaseField::NB_LIMBS; + const NB_WITNESS_LIMBS: usize = Self::BaseField::NB_WITNESS_LIMBS; + fn ec_add(p: &AffinePoint, q: &AffinePoint) -> AffinePoint { p.sw_add(q) } diff --git a/core/src/utils/ec/weierstrass/secp256k1.rs b/core/src/utils/ec/weierstrass/secp256k1.rs index 4ebcc49719..2f61b8e908 100644 --- a/core/src/utils/ec/weierstrass/secp256k1.rs +++ b/core/src/utils/ec/weierstrass/secp256k1.rs @@ -3,12 +3,14 @@ use std::str::FromStr; +use generic_array::GenericArray; use num::{BigUint, Zero}; use serde::{Deserialize, Serialize}; +use typenum::{U32, U62}; use super::{SwCurve, WeierstrassParameters}; -use crate::operations::field::params::{NB_BITS_PER_LIMB, NUM_LIMBS}; -use crate::utils::ec::field::{FieldParameters, MAX_NB_LIMBS}; +use crate::utils::ec::field::FieldParameters; +use crate::utils::ec::field::NumLimbs; use crate::utils::ec::EllipticCurveParameters; use k256::FieldElement; use num::traits::FromBytes; @@ -25,13 +27,7 @@ pub type Secp256k1 = SwCurve; pub struct Secp256k1BaseField; impl FieldParameters for Secp256k1BaseField { - const NB_BITS_PER_LIMB: usize = NB_BITS_PER_LIMB; - - const NB_LIMBS: usize = NUM_LIMBS; - - const NB_WITNESS_LIMBS: usize = 2 * Self::NB_LIMBS - 2; - - const MODULUS: [u8; MAX_NB_LIMBS] = [ + const MODULUS: &'static [u8] = &[ 0x2f, 0xfc, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, @@ -41,24 +37,29 @@ impl FieldParameters for Secp256k1BaseField { const WITNESS_OFFSET: usize = 1usize << 14; fn modulus() -> BigUint { - BigUint::from_bytes_le(&Self::MODULUS) + BigUint::from_bytes_le(Self::MODULUS) } } +impl NumLimbs for Secp256k1BaseField { + type Limbs = U32; + type Witness = U62; +} + impl EllipticCurveParameters for Secp256k1Parameters { type BaseField = Secp256k1BaseField; } impl WeierstrassParameters for Secp256k1Parameters { - const A: [u16; MAX_NB_LIMBS] = [ + const A: GenericArray = GenericArray::from_array([ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - ]; + ]); - const B: [u16; MAX_NB_LIMBS] = [ + const B: GenericArray = GenericArray::from_array([ 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - ]; + ]); fn generator() -> (BigUint, BigUint) { let x = BigUint::from_str( "55066263022277343669578718895168534326250603453777594175500187360389116729240", @@ -107,7 +108,7 @@ mod tests { #[test] fn test_weierstrass_biguint_scalar_mul() { assert_eq!( - biguint_from_limbs(&Secp256k1BaseField::MODULUS), + biguint_from_limbs(Secp256k1BaseField::MODULUS), Secp256k1BaseField::modulus() ); } diff --git a/core/src/utils/mod.rs b/core/src/utils/mod.rs index 2f79b0cfb9..69b975ae10 100644 --- a/core/src/utils/mod.rs +++ b/core/src/utils/mod.rs @@ -16,6 +16,7 @@ pub use tracer::*; pub use programs::*; use crate::{memory::MemoryCols, operations::field::params::Limbs}; +use generic_array::ArrayLength; pub const fn indices_arr() -> [usize; N] { let mut indices_arr = [0; N]; @@ -36,7 +37,9 @@ pub fn pad_to_power_of_two(values: &mut Vec< values.resize(n_real_rows.next_power_of_two() * N, T::default()); } -pub fn limbs_from_prev_access>(cols: &[M]) -> Limbs { +pub fn limbs_from_prev_access>( + cols: &[M], +) -> Limbs { let vec = cols .iter() .flat_map(|access| access.prev_value().0) @@ -48,7 +51,7 @@ pub fn limbs_from_prev_access>(cols: &[M]) -> Limbs Limbs(sized) } -pub fn limbs_from_access>(cols: &[M]) -> Limbs { +pub fn limbs_from_access>(cols: &[M]) -> Limbs { let vec = cols .iter() .flat_map(|access| access.value().0) diff --git a/derive/src/lib.rs b/derive/src/lib.rs index 3835701f1b..d3679de47d 100644 --- a/derive/src/lib.rs +++ b/derive/src/lib.rs @@ -38,41 +38,53 @@ pub fn aligned_borrow_derive(input: TokenStream) -> TokenStream { let ast = parse_macro_input!(input as DeriveInput); let name = &ast.ident; - // Ensure the first generic parameter is the type generic, and rest all are const generics. - let mut generics_iter = ast.generics.params.iter(); - - // Extract the first generic parameter and ensure it's a type. - let type_generic = match generics_iter.next().expect("No generic parameters found") { - GenericParam::Type(type_param) => &type_param.ident, - _ => panic!("The first generic parameter must be a type."), - }; - - // Collect the remaining generic parameters, ensuring they are all const generics. - let const_generics: Vec<_> = generics_iter.map(|param| match param { - GenericParam::Const(const_param) => &const_param.ident, - _ => panic!("`AlignedBorrow` supports only a type as the first generic parameter and const generics after that"), - }).collect(); - - let methods = { - quote! { - impl<#type_generic: Copy #(, const #const_generics: usize)*> core::borrow::Borrow<#name<#type_generic #(, #const_generics)*>> for [#type_generic] { - fn borrow(&self) -> &#name<#type_generic #(, #const_generics)*> { - debug_assert_eq!(self.len(), std::mem::size_of::<#name>()); - let (prefix, shorts, _suffix) = unsafe { self.align_to::<#name<#type_generic #(, #const_generics)*>>() }; - debug_assert!(prefix.is_empty(), "Alignment should match"); - debug_assert_eq!(shorts.len(), 1); - &shorts[0] - } + // Get first generic which must be type (ex. `T`) for input + let type_generic = ast + .generics + .params + .iter() + .map(|param| match param { + GenericParam::Type(type_param) => &type_param.ident, + _ => panic!("Expected first generic to be a type"), + }) + .next() + .expect("Expected at least one generic"); + + // Get generics after the first (ex. `N: NumLimbs, const M: usize`) + // We need this because when we assert the size, we want to substitute u8 for T. + let non_first_generics = ast + .generics + .params + .iter() + .skip(1) + .filter_map(|param| match param { + GenericParam::Type(type_param) => Some(&type_param.ident), + GenericParam::Const(const_param) => Some(&const_param.ident), + _ => None, + }) + .collect::>(); + + // Get impl generics (``), type generics (``), where clause (`where T: Clone`) + let (impl_generics, type_generics, where_clause) = ast.generics.split_for_impl(); + + let methods = quote! { + impl #impl_generics core::borrow::Borrow<#name #type_generics> for [#type_generic] #where_clause { + fn borrow(&self) -> &#name #type_generics { + debug_assert_eq!(self.len(), std::mem::size_of::<#name>()); + let (prefix, shorts, _suffix) = unsafe { self.align_to::<#name #type_generics>() }; + debug_assert!(prefix.is_empty(), "Alignment should match"); + debug_assert_eq!(shorts.len(), 1); + &shorts[0] } + } - impl<#type_generic: Copy #(, const #const_generics: usize)*> core::borrow::BorrowMut<#name<#type_generic #(, #const_generics)*>> for [#type_generic] { - fn borrow_mut(&mut self) -> &mut #name<#type_generic #(, #const_generics)*> { - debug_assert_eq!(self.len(), std::mem::size_of::<#name>()); - let (prefix, shorts, _suffix) = unsafe { self.align_to_mut::<#name<#type_generic #(, #const_generics)*>>() }; - debug_assert!(prefix.is_empty(), "Alignment should match"); - debug_assert_eq!(shorts.len(), 1); - &mut shorts[0] - } + impl #impl_generics core::borrow::BorrowMut<#name #type_generics> for [#type_generic] #where_clause { + fn borrow_mut(&mut self) -> &mut #name #type_generics { + debug_assert_eq!(self.len(), std::mem::size_of::<#name>()); + let (prefix, shorts, _suffix) = unsafe { self.align_to_mut::<#name #type_generics>() }; + debug_assert!(prefix.is_empty(), "Alignment should match"); + debug_assert_eq!(shorts.len(), 1); + &mut shorts[0] } } }; diff --git a/examples/chess/script/Cargo.lock b/examples/chess/script/Cargo.lock index b478c5466c..413158fd22 100644 --- a/examples/chess/script/Cargo.lock +++ b/examples/chess/script/Cargo.lock @@ -207,7 +207,7 @@ version = "0.10.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" dependencies = [ - "generic-array", + "generic-array 0.14.7", ] [[package]] @@ -403,7 +403,7 @@ version = "0.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0dc92fb57ca44df6db8059111ab3af99a63d5d0f8375d9972e319a379c6bab76" dependencies = [ - "generic-array", + "generic-array 0.14.7", "rand_core", "subtle", "zeroize", @@ -415,7 +415,7 @@ version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" dependencies = [ - "generic-array", + "generic-array 0.14.7", "typenum", ] @@ -568,7 +568,7 @@ dependencies = [ "crypto-bigint", "digest", "ff", - "generic-array", + "generic-array 0.14.7", "group", "pkcs8", "rand_core", @@ -733,6 +733,15 @@ dependencies = [ "zeroize", ] +[[package]] +name = "generic-array" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fe739944a5406424e080edccb6add95685130b9f160d5407c639c7df0c5836b0" +dependencies = [ + "typenum", +] + [[package]] name = "getrandom" version = "0.2.12" @@ -849,6 +858,15 @@ dependencies = [ "serde", ] +[[package]] +name = "itertools" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1c173a5686ce8bfa551b3563d0c2170bf24ca44da99c7ca4bfdab5418c3fe57" +dependencies = [ + "either", +] + [[package]] name = "itertools" version = "0.12.1" @@ -1094,7 +1112,7 @@ checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39" [[package]] name = "p3-air" version = "0.1.0" -source = "git+https://github.com/succinctlabs/plonky3.git#7d11ba55fa2c939449b593df298d04d7e15979d5" +source = "git+https://github.com/Plonky3/Plonky3.git?branch=sp1#4809fa7bedd9ba8f6f5d3267b1592618e3776c57" dependencies = [ "p3-field", "p3-matrix", @@ -1103,9 +1121,13 @@ dependencies = [ [[package]] name = "p3-baby-bear" version = "0.1.0" -source = "git+https://github.com/succinctlabs/plonky3.git#7d11ba55fa2c939449b593df298d04d7e15979d5" +source = "git+https://github.com/Plonky3/Plonky3.git?branch=sp1#4809fa7bedd9ba8f6f5d3267b1592618e3776c57" dependencies = [ + "num-bigint", "p3-field", + "p3-mds", + "p3-poseidon2", + "p3-symmetric", "rand", "serde", ] @@ -1113,7 +1135,7 @@ dependencies = [ [[package]] name = "p3-blake3" version = "0.1.0" -source = "git+https://github.com/succinctlabs/plonky3.git#7d11ba55fa2c939449b593df298d04d7e15979d5" +source = "git+https://github.com/Plonky3/Plonky3.git?branch=sp1#4809fa7bedd9ba8f6f5d3267b1592618e3776c57" dependencies = [ "blake3", "p3-symmetric", @@ -1122,7 +1144,7 @@ dependencies = [ [[package]] name = "p3-challenger" version = "0.1.0" -source = "git+https://github.com/succinctlabs/plonky3.git#7d11ba55fa2c939449b593df298d04d7e15979d5" +source = "git+https://github.com/Plonky3/Plonky3.git?branch=sp1#4809fa7bedd9ba8f6f5d3267b1592618e3776c57" dependencies = [ "p3-field", "p3-maybe-rayon", @@ -1134,31 +1156,36 @@ dependencies = [ [[package]] name = "p3-commit" version = "0.1.0" -source = "git+https://github.com/succinctlabs/plonky3.git#7d11ba55fa2c939449b593df298d04d7e15979d5" +source = "git+https://github.com/Plonky3/Plonky3.git?branch=sp1#4809fa7bedd9ba8f6f5d3267b1592618e3776c57" dependencies = [ + "itertools 0.12.1", "p3-challenger", "p3-field", "p3-matrix", + "p3-util", "serde", ] [[package]] name = "p3-dft" version = "0.1.0" -source = "git+https://github.com/succinctlabs/plonky3.git#7d11ba55fa2c939449b593df298d04d7e15979d5" +source = "git+https://github.com/Plonky3/Plonky3.git?branch=sp1#4809fa7bedd9ba8f6f5d3267b1592618e3776c57" dependencies = [ "p3-field", "p3-matrix", "p3-maybe-rayon", "p3-util", + "tracing", ] [[package]] name = "p3-field" version = "0.1.0" -source = "git+https://github.com/succinctlabs/plonky3.git#7d11ba55fa2c939449b593df298d04d7e15979d5" +source = "git+https://github.com/Plonky3/Plonky3.git?branch=sp1#4809fa7bedd9ba8f6f5d3267b1592618e3776c57" dependencies = [ - "itertools", + "itertools 0.12.1", + "num-bigint", + "num-traits", "p3-util", "rand", "serde", @@ -1167,9 +1194,9 @@ dependencies = [ [[package]] name = "p3-fri" version = "0.1.0" -source = "git+https://github.com/succinctlabs/plonky3.git#7d11ba55fa2c939449b593df298d04d7e15979d5" +source = "git+https://github.com/Plonky3/Plonky3.git?branch=sp1#4809fa7bedd9ba8f6f5d3267b1592618e3776c57" dependencies = [ - "itertools", + "itertools 0.12.1", "p3-challenger", "p3-commit", "p3-dft", @@ -1185,9 +1212,14 @@ dependencies = [ [[package]] name = "p3-goldilocks" version = "0.1.0" -source = "git+https://github.com/succinctlabs/plonky3.git#7d11ba55fa2c939449b593df298d04d7e15979d5" +source = "git+https://github.com/Plonky3/Plonky3.git?branch=sp1#4809fa7bedd9ba8f6f5d3267b1592618e3776c57" dependencies = [ + "num-bigint", + "p3-dft", "p3-field", + "p3-mds", + "p3-poseidon2", + "p3-symmetric", "p3-util", "rand", "serde", @@ -1196,7 +1228,7 @@ dependencies = [ [[package]] name = "p3-interpolation" version = "0.1.0" -source = "git+https://github.com/succinctlabs/plonky3.git#7d11ba55fa2c939449b593df298d04d7e15979d5" +source = "git+https://github.com/Plonky3/Plonky3.git?branch=sp1#4809fa7bedd9ba8f6f5d3267b1592618e3776c57" dependencies = [ "p3-field", "p3-matrix", @@ -1206,7 +1238,7 @@ dependencies = [ [[package]] name = "p3-keccak" version = "0.1.0" -source = "git+https://github.com/succinctlabs/plonky3.git#7d11ba55fa2c939449b593df298d04d7e15979d5" +source = "git+https://github.com/Plonky3/Plonky3.git?branch=sp1#4809fa7bedd9ba8f6f5d3267b1592618e3776c57" dependencies = [ "p3-symmetric", "tiny-keccak", @@ -1215,7 +1247,7 @@ dependencies = [ [[package]] name = "p3-keccak-air" version = "0.1.0" -source = "git+https://github.com/succinctlabs/plonky3.git#7d11ba55fa2c939449b593df298d04d7e15979d5" +source = "git+https://github.com/Plonky3/Plonky3.git?branch=sp1#4809fa7bedd9ba8f6f5d3267b1592618e3776c57" dependencies = [ "p3-air", "p3-field", @@ -1227,19 +1259,21 @@ dependencies = [ [[package]] name = "p3-matrix" version = "0.1.0" -source = "git+https://github.com/succinctlabs/plonky3.git#7d11ba55fa2c939449b593df298d04d7e15979d5" +source = "git+https://github.com/Plonky3/Plonky3.git?branch=sp1#4809fa7bedd9ba8f6f5d3267b1592618e3776c57" dependencies = [ + "itertools 0.12.1", "p3-field", "p3-maybe-rayon", "p3-util", "rand", "serde", + "tracing", ] [[package]] name = "p3-maybe-rayon" version = "0.1.0" -source = "git+https://github.com/succinctlabs/plonky3.git#7d11ba55fa2c939449b593df298d04d7e15979d5" +source = "git+https://github.com/Plonky3/Plonky3.git?branch=sp1#4809fa7bedd9ba8f6f5d3267b1592618e3776c57" dependencies = [ "rayon", ] @@ -1247,14 +1281,12 @@ dependencies = [ [[package]] name = "p3-mds" version = "0.1.0" -source = "git+https://github.com/succinctlabs/plonky3.git#7d11ba55fa2c939449b593df298d04d7e15979d5" +source = "git+https://github.com/Plonky3/Plonky3.git?branch=sp1#4809fa7bedd9ba8f6f5d3267b1592618e3776c57" dependencies = [ - "p3-baby-bear", + "itertools 0.11.0", "p3-dft", "p3-field", - "p3-goldilocks", "p3-matrix", - "p3-mersenne-31", "p3-symmetric", "p3-util", "rand", @@ -1263,9 +1295,9 @@ dependencies = [ [[package]] name = "p3-merkle-tree" version = "0.1.0" -source = "git+https://github.com/succinctlabs/plonky3.git#7d11ba55fa2c939449b593df298d04d7e15979d5" +source = "git+https://github.com/Plonky3/Plonky3.git?branch=sp1#4809fa7bedd9ba8f6f5d3267b1592618e3776c57" dependencies = [ - "itertools", + "itertools 0.12.1", "p3-commit", "p3-field", "p3-matrix", @@ -1276,31 +1308,12 @@ dependencies = [ "tracing", ] -[[package]] -name = "p3-mersenne-31" -version = "0.1.0" -source = "git+https://github.com/succinctlabs/plonky3.git#7d11ba55fa2c939449b593df298d04d7e15979d5" -dependencies = [ - "itertools", - "p3-dft", - "p3-field", - "p3-matrix", - "p3-maybe-rayon", - "p3-util", - "rand", - "serde", -] - [[package]] name = "p3-poseidon2" version = "0.1.0" -source = "git+https://github.com/succinctlabs/plonky3.git#7d11ba55fa2c939449b593df298d04d7e15979d5" +source = "git+https://github.com/Plonky3/Plonky3.git?branch=sp1#4809fa7bedd9ba8f6f5d3267b1592618e3776c57" dependencies = [ - "p3-baby-bear", "p3-field", - "p3-goldilocks", - "p3-mds", - "p3-mersenne-31", "p3-symmetric", "rand", ] @@ -1308,9 +1321,9 @@ dependencies = [ [[package]] name = "p3-symmetric" version = "0.1.0" -source = "git+https://github.com/succinctlabs/plonky3.git#7d11ba55fa2c939449b593df298d04d7e15979d5" +source = "git+https://github.com/Plonky3/Plonky3.git?branch=sp1#4809fa7bedd9ba8f6f5d3267b1592618e3776c57" dependencies = [ - "itertools", + "itertools 0.12.1", "p3-field", "serde", ] @@ -1318,9 +1331,9 @@ dependencies = [ [[package]] name = "p3-uni-stark" version = "0.1.0" -source = "git+https://github.com/succinctlabs/plonky3.git#7d11ba55fa2c939449b593df298d04d7e15979d5" +source = "git+https://github.com/Plonky3/Plonky3.git?branch=sp1#4809fa7bedd9ba8f6f5d3267b1592618e3776c57" dependencies = [ - "itertools", + "itertools 0.12.1", "p3-air", "p3-challenger", "p3-commit", @@ -1336,7 +1349,7 @@ dependencies = [ [[package]] name = "p3-util" version = "0.1.0" -source = "git+https://github.com/succinctlabs/plonky3.git#7d11ba55fa2c939449b593df298d04d7e15979d5" +source = "git+https://github.com/Plonky3/Plonky3.git?branch=sp1#4809fa7bedd9ba8f6f5d3267b1592618e3776c57" dependencies = [ "serde", ] @@ -1625,7 +1638,7 @@ checksum = "d3e97a565f76233a6003f9f5c54be1d9c5bdfa3eccfb189469f11ec4901c47dc" dependencies = [ "base16ct", "der", - "generic-array", + "generic-array 0.14.7", "pkcs8", "subtle", "zeroize", @@ -1791,9 +1804,10 @@ dependencies = [ "elf", "elliptic-curve", "flate2", + "generic-array 1.0.0", "hashbrown 0.14.3", "hex", - "itertools", + "itertools 0.12.1", "k256", "lazy_static", "log", @@ -1836,6 +1850,7 @@ dependencies = [ "tracing-forest", "tracing-log", "tracing-subscriber", + "typenum", ] [[package]] diff --git a/examples/ed25519/program/elf/riscv32im-succinct-zkvm-elf b/examples/ed25519/program/elf/riscv32im-succinct-zkvm-elf index 71cb9c6a380f1fa89b30a089c7f470e0f6c49bb4..a18b63297b080ce4c9d96476651cd4a992aee8a7 100755 GIT binary patch delta 16455 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 diff --git a/examples/fibonacci-io/script/Cargo.lock b/examples/fibonacci-io/script/Cargo.lock index d12ba8b9a2..9e1ecc19f8 100644 --- a/examples/fibonacci-io/script/Cargo.lock +++ b/examples/fibonacci-io/script/Cargo.lock @@ -207,7 +207,7 @@ version = "0.10.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" dependencies = [ - "generic-array", + "generic-array 0.14.7", ] [[package]] @@ -392,7 +392,7 @@ version = "0.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0dc92fb57ca44df6db8059111ab3af99a63d5d0f8375d9972e319a379c6bab76" dependencies = [ - "generic-array", + "generic-array 0.14.7", "rand_core", "subtle", "zeroize", @@ -404,7 +404,7 @@ version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" dependencies = [ - "generic-array", + "generic-array 0.14.7", "typenum", ] @@ -557,7 +557,7 @@ dependencies = [ "crypto-bigint", "digest", "ff", - "generic-array", + "generic-array 0.14.7", "group", "pkcs8", "rand_core", @@ -730,6 +730,15 @@ dependencies = [ "zeroize", ] +[[package]] +name = "generic-array" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fe739944a5406424e080edccb6add95685130b9f160d5407c639c7df0c5836b0" +dependencies = [ + "typenum", +] + [[package]] name = "getrandom" version = "0.2.12" @@ -1626,7 +1635,7 @@ checksum = "d3e97a565f76233a6003f9f5c54be1d9c5bdfa3eccfb189469f11ec4901c47dc" dependencies = [ "base16ct", "der", - "generic-array", + "generic-array 0.14.7", "pkcs8", "subtle", "zeroize", @@ -1792,6 +1801,7 @@ dependencies = [ "elf", "elliptic-curve", "flate2", + "generic-array 1.0.0", "hashbrown 0.14.3", "hex", "itertools 0.12.1", @@ -1837,6 +1847,7 @@ dependencies = [ "tracing-forest", "tracing-log", "tracing-subscriber", + "typenum", ] [[package]] diff --git a/examples/fibonacci/program/elf/riscv32im-succinct-zkvm-elf b/examples/fibonacci/program/elf/riscv32im-succinct-zkvm-elf index 6ddfa99127a9f1a9ac81b0e65c77e21b7292d4ef..33a33ed26ca48209deca2ea339133502737e78fe 100755 GIT binary patch delta 14857 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 E0nIXTSpWb4 delta 14322 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 diff --git a/examples/fibonacci/script/Cargo.lock b/examples/fibonacci/script/Cargo.lock index 4348f3bffa..16a714ad1c 100644 --- a/examples/fibonacci/script/Cargo.lock +++ b/examples/fibonacci/script/Cargo.lock @@ -207,7 +207,7 @@ version = "0.10.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" dependencies = [ - "generic-array", + "generic-array 0.14.7", ] [[package]] @@ -395,7 +395,7 @@ version = "0.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0dc92fb57ca44df6db8059111ab3af99a63d5d0f8375d9972e319a379c6bab76" dependencies = [ - "generic-array", + "generic-array 0.14.7", "rand_core", "subtle", "zeroize", @@ -407,7 +407,7 @@ version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" dependencies = [ - "generic-array", + "generic-array 0.14.7", "typenum", ] @@ -560,7 +560,7 @@ dependencies = [ "crypto-bigint", "digest", "ff", - "generic-array", + "generic-array 0.14.7", "group", "pkcs8", "rand_core", @@ -733,6 +733,15 @@ dependencies = [ "zeroize", ] +[[package]] +name = "generic-array" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fe739944a5406424e080edccb6add95685130b9f160d5407c639c7df0c5836b0" +dependencies = [ + "typenum", +] + [[package]] name = "getrandom" version = "0.2.12" @@ -1629,7 +1638,7 @@ checksum = "d3e97a565f76233a6003f9f5c54be1d9c5bdfa3eccfb189469f11ec4901c47dc" dependencies = [ "base16ct", "der", - "generic-array", + "generic-array 0.14.7", "pkcs8", "subtle", "zeroize", @@ -1795,6 +1804,7 @@ dependencies = [ "elf", "elliptic-curve", "flate2", + "generic-array 1.0.0", "hashbrown 0.14.3", "hex", "itertools 0.12.1", @@ -1840,6 +1850,7 @@ dependencies = [ "tracing-forest", "tracing-log", "tracing-subscriber", + "typenum", ] [[package]] diff --git a/examples/io/program/elf/riscv32im-succinct-zkvm-elf b/examples/io/program/elf/riscv32im-succinct-zkvm-elf index a5f708378b2f779b4ea5f846f771dd676d589cef..4d4a4f2c230c849e28af37e3093e0eb5291a6d03 100755 GIT binary patch delta 28759 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 R7vdyE?PbDIzUfKP@_%iu&mI5( delta 28872 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 ZPMi1>ICZ*$8_UrXxLN2Q%-ZVb{{b3-(S85` diff --git a/examples/io/script/Cargo.lock b/examples/io/script/Cargo.lock index 08181d95ab..ad815d3d28 100644 --- a/examples/io/script/Cargo.lock +++ b/examples/io/script/Cargo.lock @@ -207,7 +207,7 @@ version = "0.10.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" dependencies = [ - "generic-array", + "generic-array 0.14.7", ] [[package]] @@ -395,7 +395,7 @@ version = "0.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0dc92fb57ca44df6db8059111ab3af99a63d5d0f8375d9972e319a379c6bab76" dependencies = [ - "generic-array", + "generic-array 0.14.7", "rand_core", "subtle", "zeroize", @@ -407,7 +407,7 @@ version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" dependencies = [ - "generic-array", + "generic-array 0.14.7", "typenum", ] @@ -560,7 +560,7 @@ dependencies = [ "crypto-bigint", "digest", "ff", - "generic-array", + "generic-array 0.14.7", "group", "pkcs8", "rand_core", @@ -725,6 +725,15 @@ dependencies = [ "zeroize", ] +[[package]] +name = "generic-array" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fe739944a5406424e080edccb6add95685130b9f160d5407c639c7df0c5836b0" +dependencies = [ + "typenum", +] + [[package]] name = "getrandom" version = "0.2.12" @@ -1630,7 +1639,7 @@ checksum = "d3e97a565f76233a6003f9f5c54be1d9c5bdfa3eccfb189469f11ec4901c47dc" dependencies = [ "base16ct", "der", - "generic-array", + "generic-array 0.14.7", "pkcs8", "subtle", "zeroize", @@ -1796,6 +1805,7 @@ dependencies = [ "elf", "elliptic-curve", "flate2", + "generic-array 1.0.0", "hashbrown 0.14.3", "hex", "itertools 0.12.1", @@ -1841,6 +1851,7 @@ dependencies = [ "tracing-forest", "tracing-log", "tracing-subscriber", + "typenum", ] [[package]] diff --git a/examples/json/script/Cargo.lock b/examples/json/script/Cargo.lock index cf7ab83372..20b80fcf18 100644 --- a/examples/json/script/Cargo.lock +++ b/examples/json/script/Cargo.lock @@ -207,7 +207,7 @@ version = "0.10.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" dependencies = [ - "generic-array", + "generic-array 0.14.7", ] [[package]] @@ -395,7 +395,7 @@ version = "0.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0dc92fb57ca44df6db8059111ab3af99a63d5d0f8375d9972e319a379c6bab76" dependencies = [ - "generic-array", + "generic-array 0.14.7", "rand_core", "subtle", "zeroize", @@ -407,7 +407,7 @@ version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" dependencies = [ - "generic-array", + "generic-array 0.14.7", "typenum", ] @@ -560,7 +560,7 @@ dependencies = [ "crypto-bigint", "digest", "ff", - "generic-array", + "generic-array 0.14.7", "group", "pkcs8", "rand_core", @@ -725,6 +725,15 @@ dependencies = [ "zeroize", ] +[[package]] +name = "generic-array" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fe739944a5406424e080edccb6add95685130b9f160d5407c639c7df0c5836b0" +dependencies = [ + "typenum", +] + [[package]] name = "getrandom" version = "0.2.12" @@ -1639,7 +1648,7 @@ checksum = "d3e97a565f76233a6003f9f5c54be1d9c5bdfa3eccfb189469f11ec4901c47dc" dependencies = [ "base16ct", "der", - "generic-array", + "generic-array 0.14.7", "pkcs8", "subtle", "zeroize", @@ -1805,6 +1814,7 @@ dependencies = [ "elf", "elliptic-curve", "flate2", + "generic-array 1.0.0", "hashbrown 0.14.3", "hex", "itertools 0.12.1", @@ -1850,6 +1860,7 @@ dependencies = [ "tracing-forest", "tracing-log", "tracing-subscriber", + "typenum", ] [[package]] diff --git a/examples/regex/script/Cargo.lock b/examples/regex/script/Cargo.lock index 29bc0cddb3..4b3ca1d638 100644 --- a/examples/regex/script/Cargo.lock +++ b/examples/regex/script/Cargo.lock @@ -207,7 +207,7 @@ version = "0.10.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" dependencies = [ - "generic-array", + "generic-array 0.14.7", ] [[package]] @@ -395,7 +395,7 @@ version = "0.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0dc92fb57ca44df6db8059111ab3af99a63d5d0f8375d9972e319a379c6bab76" dependencies = [ - "generic-array", + "generic-array 0.14.7", "rand_core", "subtle", "zeroize", @@ -407,7 +407,7 @@ version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" dependencies = [ - "generic-array", + "generic-array 0.14.7", "typenum", ] @@ -560,7 +560,7 @@ dependencies = [ "crypto-bigint", "digest", "ff", - "generic-array", + "generic-array 0.14.7", "group", "pkcs8", "rand_core", @@ -725,6 +725,15 @@ dependencies = [ "zeroize", ] +[[package]] +name = "generic-array" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fe739944a5406424e080edccb6add95685130b9f160d5407c639c7df0c5836b0" +dependencies = [ + "typenum", +] + [[package]] name = "getrandom" version = "0.2.12" @@ -1629,7 +1638,7 @@ checksum = "d3e97a565f76233a6003f9f5c54be1d9c5bdfa3eccfb189469f11ec4901c47dc" dependencies = [ "base16ct", "der", - "generic-array", + "generic-array 0.14.7", "pkcs8", "subtle", "zeroize", @@ -1795,6 +1804,7 @@ dependencies = [ "elf", "elliptic-curve", "flate2", + "generic-array 1.0.0", "hashbrown 0.14.3", "hex", "itertools 0.12.1", @@ -1840,6 +1850,7 @@ dependencies = [ "tracing-forest", "tracing-log", "tracing-subscriber", + "typenum", ] [[package]] diff --git a/examples/rsa/program/elf/riscv32im-succinct-zkvm-elf b/examples/rsa/program/elf/riscv32im-succinct-zkvm-elf index 7e65713c6fb2e38fbba239a8364d90fc937b82b1..2023b313d9b5da9da09638fb939c6028e4021d9c 100755 GIT binary patch delta 44713 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 diff --git a/examples/rsa/script/Cargo.lock b/examples/rsa/script/Cargo.lock index 3f5fd0b0fc..03c80c8e36 100644 --- a/examples/rsa/script/Cargo.lock +++ b/examples/rsa/script/Cargo.lock @@ -207,7 +207,7 @@ version = "0.10.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" dependencies = [ - "generic-array", + "generic-array 0.14.7", ] [[package]] @@ -395,7 +395,7 @@ version = "0.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0dc92fb57ca44df6db8059111ab3af99a63d5d0f8375d9972e319a379c6bab76" dependencies = [ - "generic-array", + "generic-array 0.14.7", "rand_core", "subtle", "zeroize", @@ -407,7 +407,7 @@ version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" dependencies = [ - "generic-array", + "generic-array 0.14.7", "typenum", ] @@ -560,7 +560,7 @@ dependencies = [ "crypto-bigint", "digest", "ff", - "generic-array", + "generic-array 0.14.7", "group", "pkcs8", "rand_core", @@ -725,6 +725,15 @@ dependencies = [ "zeroize", ] +[[package]] +name = "generic-array" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fe739944a5406424e080edccb6add95685130b9f160d5407c639c7df0c5836b0" +dependencies = [ + "typenum", +] + [[package]] name = "getrandom" version = "0.2.12" @@ -1629,7 +1638,7 @@ checksum = "d3e97a565f76233a6003f9f5c54be1d9c5bdfa3eccfb189469f11ec4901c47dc" dependencies = [ "base16ct", "der", - "generic-array", + "generic-array 0.14.7", "pkcs8", "subtle", "zeroize", @@ -1795,6 +1804,7 @@ dependencies = [ "elf", "elliptic-curve", "flate2", + "generic-array 1.0.0", "hashbrown 0.14.3", "hex", "itertools 0.12.1", @@ -1840,6 +1850,7 @@ dependencies = [ "tracing-forest", "tracing-log", "tracing-subscriber", + "typenum", ] [[package]] diff --git a/examples/ssz-withdrawals/script/Cargo.lock b/examples/ssz-withdrawals/script/Cargo.lock index 251785f13a..14473b8b36 100644 --- a/examples/ssz-withdrawals/script/Cargo.lock +++ b/examples/ssz-withdrawals/script/Cargo.lock @@ -207,7 +207,7 @@ version = "0.10.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" dependencies = [ - "generic-array", + "generic-array 0.14.7", ] [[package]] @@ -395,7 +395,7 @@ version = "0.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0dc92fb57ca44df6db8059111ab3af99a63d5d0f8375d9972e319a379c6bab76" dependencies = [ - "generic-array", + "generic-array 0.14.7", "rand_core", "subtle", "zeroize", @@ -407,7 +407,7 @@ version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" dependencies = [ - "generic-array", + "generic-array 0.14.7", "typenum", ] @@ -560,7 +560,7 @@ dependencies = [ "crypto-bigint", "digest", "ff", - "generic-array", + "generic-array 0.14.7", "group", "pkcs8", "rand_core", @@ -725,6 +725,15 @@ dependencies = [ "zeroize", ] +[[package]] +name = "generic-array" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fe739944a5406424e080edccb6add95685130b9f160d5407c639c7df0c5836b0" +dependencies = [ + "typenum", +] + [[package]] name = "getrandom" version = "0.2.12" @@ -1621,7 +1630,7 @@ checksum = "d3e97a565f76233a6003f9f5c54be1d9c5bdfa3eccfb189469f11ec4901c47dc" dependencies = [ "base16ct", "der", - "generic-array", + "generic-array 0.14.7", "pkcs8", "subtle", "zeroize", @@ -1787,6 +1796,7 @@ dependencies = [ "elf", "elliptic-curve", "flate2", + "generic-array 1.0.0", "hashbrown 0.14.3", "hex", "itertools 0.12.1", @@ -1832,6 +1842,7 @@ dependencies = [ "tracing-forest", "tracing-log", "tracing-subscriber", + "typenum", ] [[package]] diff --git a/examples/tendermint/script/Cargo.lock b/examples/tendermint/script/Cargo.lock index 8942ac614b..76837ab5e0 100644 --- a/examples/tendermint/script/Cargo.lock +++ b/examples/tendermint/script/Cargo.lock @@ -231,7 +231,7 @@ version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4152116fd6e9dadb291ae18fc1ec3575ed6d84c29642d97890f4b4a3417297e4" dependencies = [ - "generic-array", + "generic-array 0.14.7", ] [[package]] @@ -240,7 +240,7 @@ version = "0.10.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" dependencies = [ - "generic-array", + "generic-array 0.14.7", ] [[package]] @@ -450,7 +450,7 @@ version = "0.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0dc92fb57ca44df6db8059111ab3af99a63d5d0f8375d9972e319a379c6bab76" dependencies = [ - "generic-array", + "generic-array 0.14.7", "rand_core", "subtle", "zeroize", @@ -462,7 +462,7 @@ version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" dependencies = [ - "generic-array", + "generic-array 0.14.7", "typenum", ] @@ -591,7 +591,7 @@ version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d3dd60d1080a57a05ab032377049e0591415d2b31afd7028356dbf3cc6dcb066" dependencies = [ - "generic-array", + "generic-array 0.14.7", ] [[package]] @@ -671,7 +671,7 @@ dependencies = [ "crypto-bigint", "digest 0.10.7", "ff", - "generic-array", + "generic-array 0.14.7", "group", "pkcs8", "rand_core", @@ -878,6 +878,15 @@ dependencies = [ "zeroize", ] +[[package]] +name = "generic-array" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fe739944a5406424e080edccb6add95685130b9f160d5407c639c7df0c5836b0" +dependencies = [ + "typenum", +] + [[package]] name = "getrandom" version = "0.2.12" @@ -2105,7 +2114,7 @@ checksum = "d3e97a565f76233a6003f9f5c54be1d9c5bdfa3eccfb189469f11ec4901c47dc" dependencies = [ "base16ct", "der", - "generic-array", + "generic-array 0.14.7", "pkcs8", "subtle", "zeroize", @@ -2368,6 +2377,7 @@ dependencies = [ "elf", "elliptic-curve", "flate2", + "generic-array 1.0.0", "hashbrown 0.14.3", "hex", "itertools 0.12.1", @@ -2413,6 +2423,7 @@ dependencies = [ "tracing-forest", "tracing-log", "tracing-subscriber", + "typenum", ] [[package]]