From d89f1d1243fc352952a2ae7a3b167b1afa55d3bb Mon Sep 17 00:00:00 2001 From: kunxian-xia Date: Thu, 18 Apr 2024 20:27:28 +0800 Subject: [PATCH 01/34] add bn254 scalar arith chip --- core/src/operations/field/field_op.rs | 11 +- core/src/runtime/record.rs | 3 + .../syscall/precompiles/bn254_scalar/mod.rs | 104 ++++++++++++++++++ core/src/syscall/precompiles/mod.rs | 1 + core/src/utils/ec/weierstrass/bn254.rs | 26 +++++ 5 files changed, 140 insertions(+), 5 deletions(-) create mode 100644 core/src/syscall/precompiles/bn254_scalar/mod.rs diff --git a/core/src/operations/field/field_op.rs b/core/src/operations/field/field_op.rs index 1cb91986b8..5b46c56e31 100644 --- a/core/src/operations/field/field_op.rs +++ b/core/src/operations/field/field_op.rs @@ -3,6 +3,7 @@ use std::fmt::Debug; use num::{BigUint, Zero}; use p3_air::AirBuilder; use p3_field::PrimeField32; +use serde::{Deserialize, Serialize}; use sp1_derive::AlignedBorrow; use super::params::Limbs; @@ -12,12 +13,12 @@ use crate::air::Polynomial; use crate::air::SP1AirBuilder; use crate::utils::ec::field::FieldParameters; -#[derive(PartialEq, Copy, Clone, Debug)] +#[derive(PartialEq, Copy, Clone, Debug, Serialize, Deserialize)] pub enum FieldOperation { - Add, - Mul, - Sub, - Div, // We don't constrain that the divisor is non-zero. + Add = 0, + Sub = 1, + Mul = 2, + Div = 3, // We don't constrain that the divisor is non-zero. } /// A set of columns to compute `FieldOperation(a, b)` where a, b are field elements. diff --git a/core/src/runtime/record.rs b/core/src/runtime/record.rs index 21578127db..1d96c06214 100644 --- a/core/src/runtime/record.rs +++ b/core/src/runtime/record.rs @@ -17,6 +17,7 @@ use crate::runtime::MemoryInitializeFinalizeEvent; use crate::runtime::MemoryRecordEnum; use crate::stark::MachineRecord; use crate::syscall::precompiles::blake3::Blake3CompressInnerEvent; +use crate::syscall::precompiles::bn254_scalar::FieldArithEvent; use crate::syscall::precompiles::edwards::EdDecompressEvent; use crate::syscall::precompiles::keccak256::KeccakPermuteEvent; use crate::syscall::precompiles::sha256::{ShaCompressEvent, ShaExtendEvent}; @@ -84,6 +85,8 @@ pub struct ExecutionRecord { pub bn254_double_events: Vec, + pub bn254_scalar_arith_events: Vec, + pub k256_decompress_events: Vec, pub blake3_compress_inner_events: Vec, diff --git a/core/src/syscall/precompiles/bn254_scalar/mod.rs b/core/src/syscall/precompiles/bn254_scalar/mod.rs new file mode 100644 index 0000000000..28441db717 --- /dev/null +++ b/core/src/syscall/precompiles/bn254_scalar/mod.rs @@ -0,0 +1,104 @@ +use crate::{ + operations::field::field_op::{FieldOpCols, FieldOperation}, + runtime::Syscall, + utils::ec::{ + field::{FieldParameters, NumWords}, + weierstrass::bn254::Bn254ScalarField, + }, +}; +use num::BigUint; +use typenum::Unsigned; + +use serde::{Deserialize, Serialize}; + +#[derive(Clone, Debug, Serialize, Deserialize)] +pub struct FieldArithEvent { + pub shard: u32, + pub clk: u32, + pub op: FieldOperation, + pub p: Vec, + pub q: Vec, +} + +pub struct Bn254ScalarArithAssignCols { + shard: T, + clk: T, + p_ptr: T, + q_ptr: T, + eval: FieldOpCols, +} + +pub struct Bn254ScalarArithChip {} + +impl Syscall for Bn254ScalarArithChip { + fn execute( + &self, + rt: &mut crate::runtime::SyscallContext, + arg1: u32, + arg2: u32, + ) -> Option { + // layout of this syscall + // | p (8 words) | q (8 words) | type (1 word) | + let start_clk = rt.clk; + + let ops_ptr = arg1; + if ops_ptr % 4 != 0 { + panic!(); + } + let type_ptr = arg2; + if type_ptr % 4 != 0 { + panic!(); + } + + let nw_per_fe = ::WordsFieldElement::USIZE; + + let (ops_memory_records, ops) = rt.mr_slice(ops_ptr, nw_per_fe * 2); + + let (t_memory_record, t) = rt.mr(type_ptr); + + // TODO: why? + rt.clk += 1; + + let p = BigUint::from_bytes_le( + &ops.iter() + .take(nw_per_fe) + .cloned() + .flat_map(|word| word.to_le_bytes()) + .collect::>(), + ); + let q = BigUint::from_bytes_le( + &ops.iter() + .skip(nw_per_fe) + .cloned() + .flat_map(|word| word.to_le_bytes()) + .collect::>(), + ); + + let modulus = Bn254ScalarField::modulus(); + let (r, t) = match t { + 0x00 => ((&p + &q) % modulus, FieldOperation::Add), + 0x01 => ((&p - &q) % modulus, FieldOperation::Sub), + 0x10 => ((&p * &q) % modulus, FieldOperation::Mul), + 0x11 => ((&p / &q) % modulus, FieldOperation::Div), + _ => unreachable!("type {} not supported", t), + }; + + let mut result_words = r.to_u32_digits(); + result_words.resize(nw_per_fe, 0); + + rt.mw_slice(ops_ptr, &result_words); + + let shard = rt.current_shard(); + rt.record_mut() + .bn254_scalar_arith_events + .push(FieldArithEvent { + shard, + clk: start_clk, + op: t, + p: ops.iter().cloned().take(nw_per_fe).collect(), + q: ops.iter().skip(nw_per_fe).cloned().collect(), + }); + + None + } +} diff --git a/core/src/syscall/precompiles/mod.rs b/core/src/syscall/precompiles/mod.rs index 59ba5cd2be..534a8fbddd 100644 --- a/core/src/syscall/precompiles/mod.rs +++ b/core/src/syscall/precompiles/mod.rs @@ -1,4 +1,5 @@ pub mod blake3; +pub mod bn254_scalar; pub mod edwards; pub mod keccak256; pub mod sha256; diff --git a/core/src/utils/ec/weierstrass/bn254.rs b/core/src/utils/ec/weierstrass/bn254.rs index c97eb8e1f7..9724a16db7 100644 --- a/core/src/utils/ec/weierstrass/bn254.rs +++ b/core/src/utils/ec/weierstrass/bn254.rs @@ -44,6 +44,32 @@ impl NumLimbs for Bn254BaseField { type Witness = U62; } +#[derive(Debug, Default, Clone, Copy, PartialEq, Serialize, Deserialize)] +pub struct Bn254ScalarField; + +impl FieldParameters for Bn254ScalarField { + const MODULUS: &'static [u8] = &[ + 1, 0, 0, 240, 147, 245, 225, 67, 145, 112, 185, 121, 72, 232, 51, 40, 93, 88, 129, 129, + 182, 69, 80, 184, 41, 160, 49, 225, 114, 78, 100, 48, + ]; + + // TODO: check this constant + const WITNESS_OFFSET: usize = 1usize << 13; + + fn modulus() -> BigUint { + BigUint::from_str_radix( + "21888242871839275222246405745257275088548364400416034343698204186575808495617", + 10, + ) + .unwrap() + } +} + +impl NumLimbs for Bn254ScalarField { + type Limbs = U32; + type Witness = U62; +} + impl EllipticCurveParameters for Bn254Parameters { type BaseField = Bn254BaseField; From 11bf5ad526db9e06bf8d1630f214e64d45ddc966 Mon Sep 17 00:00:00 2001 From: kunxian-xia Date: Fri, 19 Apr 2024 19:15:45 +0800 Subject: [PATCH 02/34] refactor --- .../syscall/precompiles/bn254_scalar/mod.rs | 64 +++++++++++-------- 1 file changed, 39 insertions(+), 25 deletions(-) diff --git a/core/src/syscall/precompiles/bn254_scalar/mod.rs b/core/src/syscall/precompiles/bn254_scalar/mod.rs index 28441db717..6341f541d3 100644 --- a/core/src/syscall/precompiles/bn254_scalar/mod.rs +++ b/core/src/syscall/precompiles/bn254_scalar/mod.rs @@ -1,6 +1,7 @@ use crate::{ + memory::{MemoryReadCols, MemoryWriteCols}, operations::field::field_op::{FieldOpCols, FieldOperation}, - runtime::Syscall, + runtime::{MemoryReadRecord, MemoryWriteRecord, Syscall}, utils::ec::{ field::{FieldParameters, NumWords}, weierstrass::bn254::Bn254ScalarField, @@ -11,6 +12,8 @@ use typenum::Unsigned; use serde::{Deserialize, Serialize}; +const NUM_WORDS_PER_FE: usize = 8; + #[derive(Clone, Debug, Serialize, Deserialize)] pub struct FieldArithEvent { pub shard: u32, @@ -18,13 +21,20 @@ pub struct FieldArithEvent { pub op: FieldOperation, pub p: Vec, pub q: Vec, + pub p_memory_records: Vec, + pub q_memory_records: Vec, + pub op_memory_record: MemoryReadRecord, } pub struct Bn254ScalarArithAssignCols { shard: T, clk: T, - p_ptr: T, - q_ptr: T, + op: T, + pq_ptr: T, + op_ptr: T, + p_memory_records: [MemoryWriteCols; NUM_WORDS_PER_FE], + q_memory_records: [MemoryReadCols; NUM_WORDS_PER_FE], + op_memory_record: MemoryReadCols, eval: FieldOpCols, } @@ -37,56 +47,57 @@ impl Syscall for Bn254ScalarArithChip { arg1: u32, arg2: u32, ) -> Option { - // layout of this syscall + // layout of input to this syscall // | p (8 words) | q (8 words) | type (1 word) | let start_clk = rt.clk; - let ops_ptr = arg1; - if ops_ptr % 4 != 0 { + let pq_ptr = arg1; + if pq_ptr % 4 != 0 { panic!(); } - let type_ptr = arg2; - if type_ptr % 4 != 0 { + let op_ptr = arg2; + if op_ptr % 4 != 0 { panic!(); } let nw_per_fe = ::WordsFieldElement::USIZE; + debug_assert_eq!(nw_per_fe, NUM_WORDS_PER_FE); - let (ops_memory_records, ops) = rt.mr_slice(ops_ptr, nw_per_fe * 2); + let p: Vec = rt.slice_unsafe(pq_ptr, nw_per_fe); - let (t_memory_record, t) = rt.mr(type_ptr); + let (q_memory_records, q) = rt.mr_slice(pq_ptr + 4 * u32::from(nw_per_fe), nw_per_fe); + let (op_memory_record, op) = rt.mr(op_ptr); // TODO: why? rt.clk += 1; - let p = BigUint::from_bytes_le( - &ops.iter() - .take(nw_per_fe) + let bn_p = BigUint::from_bytes_le( + &p.iter() .cloned() .flat_map(|word| word.to_le_bytes()) .collect::>(), ); - let q = BigUint::from_bytes_le( - &ops.iter() - .skip(nw_per_fe) + let bn_q = BigUint::from_bytes_le( + &q.iter() .cloned() .flat_map(|word| word.to_le_bytes()) .collect::>(), ); let modulus = Bn254ScalarField::modulus(); - let (r, t) = match t { - 0x00 => ((&p + &q) % modulus, FieldOperation::Add), - 0x01 => ((&p - &q) % modulus, FieldOperation::Sub), - 0x10 => ((&p * &q) % modulus, FieldOperation::Mul), - 0x11 => ((&p / &q) % modulus, FieldOperation::Div), - _ => unreachable!("type {} not supported", t), + let (r, t) = match op { + 0x00 => ((&bn_p + &bn_q) % modulus, FieldOperation::Add), + 0x01 => ((&bn_p - &bn_q) % modulus, FieldOperation::Sub), + 0x10 => ((&bn_p * &bn_q) % modulus, FieldOperation::Mul), + // TODO: how to handle q == 0? + 0x11 => ((&bn_p / &bn_q) % modulus, FieldOperation::Div), + _ => unreachable!("type {} not supported", op), }; let mut result_words = r.to_u32_digits(); result_words.resize(nw_per_fe, 0); - rt.mw_slice(ops_ptr, &result_words); + let p_memory_records = rt.mw_slice(pq_ptr, &result_words); let shard = rt.current_shard(); rt.record_mut() @@ -95,8 +106,11 @@ impl Syscall for Bn254ScalarArithChip { shard, clk: start_clk, op: t, - p: ops.iter().cloned().take(nw_per_fe).collect(), - q: ops.iter().skip(nw_per_fe).cloned().collect(), + p, + q, + p_memory_records, + q_memory_records, + op_memory_record, }); None From c9265099df7c0bf398732712ab5bdf2e7b886f98 Mon Sep 17 00:00:00 2001 From: kunxian-xia Date: Tue, 23 Apr 2024 20:08:58 +0800 Subject: [PATCH 03/34] finish bn254-scalar-arith chip and add unit test --- core/src/operations/field/field_op.rs | 6 + core/src/runtime/syscall.rs | 12 + .../bn254_scalar/general_field_op.rs | 81 ++ .../syscall/precompiles/bn254_scalar/mod.rs | 192 +++- core/src/utils/programs.rs | 3 + tests/bn254-scalar-arith/Cargo.lock | 953 ++++++++++++++++++ tests/bn254-scalar-arith/Cargo.toml | 9 + .../elf/riscv32im-succinct-zkvm-elf | Bin 0 -> 4224 bytes tests/bn254-scalar-arith/src/main.rs | 23 + zkvm/entrypoint/src/syscalls/bn254.rs | 17 + zkvm/entrypoint/src/syscalls/mod.rs | 2 + zkvm/precompiles/src/lib.rs | 1 + 12 files changed, 1287 insertions(+), 12 deletions(-) create mode 100644 core/src/syscall/precompiles/bn254_scalar/general_field_op.rs create mode 100644 tests/bn254-scalar-arith/Cargo.lock create mode 100644 tests/bn254-scalar-arith/Cargo.toml create mode 100755 tests/bn254-scalar-arith/elf/riscv32im-succinct-zkvm-elf create mode 100644 tests/bn254-scalar-arith/src/main.rs diff --git a/core/src/operations/field/field_op.rs b/core/src/operations/field/field_op.rs index 5b46c56e31..cd74f3ec28 100644 --- a/core/src/operations/field/field_op.rs +++ b/core/src/operations/field/field_op.rs @@ -21,6 +21,12 @@ pub enum FieldOperation { Div = 3, // We don't constrain that the divisor is non-zero. } +// impl Into for FieldOperation { +// fn into(self) -> u32 { +// self as u32 +// } +// } + /// A set of columns to compute `FieldOperation(a, b)` where a, b are field elements. /// Right now the number of limbs is assumed to be a constant, although this could be macro-ed /// or made generic in the future. diff --git a/core/src/runtime/syscall.rs b/core/src/runtime/syscall.rs index 4e6304b429..b953d03599 100644 --- a/core/src/runtime/syscall.rs +++ b/core/src/runtime/syscall.rs @@ -5,6 +5,7 @@ use strum_macros::EnumIter; use crate::runtime::{Register, Runtime}; use crate::stark::Blake3CompressInnerChip; +use crate::syscall::precompiles::bn254_scalar::Bn254ScalarArithChip; use crate::syscall::precompiles::edwards::EdAddAssignChip; use crate::syscall::precompiles::edwards::EdDecompressChip; use crate::syscall::precompiles::keccak256::KeccakPermuteChip; @@ -102,6 +103,9 @@ pub enum SyscallCode { /// Executes the `BLS12381_DOUBLE` precompile. BLS12381_DOUBLE = 0x00_00_01_1F, + + /// Executes the `BN254_SCALAR_ARITH` precompile. + BN254_SCALAR_ARITH = 0x00_00_01_20, } impl SyscallCode { @@ -132,6 +136,7 @@ impl SyscallCode { 0x00_00_00_F1 => SyscallCode::HINT_READ, 0x00_00_01_1D => SyscallCode::UINT256_MUL, 0x00_00_01_1C => SyscallCode::BLS12381_DECOMPRESS, + 0x00_00_01_20 => SyscallCode::BN254_SCALAR_ARITH, _ => panic!("invalid syscall number: {}", value), } } @@ -336,6 +341,10 @@ pub fn default_syscall_map() -> HashMap> { Rc::new(WeierstrassDecompressChip::::new()), ); syscall_map.insert(SyscallCode::UINT256_MUL, Rc::new(Uint256MulChip::new())); + syscall_map.insert( + SyscallCode::BN254_SCALAR_ARITH, + Rc::new(Bn254ScalarArithChip::new()), + ); syscall_map } @@ -433,6 +442,9 @@ mod tests { SyscallCode::BLS12381_DECOMPRESS => { assert_eq!(code as u32, sp1_zkvm::syscalls::BLS12381_DECOMPRESS) } + SyscallCode::BN254_SCALAR_ARITH => { + assert_eq!(code as u32, sp1_zkvm::syscalls::BN254_SCALAR_ARITH) + } } } } diff --git a/core/src/syscall/precompiles/bn254_scalar/general_field_op.rs b/core/src/syscall/precompiles/bn254_scalar/general_field_op.rs new file mode 100644 index 0000000000..58fd6640f4 --- /dev/null +++ b/core/src/syscall/precompiles/bn254_scalar/general_field_op.rs @@ -0,0 +1,81 @@ +use num::BigUint; +use sp1_derive::AlignedBorrow; + +use crate::operations::field::field_op::FieldOperation; +use crate::operations::field::util_air::eval_field_operation; +use crate::{ + air::Polynomial, operations::field::field_op::FieldOpCols, stark::SP1AirBuilder, + utils::ec::field::FieldParameters, +}; +use p3_field::AbstractField; +use p3_field::PrimeField32; + +#[derive(Debug, Clone, AlignedBorrow)] +pub struct GeneralFieldOpCols { + pub is_sub_div: T, + pub is_mul_div: T, + pub cols: FieldOpCols, +} + +impl GeneralFieldOpCols { + pub fn populate(&mut self, a: &BigUint, b: &BigUint, op: FieldOperation) -> BigUint { + let (is_mul_div, is_sub_div) = match op { + FieldOperation::Add => (0, 0), + FieldOperation::Sub => (0, 1), + FieldOperation::Mul => (1, 0), + FieldOperation::Div => (1, 1), + }; + self.is_mul_div = F::from_canonical_u32(is_mul_div); + self.is_sub_div = F::from_canonical_u32(is_sub_div); + self.cols.populate(a, b, op) + } +} +impl GeneralFieldOpCols { + pub fn eval< + AB: SP1AirBuilder, + A: Into> + Clone, + B: Into> + Clone, + OP: Into, + >( + &self, + builder: &mut AB, + a: &A, + b: &B, + op: OP, + ) where + V: Into, + { + let one = AB::Expr::from(AB::F::one()); + let is_sub_div: AB::Expr = self.is_sub_div.into(); + let is_mul_div: AB::Expr = self.is_mul_div.into(); + let not_sub_div = one.clone() - is_sub_div.clone(); + let not_mul_div = one - is_mul_div.clone(); + builder.assert_bool(is_sub_div.clone()); + builder.assert_bool(is_mul_div.clone()); + + // mul: 1 0 + // div: 1 1 + // add: 0 0 + // sub: 0 1 + let assigned_op: AB::Expr = AB::Expr::from(AB::F::from_canonical_u8(0x01)) + * is_sub_div.clone() + + AB::Expr::from(AB::F::from_canonical_u8(0x10)) * is_mul_div.clone(); + builder.assert_eq(assigned_op, op.into()); + + let p_a_param: Polynomial = (*a).clone().into(); + let p_b: Polynomial = (*b).clone().into(); + + let result: Polynomial = self.cols.result.clone().into(); + let p_a = &result * is_sub_div.clone() + &p_a_param * not_sub_div.clone(); + let p_result = &p_a_param * is_sub_div.clone() + &result * not_sub_div.clone(); + let p_carry: Polynomial = self.cols.carry.clone().into(); + let p_op = &p_a * &p_b * is_mul_div.clone() + (&p_a + &p_b) * not_mul_div; + + 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.cols.witness_low.0.iter().into(); + let p_witness_high = self.cols.witness_high.0.iter().into(); + eval_field_operation::(builder, &p_vanishing, &p_witness_low, &p_witness_high); + } +} diff --git a/core/src/syscall/precompiles/bn254_scalar/mod.rs b/core/src/syscall/precompiles/bn254_scalar/mod.rs index 6341f541d3..25e698207a 100644 --- a/core/src/syscall/precompiles/bn254_scalar/mod.rs +++ b/core/src/syscall/precompiles/bn254_scalar/mod.rs @@ -1,18 +1,37 @@ +mod general_field_op; + +use std::borrow::{Borrow, BorrowMut}; + use crate::{ - memory::{MemoryReadCols, MemoryWriteCols}, - operations::field::field_op::{FieldOpCols, FieldOperation}, - runtime::{MemoryReadRecord, MemoryWriteRecord, Syscall}, - utils::ec::{ - field::{FieldParameters, NumWords}, - weierstrass::bn254::Bn254ScalarField, + air::MachineAir, + memory::{MemoryCols, MemoryReadCols, MemoryWriteCols}, + operations::field::{field_op::FieldOperation, params::Limbs}, + runtime::{ + ExecutionRecord, MemoryReadRecord, MemoryWriteRecord, Program, Syscall, SyscallCode, + }, + stark::SP1AirBuilder, + utils::{ + ec::{ + field::{FieldParameters, NumLimbs, NumWords}, + weierstrass::bn254::Bn254ScalarField, + }, + limbs_from_prev_access, }, }; use num::BigUint; +use p3_air::{Air, AirBuilder, BaseAir}; +use p3_field::{AbstractField, Field, PrimeField32}; +use p3_matrix::dense::RowMajorMatrix; +use p3_matrix::Matrix; +use sp1_derive::AlignedBorrow; use typenum::Unsigned; use serde::{Deserialize, Serialize}; +use self::general_field_op::GeneralFieldOpCols; + const NUM_WORDS_PER_FE: usize = 8; +const NUM_COLS: usize = core::mem::size_of::>(); #[derive(Clone, Debug, Serialize, Deserialize)] pub struct FieldArithEvent { @@ -21,24 +40,34 @@ pub struct FieldArithEvent { pub op: FieldOperation, pub p: Vec, pub q: Vec, + pub pq_ptr: u32, + pub op_ptr: u32, pub p_memory_records: Vec, pub q_memory_records: Vec, pub op_memory_record: MemoryReadRecord, } +#[derive(Debug, Clone, AlignedBorrow)] +#[repr(C)] pub struct Bn254ScalarArithAssignCols { shard: T, clk: T, op: T, pq_ptr: T, op_ptr: T, - p_memory_records: [MemoryWriteCols; NUM_WORDS_PER_FE], - q_memory_records: [MemoryReadCols; NUM_WORDS_PER_FE], - op_memory_record: MemoryReadCols, - eval: FieldOpCols, + p_access: [MemoryWriteCols; NUM_WORDS_PER_FE], + q_access: [MemoryReadCols; NUM_WORDS_PER_FE], + op_access: MemoryReadCols, + eval: GeneralFieldOpCols, } -pub struct Bn254ScalarArithChip {} +pub struct Bn254ScalarArithChip; + +impl Bn254ScalarArithChip { + pub fn new() -> Self { + Self + } +} impl Syscall for Bn254ScalarArithChip { fn execute( @@ -65,7 +94,7 @@ impl Syscall for Bn254ScalarArithChip { let p: Vec = rt.slice_unsafe(pq_ptr, nw_per_fe); - let (q_memory_records, q) = rt.mr_slice(pq_ptr + 4 * u32::from(nw_per_fe), nw_per_fe); + let (q_memory_records, q) = rt.mr_slice(pq_ptr + 4 * (nw_per_fe as u32), nw_per_fe); let (op_memory_record, op) = rt.mr(op_ptr); // TODO: why? @@ -108,6 +137,8 @@ impl Syscall for Bn254ScalarArithChip { op: t, p, q, + op_ptr, + pq_ptr, p_memory_records, q_memory_records, op_memory_record, @@ -116,3 +147,140 @@ impl Syscall for Bn254ScalarArithChip { None } } + +impl MachineAir for Bn254ScalarArithChip { + type Record = ExecutionRecord; + + type Program = Program; + + fn name(&self) -> String { + "Bn254ScalarArith".to_string() + } + + fn generate_trace(&self, input: &Self::Record, output: &mut Self::Record) -> RowMajorMatrix { + let mut rows = vec![]; + let mut new_byte_lookup_events = vec![]; + + for event in input.bn254_scalar_arith_events.iter() { + let mut row = [F::zero(); NUM_COLS]; + let cols: &mut Bn254ScalarArithAssignCols = row.as_mut_slice().borrow_mut(); + + let p = BigUint::from_bytes_le( + event + .p + .iter() + .flat_map(|p| p.to_le_bytes()) + .collect::>() + .as_slice(), + ); + let q = BigUint::from_bytes_le( + event + .q + .iter() + .flat_map(|q| q.to_le_bytes()) + .collect::>() + .as_slice(), + ); + + cols.shard = F::from_canonical_u32(event.shard); + cols.clk = F::from_canonical_u32(event.clk); + cols.pq_ptr = F::from_canonical_u32(event.pq_ptr); + cols.op_ptr = F::from_canonical_u32(event.op_ptr); + cols.op = F::from_canonical_u32(event.op as u32); + + cols.eval.populate(&p, &q, event.op); + + for i in 0..cols.p_access.len() { + cols.p_access[i].populate(event.p_memory_records[i], &mut new_byte_lookup_events); + } + for i in 0..cols.q_access.len() { + cols.q_access[i].populate(event.q_memory_records[i], &mut new_byte_lookup_events); + } + cols.op_access + .populate(event.op_memory_record, &mut new_byte_lookup_events); + + rows.push(row); + } + output.add_byte_lookup_events(new_byte_lookup_events); + + // TODO: add padding rows + + RowMajorMatrix::new(rows.into_iter().flatten().collect::>(), NUM_COLS) + } + + fn included(&self, shard: &Self::Record) -> bool { + !shard.bn254_scalar_arith_events.is_empty() + } +} + +impl BaseAir for Bn254ScalarArithChip { + fn width(&self) -> usize { + NUM_COLS + } +} + +impl Air for Bn254ScalarArithChip +where + AB: SP1AirBuilder, + AB::Expr: Copy, +{ + fn eval(&self, builder: &mut AB) { + let main = builder.main(); + let row = main.row_slice(0); + let row: &Bn254ScalarArithAssignCols = (*row).borrow(); + + let p: Limbs<::Var, ::Limbs> = + limbs_from_prev_access(&row.p_access); + let q: Limbs<::Var, ::Limbs> = + limbs_from_prev_access(&row.q_access); + let op = row.op_access.prev_value().0.to_vec(); + + row.eval.eval(builder, &p, &q, op[0]); + + for i in 0..Bn254ScalarField::NB_LIMBS { + builder.assert_eq(row.eval.cols.result[i], row.p_access[i / 4].value()[i % 4]); + } + + builder.eval_memory_access_slice( + row.shard, + row.clk.into(), + row.pq_ptr + AB::F::from_canonical_u32(4), + &row.q_access, + AB::F::one(), + ); + + builder.eval_memory_access(row.shard, row.clk, row.op_ptr, &row.op_access, AB::F::one()); + + builder.eval_memory_access_slice( + row.shard, + row.clk.into(), + row.pq_ptr, + &row.p_access, + AB::F::one(), + ); + + let syscall_id = AB::F::from_canonical_u32(SyscallCode::BN254_SCALAR_ARITH.syscall_id()); + builder.receive_syscall( + row.shard, + row.clk, + syscall_id, + row.pq_ptr, + row.op_ptr, + AB::F::one(), + ); + } +} + +mod tests { + use crate::{ + runtime::Program, + utils::{run_test, setup_logger, tests::BN254_SCALAR_ARITH_ELF}, + }; + + #[test] + fn test_bn254_scalar_arith_simple() { + setup_logger(); + let program = Program::from(BN254_SCALAR_ARITH_ELF); + run_test(program).unwrap(); + } +} diff --git a/core/src/utils/programs.rs b/core/src/utils/programs.rs index 7fcf1c6e38..cccee4dbc9 100644 --- a/core/src/utils/programs.rs +++ b/core/src/utils/programs.rs @@ -82,6 +82,9 @@ pub mod tests { pub const BN254_MUL_ELF: &[u8] = include_bytes!("../../../tests/bn254-mul/elf/riscv32im-succinct-zkvm-elf"); + pub const BN254_SCALAR_ARITH_ELF: &[u8] = + include_bytes!("../../../tests/bn254-scalar-arith/elf/riscv32im-succinct-zkvm-elf"); + pub const SECP256K1_MUL_ELF: &[u8] = include_bytes!("../../../tests/secp256k1-mul/elf/riscv32im-succinct-zkvm-elf"); diff --git a/tests/bn254-scalar-arith/Cargo.lock b/tests/bn254-scalar-arith/Cargo.lock new file mode 100644 index 0000000000..1824553209 --- /dev/null +++ b/tests/bn254-scalar-arith/Cargo.lock @@ -0,0 +1,953 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "anyhow" +version = "1.0.82" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f538837af36e6f6a9be0faa67f9a314f8119e4e4b5867c6ab40ed60360142519" + +[[package]] +name = "arrayvec" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96d30a06541fbafbc7f82ed10c06164cfbd2c401138f6addd8404629c4b16711" + +[[package]] +name = "autocfg" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1fdabc7756949593fe60f30ec81974b613357de856987752631dea1e3394c80" + +[[package]] +name = "base16ct" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c7f02d4ea65f2c1853089ffd8d2787bdbc63de2f0d29dedbcf8ccdfa0ccd4cf" + +[[package]] +name = "base64ct" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8c3c1a368f70d6cf7302d78f8f7093da241fb8e8807c05cc9e51a125895a6d5b" + +[[package]] +name = "bincode" +version = "1.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1f45e9417d87227c7a56d22e471c6206462cba514c7590c09aff4cf6d1ddcad" +dependencies = [ + "serde", +] + +[[package]] +name = "bitvec" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bc2832c24239b0141d5674bb9174f9d68a8b5b3f2753311927c172ca46f7e9c" +dependencies = [ + "funty", + "radium", + "tap", + "wyz", +] + +[[package]] +name = "block-buffer" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" +dependencies = [ + "generic-array", +] + +[[package]] +name = "bn254-scalar-arith-test" +version = "0.1.0" +dependencies = [ + "num", + "sp1-zkvm", +] + +[[package]] +name = "byte-slice-cast" +version = "1.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3ac9f8b63eca6fd385229b3675f6cc0dc5c8a5c8a54a59d4f52ffd670d87b0c" + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "const-oid" +version = "0.9.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8" + +[[package]] +name = "cpufeatures" +version = "0.2.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53fe5e26ff1b7aef8bca9c6080520cfb8d9333c7568e1829cef191a9723e5504" +dependencies = [ + "libc", +] + +[[package]] +name = "crypto-bigint" +version = "0.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0dc92fb57ca44df6db8059111ab3af99a63d5d0f8375d9972e319a379c6bab76" +dependencies = [ + "generic-array", + "rand_core", + "subtle", + "zeroize", +] + +[[package]] +name = "crypto-common" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" +dependencies = [ + "generic-array", + "typenum", +] + +[[package]] +name = "der" +version = "0.7.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f55bf8e7b65898637379c1b74eb1551107c8294ed26d855ceb9fd1a09cfc9bc0" +dependencies = [ + "const-oid", + "zeroize", +] + +[[package]] +name = "derive_more" +version = "0.99.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fb810d30a7c1953f91334de7244731fc3f3c10d7fe163338a35b9f640960321" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "digest" +version = "0.10.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" +dependencies = [ + "block-buffer", + "const-oid", + "crypto-common", + "subtle", +] + +[[package]] +name = "ecdsa" +version = "0.16.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee27f32b5c5292967d2d4a9d7f1e0b0aed2c15daded5a60300e4abb9d8020bca" +dependencies = [ + "der", + "digest", + "elliptic-curve", + "rfc6979", + "signature", + "spki", +] + +[[package]] +name = "either" +version = "1.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a47c1c47d2f5964e29c61246e81db715514cd532db6b5116a25ea3c03d6780a2" + +[[package]] +name = "elliptic-curve" +version = "0.13.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5e6043086bf7973472e0c7dff2142ea0b680d30e18d9cc40f267efbf222bd47" +dependencies = [ + "base16ct", + "crypto-bigint", + "digest", + "ff", + "generic-array", + "group", + "pkcs8", + "rand_core", + "sec1", + "subtle", + "tap", + "zeroize", +] + +[[package]] +name = "equivalent" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" + +[[package]] +name = "ff" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ded41244b729663b1e574f1b4fb731469f69f79c17667b5d776b16cda0479449" +dependencies = [ + "bitvec", + "rand_core", + "subtle", +] + +[[package]] +name = "funty" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c" + +[[package]] +name = "gcd" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d758ba1b47b00caf47f24925c0074ecb20d6dfcffe7f6d53395c0465674841a" + +[[package]] +name = "generic-array" +version = "0.14.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" +dependencies = [ + "typenum", + "version_check", + "zeroize", +] + +[[package]] +name = "getrandom" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94b22e06ecb0110981051723910cbf0b5f5e09a2062dd7663334ee79a9d1286c" +dependencies = [ + "cfg-if", + "libc", + "wasi", +] + +[[package]] +name = "group" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0f9ef7462f7c099f518d754361858f86d8a07af53ba9af0fe635bbccb151a63" +dependencies = [ + "ff", + "rand_core", + "subtle", +] + +[[package]] +name = "hashbrown" +version = "0.14.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "290f1a1d9242c78d09ce40a5e87e7554ee637af1351968159f4952f028f75604" + +[[package]] +name = "hex" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" + +[[package]] +name = "hmac" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e" +dependencies = [ + "digest", +] + +[[package]] +name = "impl-trait-for-tuples" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "11d7a9f6330b71fea57921c9b61c47ee6e84f72d394754eff6163ae67e7395eb" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "indexmap" +version = "2.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "168fb715dda47215e360912c096649d23d58bf392ac62f73919e831745e40f26" +dependencies = [ + "equivalent", + "hashbrown", +] + +[[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" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba291022dbbd398a455acf126c1e341954079855bc60dfdda641363bd6922569" +dependencies = [ + "either", +] + +[[package]] +name = "k256" +version = "0.13.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "956ff9b67e26e1a6a866cb758f12c6f8746208489e3e4a4b5580802f2f0a587b" +dependencies = [ + "cfg-if", + "ecdsa", + "elliptic-curve", + "once_cell", + "sha2", + "signature", +] + +[[package]] +name = "lazy_static" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" + +[[package]] +name = "libc" +version = "0.2.153" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd" + +[[package]] +name = "libm" +version = "0.2.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ec2a862134d2a7d32d7983ddcdd1c4923530833c9f2ea1a44fc5fa473989058" + +[[package]] +name = "memchr" +version = "2.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c8640c5d730cb13ebd907d8d04b52f55ac9a2eec55b440c8892f40d56c76c1d" + +[[package]] +name = "num" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3135b08af27d103b0a51f2ae0f8632117b7b185ccf931445affa8df530576a41" +dependencies = [ + "num-bigint", + "num-complex", + "num-integer", + "num-iter", + "num-rational", + "num-traits", +] + +[[package]] +name = "num-bigint" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "608e7659b5c3d7cba262d894801b9ec9d00de989e8a82bd4bef91d08da45cdc0" +dependencies = [ + "autocfg", + "num-integer", + "num-traits", +] + +[[package]] +name = "num-complex" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23c6602fda94a57c990fe0df199a035d83576b496aa29f4e634a8ac6004e68a6" +dependencies = [ + "num-traits", +] + +[[package]] +name = "num-integer" +version = "0.1.46" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" +dependencies = [ + "num-traits", +] + +[[package]] +name = "num-iter" +version = "0.1.44" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d869c01cc0c455284163fd0092f1f93835385ccab5a98a0dcc497b2f8bf055a9" +dependencies = [ + "autocfg", + "num-integer", + "num-traits", +] + +[[package]] +name = "num-rational" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0638a1c9d0a3c0914158145bc76cff373a75a627e6ecbfb71cbe6f453a5a19b0" +dependencies = [ + "autocfg", + "num-bigint", + "num-integer", + "num-traits", +] + +[[package]] +name = "num-traits" +version = "0.2.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da0df0e5185db44f69b44f26786fe401b6c293d1907744beaa7fa62b2e5a517a" +dependencies = [ + "autocfg", +] + +[[package]] +name = "once_cell" +version = "1.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" + +[[package]] +name = "p3-baby-bear" +version = "0.1.0" +source = "git+https://github.com/Plonky3/Plonky3.git?branch=sp1#056f328a5096049b2b308fb6dc3497249e81d354" +dependencies = [ + "num-bigint", + "p3-field", + "p3-mds", + "p3-poseidon2", + "p3-symmetric", + "rand", + "serde", +] + +[[package]] +name = "p3-dft" +version = "0.1.0" +source = "git+https://github.com/Plonky3/Plonky3.git?branch=sp1#056f328a5096049b2b308fb6dc3497249e81d354" +dependencies = [ + "p3-field", + "p3-matrix", + "p3-maybe-rayon", + "p3-util", + "tracing", +] + +[[package]] +name = "p3-field" +version = "0.1.0" +source = "git+https://github.com/Plonky3/Plonky3.git?branch=sp1#056f328a5096049b2b308fb6dc3497249e81d354" +dependencies = [ + "itertools 0.12.1", + "num-bigint", + "num-traits", + "p3-util", + "rand", + "serde", +] + +[[package]] +name = "p3-matrix" +version = "0.1.0" +source = "git+https://github.com/Plonky3/Plonky3.git?branch=sp1#056f328a5096049b2b308fb6dc3497249e81d354" +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/Plonky3/Plonky3.git?branch=sp1#056f328a5096049b2b308fb6dc3497249e81d354" + +[[package]] +name = "p3-mds" +version = "0.1.0" +source = "git+https://github.com/Plonky3/Plonky3.git?branch=sp1#056f328a5096049b2b308fb6dc3497249e81d354" +dependencies = [ + "itertools 0.11.0", + "p3-dft", + "p3-field", + "p3-matrix", + "p3-symmetric", + "p3-util", + "rand", +] + +[[package]] +name = "p3-poseidon2" +version = "0.1.0" +source = "git+https://github.com/Plonky3/Plonky3.git?branch=sp1#056f328a5096049b2b308fb6dc3497249e81d354" +dependencies = [ + "gcd", + "p3-field", + "p3-mds", + "p3-symmetric", + "rand", +] + +[[package]] +name = "p3-symmetric" +version = "0.1.0" +source = "git+https://github.com/Plonky3/Plonky3.git?branch=sp1#056f328a5096049b2b308fb6dc3497249e81d354" +dependencies = [ + "itertools 0.12.1", + "p3-field", + "serde", +] + +[[package]] +name = "p3-util" +version = "0.1.0" +source = "git+https://github.com/Plonky3/Plonky3.git?branch=sp1#056f328a5096049b2b308fb6dc3497249e81d354" +dependencies = [ + "serde", +] + +[[package]] +name = "parity-scale-codec" +version = "3.6.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "881331e34fa842a2fb61cc2db9643a8fedc615e47cfcc52597d1af0db9a7e8fe" +dependencies = [ + "arrayvec", + "byte-slice-cast", + "impl-trait-for-tuples", + "parity-scale-codec-derive", +] + +[[package]] +name = "parity-scale-codec-derive" +version = "3.6.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "be30eaf4b0a9fba5336683b38de57bb86d179a35862ba6bfcf57625d006bde5b" +dependencies = [ + "proc-macro-crate 2.0.2", + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "pin-project-lite" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bda66fc9667c18cb2758a2ac84d1167245054bcf85d5d1aaa6923f45801bdd02" + +[[package]] +name = "pkcs8" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f950b2377845cebe5cf8b5165cb3cc1a5e0fa5cfa3e1f7f55707d8fd82e0a7b7" +dependencies = [ + "der", + "spki", +] + +[[package]] +name = "ppv-lite86" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" + +[[package]] +name = "proc-macro-crate" +version = "1.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f4c021e1093a56626774e81216a4ce732a735e5bad4868a03f3ed65ca0c3919" +dependencies = [ + "once_cell", + "toml_edit 0.19.15", +] + +[[package]] +name = "proc-macro-crate" +version = "2.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b00f26d3400549137f92511a46ac1cd8ce37cb5598a96d382381458b992a5d24" +dependencies = [ + "toml_datetime", + "toml_edit 0.20.2", +] + +[[package]] +name = "proc-macro2" +version = "1.0.81" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d1597b0c024618f09a9c3b8655b7e430397a36d23fdafec26d6965e9eec3eba" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.36" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "radium" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc33ff2d4973d518d823d61aa239014831e521c75da58e3df4840d3f47749d09" + +[[package]] +name = "rand" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" +dependencies = [ + "libc", + "rand_chacha", + "rand_core", +] + +[[package]] +name = "rand_chacha" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" +dependencies = [ + "ppv-lite86", + "rand_core", +] + +[[package]] +name = "rand_core" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" +dependencies = [ + "getrandom", +] + +[[package]] +name = "rfc6979" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8dd2a808d456c4a54e300a23e9f5a67e122c3024119acbfd73e3bf664491cb2" +dependencies = [ + "hmac", + "subtle", +] + +[[package]] +name = "scale-info" +version = "2.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7c453e59a955f81fb62ee5d596b450383d699f152d350e9d23a0db2adb78e4c0" +dependencies = [ + "cfg-if", + "derive_more", + "parity-scale-codec", + "scale-info-derive", +] + +[[package]] +name = "scale-info-derive" +version = "2.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "18cf6c6447f813ef19eb450e985bcce6705f9ce7660db221b59093d15c79c4b7" +dependencies = [ + "proc-macro-crate 1.3.1", + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "sec1" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3e97a565f76233a6003f9f5c54be1d9c5bdfa3eccfb189469f11ec4901c47dc" +dependencies = [ + "base16ct", + "der", + "generic-array", + "pkcs8", + "subtle", + "zeroize", +] + +[[package]] +name = "serde" +version = "1.0.198" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9846a40c979031340571da2545a4e5b7c4163bdae79b301d5f86d03979451fcc" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.198" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e88edab869b01783ba905e7d0153f9fc1a6505a96e4ad3018011eedb838566d9" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.60", +] + +[[package]] +name = "sha2" +version = "0.10.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest", +] + +[[package]] +name = "signature" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77549399552de45a898a580c1b41d445bf730df867cc44e6c0233bbc4b8329de" +dependencies = [ + "digest", + "rand_core", +] + +[[package]] +name = "snowbridge-amcl" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "460a9ed63cdf03c1b9847e8a12a5f5ba19c4efd5869e4a737e05be25d7c427e5" +dependencies = [ + "parity-scale-codec", + "scale-info", +] + +[[package]] +name = "sp1-precompiles" +version = "0.1.0" +dependencies = [ + "anyhow", + "bincode", + "cfg-if", + "getrandom", + "hex", + "k256", + "num", + "rand", + "serde", + "snowbridge-amcl", +] + +[[package]] +name = "sp1-primitives" +version = "0.1.0" +dependencies = [ + "itertools 0.12.1", + "lazy_static", + "p3-baby-bear", + "p3-field", + "p3-poseidon2", + "p3-symmetric", +] + +[[package]] +name = "sp1-zkvm" +version = "0.1.0" +dependencies = [ + "bincode", + "cfg-if", + "getrandom", + "k256", + "libm", + "once_cell", + "p3-baby-bear", + "p3-field", + "rand", + "serde", + "sha2", + "sp1-precompiles", + "sp1-primitives", +] + +[[package]] +name = "spki" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d91ed6c858b01f942cd56b37a94b3e0a1798290327d1236e4d9cf4eaca44d29d" +dependencies = [ + "base64ct", + "der", +] + +[[package]] +name = "subtle" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "81cdd64d312baedb58e21336b31bc043b77e01cc99033ce76ef539f78e965ebc" + +[[package]] +name = "syn" +version = "1.0.109" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "syn" +version = "2.0.60" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "909518bc7b1c9b779f1bbf07f2929d35af9f0f37e47c6e9ef7f9dddc1e1821f3" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "tap" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" + +[[package]] +name = "toml_datetime" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7cda73e2f1397b1262d6dfdcef8aafae14d1de7748d66822d3bfeeb6d03e5e4b" + +[[package]] +name = "toml_edit" +version = "0.19.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b5bb770da30e5cbfde35a2d7b9b8a2c4b8ef89548a7a6aeab5c9a576e3e7421" +dependencies = [ + "indexmap", + "toml_datetime", + "winnow", +] + +[[package]] +name = "toml_edit" +version = "0.20.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "396e4d48bbb2b7554c944bde63101b5ae446cff6ec4a24227428f15eb72ef338" +dependencies = [ + "indexmap", + "toml_datetime", + "winnow", +] + +[[package]] +name = "tracing" +version = "0.1.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" +dependencies = [ + "pin-project-lite", + "tracing-attributes", + "tracing-core", +] + +[[package]] +name = "tracing-attributes" +version = "0.1.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.60", +] + +[[package]] +name = "tracing-core" +version = "0.1.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54" +dependencies = [ + "once_cell", +] + +[[package]] +name = "typenum" +version = "1.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" + +[[package]] +name = "unicode-ident" +version = "1.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" + +[[package]] +name = "version_check" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" + +[[package]] +name = "wasi" +version = "0.11.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" + +[[package]] +name = "winnow" +version = "0.5.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f593a95398737aeed53e489c785df13f3618e41dbcd6718c6addbf1395aa6876" +dependencies = [ + "memchr", +] + +[[package]] +name = "wyz" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05f360fc0b24296329c78fda852a1e9ae82de9cf7b27dae4b7f62f118f77b9ed" +dependencies = [ + "tap", +] + +[[package]] +name = "zeroize" +version = "1.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "525b4ec142c6b68a2d10f01f7bbf6755599ca3f81ea53b8431b7dd348f5fdb2d" diff --git a/tests/bn254-scalar-arith/Cargo.toml b/tests/bn254-scalar-arith/Cargo.toml new file mode 100644 index 0000000000..0ff405e930 --- /dev/null +++ b/tests/bn254-scalar-arith/Cargo.toml @@ -0,0 +1,9 @@ +[workspace] +[package] +version = "0.1.0" +name = "bn254-scalar-arith-test" +edition = "2021" + +[dependencies] +sp1-zkvm = { path = "../../zkvm/entrypoint" } +num = { version = "0.4.1", default-features = false } \ No newline at end of file diff --git a/tests/bn254-scalar-arith/elf/riscv32im-succinct-zkvm-elf b/tests/bn254-scalar-arith/elf/riscv32im-succinct-zkvm-elf new file mode 100755 index 0000000000000000000000000000000000000000..b68d2a2c089d658a683de18f6796b706a8dfc902 GIT binary patch literal 4224 zcmb7{&x;&I6vwOMuJIRS4v2qNmigP4OC{{TTHh+c9J=)r?}5D`h#;Sq#g4Oe_8<(Qroa>JD)iCTme$Q@^OZdIEsUd~ z&Ndjkc)QK9OB=3>?E%K7C+{u7Hen16=i@LeF>l`C>&(04c~3lcY%x&Jnl|h07j;uj z#y!EKko()?YIo2M4|-cN2~(W}dD)Y`RNKDXmg;G?Q;qkE`q|#j&V`$}5cM7^|8|(FcAS*c){gIsdF!Zms5-!B~+nrS>tkl!YJK==c~Ul9I|@Gped zR|3NQHVHpR_$|US!tWFQobWe*L&6^uzDf9R!e@>jjsGIyON2im`~%^C2yZ=fbp1C7 zUncw+;U5X#A$<1XqwBv(nDJuJFKaU@7|$l7Q88{ApZ`X2)3$Y$&f213yg3-PCWY&u zY3oIAab@XPhN|CWW@zfZsjGI-hZ!x;RIKw*XF>+C3W9Pw+nsTrsXhJ9WVg-t_GO^M z!-O?$&Q+XeNgC@ok4+L8weXb|EwE_HqJ4S>5h_(zt&0A*LG6Yo*Kb6yJSk(P= zRt?)~+;AaeqI?yXWtbNt$rr^I;3jUaKHjFAYk<)?y1K{e|BqF%3>*W%qHuFn?io;6 zFm9{*SOjja+C2l>JpkU`d~W)wsK@*F$h!G3_r791jBtdz&O~-QHFgA-}&cYtZUtRF$}Ew N{S1CrSH5XGzq@j;)wlov literal 0 HcmV?d00001 diff --git a/tests/bn254-scalar-arith/src/main.rs b/tests/bn254-scalar-arith/src/main.rs new file mode 100644 index 0000000000..64f87c9180 --- /dev/null +++ b/tests/bn254-scalar-arith/src/main.rs @@ -0,0 +1,23 @@ +extern "C" { + fn syscall_bn254_scalar_arith(pq: *mut u32, op: *const u32); +} + +fn main() { + let mut pq: [u8; 64] = [ + 1, 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, 2, 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, + ]; + let op: [u8; 4] = [0, 0, 0, 0]; + + let c: [u8; 32] = [ + 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, + ]; + + unsafe { + syscall_bn254_scalar_arith(pq.as_mut_ptr() as *mut u32, op.as_ptr() as *const u32); + } + + assert_eq!(&pq[0..32], &c); +} diff --git a/zkvm/entrypoint/src/syscalls/bn254.rs b/zkvm/entrypoint/src/syscalls/bn254.rs index be24fad923..36202a5c00 100644 --- a/zkvm/entrypoint/src/syscalls/bn254.rs +++ b/zkvm/entrypoint/src/syscalls/bn254.rs @@ -40,3 +40,20 @@ pub extern "C" fn syscall_bn254_double(p: *mut u32) { #[cfg(not(target_os = "zkvm"))] unreachable!() } + +#[allow(unused_variables)] +#[no_mangle] +pub extern "C" fn syscall_bn254_scalar_arith(pq: *mut u32, op: *const u32) { + #[cfg(target_os = "zkvm")] + unsafe { + asm!( + "ecall", + in("t0") crate::syscalls::BN254_SCALAR_ARITH, + in("a0") pq, + in("a1") op, + ); + } + + #[cfg(not(target_os = "zkvm"))] + unreachable!() +} diff --git a/zkvm/entrypoint/src/syscalls/mod.rs b/zkvm/entrypoint/src/syscalls/mod.rs index d6d8a62759..9225c73144 100644 --- a/zkvm/entrypoint/src/syscalls/mod.rs +++ b/zkvm/entrypoint/src/syscalls/mod.rs @@ -103,3 +103,5 @@ pub const BLS12381_ADD: u32 = 0x00_01_01_1E; /// Executes the `BLS12381_DOUBLE` precompile. pub const BLS12381_DOUBLE: u32 = 0x00_00_01_1F; + +pub const BN254_SCALAR_ARITH: u32 = 0x00_00_01_20; diff --git a/zkvm/precompiles/src/lib.rs b/zkvm/precompiles/src/lib.rs index 8c28e5e0b2..b6e16fc063 100644 --- a/zkvm/precompiles/src/lib.rs +++ b/zkvm/precompiles/src/lib.rs @@ -33,4 +33,5 @@ extern "C" { pub fn syscall_hint_read(ptr: *mut u8, len: usize); pub fn sys_alloc_aligned(bytes: usize, align: usize) -> *mut u8; pub fn syscall_bls12381_decompress(point: &mut [u8; 96], is_odd: bool); + pub fn syscall_bn254_scalar_arith(pq: *mut u32, op: *const u32); } From 30186b71331bb1e7046221090e9dc7ea6ec0a212 Mon Sep 17 00:00:00 2001 From: kunxian-xia Date: Tue, 23 Apr 2024 21:41:40 +0800 Subject: [PATCH 04/34] include entrypoint in unit test --- core/src/runtime/record.rs | 5 +++++ .../syscall/precompiles/bn254_scalar/mod.rs | 10 +++++++++- .../elf/riscv32im-succinct-zkvm-elf | Bin 4224 -> 113844 bytes tests/bn254-scalar-arith/src/main.rs | 4 ++++ 4 files changed, 18 insertions(+), 1 deletion(-) diff --git a/core/src/runtime/record.rs b/core/src/runtime/record.rs index 1d96c06214..25033d5009 100644 --- a/core/src/runtime/record.rs +++ b/core/src/runtime/record.rs @@ -243,6 +243,11 @@ impl MachineRecord for ExecutionRecord { "bls12381_decompress_events".to_string(), self.bls12381_decompress_events.len(), ); + + stats.insert( + "bn254_scalar_arith_events".to_string(), + self.bn254_scalar_arith_events.len(), + ); stats } diff --git a/core/src/syscall/precompiles/bn254_scalar/mod.rs b/core/src/syscall/precompiles/bn254_scalar/mod.rs index 25e698207a..39f4505825 100644 --- a/core/src/syscall/precompiles/bn254_scalar/mod.rs +++ b/core/src/syscall/precompiles/bn254_scalar/mod.rs @@ -98,7 +98,7 @@ impl Syscall for Bn254ScalarArithChip { let (op_memory_record, op) = rt.mr(op_ptr); // TODO: why? - rt.clk += 1; + // rt.clk += 1; let bn_p = BigUint::from_bytes_le( &p.iter() @@ -122,6 +122,14 @@ impl Syscall for Bn254ScalarArithChip { 0x11 => ((&bn_p / &bn_q) % modulus, FieldOperation::Div), _ => unreachable!("type {} not supported", op), }; + log::trace!( + "shard: {}, clk: {}, bn_p: {:?}, bn_q: {:?}, r: {:?}", + rt.current_shard(), + rt.clk, + bn_p, + bn_q, + r + ); let mut result_words = r.to_u32_digits(); result_words.resize(nw_per_fe, 0); diff --git a/tests/bn254-scalar-arith/elf/riscv32im-succinct-zkvm-elf b/tests/bn254-scalar-arith/elf/riscv32im-succinct-zkvm-elf index b68d2a2c089d658a683de18f6796b706a8dfc902..78f0a45c839d4effa9c9e7f127efa1ecec2d13e7 100755 GIT binary patch literal 113844 zcmeFad3+Ytz4(9TnP;9XhINv#L*PlmBBJd8v707^0NP$@jcjVQPI(s1!9sWvFx&;l4Z@ zNlp2GjopKM?W5MG1NkZc0$=0S`siQ3 z{zZX*QQ%(`_!kBKMS=fMQo!6;XP9}Ga_2;h*aHz|&xwR$y(6l}Hl=2%_>LYG`g(g0 zPp;-X+b~W=M|4xs;bkg1?0zL}#{j8nX(805s3+%)b9XwO#+lgm8cvg6xop_~# zXQk)bi8niVRx{L29O>Yh8e%8H#@XknFrWGB;8|%d^Vh+%nnBE82hY?%=C6Zig#(zs z4xW|vWBxjLR?~<1>)@H{&HQ!ntgt8Z*TJ*WZ04_nXEmA3UkA^W&HQ!ntgsvN*TJ*W zF3evC&uTik^N;ZC{1s zSjW&yspzFt^irxF?y8~@aI;Ju9rEL9b@mBX|3A)bZWKPy}x%{Rifb%Bbe zuIJj#I_>#7+p1;EwP810t5zz3S2~C}h=5NhI&3{x!-@`m$(|aLqST{d;x&qJ!3_Mstl++NP}huE4JOEp$s`?$YA9MQMyNU1${@VMsqI z&?3c-P*>wo_!pr=!2$GcWP3k1B03p;UXCs|wGQtd(D|(MZZD$leC$Bj@@a3?^>c&v z!8kj+X_ks9D-^pf*RaEB%1)#yHxc&dU(>c`jobt07JfT@u6wu|mwg@D9pBE(@a>M7 z=U>N+5E{9Wx_)+q@g=}B!MJqY_yaPoU~J9N{BFu!U}-+mZ7gemrf*7djveW0xWW^O zlq6sO0bGR-4QXGHHxPSP_n=#Tv^kay9VpvY@uS|H24z=gD=*PdXr~-+_GVWrCsC=K zNS&&-REC?#QnA~gRMpgvK31pk@o83L$(*<$)%{lHs4b3mIb*P7j&hQG1V467{?_e; z$90?F+QSywnY(;`u}1jzR((VIi02in*b++?ZG&eaw0&`l$6#tb4?leakw( znt8Cx>qfcO&qIFyrC-zX2j94f#CrZ2lR^I~;LFkvrd!(}1!lCp?BdA8xM zSgxFd+m+j6xw3nHPC18C3_B}JRi_%tU6}g5Gds(0cP%iy8;&Yxc2AxqsQXL9d3%#` zmuD&GD9;H`SwQUCRgM=71=eTs!GK&o>TU?lcsHDL38wgmY34$ z-VL8O?BYeHYn3YJhO3O&52{42z`d*HYhPc~?6R#gV3krY*|z2yyJ3-0VXn`x8`6xZ zzAjP~q4gQj&}TZ?lXzzEY!c7(m1l})YG5aUkK6*UtGY#%8q7mVbkJu~&g{4F5Ai&3 zX-udB!O61TcjjzVZezl5W;QDCSfz4Tlq+*^5%fqH-u?#V?XOez$vjfZkFdNJ_Mhx=R(7qb%J?3sN7u(l_xNEbMIh^;hfmaye?GnK}CkUinfPRbzOV+ zJmuUDjNS7L=lY(8cj95ib7e-$40q`~!#mVn*LA1Hl?M#>@;LXVD)0LhisvdGtu<_$ zd(%sl)OBB`-iHq>dnfnam=0f5D9tNw+;H|+C}+kbbiw23+1k|Tke9FxuVW)VNJWRH zMRU5HgU(H7e$!=6qQf4KFvp?j@W&&*eimI^s6;RO^H!A9wS&#PGUl;V#j>k9!{5pr zj?Fx`SefT0RD4*SGKX2%xMIT`nlRvf>}j15Ta1hZvKi>?P3Q*fr~+1o5*^`}h5ycJ zQ%3h$ZOa$%JiX2HLY}uRe~ss9ZJvLV=WWa1)%-2}`8v;97wc|C0=<%y@zJd^UfA8& zF^n_6NJVoVhbFZxIu;%I1y&rGe)I`EGq)?rSyj$8SV zj%R)p%Sa2^y@n=Zp8oElvCu~RGA--q6Jj4781-)b4LdFh>9Y&db3GPf2hZ`ze+?Di|Q?;~`( zMX5BqVUH2(Z)Mo4hpO16X&Lr8h2U9;T~7;XUMODvpi9|?Usk@~+)O<8!&u1b9DCr# zbIeU)_y`(eTg1PJkME((2`O41h|HT42CMjl0%fO+S9bdI&34b!cCsIR=ooy54lW<3 zn!f-1C(#^Yp+O^!Xzml@GlWdW7tbvU;WLEr4-In|KI^a|!#o#VV;H8k(PDorYn(rC zRp3me?PKYY z&SF2j2zoN*0#$L}lc!?eJkYs9|iBGHZ9+syw~{vYLkQ1z*3F8}$|J3dai2hrJ)V}*7q`fCVnZi<**`7!W* z-;h39;GPcWu_u|&$SJox5^B1s{u80Gdu)_)pUhTv0X`45A+{#c*{RA_A^gQ} zH_}r@6?Qptj4>4`Z`99~b72iS+cMk*J>ZiRWiO1Vrd6q*xJO5;*gPx4O;MrP&Bq40 z&@xtjw7Z*w)E(r_}~;3ErmxK7O09+@Y3DX9IIGbO+ZY%(v@4ac7sS*uBs%FNL<_sV{TFSj)?)yFj_K#|e$H z<+(f)84)=Gk1XlSO=N4@XnJcpui=q?ziD$0bW&~bLYimeh@*($ce z((z}qy|lGc1_xu5x$)~Y-D`a!b>z9oN3#Ce`is+_nL0)H7q@1q=)7a9VqV0Er_5E+ z_>;87$4XtPD&pXnvPnhfgYSHvTh%I>kbCt!-=!)NQum;WBEuE%Wjy7$iY^fRL?$9e z#eyV$<*I3k_3r-!C(VC}a*dNeX7uw4>+M_KzxJJ#1~#m$c5)Ba<7}fSVGcCZdkXtt z7&_L%CZUVS_vH>GcAUSSypf4-8x}j^`#9>+=!oz`V&|j7H#}6mKkY_0F?(io!xO5y zYSypa#H2&fjr=}(^B3JjUO{xT{GM3pCMrv!Tlqby^Vi+P(ZSJ2`90fu&`s1Wj6TNi z{qX^AqUwR@Lr;XN8(zE0O)P&Y`tTE>=*Dm;x*;5r7{)HQ)M zkKjKi5{hoFTpQRq>@hfNn^$_?r}+R;$)kiL_-Z-Ym#`z~vz~Qbwf)SmTOZF)tQQ|U z);ZGEwi4^jODz0*6?P(dMX}qS)pl0yJ60b4i3Ppz50sAgH+$hl$b8K?vCe5>C;V)o zx2VpKL(_?^!s({OHg?+LWc^ArZ!xje^Tdwm=h0cpOVlymt)XcCukgRRVk`X^J(!Dg z#4ogGhd*&|J7U_CuT#$aN`;-%IJpsU-BccmZ`vNR;Rh$RUO5Gauut&ehKL#6cp&7% zDUHZj8N&t_f66Xz!GDe1kA|0Tj-Mq5fISz!(K6@TW^01B$>oX5w6E#g-fsuA--pkW z1ApbfUpe?Z1MztV;PVW?=NW*{Gk|z?0M7^Td_Xj3{eb9*$NQP*%!s<>fqWS!;O4$wkEx_k~ygT)O4t(l=CfBz1Uj=-AXH2rKQLh3&qhQ9<-v`bv z;Aa$6?JcE_z|SbKUVYHEX5R?>jDn*N)>5Yj@G}Z#Klmmv*8o4Gp!n(cY-`5tz|SbC ztnI?@SAoy(4En0;3;gtgQE#2cxV8g7y&!ShrM6XhDe%(^s(yYob$$x`^n&Fl=WzcX z;HMW%x@eVc^30zzt{(v(IMaRyZl3@@wIJ)Y?TqDjz)vk$ zzNvxxnZQpinDIO@cGf81rxuJFn#uhYz^8uoU}&`&_^AbXeMSJ&27YS6?BV|gKKp=A zoeN8V`4aFW1+&ve?cMsF= zV&F##X7mRCs_TFsDOmoMXOO{a;71B3-Bb_!-oOtR99{a7Z7nYYez?F|-AG^4fgdgy z)%gf8rvg7*POX)VDyZ6h8FbzN{7^x|nyZ+X4Zsf-%pP$)b}e z_}t$yAKc1-A1biwm(Xtx@W~nc?kB)(2EHno{k08@_XXgqg36OmL-UJ)uL=_1V~+Cf z13o(O@xIYvFZGHJf4x_9L~XBV?)Ul^|_UoA@ZOq~se%tM{k++w6`*0=&aPW1= z?>I9Wh>!8bB#$!_|7dt^P>)DO#9*A%4%(&6>8Ie$a|0WxgTV;wx1ko(|^c&OWJ?NZf(E3P5VU16Z{8# zy;p1d#y0J@hdkZ?_jECqr)Bm9LeOucv*X_N(NW1%c z`E*Q}ZTdF@+G{wv{jl}DrG1hoqC;wX+YL7}&ySIxsl?ZRTG=bEF}xYXLB&;+*BbVU zJ5{pm)ukBT(FVh-JE}Z_N4QboAsU#YtlaW@8VWilWu{Re%1}G zK+diQvCXWN@IPyRgUY(gb8p;k#=Khz&VsK)%;Do|Xk0yTwHv{8<$h$Zp1dHquJmzr z#)0cDa9!!+DrILp^^Sw9aqr-V;C3v)otWh2x0P3)YIt)GbA<=yyeKboxkhwQQ4fvt_*vlW zg7d8!XQy~S^T^yE98W&?B>M05Y%jG3W0_9=R%ks7+MWPTQ9x(2(N^AP=QR_@f@ z${ui`;axw#aEj5VQ?EDd0h?8_?CsdDyxV&kPBYgXw6U`IM|KxhBir!t%FX1e`MnE1 zUI!n8x5&1}b!@e)XJ-0%Zvt;*ZrSZVt?QC_!`HJuM(@6!>6qYJ&wL+;F7;EO@nPT? z0p9d634XSby&2G`qyfC)=h!XuH-qvF@P?m*vNLA4a&Dagy}6EQGQ7kLyg#DC%Mjr-kPsF`+QA*$f3IwxjOKSa$g2-ca+X|JLBN%m%-bGho_g&KRo|NipekiBySJP6MT zP2dB`w|j4Vi0n=idUy9saQ$*G`lH`xx+9Y%0;jV#?+rZ$_wsybb3pfDmo#d5bedw+ zoesTcYI#hSoo&$m)|px!oiVo}hv0tqhss%)Vz^V_lkV_|;C(rKV#6nlSLRr7HOJ2l zMMu1z9Up{DJ~KUJm#hLdd?J0d;Qa>lz7qTWdT-6&&*U54_osr(Aj4ZY6*xtmy@kjn zyzWjtm;U~&*B;!<|BL><;PHVl*{#BA4apYcfH+mMm z-AUWT#71lt^j-J9{<803|oMYROuWWLvJ9u8!$+vIx(=e2N-U?{7hdkTo!2N`tV|UjL`whG z)1LYueE37>}r zpwCC?e4F59Pn|*T4tbO{I>B?t9for|`s4)H2|cm9%;AE1<(YG!Gq!ydwrA!J?3qXY zutdWVoS+l3S#82AJZ2A`3W1CvxN3|FIhf)5k&Rw1YK6d>gj_+vCG>ch3SgJRFq038TQdhvD4Hb;tGS zL76{ja`$Y*ZGhgZ9>Mk?m%E|23%zOQ)k%MX_i+CmM7W#w#(8P4HvV=v&%@|nWp8N%b@yNPe2b>U3p5?yHb8jbA%*7liN z7uvlx`miZG+cs%k=$zy_CaPh1<>0+&l;N&hYq*o}E%yITxxLq5Tkb^9-KgT{mvwj7 zt&=@H-R(WMDet}WS!=|%?zP&852>}?KcWwBn8w&@ySY~mHr&4NDDUm7g|^+@s|VxD zzAHYW5g$=xyRVKg+_i5i@7=YAIlQcod-ZU`{VBTfFF%Dolko4Fz;U19UAEeAul3kWsv(E75XDWx)QgcLEZ|B|}hGT9s%n`MHz%5Ic z?|s2=`!_51+DyZH_mtrd*r(hpMjGCG>ogqq+Mg*mwF~jj>)pKHpEA4*;)1o;A4@w3||LT`#xR&{d!FHH4VzmM2|riuda@{LXTyl z$AYqR*)HYW2`}Ep6*_6Y#HaJ_u1AkSr z4q=192|GNb_8h@U>(*W9*0tb7eS0rBEemj}hky2h)3N|3%Fbo`p^@OkRd8BRZ+MH* zt!a(eEL42<3L}1gZFjekxL~G^Gc(;4D-3g(k?BtP0rA~2){l%VcO|krs5aBy%N!o8 zN4AQx?f%H`5F^{Y0@=TLEqe~iZ1)xN#jD>_-gT?dxn-I5H1@{ydt12~>B@QQJcD~# z?l-8j>fTnwGcmHo;WxzF{A z&tr2IaJ^8TD<{0daMIsKkBvkBBCpsVaPI4+;2)%%Qtpz@(5XLkf!@rO`^rV&xL4yS zG;v>f40(Ae%lWsp%DHC~{-7_Pn!X~RnIfOexzHE+l&ko>?v#G;Bz?#{T=OOB{i#j8 ze^<^6)Vp^(@o6@3_c0wSyHiF}uMrv^@%@h}_$R3m^iFMW@kg96dMxq^J_|8`$h`Jh ze#sn9!$%6*AoK3BJ6d2k=X}R-J9ok^ukVrc0kof=BD`Ft`9{aDjl+Ngoelv1l|L$b z_2&(lCvW=-$~Qujt(qoM_MWX&-jN5CbCT<`xzLt-<=}VsLGlRjviK4Q4?=@qBNOm4 zxJg{@PI-{=!OKC}i{o$BBlFr%m)grrgfIYsG^6G zWpCTBbd2g9;kwO54Fa?0qTUg)8q>^(af*;)ymxI!n#TCTiQk$H57_yEYfAAdrpWj>vJJp`SW z`E-)9mp1xrGN0a}hZ=^^{t&R9V6JvEci1ACyE<@sg_w9XF>z4##_nS7Rw?HWt}=HC za1uSVcna$hMS(0A^>$woSzak}o9!-JW|-$2-Rx=PA>Pczwior#wmqk;x4Y-N*!IuK z9@-x6>ea|_Z6Etee1NwuLH>*S+E)%S>@~>qJ;?KoUnTcx^sukaL+;;Gw$(*Bf4PTx zWj)+)P;cF9#Mi%*c0Hx+cE=BR;}?v5JoKAyI1}F@uAHXqY1sYx!G=9;lpce<=K|$S zJfHGNKc-s19Ei>Dav!nWhlbk)8J~uX_d>?s8fv)Hkn!HgID77#OFl;#8PBinA-~N$ zWNqHV#M%CHkx*gx}EpTXKA;QoK|hN^ZU;lPM39tlX0KnUfzp% z`y}zmwaUI0*uC~B=RLvu4a2?`fBZk+z#q9zdG|a)-M-ZQB&dr|kohWg-wf(L3Vp;@ zm-X?UrOkp}hO=ZP{CXoX(N-N3xi9~Uyv3EoS=U03Da6$eKtuF$PhXu-QYHlxbp5@_?f=!YrTZ*+XLX~S}edNVOhs3nK*ZQb!eoFL_ z*!y*2@5xtD_U`^M_8y$Iy`KVYw7m~-^7WCuPW&QxcV8oP!Y_g@&iI4mhtNl>@r#18 z^Wra{(*fwj6*@U7=nTE!Dp=(NtKla#&mt51{tkHp@m`Le%B z>mz#ruxI=XeuHl4BaK7xe)w$`{I|)+iL&$JWO7Oe!HKKjWN|M-AB(E7$F;UQ={9ut zGOd%akv+w(Ba7YaYthpO526FgdfEfT&oAp{{}DZW%S3#E+Magr2eA1@U-!y8k?|`H z_e$(~Uu0K&{5%669(nJ12!2i_ZdoNTxre;3dQ-WjVPddVz%+WfuVVXq5ewX~TKoE5 zeGg*3E`~Q@7-Jd9ntm9aCgVcx$#>fOkoyUTC|{)Wd*Ua0?Dug}chGN9Z*Spd_K|mD zuCT?c{|dfu8TOtp8TJF%;v0rh2ic;I)*XBP9a(<7m;CnbIYcfokWF%n_O)LGFJzPU zBpWC;1jdDyMe#%PdW$bE!d=ER(Ch{ej>idy$A6hdJ}hk z1kasN_SDZqmp}TkZlZyCP9gr?O59M?$J>!&IQL~~|6ber{nhX*{{1R!J#BqEu^JlQ zpNM{Li=3A@-E8!^OA zI1`3oCoKNS8QeVuJN|9pV7v4feoemWD&lT*iN^my^!5)K6J_%U;KMj{41W%^xZQ9T zn#6=fX|l%Q=b`h^XYe8QCBNuOe({YG`kbosi>~AsgR=MK1L&|x`1V}UV@~Q+{-MP@ z_`Y#Ea{h4O6a4}>m!l&O`?_b>QgY+yJt>QQ$CvW``VYacK+Ac2hyk5?h@M4{VNY%B z=>c?4$!_R`J&i$U(LE*CL#NH?9>45us{>0lMO$@`_(HpU8}I8L=p=DIIA~u8 zzut9`bHOPMSrq+KKfRq_Pkfr{<0P=!`$9IlM{tn%P3P;;J;|~+<|#j4e+O4^YW0QK z&vTxUZ4<-0J$~xvji%hn_*~}lr0jdlva#px>YuQlI8Y7X)3YdUUsUmarD60_e#AH|d4i{r%WdkpVI_;uQ7_G3oy zm-6`SFy_I?(SNysQ78sI8aQAKS^9hMvtk3kM?g{3Ne8Ij8sk>X(bxco>)7^*8 zxi=M@yY=&4WZYd2(HpPlFy^qq^oo4FGl zu-B{6cY=fD&)VkZ;&ZOu5 z+tr^jobq#MdoQBxUdHk)veN|odh#HTF@}2bc-w&8)3DtW)NNuek>_Q*;jin6vsVC5 zk0?%7?k-`3wK6;J19(g|A z1k5R{&A%n`oZ_VPKsN)UF&`KQfVYkQu*>3C!e6ppXUkfw_?1D~LAN`HXCgaXp}7;` zx2$(}Iu32WgI@plAol((Ip1$+o#V&e%(MMtdJ~cBYAA*>kh8aNpy^JFLHEu3i=p%mi)W;FG2oY^o{mkc0UMCKh$d*o_QO1 zq~O1xk4~I}-q;-YFSQZzU&Qxtr;GrnclDU;lD+s17a7U5KfB~+)&k+RrWkO*WlTLd z-Hc3g9dj$=Lk}-V!B5()+(akz%#Xo~Joij|j;TKa?i#HJ@nw73C9@gta$mNwdA8W) z)yOh>-ra*;e&8L&{+V9BohE0V`4?jKE3nyl#M=9j-)|T$vTQ$iNIBpBH9inLHenTb zlo;OF8<5>m=&pQZ?~B^sli1pqX>79O3ChbE?`Dx_@tb>l^EW7aPhVo5PyCpA5Ao{* zuM+ovUVQJq@?6K(dmdGu*qucq4fl#n=IDsdMG&ha`>$x(cg!(5KVna#&F|?eHE!5T z(%}7GV6P=TFMcn0Esk$W{2W9KBu+eAf8z#hLq! zz6~sSl6jx(>jSZYB`cue93Rd+qlmm|Ji7JHiS>lRIy##Y@Tu-fVt z4W}Nv1)P&yMYp70uYGJ;Q@7cdqV2NQlWpv>){&>#W$rm+z_Gnuj`%jP2|YE0F&#o@ ziVc8ny)T51hXuO-diVl93(C%O$B<#-kB_)sf`5`Sn1AHPLU-?+!FVb)ZR|Z&_^Fe8 zIN)yYSq?wW)^NNyv8s&cxo3PEf5~&?2BPBMT3+1NHrg#=?!>3Ur`A4IZ*&Vdh~2fP z%>pOpE+{*fz+2)|{eUYt2`pz(4A~%mIgEIh+_-B$pnZL}g@0q0QLg9O72;V>fQ) z_Xy+;+x-^4o9ONxHh5lYc$a*^u&*Q*CSPV>c`-5Z1jGI#zV)^-T)F?;CFps^xUeVV z-zhPBFK^LvMs&pb-uAUwev1_I>2Ow__4}f~d0t`DINO`L+DD*<19fVT&D=&crb zHvkWP6O_FPDTa4@FT=Z)EBN?!vmTg@_;@pcvyu1_-k$m-a3=e3wr7La3gFD~;e@_H zZf<=qkNe&P54^bUc#8cS-C6f2vh;qAg}{(?=cNaM_cAf@F5<|7*1csf!<(}1{6-1- zdop_~-Xcbxf{o$YvbQXoTtX@_{w?73GrdOcPW>JB{aU@xMAp^asq2W_@n3n5)l2*u zz0wn$&`Gxs04MY%YvI^pORka&(EG<$9q?i8ZUn#4t*~~_gF19^W|;OrR8S~z3- zkgL!g+v%k~g&(vZn?8$N!loc6Q4LO0{9J<0Nvs5?xjL8NnAlD3ITKzaFOkA^2XM$G z45|%F9>BAn!j==aFGa8DT*7Yj)rG##g06O7z8?Fq+4or}d(Rw$PT+EwtN1Lya7=Jo zl!sgr_cq*#ZCLB$wfipMuG4Udk$bu?6C=AnA$~5AcZ&PEJHL-DUW$z0q1-*l<^%Yk ztSf0-{KxaLxyUf`ZvR&@M!uQfgOHgwkmnomdx%RWOeKbGK#s>4?loUztPQLaU(7u0 z=1QK6XYSt5A}>3k|50>vPwmG^e$9(luot8c@%P8XyAscSff)6_bUYhBzl`UHHEeh9 zBlz{_;3s^qm%wwDRFG?`?ciSOVDrosKb+P$eg{JPyHh3NO>+W^HYp1U3C93chsk^sA*Y&Vv z?xY)(+kXrB$ESh&OXUuj#+v#*=)>5rSxrCWTx88W@_S7m?=ocK&OOBF?{bg5q$A3B zuVp*Gp9EGESm+cDYbUUrHn3vAqTc|v_rh-F-3eWrxf1VlwgUfk$nr6C0&vbEqV5J#G^sknTXz!Jo{Z-CpMF}z{k9oIa<66eQ+bWuB}0?D_8>{hwblK z3f2H9J1K|sJ#TzIc_ng=^f!z-z@GSvt0fCgqg%@NA$iVy97Jk{}o*q zAH9#a1UW^w+a=_;xH|Xr#i!~4JmwX6_TB<)HMD&9Ip6;WcYE(9Z0QGm^*9#Jr0ost z#n^%mMtzalUifI#m*=*~Y%lUNQjR>U$L?H)e!r9QW!G?TyS(3Eip`Wb*4}wOdl%mG zVeMt!SK~h|l?FGwWS{kH=c{h_uzYjTyi~ zj|64svctfsLr-$OY_EppbVlYf4uI25>>YYE$YcBloUTR>5RX6yd)FG^{D?h$lot&F zPiRwrBm3;(fA(=ZDdaHnYeOwK5eK{d-_`BiYxc7C$M|n%ZpQCIPa-b^&?77Wfo|=A?%VIj!sQ!vUdV||!H?*ItbjlJKiuwr zg?^Gh`4T=Kek?wkk(F4to7N6;2~HT??ma`3|Hiwx(wMcDayl;MTdkLmoKl$|5+?IlkWmyJM{ zxk|2J-XQ+p0515H@ZalaevCKmcg!>Wy){(Fr}i{_)?VNgl%40+k?TGmc&ix`0yDHI zBv*;8?VW?b1DLTJ$XmROZux90oITUgEf2SW15PIgk>gy1PZ;NaC-0_;E+7w)y#b$s z-;l&o`!9foEG!vPQ$kL{!1XU!||cfGsK_nAJ4;oe#iHpugWvrKEw$#HWi(@H&Gr=jOH_>9b>j+@ug?oND0%HmUS&zX2H{@J@+@6+wkkABP_pNo$%1igGn z`*-%W=#$I~efgHP^lOQaGVw7)zQwnDaRz$@4jIl7t^q7>!CZ2>C9?kloE{EvA{Vsm zavzSyiCj?fog~5MMP#WNxtoZsEb@Nxs1<5_F{~y0$JS09te+dmH2SBA7ETA%e}DeC66GAL zgC8bSZeY)byiZW;KeHO($sxRt$2=X_PCv})$_wdd7xfz{Gp8$wd8N#r7X9ws_QRaD z1zy|bU4yb-$#(-~A2jiOZ~U>oUinV)5-;_QNBO<5huGv^BI8aMY)9wKvPZ9Iu>zc{`$W0!L@xkza&gd+RsTmOq{vCuQ}N0N1d)Q-tE7o=Duf;d)89+^KL^O zIn~*;%VN#5fwO}w&X+l=q9gXpI&=>9BqyF*lw%Gxa@booz#LXKAU>>UfO)PlAbxIb ze{*oe#$<4Vqim9qzWc+JhTlzCE~pMG9MG-se; z&pz5k&JvPy2V>JWa;^&JD0Hq8T-X~^hOR8)tR+L*8Un){I+lB3-v3O)*9dbyqQ&n^ zl$@(&<}cFsR{mVhEUNjywQ9ft*ql#rHh4a6W8MSy8RsF|5tW)eM=5ryj`J1fGp4aB z_CTeExAFpg?&A{wei*)};w+ry)S1uoEaq{8obA@hZg>J(8;Y~FLUzM-%AR3maPFkC zk8<{cWu;c|+YRT)c@HUeL)eJ*mU_=hz0SJc^0DaGN+Ve}*)EzQ?Jl5QVc1@dO`Oyq zb-MU%-lW{7O&b`}E(xPT!zhHN{@6H+qA2#wYg< zii@0CA!kfzTuSGB8ZPjy@XML_C7iVB-8pak!(uH<5v~$zQc|SOsb@VylF%B8A{C7#pk2P~X0B15qPMO0N zLGw$Xc`;{_jI#7OAu^uwBp!t~Nga4IWFl|WW4!0^JUuzyYn=2e4R`*0_~H^Hw&XTb z;KjF&RpukYL&Zf+w@vzMD_q+7K1Ci^HuVZSijip+JGJkS@PHbkCT3M)d&;1qFdgkR>^x;^s1JEtZnVskktBiR< zH>wEp%lT=Xy=mqbh2r_OMnR9?{FQUZu9vv7VAsR7c1rys{oXlttoqpFiZiE6 zuPV|W=X{i|oC~!<&Zp|F&lJi_tdX-(V|}emmvg{1JtD=N6;l)r&JD^-)~mKushc?3 z?9Are)81BQbbeT$AC$x)I{bccPU2BBA(n3S6gow7ma|U#xZoQyp}QXILzSFsB)`in zpT_DsJKRiZw{QGrPRCuQY`gUpR8kY00{_NK+%xTKB-j;c) zV4kpVZ&e=^o+*A@Xc*P!$K*h_#8!AE5*=hjqPYfV&~Ps@>T!KdDXtP)aULxY{Kj$gNUFMQ9O!&BhZ zf`?W7rzCDt&$a5B^gMr4+84ek?V;sI=&3MzDl9x29Wu~Dw_4~{i*rY;XwJ7RJI$9j zZF}a+JYS-HF=QfCP^oF~yyz$PNrb8?dq%ie(gIf1cx>=nwozRn^tCIA1Wm zDk8ie>slpeqK91kQqf!DPr$$Dn2&(()->?OwqgH#pYkh#PkFb#xAGzJDNDcF;!|R; z{dS#s z0*>H!P>&Ctia#RuK;s_Z?MC329GRz@JZOOKucb|)ioIRQm9a;vLdb-LOjyW-Wezng z=oH592;gZ5R=elfTQS_Q(Ilmhpo}F#a#x^8PyUQ#kXf8)GU%H{Z`(4>V15 zoA~O&%lh2&q0ppwHD^~9LjS^`ed#F9B0bA}H8R%ON{vffc*;(opB~ykJLrl2kaKsF zzP*n}&1YNs;T$@%c-d+FsPp}PPQPDz9=a)XdOxC*MJAyk<0vzsp$QGyg=2(;X1-h{ zilUsSq~{nOMaG$_gRyiT8)sO^2>RH<*~*P(mlY;JT=ZY^}+{B3O~3iqFl_kCZvn7DSV_!(g{U;GYq zEVetEZ=lDMez7$}>`&ll55%WKXBeiLkG>P#mxE0kQOg;T;>@{P z=Ael9#=tkBZf^4YbH+P}@#bs@+9hTR?_oC#>_*#ft>}4-lGEa>O6(#sn_Jvw?4@nS zUid8fgcxIaa;&qWgAxL>B`3yMbw11=YiSbCSA(&Bs?Sz1WFY%{7p`#^r9cP%7n9c@ zw;_IY(qi`-ctj@mO>&W+n*EBEIY!^HNziuMDb4t z%(y?~`>@5EfX8{NM!>73$Ku6hCcKmyyO;bNzs=lQQ~VEnrPRPzN)>$NKVA%9EX8hW zdnj?E_!{s>sLG$Kd}~W|NPGNaU*?S0NH+Xa$C;AWmN>aA>@MRsV;GCH^C)#fczakThrRgV}HLdR#S1NttfpsIS!wG*7tn+iM;vrYcnTWzBN6O zO-;ivXZY$kK+{nC?4-QE0S)js$S!3{cLeXI_H2 z5?@&AHogDEhr~`FimYoI<<$`vCeRI%Q!3NB3V8;d_&P z3xBrcj7~deIhr%jh!f+8{t)?(O|N3i`26=)w$l;#tCB1G`}5{M(P#bN*_N-`>YOCJ z9(Ki*qf#w&R0d+KK5E!j^mxii*GuvIxvz^`Hhu$7X-7(@xuQ&qGlrknwpY_SoTPQ}G8>s|rFG$k zxX5?J3dNR;5?LT7^yNGDZlEK(R*~!B+Y#UdZ6fkK_S!E~HQz0%jF7wX^&@?smVZi* zhKbYju=P1(4bg>Xk2lbZ{#Y*(`GubC;;#5m=sOIbV^~oLy6PA#K8#%RP~!GVa@NG- zdX6hE_2c%9i}k%=KEK{F$LJ3KUd_a&RpBG(q+@}9WV-O`E$FcX&M8+9II~y%?8^DhXeB1h_ z_DQrK>$iIq`>S(|;JMYT3;S_?_bPHtTBZ#2lh{XeOf4~Ii+Px=pi!TChAt%5z!Ztzv0_nQTf)@n47?}o$nO=-_?I3 zT6snLaVaDRXlQ`YaWG;9kmtW_Q5? z)s&rbN@x^&bK@Xq(Z<49BrVg<8pR%@jiM8c*qSuX4ct-~OHb>rEBr`Ln*LWhw*fxyi#OU_PoP}pQ{ z;n{X2#F04VlByNyCdm=6OaaeqOEk`R%3Sy|P}o^yAdsIW$Qtd@>F5C+k7&8F79dy1l&@pR)h;1F9{ByGx3#p7 z)cr(sVIW)DuWjis5lQx!66m0on24Mmum|dOM2T%|vCV2=V4KBW;M;5cTv`;^W%x4h zG`n24qK#c9#wh|ut`VF0-?7Uzt+^29%h%bZM*_R-(>Acn%#*=9X+MB@YKgh3XFq7U zi5b6-=2xj|i!~?oi^P%DRV73C&9@f$-N5=&V$w+Q^JU%&jxjfp@>OoRuY>fr6CM4{ zz0b;XvHyCnK^}Ta_BUu>$o#XO^FUA8sVT}`5J6}9@vcw*#7gv_ZwpeGheB=FXLUFa ze{27N=G)Tw|G(IO;QMKFKW)t)xeNJnC$b&v70@(NrT^6Z2O5{sn?DT~^o01`XX2yu zoX>5u|KR`7uGQ51eRgfk)8O6?FLPr;`|*0sbUwarCA^P*@@2AcSF{}84qsbzXH;!y z7lQ!H&r^KL8a+O+zu$uIm6=-;==Zgs`?r3*5+`jKzGp5mIXIR|>`=pck;De91+}YN_`HVqa4?>S z^my9o7nxt|0CujZb)HY7nfP<)k!E+rXzkazR^p}Dy%BWccDc_wdwFxy!tkkh9^WBR z{h1$Xh{W}$D>vUJ~9cx^-A zEBuPRTN_x1O3UCK=|a9ud<)L#)M z7Vzgn+KH`}Io0$I3!eD*dfo~*M%A*wmrraIdx(Ado3Tt_qxrT`(nhO$#5T0v#|C~) z^hfF4Ew9 z&f*hnYV`>UYd*y%*z!;D2}uoJMECD_Ay~11n5uf06-Db~+7m*jyGn(I8F2`{*^6aXj?=lbcxAbY@vSnm68VI$ zUG!!!hFR?EAa9n-I&Ud{gXptmq8CiQxvgV9Q}W}CS^JE7+-iDLs`ZJBYzlq-`Zc<( zE50N7incf>V;A2>^6kmYv`>h2&)8okat)4rI~%+u*O5v21m7Hy@0@+i=v7 zT%fEKu!hfA=x;ce9UKyP`c|55vw?@ee3XeotKiB=W z%cXn(-{9ZF^FhA!5`hJNEwn%m$yp3EHUAbP)AC)(37aB}TVyg_WL$g{Gf!+WdX4;D zY++b`%S_9dr3!@}cA6^mWwZ2L=opDU1h3;0h@TVP2#q%98qux%Ucx`QFUf-mT>J{? zNe;4qRk$sWB7c&%(tPUEF|pOBjrEjX!zEtToKRS#2+K z5teZVdH8L@FX+Q#LHU`cuGS|4LwJF2x~}2b#{t~~o-O-3dA8^@o>l$N#s8p3+_AD&71nD8_g12( zuV8Iutl=(tuGtxNfzgqy5@&_Tx3%Q`%}2&6a|`hFe!U>?pVxN39zLz_FTQjZfAJ6O zS341`FW>3QPt6N~OlqFi^OhUTTbNu}NAng&Ck6Dckl!86n><_IN^@N|Id7J+0y zZj?H_vm$L6YnwK0VMJ3}VN_@sC9(i z-l5+!Vu$~gHC;beSl=QC*bLzbd}nA_#5$j$`NOyU@wJlUN#Z8_EGp~gpGA< zILjXtze=w=eplP?*)Hw0O%&f(#*!ocaN&J|x4a{SP71kc(gy#JoP~}Zeg4Ukcu?Zs zXwFEnA?@V*Y`MC?uTBIs`Bc7f$q&dr26-RNr^`e1FFZq@M&np|7rBp!y_neQz}SBA zEv!dxT|}&ro^DpkyH%5lVn5j0)vT2FrzWv}CV9ygdZl}dFXemj(+u%TBo7(HHJi<1 z%EDujs#N^AE&|sSxEbl>4+Pd$=y|x1iSW+Xu?+z}GB%-03m<;s&3^#B zyIRW%aZ5z}RT(35$vy%fU!4aLdT4o8Ym<04rB=NgFGin?8)(GGbu%hV_Su=ws)`Wr z^s}CAj{88x$Gxu1@h`DA>j`{xd=ujp-m!TznS<_7*3fVMzKj5$mRyX+p=LR2;Gg)u ze%2qwN43j~Uv;eulJ8^Hw)GYKxV!iPkrh97DBL7*m5JYL^KMI0Z;H;;N>}j(LvUz9!0OzVU@~%`$IQnSan&@K#qiI?ABR^k7fBst4OJU*C4U^l&S@()B_AXRP1*`YG`swxKh7_C&78%eC3>#oj}| zU+cIZQ;|;ya<9PW-3PH9(3Cs|aV~oS*sB;WWS>*p{fP#9z_2YoU2cM(P063e7A|K` zk3qazWNO)eEqIrM{Y=OVdabBsuV8FxC2P`Sv1Q^1Bd5^(j6F`Rb3L%dPFTtLuNeSM z!}tN=cy5ti--fPw?V5E<#?4qx-{&UtWLYQA9Jj%Kht_cmeaMY}EHWO%r;CN&1^ELd zU;k6Fw-R5*Rz&y~HFYD2pV4>Vdq)^Yq-FoO$dSJfBz}(UTZrcu%ezkCflf}KZz3td z^KBVPz7U^8&tqQkTH){5?<@7*CjGl>RaZN#?Mb?ef8)O!M7}1oiv3mEr%es;|3vV& zBd-NMK=jrWv(v^tkwJ;<*%9d|A0DwNyfu%=BPP2k5T-~WKR5l zXasY32wCne`q$?ptI>`W8X}**k5sc*_CQ9(UmiA4+kMd${@$wMcXghN7*2BO{vOlf zuW0?FWv^}|eIuLX8rkb5?~mD58NRLDLl3bR)wRm_O<&qKQNI>G6~Bdds4|3qTY0i( zA3Eh6S7adbN%lJz<0BwnmB<${(AjiDupg_@EY2cVg4`yoFWXsptd~^=`zFSHRlcPy z{2*(@GA{NzA*0#zF$}ijGpW{mwCn(K>LR_w8EVEOX$Mh*Hu;~d2n*z=&RH%on!se+V}=FLXSXS z75+xxi7&6;2_6J~0z1Li82{tod&awhLQ@%QQ{OG`+xTbjyCqjMA3rvaoB+8+nM={% z(LtO)Hac6mPiEali|9(EJS$cLp zE4-in&Un{R^I0gIn&dNc++lZ+8cSN~J_=bOU2HMgHZD}A4L zht%KTpJMcr=AUWIMQOK=^;D^^r~LlDN350E!at!;(Nli?o6q1MAHVN_-`V*`^i(l= zsyI{YsHj3$!9T(`XVp_ayz9?Shnkt-8}5*2TJ%&YG9vskP21~e=sDtEWbB`=Yf4{l z;T7L@UDuvhN&_8KGv~k0D>Y}@GEE~j`Rp_*y#iVO=h!mcPw7N~*TN&8X3PBgUp+gI zsIUCfY?(j)aUG0*EcpK4*)nZoYR>!Lv1O(BpMfp&`Rk(g{Dm#^`~O}t&~+T&6)ss)$i{(<)W9{%U_Tlh%(ehc-wW5?qy&Hm@~ zTT{`#-!K#K0sF5EUI%aI>7jsy8K*reX%P)e_#T#ii#j1y2$*#=T=pBb}y2lbAqP_ePUF`zKyyL+(o^}#%&ukvu$sudGJyGzIM$1@DH1Ix8ARr z_j6~wP1}O+(azoX0~gU{&TG?ljk*1>Nmwr9y z9FJ)i|27@a?&vg){y)?%X8_2rO&!zl?RMNY>;v}2cH>9$_E|rCW0dc5ijGWl(xV$* z<-68e^Zpm_e|@xlpcR{zKOkqco7-OPw4cAzx3_9_N0C!U+vqRf4fXl+dCa|b+IN(U ziNb~QJ)pJw=QKb4BebviFxvO-I_-O^rhU-oc>HM|{?>G%@16p8zY1{I-5~C?)YNU; z64)MiWBcaY2HqNNTjyz0w{7nuf;XjG;hr|OV(2_&uFE+O^RQXYBSu8eHcodo(LFf1 zi#A_;aAabpLMY} z8CEhmGC%i%WzAwf$$pNzQZlc(gG%1_9$sGbNuoC=pC)zfrY_Mpa3@}L0_sjYXQDGk zufHCEC3W7Q?LRjE2U&;hpDUZumeCf`vjJbR6Wns1baP7E z-SXKGt{JPlSOWrlD|!)|k}c4UvcIS~a~PT6P95~*-JzRAw=sXg5_NBSK6X~~J+)Pm3Nj#+eOwNw|N7UyHyVQDlE?Kk<3>?bzs*Z`1ZnKL$M+cOj?W+q9c|g&o7# z4q+=x`(pO%Uy`?GZ#k;XyR&$dHp0Gi^sctoM;|?&bJrh0w+Fema2z(&ZEw&o?gCQo zj5(C|WRsM&e_reF_3UmyBNj zR>t&qV~owr=96d0d{p_w&*lD>);F-#c}eL|Py9OH<(a3A-pKFidC=Zo`oeh6fd2ft zn@>Foo^c%Y|M!@!9gQvfj0#?Z@}zCpQv71_wsDS48rt{5$jMLC;7iW1_Mg=H{O*>U zmW&?t(pX2!OJnA?tv&$MGWdtyFd%b@HSWIkvIn?~*e2hfq6+e>@pOipxE z$ZnipwKO%~4h=|rl?K#V)Cl$>&D^tO?h3s$;omu!+Y`qlGfdVt=CZOqVJ^pHo(f+b z!H=`Kj(Ns59yyzP*rVU$`z-i3CvNoRmz#GN{*v!H6yOmr&**4ASL}v= z*U@}3>1@Iuma#b0(Jc8M=DSx{N&IW}^dGj5U~6RmXIsnY!Gp6prfD&7R)o@lE(2^|r~mm+W=? zbC%`%i|Ie0dx!VI18(0pC2hf9)Ezr`Rfx`X^ze7_Er%0XpZHyJB0eC_$HtU0Wln!Q zG^g)EF4!jYjg6?!BZR)?d}ZXW?=WAhv|U60f79BuyQOnU$I+pAtGUh1k@A9hOFyC2 z>6)2dI;H(lr60@(?3uwq7dUtn844bGGV&E+X8u(6vU08}XOhi#Z$q}B zj8mYG7Uu3Y#?_b2ex^<13BGIrgHJJK`1IP?fRofj$&( zY@YAY%gD)$KVg+Uv697`zl`k;c!MTL=aqllkk~LN9_{NTJU-7EYvqi2-_zAI=B^Fi zTFtsF`&I6ha5jZ4$U{n2?P#r>ORe|!RO)=Qqiq{}V4sqs{d4OdQw}~t9;*6E;+%T^ zY5!L71Hu{VMyW&X1EhS;!=&xrK4XcbrT&MA$Bsnl5BKI7$BGY5=-4}3MQ`WH;gqrP z-@x4xX?t*f{$u1q&culmUrqaT;=BG6`QNwW*|&*s!Z<&d^J?}doblqz4%r<1P!@8= zG+(}|+`UrtGI}jC_Q6NTc3*dYXJuc+-G008Aadft&W?@4yr1v1i_g#OxQ;p0&f0a| zoqWq~3pY0-tK%(>C@-$M%E2 z-oyDI{D%$eWQn&UJ1cHwb+ z->Eg$(S?rVRlfam!AZa~V;vW~F=oEO_d#63t{R4hxQje<=I`yb*s`DxvA4E0ncIHA z86^A!fARb0zWRpnP0_u8|0@3w-X955Gsev!(1Kv1@_8 zYJBv}kN7@r{t`Um4(8fv$R)@w(zemot}8p*_JUKKuVC=f|Nx{MvbaWsWHNOiWCl*d2IlY+yUOWg7f*wz5IpI$imjX1;&4L-aX*n~0yu zo|F5{w_!6sUA{xh9+X(61&i5u}?jD zAGnXvPj9_#7XFXC+8pQ_-;D2he2shfjr0Y3h>>?m-N-T3{(*OmwkW>e3g2&Ktr_P7 znep}f9|e37*{S2AF7#@%Pw8kIXtJHxrpvoy+HFmHPT2Erqt|_YIJ=N?+uJYSGZ)(5 z{=j*oO`IFQ0&bhp2w;A-qHT&d`s}U_M$Jhl9;ak&oYW7vnQ9t^{X~a)^jPTax`P$vAvFyQ)L*}BqEai1fqrBF;u}|~L z8zsGb!|C=dKhx%Kxtn+||LC-VCc--vjkk4uRPhAlRiDq-ocAbwr^uqrcYp1Cu9@|( zW6i-OyU)E#Gq>H<*>Nsy`@lhXq@=4^JAW#BijLa+&q^3=S9U(4-+~rA9qvK;(01-e z=i{@`yT8HT(68b%%I*iAGf#L7>)^fWeCnhnOK|Gn(D54%miH{tuFnSV0tB;VedzwlX4 zH%vS26TjXja!yC9yG8cQ-rrqYg7tCaPGm~Twr@tBV_hV?%A4UGgvtG|AnZSdzbJdD zcm6#-vfyW`?A8(TwRE(~J)kYqy|8V59RujmygK%8Y5jfko#!D7OcT8hxcqx~(PPA4 zhkofi^h=}@`9ge6ayB?WuGakt+Vqg(Z`rRiuB~0~ls2h$ia)bJ7NBjaohQ>y@nfdi z*|p7UXQ%WT|6Z}S(bgs6zpI5Zr2nm>75(^@!0&29deHd`uCDP1rtTMPg>Kp3i;hC> zJM3v?-M``0U++0?`t;Eo?%dgY`Zjg0B6nfM&P|QUwxvo&^XTLUgF>UDZ`rA3w{6+d zfxlCkn#yA&wspJv;R0pJzYc)*|~_&V?y9{@gUywQKQB`snN6s>!^L_MFFA$@D$V zUVAt{p`QJ(KYGY+zpG{Uwbb({?cIJqeUbL=Q~E!-L$v$a&&5V>B<#@1zme|_Ht$3K zbL`iDBV*a|3G`a%X#|JdE5={y7k@d5@0l=;_uq8-FBHzSEzqg*e^^&fitcV=-(!>L zfz&sa&SkA!z?yj~>l`#^Yi%tfcYWKJU4EeUC$es;F~ug`Z_DI+r)`c;S6{;BQuIme z_gROL6DQ6ix}wltR`zMlU2E7UE)_nc>f>7=o^4>)zS!ui><7QVUhiGo)PA|TAN(wP zJzcFoX8K+wm$J@RWYh8Kw^jCr^PBD%m!39FId{EwG6&JIkBUr(Z%uVy>U!FL+EV7i zcVeTmcjesE%&g>Gd-@FFBgli-L0fOJZx;VWH_(UohW51kR38+sxo4}&pzPbH;UAiG z%_rZ0jD}46&W9-HH}Jc^Cww}0UnmQme)B2#zd7XwX#P7&rj&D&`R(vR_CWJbdltS$ z9=@w5GMTI)&HgxdwC=lHc;_hR(4yZH-3T&j%gDQ~mididFxYdumG*JI*zEP^>(`CY zF0UVtvQ{4N(F$k4Qohm`qU)A2W#2r%W${3H?Z7rf78@Utx(4FXsDt+s!^i7p98=3fI+7IoDo?hAy zFPdS0Zlb)co*sa@)z}@2|03#?a&DgnZ>65*yRIKUc6S~XYkm~{H|JB$cb^Z>x*q?I z-)?N|Xq(69Lt{r<)!1>yFxA*~U|&4HX=&{CrpCuW`N2kJlKHRB|B#o0IVF0#Jwn^t z-lg!cjyaueLvCn0cYBTewO@2sBky5cy?r|Jkl0Ym{;awO!iO^JyU?QSgIH^uy!E&B z6KaiXooZjs9xr6Kc7*kOvhjNS{eK&4^)%L~*B%?&ea+pS_6uu{-+k?x&W<0QEO(@i zAAL1LAJL_5eXMEsH1q)N?3>%$wb5Peua7=HS2J6Wi>Y&Y+3Vjt?Ty_{A5drcLZ=<* z6U=MBrHQUMICI*4-H*UEYq+dAH@CjA2V8OfG&|ci2F?%8LN~xZowF(Ac$uf8pINBw zZn~K7!=JEZ^pzZY{D=9T?}%m&KFl|DALg6g-)rhv)f|)WN7{eWJj0$oZAQm-^bgZS z*4Ji?Zf6ZV@H4R$K)=oU^`nK_{ON+*4r1f(WZ87jkp6vmO9%Y|{IWP0o)Mh`tc zYxI_d$Ody`qYq4*vAcctlHISdCweW5PW=@8;Nx4heVI1;twUp@|6byp7asUn zD>!|gw#c4{JxQx~PAF}bHksR=@07Q~XdP5rcXy#_vXbS<19ez0sW zUT^jG$IFA-z0c|zVx#s}epI13rG6LHyY|Ghx`G#;s%ekRtd_rtzgL$xpIa`iU)9%Z zyItjSsZ9ECnq8!^t-e0j(brz+4i5JXoq6VP|HiU4u<+EidZ}Nx`t`MBT&r)e`i5QY zanj2Z8Qe zscdj@kJUFMUD8(mRM*}^S@ZbG`v}Wh@2)SEH&fzH%Il<@I6uU(O5aut4E2`!qkYrY zUH}gLz8zuJm9A)S+wb*d4)xCD7r>|S_i}zTE8KF4IIX2hYk$1)=q*XRzCydsqDtwv&{fcl!68TWV!-O}wJ+=K zUq|AA{u^l1*`-ZqIh*_SCH$*1OJomj7iH=ZDtn+73(C9w_MAT3grl^3Huk z*A9JD*Ork^9+^8YUaMBtXkcD_L6hnxB9{* z=XAZ>SPS)S=q;D}*F%NO?Q*XoKQ(NF1AW$J-O>vdZ75r|Fqs!9_X5g21YTvXZl$u5 zc!&GmL*KP-`tUKmCj6DOOl(ey@ml-usF4^wjAep>E<28jmP2OZRuWbzv zg695G{~2(>-hOA2Y}(wP>Dn3OD_TQLXz)DLyWR~ZcG03@N9I6pfA3JQHAE|f-WGWY zbn>kvf0}nNUK5s6-Y8_C%YPJCES2?*Wy;VL22ZxFez=`pcJ1NvVDARE58h>8KHOV&_4UI;?xp~x zkrfP)!R}FO*!QScr=3B>kLLZ0^vUCWSP=GajameX%9F7?|ksU6Y^ zUY_J9JWEY*y9EExOB>vBv9Gidra@;!aREgdYdqPTteV19XOBV;%GDf`9NRKY9JUc zz{Y4IvmI^}LifBES>womDQ|hG6s}cSJtTv!C_n09ci~OLItD8oc5Rsyr{3Y-&NeE zJlNB_9s;oj2i>wlyT^{s)Ytbq`dRPR2i?A691ghf)S+K`^Dq|Ev{UIrl~`opH0}Gu z3k|$^SV3)uSCo4J<^Bi1v-vGi9aOste-2tI1kqu&C%P;zF^~0CL#48{&h>T> zx--oBvrcC*v(!rOxPwFGVI_%D=DoM-{O`#~o4zofA9`#2Vy2DNCzJ2qUwL$YkUW?_ zjhn-MdXI-z8T>jIfmhb$;r`yshh5eeC2F0&^h~|bJ2W_e(4)JXdXNU7%0Ey?ma?DW z{U^M4KsayV?QJ@AHZ-(G4OywEBkvBmgSuDMbZz;sb?rFPTD)aUYNCOI_$|asnNeC% zh11cU#B&U(6&Q2jF}3nsqdSXe=}IaQG-_}7<-bbV$MUmFYzfq$Fw+N_sTHzZ+vgUC zWbe{DaCWhqCfayP+G^g*92JZzVH*YylB z!IkKArZAfIy-01aAII(Qb)A|96-7$xcZX!d60S9rNJ)w$f^Yeuu46e4of#AcO925S zNvsXjD-v)}s8ib5UnrL@6GquPAlz8GYxN14Y=$&?2Zsi$bA4lJxX;lG!pv1^?0w*m z^lx)7{H+RAf)ziNjnZZ*@QhMFTv<@XlEeN)7iKmWIpB ztitf%W_J_o^-!e<6^0gJaPSO=b&5o)6ZEsJ=tl}!Z}o3h!Gn}GtTrxvj018k6_ond zRmVfkhw|_MlQ$&z4fng72EZ7-5<+CMO8e-b{OL{R5`v~L#t!#0soiy@a_<$ALALDr z!qTAsm+;+%FX{ZRY43i;)5|R5&Gf8JO`QPVCirINP2-ye7 zlqi=5*aJ|8Ia%K7gbk+DWiA9f2<6iu{T=Vt-`DlQ?p0kEtp31~<7`8R ze>*?ft4NrnIi8=CD|N`50KXp6 zJj(lNe!t=OI=^GV;oJG0#&5Z`8N%|{#>Ula+AUwz>7lp&?cnc#hSWOX>(Kgb#j>?~ zU-k9_C5SFbp7CkR*2eA)t|YfD)-+*Zfs{%5L*ze(_tU(E7T>`>k*!pvoQl9)TtBq9 ze^{gwZNWirPuWX48OOw?L?U4%k_j`BN~9B+L^hF20&StXNY%ZJ6C2~eC znKN^#TsoJ@WplY)K2H<#RG+8lJlXODu{QrhRR&!4n65qfZS)r3Wq)h+u>zJ66L`)p z!3j3L-yhpxK|nu2sOzZx^orM@1#okw;F7=Pk+<-M;4KNa`*HFH_1Y``KIHHCTjomu zf11Bf;`gARzM|kz+8`qK>HO!>%z?eS2A4xe$AX{|YT5zv$-Mf$pa0$Oe#g7nu-iSz zDK*RPbe%1Bap+8ax))9(bI|#0^3FP>tMNXWx0=gAQsRO%xAe%+C>zh9#Wl8*Yep`v}5h7SRQ;){)BKV2o*w{_HC4O~~ zf3#K833{C0S?k8e?%*x)7gytNZX;*`zZdyENSb+G9SJ9#=Cjj2*Z%pVRG;P$e{WB< z?>hOos;b>V*iQbQsC>c2a?R*Y!u!+i_LzOw=2ZqMRR`NIX&t7_UO!aLg;kyVwC2>V z{4F?;O%Ar~u2<_f7{nn$uFypV@qUhr((l5Gt zZ0s5G(#D$kByBiE{ENh=B%VjY_`IPu<;pe2+}=wX?kHz$dF zdJtT%C43QSC!5z>h#%rx3paWBYUZ`%-%0!d;wQq(T;lfBj~1ssrbUdxE&hXh7P2DQOjXmwfCxU)Ux!)&l_6-xqy+quT z#Le(&JLr?t$<+*P@5jf+7Wr}EI%V7!5&y)EwY1Pl*n@;EkaqCs{8szv)_Uc1MtQNc zaT96UKM6haH+`?PUua1f_C3VO--4H5F5g4=F2aMkEb)5@+ew(L4>HC<+NTIle5y*{ z(!Li7TS=JkM$&dp#9O7zIn(&>)0J^k^$UI$5&k&gIWPaXIklYlXFgLqf7TNALL_X6 zu$Mw%QZ{A=+9ASj;cw}4828eqUBnOYeZ_?mzs$pl!nU zs!D$n)<@VggazeF8@CYl6k!vMyX4tP{K_5GdL_?&gk4Hli@z2``}KX|JO9S#iL1Ri zA^Bb;{7S;t`s-GBU6XiRU26~Sgx^gPzliv!{}%o*Nj%$R?S(rgE?>r}kNAamkBx2O zZ^kwejNewmw@(nhL&}>V{64~$?W!$D#^VXXcM(3|l|MTe4~ct$xYw(BYT{bhIA8pw zD&GruskB)quII}>-G+Ekj_^Lh1KO3bT29!dL0VwRzm_nEuBTd31iAgdHI41+R<=Wpjr#yS@SKdTA=^KocHHQJ=)(&`imc`%&Jx5mb9^xCj8x+Y7S1EhK2;jyu;lcW*cwe#QHeau(>mPf+o z@n4FtFzqD>JBzR$Nfe^7WrW`t370a~^54^hD>)fh!iFU5vD&(}6LyHOU_42to|nF& ztM?}Vt@-cmU-rTkyhfR8>2@E7D029zjzx@AJQ2^Far)^f){=<~zck7;*(qCiCe+CT}`Lovf)d z63H`?sZ+J(oGZ8(t}S1_R5!9xy|zS}S?(RQH)yfr`LktqYk7m2>`e|B-RqMB34+Ew zGEBkKqW#7jlXhK`#7$aElX)z*kB`F(1>Ot1Pm@j+m*GY#O!fu8{G^y4o%AD%$@@A30LA_@IR@OJ?Car&bZCjH5@f)CQG z_7bud_|pAVeB1!s7lOYId>?R-{u$tBLh(nl&w42YXMnE+UPyg{9}D=7Q2dR+fla5x z-wzx-(%z%qOZwwNo^#$)b@?@;qr z;7cOqAE13($bY&@-=w{3Ir3_#{YBuwUQ^nCMI`?hBJiFF{QU_0n+QBJ#B`;OnaL20^dPEkUktQ>2_GUym(^TD&$mwMQ5+Y~A9$w>MzoFo1APk;6<&R*bO z0|)l@0-rdiYR4@w?&B-=@&XS42R7;g{}pgxcP{Xwz=1uvz`p?w?860~hap5@?=A4X zD?NJcWGF;l_)lP=M>z`1+fXV8O4nSDv*Sb@i5zH1RhwABCULT5S`s#LFJ4!hb^PB_oy#^5XH@ z6Ndkp{3+^dQ?X6je*w<{4#s=V3Fvl0u#~d(3SC}2UU^~o&qyEG#7p}>3>?_T3;bE& zz{XwRV^(Y0LjiwjYSq>OOL=PjVm$t}8~h?4Es)xfkB(c*d=2Okd8gB1zX1F;72l-o zrTpNL@sYp9=G=Sy@%YH(@YCea{Z|$L)0p@-hWeibegxRVf0Onh;3q=y+kt10Kfs^V zEB9Bt$E!aI%N>s(emD68+kC;#Pk;lPeSwd9EA&r&XOKbQ6mVc)FYvk#(SG{3SLgx! z?F5$ko*})!x7*M^?W0&F@80ct__@W8Kdb1~52)hLTgUnp-~)UYdYBKuEJG^3oBD$% zz<0Pm5+}C#-V@V4Li+7N{j^sevG4bun06QOV&5N@Ujz=~<-KeQ_!aVRqWl2=e{v%7 zGwH+fioo9EjmHaHs_;iiFYrwy2mRO#Z;Ze{rhUO9_0{mcTJhuV=7Py@Pgx>E3emxZb zW8kyMAB?}$Blp6*$7@d%elZdshT9m(;O>XiX8;FxLIl1PIJny(@O8k!{SAS~SU;q` zXJ~+o_cZ3?5bX=*-(u)vDfk%j;~ikZSEmn;0tviC#w%4YQ!uMTYjlURtNqJ9GgW&5L^e6|o4@Y67UZzW#tl*sxX#0%^_bdqPzjk^(6p|913Ul&{8{6!J)Z?}=#+@h=fS zhXCOZp8{_AWfhima>vtqV%q;AKDhrQ>7N4*?&}EL{y`5vYkhjS|= z(66*4hJ4jsX8opqd1Sm!9Q5FJAD*pCjQ0fdJ=`9Nk-LlD7qxhxj1^hjf{sY7>i^R+QIPZyRTljNsDE`a9a{oy2OEpV9I7lyVxx?f= zUjL%-oJhRfZ3?H4!g9wc93O>W_-t)_6n_14)%bI|J^Dydpp5Sy)_VN|RO5LK^01V@ zz^8|Uz%pJ>`S7X8dxAe$dIu5yQ=zv|f0qz{8||A<8lm?-;75RG z`>`V$}DI3%&F~e~)2)Jwo|0sg3#c z@9=9GAF+Fp{vZENDbag^{si~3qi=K%-z@+AHS;Nb3@ z!2cUKxKk(aufbRF1oRfhzr^hdjmOaoC@(}W690H8USRPl;5{+z{iJ^(lzs^ONO_V% z`a8(}Me3X3!}-mWM}KDmOZz?od?3gV{vHSZA@RZ=B!2o8@UNGu5sq(qm!|2z_4Lm|e?!2JgkUMZ<%^PAo|yJu z#4mrPx<1W8uycUb_>*6r_Snb*gkHW9tSsNdP7w)Q!kHVGnbn5>w?SCTDzi_;2$X9C13(n<(_Epa7{r*JZ;9NgQ zABB7Fsh0m)+9UUv#aWgIbgY?b%GB+ z1T6Qpg7&@$EO)n#^5ai94gLi@-G|Qxmit^m{`J6ew<{?B7GSyO6}0zZV7c=Z;O|$! za{p_NU*22U$jCjgxB2i=V7U_(f3iY`l zMZOVu6L4^!QQ&U?hwFbC`~*+HkHhm(;+_i4&xzobf2T_@5BLNTl79e5`u7K5$se?L z<{2uX`cLXJfF-}$|B_#xaCrh>`BhzBJYIYl9*mTCYXtsg1b!|8H^se@<$r0<+avH< zz;X|I~)oBJsgpNXh?g;NS_yH=O=?;%6N6>7Dem6YM{M zgZj<{4(>)ud0)Je`Ahxs2t7UP!vVcHqz|5;zU`s*T^))4n+Pm3<|cShh_?$afh$Lntxev0xR-=k|ghz;mbVDItLM`7oI+W06u^o`p1 zD7-Zie@6s96oIvWsx2=HUmS_Qu?~DkB>uh-{LYVQ>aMDqpTfVlAaA|q%WsU=lUHk6 z9$4aKe2%$>^$@t#hyNN_%AXA^{OUPiDSxgHzun*u{|V^%iBSD#5x<1;W|BtchdeKY z;)}#P#H;nhk3Z|5b(KzXe46;+j;!Q=aVzoy>7{;Y?-|?R=fLs^-0#CO(gHsiY2SYU z2X|?M_B;@(uQ`c+nDV5*L44wyI*>duEl&JBq4*C1?+C$?YWrSYUOX{vEAhddT`BKt zz`+yXE1dob;^ppcfRC@ypWrU9^yjq+@*fD*CuPrlNS7B6cS20$dCHUZTk8Ka;3t7) zB!d2F59>hk#I)Z~pOlvZlJWj9>4PU|Z#ccg?R-S{lL*$w!}mqvp9#SiLQhiOPO?gU z*=t#kX`ejO-|Hgv-w}ZyioidKz*5d{L-h$PcZ$6yrv101-&ebS1$U$cAM&&i?>#YX z1Bj`#4=nEV;V``{4W*ZSH-_Nvkp8!!@%=6E>mgXu9|)yCDXnR3hpOXsK5$D29s*7P ztNB2Cz6jh7JdJW>e7^&{8d&#XUYguj_a3i*QCRM>hvTF0z;|lnqj1Z=)W%2Qo1UnR zkHT}lTN@vR<(|FwcwW0KS2KpyHJYJ87;@?O7Goknmzy}zgfPd`- z4(_)Le*XpdWYP!wiG#qwopy>{(J=fRs{ZK1fH9(E&rSd+#i8&jlhpY;9p1J z6VI$IzbgU{MBu-Qz>h}Y-$dYfe_C7qc@elAfhBc#JOmyJjn5YtZ;4M3F7)-+k^GNG z;8!B>NoPrk-Xr66egqzhz+a5O--*CdQn-CrpY6fH{CYK#UVpb=IWMXIeGzy=1imc- zKM{dni@@)EPi^_{kHDKE@a+-!yAk+z5qQC$)t0{^0$&k% z`y0vsIbhkZ?eNnd1eX1a+zpiYcTuqHFLgiuL%^~h3C8<&;771GlV`TprtJcLf&M01 zz5Mgf_vDwL|4#wma+0py!?;WNzk08x_Sa-n@V~rItK1KmP5i$D-}sK8{1)x*<(~Y% z+E4#1u&lp5KD^-lwf(&wINaY~0Eheg{tJNVkM8Hc23X|HfF7R%4(IP$QJeoxVA-z) z?fD6?$TK(l<;{aIWxqGuhyPq)Ti3*2iS&OP@J--P;*SA;@eApXum6|v9|o55y0w1( z`KyTEp=(QHUjAK|c=ou5{P^TwfX{z`-kQAl4+4vQ?G``&C%|G)+vmg1rN}eD;txdH zvlDpkL%Q~YU;gBM|T5@J|f|d$7ep~=`-f}OZ@*UL4_(SnlA(al>5hE#UQ*cpL%ZUypYW4mQ2Nyth{9Po`7d;`iJt zcjNkdsHdA8LvcHm%Q)$bZ6xuQWtzn^>~+KOgw}n@1*v5Bg5|3hEV%I81*;bfCld>- zLG=0TY&d0FOI?<^ytHn} zxokty%%rc#YkYd5TfRXNPZez=le3*nvXCe^g~Xd8W;<(}uFa*|jE%24vpPJEn=P8D zj19#Y;$Nmj@M6`lG&6CI-3hVtda5DSQ=RZx|PpB z{_kCfo9EoJt|cqGSFTtEvEhpkjNolAn@AT6meu7=mBT5{@QAtFF7-Lxfx|h9&Lj#6 zW=J|`rX6w5SE1v&T}mDXqUsH^p?FO&V;PL-jP=~=#>F>c`~$8nlX%!n$_(~raUxYn zr1DuSmA3Iyn95c9QOxHG*@BgEQu&-|ScO#5F>J#vBpn;>lgr1ebY3rIKA?=cWmbu( ze$omN)lXWT=JlFtq#JK*l_AwFwaSs|CC$~D*vUHarnVl}=iN*XTsg+=3Sv7Q39YA+u486#L7B^D%#@w(s?&y4o%pnP z-drEI(nc|rNw5Mrrd!DStFSRuWMZnwIR$+5@!L`b9gd7*1UCbHDY$|1B{Z`>~)9L1`MEr|qjAYJ9rLA<)E)kg7u35ukjW%j(M<|KU%+yZ0}(AxHc4#sgq77S16`zvuJwM`bTSnKkSes-Oncq z;$b?)3W+=D1PkvUv-{~{-|%3MP+OW^9j6i!bk7(J4Clf-B6R@y=Ie&bsYn z@8DCw5w_Df_xua_K-$VB7o2|%jn103!;+NGr`R1K?8^qJQS>GcV4RK&u zWmgS3EVN+_nMx>8ib2RyQsF1*gi%P_Xs%p4VI=d3#-~Q(2sREQX|7=!HyTH9vhiU{ zHr@cU@%d;rJ|E4-Y20K(I;jw93ZYb_$lQ1-vX&^~ac^-|YSbl;#b-;(BF0rx@kf=o zmh+LBKq7%v*~wfQ+1be(mSLK9RWrq>4T{CIozB|0aw`_xe8$T2IfgVk$+XLg9Zyy! zfBmG2^n=A+HOEM;ShITNn$_LsELpjF&4pdr?rx;^-l24NHy;+EVOGXX7hFCAk#|hn zGClooO%bM{K1J9)ROICn7oQd*{Cd<=ILQ^koz_oUSzPNU ztt?n|lUDbj^^^Qy@bhBpj1-%x|OzCDVS95OvZ3HHZf8O z4&15}k)89@?J=vwRyS#7qg=n#%Hml+X@zsvPg;=)>L;zp1oe|nu}|e_E8x|YFDd8G z4!)_J<-41F5S3$y3znR{ylbg&L?`9goVM@HJ0M?UrKdPz&s&MS z!xF+54)cm)|A%Xgrz*6cFw6psjn6A4v0_Q00f2GwO+_bDv^n+4$5R!0s-LtnP3kAD z(0<*d>Bf^*Hh6Ult<0yoDI3RBMQW{EW`#%8O<7%K>nE+OJ@u1TxOV-djbp#Maj9Qw z<5)Esr@!hRr+xz(AFQgXrf#WKRZab*jgMAUV5?thqe6*@sruq$N ze8N=4>$;^@4-M)kZG6I*jkA`j1X8~Njk8v?&%R_=ztqO@nmP>L+Bj*a8pms@al9VJ z>XybTW>VQUt$8xG`dob6NpV(dX5DNqlSNzz89*DpEUwZiQ?O)GPJX&EC+k*$*p>|r zTI*bve-!Ojs^H{p*UF{MB3oDWwUutiD$jt5ot`7v-V&kZBAm5;uRl93gi2|aVWL&Eo@&EVVSOr z%|;6A8z*HZIr$P1%-h?0MlDkmF-{tr(EOa!kc5#3|H-18FhkmoM4?znU{aJofXx@O zR>8KAYMneLJWj5dwW~+HbyHR+LA^4obD&J+G#(wu6fD#a9C49gRIKfB;&9X6U4p* zOD`7;XmuguV%uby&{#h0pg2P{oN(A1<>D2tTQ_CZa-)9IDG^W^a?{CXY%X7<@_c|D zg#?x)2~N*U*#Q-cDYr`DbyHTQo%%^D$f=*SG9BtBMKYUWJSsv<%C%i=E3rIxu)xo! zQyi$9*hgi-03VRYN-;H6Ih8q(PjYL;W^!Q2pUxEdwtdP;BecC5;u^^@kN zsxmuO!z&mxVkB;Q=@Lu>h_{;((0jn{iKcezbc2LXD$}@r z(h75`o3t{g>!z$8OVm%=c>T%7Ngz`ZnCmtmGZpJ*37BHmno~ti#nw>jqL3Tt?Q_c* zSoHP{_4W_O#ULYZDpg@aH)+CLAvpQg`qXt03}Z}hJnms z;Po&X&^WndM4V`>t=Yy0HrsexvyBfyw()Ky8fO{V#xam<90R$=i7?lA1M-dIHQzV} z@{JEczHxfZH{2}_RU0Kjj{F->dKe85xw)ZPU?Ai-oV4)0=Ha30@Y0qIn<=#)I^yQ_EZh4uzNm*$Jmw#%CPg3yJ+ID#W6X8Gm|O9yFOHDeMobWaKxuVcVF+I*rRZP#O2mc)-cl2 zDDTowC0kA;JdDo=^U4v!a`L1xaw>0@%^0?y8LWF!sRH+v{cBQF<;)a&`+L=$7n6&M zNfcz5jdJ5z)Mx=JLN_h)HQo%^GWMf(p~2joC>AqL!om*(s?aXYyM8M#d;NfvBo+X2 zSBqC~DI<3!`=zTKr=nFsL1>y>-nP8EMLF**IJom3kN3FN04Db`#_kfiycM>)_Xb>1 zV?4gDuT-%5;_>s;+e<5!_$r$E@-Ai*hGBB&gM0iIH+!Us1DgY~R_Owx1TH2bQA^ai z?ow&}6luB#drHIHkM|~>KVSMw{>A*kp5FD{+^iaA8!ad8n(}H<_nti8@9yivzdnI6#D1?^o z9YnDsz;po549P?uHDaDQz=g~ytIK2+6ZMIGvXUFqnBy}gi54bdiWwjtBBricv5$;* z_tY?163W&<)tw2Z4=IePFe!8ku4#M5dn!wnZKTz-pvx9FPcsF~pN(vyU=_VvoRP#{ zwr<$3WZ=R>CW}o`Qp~0u%quD*>hou{z)Zdb1U4cy3ykOg!Czqvj9rU`q=6%g3)Rd1h)-2?(qbgcXqL_@V0d>lsc!{YgKbNtwMN4PgVlHhJvyt+v zYmA9hmsT07JfljpE$2lSV#i=bd6?O{!Lt zMA;xq+0Zb&y1Urx_BjSGf00Sxt;e;pDZ|Kc8@wRw-W363A`d629;#N%{edOR z*L1DwUbbY_vaSnd5)?CbD&b;{mq*!M@XpXuawR__|D`h+0V3}*Lk9&QgDh`GB8wp> zZfp|XQl785>K*onvRau(hFFKcmZ~&^1FnrzsuBwr+F%x8U}0zH`&XA%b8q^5RRCNq zUr9(SU}{Ff;?R>uC*6#P>r6Uq=2hE@-~x82B_Uxh>UAoUvoe;I$s}wi;ba}}){#fT z*|N2ty4CM zrDG-wu_W^TU>h9c8ad3V@&A&=3jphvW2D>!7XuPmI}!Jnp*K;&RBiBue(qi=$)NxOOIf=?yXtwiilfze3&qK ziz%}>(T4Cam+RW{IiWVivm84TE?W9rOVL;bvy+!UA!cjKXLlqgm$LE14L~X+FG=}T zyc%4-mvz)Tc!P4e_?gJK8JLpgn3nH_q0+F*rqD1Hqg#DmuR@+RHosWyxfdXf- zb%v8#sj@&D4UWCJlZmN}Z0ne*5zF-&9|7b^SVcEwTLxV#THJb`AWvW`&gGOGtkV)2 zOD40P|Ge7bO>bLkW-;NgQ*K&Lx2;Uo`$u)v_EYBbIsCKaS>Y4lIXO}FeoFi;C9Og+ znaSgZ#d4;ooy&WPoShaCF_A_7P+f|wH2DjyjURB8dofuNl_wEHgl4zA0Wqjl?jG=5 zOCWD!36Bs&rRW|SE{sb}s;s2pl)8g*#c_`(tqFm!@dxWj_6#(xb}E>cZTCguwWVgR zVlt3Ua;G?l%SMR9Ye+5j15+sPT0-u;A=V+%gZ(J|K&|u$rd(- zHw^!pnH;1W#_DAkb}d=jef|aKt{8WHBcILLHX!f}xqDSZ|i8TYW}mNx61@dAIF_j40Tkr#ZZBW=z*f6}hn>t!g|w zUYK$sDdFfRmC6)6ZlJiU5=v5~es&w#75sk=GD-!}Mp_7l*$tmU*ytTHObp@rdU3 zcL)EzVkU}a$jEa?&sX&vNl6$ap~=Qm8*3puIIpBAx6W6%d^*rYr=1-4KSlP#L!ODV zRFAak8eXRZx{%#gLj2sN%{15M@U-T+R9131w~qgZ9J>Xadg9gyB9i5ytlj5Y{lf#< zbC!24xnPZWxwK3xi~gP;d)$nPvsk5m#=dUSWi!0~RWX{(_!@B8f}t5Nht^c;aj;he z!MTJ9qVlFEd7utfngLpOWLKZZX${mia{Qg&+>mvd%dS#PLOE1Ie~`{tMkb438Bzy{ zFkbNjm&8QeOlH}0+6g=Zc+3C)Sc8L0%INI4(4EA6SiwMZtQNTckz3MXjA2O4k(A5D z*L;$zF%Nnsq9Dn4) z5aEn`93x?a;Gzx@C*c;7U@(pA`ZP%ToHY+k;)opb6yXsqP%f`5@oNuv)ER6LR6X8O za<-9EC#j-A6*W}g%de0^KIYKLMj3|2yt<2-SU_isD?4y(*ReT6W2*-I{{yE~s%;QI zVm90=<5)!wJqpNpVL8t0$9R8)mXR)?Ku#tsJQ1bj;<3LajP}73eiAOu+)Yv78)+oU zDl4uep9EJa9I~N$bMj6qhijXVJf>!*YF^EDhAR)~=3rhZLsR(a@EVp;JY@n$_EtY9 zGfVo_<wyFkm-Eb^+r{btfx_7vxAltLWHgOOxL}&W$0}r5-7*p)`uF00{R-JFqNy+n?C=t4yoNGS{HD~E>rG#*8ZQ_(CfA$(Y47;_B9jS+ z&6K=*%O-x@;Y-z1Jh+mB?@AMec|M)=S2!gp^p;R96^kzJNb~%mm`B;jojqJsb5OZ2 zyGRYGa-J#vy#xhl&rGi56uB>L;0vHayR{Bl%nMzyT(J6w-p`jTHdPRs@(|sV<|Ydz z+36H_M-slIkoQ)M3Q+~ki^pZ(NLX$il=K&!Y7UT&Zhi56MhlUT%9bf~~>?RHeqgK4DH#0(2SCk{aGYaQ8Y+bZ8C-beRNvJ6lY1(17ueS6C)vCK0zm zIm&L6vts`QuD%-?f0j(b%qt^YRhB1|vV66iRj0kPYPLa{TnhJWI3r41c>aQ*8bgH{ z8~{!-NB_w40Q)k$KW1&*+T@Bj>Y0eBBl7??85R$=f!a8Wiro{)D_ELf9$2}glSgC8 z(UX}diuBhYY66wRB&hM~g!=1!awmZn%ylr>!x}1?K(g{E2IoZhcQ;{&$eEmSWU%k{ zS8ti2-YwqJV8%0#l!*Xkar}=qvS8(4@E)>)9cYbP*AN35zt=#dH*aa7GPvUq&O;HrvOebE!Ml_})7<%^*2G+0+UGkIMVy-Yk_ z@ldmB^ZG)m&+i`$Kb?fmVan*s^Nse8`)SesHO5#~DyV2;2f$V4YNnFR54@{kNtB13 z`M8*9JL%IVo1g}TtH3k7>?q|!JdiLfGLLnFnao%@4ujbqsJU2oo9j=-iJH||0ZCs> zou~vl_D5!O2B-I|!)yz=_01VY18mMQ9Rn}&%y&$9IIo;2OU;IawE*J)lh1m|M;g+B zj=3&slcvXxCc#W)s{Ij2QFdHaQpAgv?9go-_vdlJ6dZs})-F$=E|i#J|dSWq~rjH z(`j`uLk=$9vu(z7Im=OKqg~)rUrH}Jz7LI|AmvlZ5$B)u{KaQ06Dwuao+`z$skmu# z`9J{<{qm^da8Qv5)=>j?j-HcS)hN!fA3_!4+XvMh*yN;}&&IHl^c4IjWd+^B)pq>YM>ju+_kpnFH`7hretYt0n3Tl6jOX_A6f*7q!j&(q)(J|6dO3siKy6|taUZpFb44jZ_9j-Z&tMVdd= z>oz?Zi1d@RJ#@ZoCatoq?n88Y-cXd$huZV`0Zcn|l-WEV55zAk*1F>3+#g)ukzQ_f zj~Kn3@0chuvdZl8PKN z%e9Tb{Cu)9)#Byp@fY0dq?fLF|NB2U&VD1u z_eYb6{0S?E^}DZZt}O2i(1envXSjiyN-Q_fK6A`AI2gVWV7nYWBGq8YfbA@r0gt6j zHY6F(qF2qFDaxK?NsoNQHCM3QtXK;pI`ECvivF~oH_bpAoUoCKb=Ex;4-5+4L=lyF zI+;;L-A4F}@|$UczXHCQA_6tvksr+mGU$Y@fH!zlid0v*op*S)uDuaEQRFH74Ot0% z1ao+w@@7{}C5LP4I<5v2J1x%hIZwCvcy2^|R~INIx2B!gA~VtlTobW(&7eJ?me z@rrPZ7*5%^(s58ev%MGQi_NBd_LaRpXR#GS9Pz%B!Zr{gRE`li{IA$V`F3TgRm)ba zS-v#*gobS2FjwYsV-beQ{w*gSR)fvM_`(`%P9T_0)SL!OsBG#z$TQB20DC##2>i&78?P-n8;#7p{jlnfmrh* zOjLxwj5o00O|*dG&>hdOnOu_ZvE&LlPZ^jFUm;Wbx{B+pNiaUK#@$V3SoRDoHyk5v zXTutI6h!I&*V@_ZHW37Id<_vGQGjTobWVeikfQtaol6Q*B1$^2k29i3urTQ;Qc~m* zQt}8CyaF9ayZ{}gOQ7O6yF1Qd-(~HXl`ebsZRU2@ceAte@gL_cn&GBu&uo6c8BaWx z9Q@w~ld_5@Ng^2(-9s6IEz^l6T0F%&s6g#gA{oSSR<21wd3z@XAhd_|80TKG^C0Es zqans|Qeh(PV!^Ht79Kv)FvkrTPKU7p_%Alvt`9*93nNJjg=Mz9X-M;H3vw=oai*D& zluE4Ns6%t|yQ>u^*g>5nRB9_j+@OQ)47b@qRFe1)AZ#IeBIh-Aos6LA0sjx28`5)v zw=C8vbk-RekXQ)p0~8$D;$^>VWT;tNfrELG#pf?l?HqQrMy`&!{z8u$YEHAMNnFI?J!imHSFD7+V1n7mG zU;2+b0}%_T&vHRbLqKG`XE!1#A)|pVTy4X(1cH!BsfscLleaB1$ zd!eeGZAhpT+1ZQW@8M^&^Y;i6@N?NlV3`w0JWs(x{G2dq;qm1N&;roMWrJH`jP*Mh z?5Ehhv9)G70YZcufUG2>Hn)_(o5#aJ1%@1}2yqVX$-j!5Xhpg-K;rSjC*m8keh4h*YO~MSR*N~N2k6jw1P5sPpm;#ERz@AW%x^N0tKUtcJHOn6OUqHY8NI@8sj* z)kFoCEl8;F+(u$C!@RExmx$7Z57rl$GIkQiC?EmzEN%Gtn!oO4Gr+xJKFcUgDJn&) zT|Anym=wgZgFKyJpRWb9<*`|}^k^u@4f%&#eGX&Ze~}Na?D+a7wY0m(ar&cgPQMv5 z-Q|NXcYS?_TH0OXnE&dV`A=ic^&;OXy*=OVI`!G!zB&7C%mdD~XuCdN&?O`7KGW_K z?J~}_$TcbVIker}xBG6dxIfzNAs?lGk-sMN&i%Pma!n4o2lt#(+4A&{G5h*~TG~iC y_R}sA;W*dA!E?;G47cc`hi;MJ>$IDZYSxPuOBWNYP-Kq(D>*8 literal 4224 zcmb7{&x;&I6vwOMuJIRS4v2qNmigP4OC{{TTHh+c9J=)r?}5D`h#;Sq#g4Oe_8<(Qroa>JD)iCTme$Q@^OZdIEsUd~ z&Ndjkc)QK9OB=3>?E%K7C+{u7Hen16=i@LeF>l`C>&(04c~3lcY%x&Jnl|h07j;uj z#y!EKko()?YIo2M4|-cN2~(W}dD)Y`RNKDXmg;G?Q;qkE`q|#j&V`$}5cM7^|8|(FcAS*c){gIsdF!Zms5-!B~+nrS>tkl!YJK==c~Ul9I|@Gped zR|3NQHVHpR_$|US!tWFQobWe*L&6^uzDf9R!e@>jjsGIyON2im`~%^C2yZ=fbp1C7 zUncw+;U5X#A$<1XqwBv(nDJuJFKaU@7|$l7Q88{ApZ`X2)3$Y$&f213yg3-PCWY&u zY3oIAab@XPhN|CWW@zfZsjGI-hZ!x;RIKw*XF>+C3W9Pw+nsTrsXhJ9WVg-t_GO^M z!-O?$&Q+XeNgC@ok4+L8weXb|EwE_HqJ4S>5h_(zt&0A*LG6Yo*Kb6yJSk(P= zRt?)~+;AaeqI?yXWtbNt$rr^I;3jUaKHjFAYk<)?y1K{e|BqF%3>*W%qHuFn?io;6 zFm9{*SOjja+C2l>JpkU`d~W)wsK@*F$h!G3_r791jBtdz&O~-QHFgA-}&cYtZUtRF$}Ew N{S1CrSH5XGzq@j;)wlov diff --git a/tests/bn254-scalar-arith/src/main.rs b/tests/bn254-scalar-arith/src/main.rs index 64f87c9180..e245a051b4 100644 --- a/tests/bn254-scalar-arith/src/main.rs +++ b/tests/bn254-scalar-arith/src/main.rs @@ -1,3 +1,6 @@ +#![no_main] +sp1_zkvm::entrypoint!(main); + extern "C" { fn syscall_bn254_scalar_arith(pq: *mut u32, op: *const u32); } @@ -20,4 +23,5 @@ fn main() { } assert_eq!(&pq[0..32], &c); + println!("done"); } From 7bf8d1eaf8546dd6dbee55a98fd81e2e1e67fcb4 Mon Sep 17 00:00:00 2001 From: kunxian-xia Date: Wed, 24 Apr 2024 11:40:41 +0800 Subject: [PATCH 05/34] include bn254 scalar arith chip in riscv air --- core/src/air/builder.rs | 4 ++-- core/src/runtime/record.rs | 13 +++++++++++++ core/src/stark/air.rs | 5 +++++ 3 files changed, 20 insertions(+), 2 deletions(-) diff --git a/core/src/air/builder.rs b/core/src/air/builder.rs index 32e2bd0da6..2b3822a531 100644 --- a/core/src/air/builder.rs +++ b/core/src/air/builder.rs @@ -514,7 +514,7 @@ pub trait MemoryAirBuilder: BaseAirBuilder { verify_memory_access: EVerify, ) where EShard: Into + Copy, - Ea: Into + Copy, + Ea: Into + Clone, Eb: Into + Copy, EVerify: Into + Copy, M: MemoryCols, @@ -523,7 +523,7 @@ pub trait MemoryAirBuilder: BaseAirBuilder { self.eval_memory_access( shard, clk.clone(), - initial_addr.into() + Self::Expr::from_canonical_usize(i * 4), + initial_addr.clone().into() + Self::Expr::from_canonical_usize(i * 4), access_slice, verify_memory_access, ); diff --git a/core/src/runtime/record.rs b/core/src/runtime/record.rs index 25033d5009..af2501f2ef 100644 --- a/core/src/runtime/record.rs +++ b/core/src/runtime/record.rs @@ -126,6 +126,7 @@ pub struct ShardingConfig { pub bls12381_add_len: usize, pub bls12381_double_len: usize, pub uint256_mul_len: usize, + pub bn254_scalar_arith_len: usize, } impl ShardingConfig { @@ -156,6 +157,7 @@ impl Default for ShardingConfig { bls12381_add_len: shard_size, bls12381_double_len: shard_size, uint256_mul_len: shard_size, + bn254_scalar_arith_len: shard_size, } } } @@ -289,6 +291,8 @@ impl MachineRecord for ExecutionRecord { .append(&mut other.uint256_mul_events); self.bls12381_decompress_events .append(&mut other.bls12381_decompress_events); + self.bn254_scalar_arith_events + .append(&mut other.bn254_scalar_arith_events); // Merge the byte lookups. for (shard, events_map) in std::mem::take(&mut other.byte_lookups).into_iter() { @@ -502,6 +506,15 @@ impl MachineRecord for ExecutionRecord { .extend_from_slice(bls12381_double_chunk); } + for (bn254_scalar_arith_chunk, shard) in take(&mut self.bn254_scalar_arith_events) + .chunks_mut(config.bn254_scalar_arith_len) + .zip(shards.iter_mut()) + { + shard + .bn254_scalar_arith_events + .extend_from_slice(bn254_scalar_arith_chunk); + } + // Put the precompile events in the first shard. let first = shards.first_mut().unwrap(); diff --git a/core/src/stark/air.rs b/core/src/stark/air.rs index 660d602b71..9eae9b1820 100644 --- a/core/src/stark/air.rs +++ b/core/src/stark/air.rs @@ -21,6 +21,7 @@ pub(crate) mod riscv_chips { pub use crate::memory::MemoryChip; pub use crate::program::ProgramChip; pub use crate::syscall::precompiles::blake3::Blake3CompressInnerChip; + pub use crate::syscall::precompiles::bn254_scalar::Bn254ScalarArithChip; pub use crate::syscall::precompiles::edwards::EdAddAssignChip; pub use crate::syscall::precompiles::edwards::EdDecompressChip; pub use crate::syscall::precompiles::keccak256::KeccakPermuteChip; @@ -99,6 +100,8 @@ pub enum RiscvAir { Bls12381Double(WeierstrassDoubleAssignChip>), /// A precompile for uint256 mul. Uint256Mul(Uint256MulChip), + /// A precompile for bn254 scalar field arithmetic. + Bn254ScalarArith(Bn254ScalarArithChip), /// A precompile for decompressing a point on the BLS12-381 curve. Bls12381Decompress(WeierstrassDecompressChip>), } @@ -148,6 +151,8 @@ impl RiscvAir { chips.push(RiscvAir::Bls12381Double(bls12381_double)); let uint256_mul = Uint256MulChip::default(); chips.push(RiscvAir::Uint256Mul(uint256_mul)); + let bn254_scalar_arith = Bn254ScalarArithChip::new(); + chips.push(RiscvAir::Bn254ScalarArith(bn254_scalar_arith)); let bls12381_decompress = WeierstrassDecompressChip::>::new(); chips.push(RiscvAir::Bls12381Decompress(bls12381_decompress)); let add = AddSubChip::default(); From 52b5103f4541833a93104a10ed9babdc6fd15ec5 Mon Sep 17 00:00:00 2001 From: kunxian-xia Date: Wed, 24 Apr 2024 11:41:50 +0800 Subject: [PATCH 06/34] add selector --- .../syscall/precompiles/bn254_scalar/mod.rs | 36 +++++++++++++------ 1 file changed, 25 insertions(+), 11 deletions(-) diff --git a/core/src/syscall/precompiles/bn254_scalar/mod.rs b/core/src/syscall/precompiles/bn254_scalar/mod.rs index 39f4505825..d265c6959f 100644 --- a/core/src/syscall/precompiles/bn254_scalar/mod.rs +++ b/core/src/syscall/precompiles/bn254_scalar/mod.rs @@ -1,5 +1,6 @@ mod general_field_op; +use num::Zero; use std::borrow::{Borrow, BorrowMut}; use crate::{ @@ -15,7 +16,7 @@ use crate::{ field::{FieldParameters, NumLimbs, NumWords}, weierstrass::bn254::Bn254ScalarField, }, - limbs_from_prev_access, + limbs_from_prev_access, pad_rows, }, }; use num::BigUint; @@ -50,6 +51,7 @@ pub struct FieldArithEvent { #[derive(Debug, Clone, AlignedBorrow)] #[repr(C)] pub struct Bn254ScalarArithAssignCols { + is_real: T, shard: T, clk: T, op: T, @@ -97,9 +99,6 @@ impl Syscall for Bn254ScalarArithChip { let (q_memory_records, q) = rt.mr_slice(pq_ptr + 4 * (nw_per_fe as u32), nw_per_fe); let (op_memory_record, op) = rt.mr(op_ptr); - // TODO: why? - // rt.clk += 1; - let bn_p = BigUint::from_bytes_le( &p.iter() .cloned() @@ -190,6 +189,7 @@ impl MachineAir for Bn254ScalarArithChip { .as_slice(), ); + cols.is_real = F::one(); cols.shard = F::from_canonical_u32(event.shard); cols.clk = F::from_canonical_u32(event.clk); cols.pq_ptr = F::from_canonical_u32(event.pq_ptr); @@ -212,6 +212,16 @@ impl MachineAir for Bn254ScalarArithChip { output.add_byte_lookup_events(new_byte_lookup_events); // TODO: add padding rows + pad_rows(&mut rows, || { + let mut row = [F::zero(); NUM_COLS]; + let cols: &mut Bn254ScalarArithAssignCols = row.as_mut_slice().borrow_mut(); + + let zero = BigUint::zero(); + let op = FieldOperation::Add; + cols.eval.populate(&zero, &zero, op); + + row + }); RowMajorMatrix::new(rows.into_iter().flatten().collect::>(), NUM_COLS) } @@ -230,13 +240,15 @@ impl BaseAir for Bn254ScalarArithChip { impl Air for Bn254ScalarArithChip where AB: SP1AirBuilder, - AB::Expr: Copy, + // AB::Expr: Copy, { fn eval(&self, builder: &mut AB) { let main = builder.main(); let row = main.row_slice(0); let row: &Bn254ScalarArithAssignCols = (*row).borrow(); + builder.assert_bool(row.is_real); + let p: Limbs<::Var, ::Limbs> = limbs_from_prev_access(&row.p_access); let q: Limbs<::Var, ::Limbs> = @@ -246,25 +258,27 @@ where row.eval.eval(builder, &p, &q, op[0]); for i in 0..Bn254ScalarField::NB_LIMBS { - builder.assert_eq(row.eval.cols.result[i], row.p_access[i / 4].value()[i % 4]); + builder + .when(row.is_real) + .assert_eq(row.eval.cols.result[i], row.p_access[i / 4].value()[i % 4]); } builder.eval_memory_access_slice( row.shard, row.clk.into(), - row.pq_ptr + AB::F::from_canonical_u32(4), + row.pq_ptr + AB::F::from_canonical_u32(4 * NUM_WORDS_PER_FE as u32), &row.q_access, - AB::F::one(), + row.is_real, ); - builder.eval_memory_access(row.shard, row.clk, row.op_ptr, &row.op_access, AB::F::one()); + builder.eval_memory_access(row.shard, row.clk, row.op_ptr, &row.op_access, row.is_real); builder.eval_memory_access_slice( row.shard, row.clk.into(), row.pq_ptr, &row.p_access, - AB::F::one(), + row.is_real, ); let syscall_id = AB::F::from_canonical_u32(SyscallCode::BN254_SCALAR_ARITH.syscall_id()); @@ -274,7 +288,7 @@ where syscall_id, row.pq_ptr, row.op_ptr, - AB::F::one(), + row.is_real, ); } } From 3a6f21bc130f4921e3f8f32ea9a423ac0014b7a9 Mon Sep 17 00:00:00 2001 From: kunxian-xia Date: Wed, 24 Apr 2024 12:35:33 +0800 Subject: [PATCH 07/34] pass op through value not pointer and refine testcase --- .../bn254_scalar/general_field_op.rs | 4 +-- .../syscall/precompiles/bn254_scalar/mod.rs | 31 ++++-------------- .../elf/riscv32im-succinct-zkvm-elf | Bin 113844 -> 114700 bytes tests/bn254-scalar-arith/src/main.rs | 21 +++++++----- zkvm/entrypoint/src/syscalls/bn254.rs | 2 +- zkvm/precompiles/src/lib.rs | 2 +- 6 files changed, 23 insertions(+), 37 deletions(-) diff --git a/core/src/syscall/precompiles/bn254_scalar/general_field_op.rs b/core/src/syscall/precompiles/bn254_scalar/general_field_op.rs index 58fd6640f4..d657390d75 100644 --- a/core/src/syscall/precompiles/bn254_scalar/general_field_op.rs +++ b/core/src/syscall/precompiles/bn254_scalar/general_field_op.rs @@ -57,9 +57,9 @@ impl GeneralFieldOpCols { // div: 1 1 // add: 0 0 // sub: 0 1 - let assigned_op: AB::Expr = AB::Expr::from(AB::F::from_canonical_u8(0x01)) + let assigned_op: AB::Expr = AB::Expr::from(AB::F::from_canonical_u8(0b01)) * is_sub_div.clone() - + AB::Expr::from(AB::F::from_canonical_u8(0x10)) * is_mul_div.clone(); + + AB::Expr::from(AB::F::from_canonical_u8(0b10)) * is_mul_div.clone(); builder.assert_eq(assigned_op, op.into()); let p_a_param: Polynomial = (*a).clone().into(); diff --git a/core/src/syscall/precompiles/bn254_scalar/mod.rs b/core/src/syscall/precompiles/bn254_scalar/mod.rs index d265c6959f..20fac49698 100644 --- a/core/src/syscall/precompiles/bn254_scalar/mod.rs +++ b/core/src/syscall/precompiles/bn254_scalar/mod.rs @@ -42,10 +42,8 @@ pub struct FieldArithEvent { pub p: Vec, pub q: Vec, pub pq_ptr: u32, - pub op_ptr: u32, pub p_memory_records: Vec, pub q_memory_records: Vec, - pub op_memory_record: MemoryReadRecord, } #[derive(Debug, Clone, AlignedBorrow)] @@ -56,10 +54,8 @@ pub struct Bn254ScalarArithAssignCols { clk: T, op: T, pq_ptr: T, - op_ptr: T, p_access: [MemoryWriteCols; NUM_WORDS_PER_FE], q_access: [MemoryReadCols; NUM_WORDS_PER_FE], - op_access: MemoryReadCols, eval: GeneralFieldOpCols, } @@ -86,10 +82,7 @@ impl Syscall for Bn254ScalarArithChip { if pq_ptr % 4 != 0 { panic!(); } - let op_ptr = arg2; - if op_ptr % 4 != 0 { - panic!(); - } + let op = arg2; let nw_per_fe = ::WordsFieldElement::USIZE; debug_assert_eq!(nw_per_fe, NUM_WORDS_PER_FE); @@ -97,7 +90,6 @@ impl Syscall for Bn254ScalarArithChip { let p: Vec = rt.slice_unsafe(pq_ptr, nw_per_fe); let (q_memory_records, q) = rt.mr_slice(pq_ptr + 4 * (nw_per_fe as u32), nw_per_fe); - let (op_memory_record, op) = rt.mr(op_ptr); let bn_p = BigUint::from_bytes_le( &p.iter() @@ -113,12 +105,12 @@ impl Syscall for Bn254ScalarArithChip { ); let modulus = Bn254ScalarField::modulus(); - let (r, t) = match op { + let (r, op) = match op { 0x00 => ((&bn_p + &bn_q) % modulus, FieldOperation::Add), 0x01 => ((&bn_p - &bn_q) % modulus, FieldOperation::Sub), - 0x10 => ((&bn_p * &bn_q) % modulus, FieldOperation::Mul), + 0x02 => ((&bn_p * &bn_q) % modulus, FieldOperation::Mul), // TODO: how to handle q == 0? - 0x11 => ((&bn_p / &bn_q) % modulus, FieldOperation::Div), + 0x03 => ((&bn_p / &bn_q) % modulus, FieldOperation::Div), _ => unreachable!("type {} not supported", op), }; log::trace!( @@ -141,14 +133,12 @@ impl Syscall for Bn254ScalarArithChip { .push(FieldArithEvent { shard, clk: start_clk, - op: t, + op, p, q, - op_ptr, pq_ptr, p_memory_records, q_memory_records, - op_memory_record, }); None @@ -193,7 +183,6 @@ impl MachineAir for Bn254ScalarArithChip { cols.shard = F::from_canonical_u32(event.shard); cols.clk = F::from_canonical_u32(event.clk); cols.pq_ptr = F::from_canonical_u32(event.pq_ptr); - cols.op_ptr = F::from_canonical_u32(event.op_ptr); cols.op = F::from_canonical_u32(event.op as u32); cols.eval.populate(&p, &q, event.op); @@ -204,14 +193,11 @@ impl MachineAir for Bn254ScalarArithChip { for i in 0..cols.q_access.len() { cols.q_access[i].populate(event.q_memory_records[i], &mut new_byte_lookup_events); } - cols.op_access - .populate(event.op_memory_record, &mut new_byte_lookup_events); rows.push(row); } output.add_byte_lookup_events(new_byte_lookup_events); - // TODO: add padding rows pad_rows(&mut rows, || { let mut row = [F::zero(); NUM_COLS]; let cols: &mut Bn254ScalarArithAssignCols = row.as_mut_slice().borrow_mut(); @@ -253,9 +239,8 @@ where limbs_from_prev_access(&row.p_access); let q: Limbs<::Var, ::Limbs> = limbs_from_prev_access(&row.q_access); - let op = row.op_access.prev_value().0.to_vec(); - row.eval.eval(builder, &p, &q, op[0]); + row.eval.eval(builder, &p, &q, row.op); for i in 0..Bn254ScalarField::NB_LIMBS { builder @@ -271,8 +256,6 @@ where row.is_real, ); - builder.eval_memory_access(row.shard, row.clk, row.op_ptr, &row.op_access, row.is_real); - builder.eval_memory_access_slice( row.shard, row.clk.into(), @@ -287,7 +270,7 @@ where row.clk, syscall_id, row.pq_ptr, - row.op_ptr, + row.op, row.is_real, ); } diff --git a/tests/bn254-scalar-arith/elf/riscv32im-succinct-zkvm-elf b/tests/bn254-scalar-arith/elf/riscv32im-succinct-zkvm-elf index 78f0a45c839d4effa9c9e7f127efa1ecec2d13e7..681964662373ec207a7c7864d533738d2be5b5c0 100755 GIT binary patch delta 24411 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

RUo{zi|)A88LK3^`$Bb2C*shtHuj3x3J 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 delta 23324 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 F{|DJ1A_)Kh diff --git a/tests/bn254-scalar-arith/src/main.rs b/tests/bn254-scalar-arith/src/main.rs index e245a051b4..09c77394fb 100644 --- a/tests/bn254-scalar-arith/src/main.rs +++ b/tests/bn254-scalar-arith/src/main.rs @@ -2,26 +2,29 @@ sp1_zkvm::entrypoint!(main); extern "C" { - fn syscall_bn254_scalar_arith(pq: *mut u32, op: *const u32); + fn syscall_bn254_scalar_arith(pq: *mut u32, op: u32); } fn main() { let mut pq: [u8; 64] = [ - 1, 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, 2, 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, + 69, 44, 191, 0, 130, 148, 188, 171, 61, 47, 83, 78, 152, 132, 196, 72, 209, 29, 140, 237, + 126, 75, 223, 58, 115, 139, 235, 236, 200, 47, 2, 28, 169, 1, 76, 216, 163, 152, 124, 133, + 147, 234, 54, 244, 220, 34, 93, 224, 147, 90, 136, 227, 1, 70, 214, 130, 142, 119, 53, 203, + 16, 160, 133, 43, ]; - let op: [u8; 4] = [0, 0, 0, 0]; + // multiplication + let op = 2u32; let c: [u8; 32] = [ - 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, + 43, 132, 167, 109, 73, 175, 44, 161, 152, 82, 20, 126, 173, 132, 9, 50, 112, 242, 217, 141, + 87, 50, 0, 64, 74, 105, 9, 124, 167, 37, 39, 37, ]; + println!("cycle-tracker-start: bn254_scalar_arith"); unsafe { - syscall_bn254_scalar_arith(pq.as_mut_ptr() as *mut u32, op.as_ptr() as *const u32); + syscall_bn254_scalar_arith(pq.as_mut_ptr() as *mut u32, op); } + println!("cycle-tracker-end: bn254_scalar_arith"); assert_eq!(&pq[0..32], &c); - println!("done"); } diff --git a/zkvm/entrypoint/src/syscalls/bn254.rs b/zkvm/entrypoint/src/syscalls/bn254.rs index 36202a5c00..618fd5aa15 100644 --- a/zkvm/entrypoint/src/syscalls/bn254.rs +++ b/zkvm/entrypoint/src/syscalls/bn254.rs @@ -43,7 +43,7 @@ pub extern "C" fn syscall_bn254_double(p: *mut u32) { #[allow(unused_variables)] #[no_mangle] -pub extern "C" fn syscall_bn254_scalar_arith(pq: *mut u32, op: *const u32) { +pub extern "C" fn syscall_bn254_scalar_arith(pq: *mut u32, op: u32) { #[cfg(target_os = "zkvm")] unsafe { asm!( diff --git a/zkvm/precompiles/src/lib.rs b/zkvm/precompiles/src/lib.rs index b6e16fc063..60296b989b 100644 --- a/zkvm/precompiles/src/lib.rs +++ b/zkvm/precompiles/src/lib.rs @@ -33,5 +33,5 @@ extern "C" { pub fn syscall_hint_read(ptr: *mut u8, len: usize); pub fn sys_alloc_aligned(bytes: usize, align: usize) -> *mut u8; pub fn syscall_bls12381_decompress(point: &mut [u8; 96], is_odd: bool); - pub fn syscall_bn254_scalar_arith(pq: *mut u32, op: *const u32); + pub fn syscall_bn254_scalar_arith(pq: *mut u32, op: u32); } From a0afb445ab866f429a0b14bf1696c2f1080d482b Mon Sep 17 00:00:00 2001 From: kunxian-xia Date: Thu, 9 May 2024 12:30:59 +0800 Subject: [PATCH 08/34] add poseidon_bn254 example --- .../syscall/precompiles/bn254_scalar/mod.rs | 1 + examples/poseidon_bn254/.gitignore | 16 + examples/poseidon_bn254/program/Cargo.lock | 1043 ++++ examples/poseidon_bn254/program/Cargo.toml | 11 + .../program/elf/riscv32im-succinct-zkvm-elf | Bin 0 -> 192100 bytes examples/poseidon_bn254/program/src/main.rs | 32 + examples/poseidon_bn254/script/Cargo.lock | 4699 +++++++++++++++++ examples/poseidon_bn254/script/Cargo.toml | 11 + examples/poseidon_bn254/script/build.rs | 5 + examples/poseidon_bn254/script/src/main.rs | 25 + 10 files changed, 5843 insertions(+) create mode 100644 examples/poseidon_bn254/.gitignore create mode 100644 examples/poseidon_bn254/program/Cargo.lock create mode 100644 examples/poseidon_bn254/program/Cargo.toml create mode 100755 examples/poseidon_bn254/program/elf/riscv32im-succinct-zkvm-elf create mode 100644 examples/poseidon_bn254/program/src/main.rs create mode 100644 examples/poseidon_bn254/script/Cargo.lock create mode 100644 examples/poseidon_bn254/script/Cargo.toml create mode 100644 examples/poseidon_bn254/script/build.rs create mode 100644 examples/poseidon_bn254/script/src/main.rs diff --git a/core/src/syscall/precompiles/bn254_scalar/mod.rs b/core/src/syscall/precompiles/bn254_scalar/mod.rs index 20fac49698..1e67379aa6 100644 --- a/core/src/syscall/precompiles/bn254_scalar/mod.rs +++ b/core/src/syscall/precompiles/bn254_scalar/mod.rs @@ -276,6 +276,7 @@ where } } +#[cfg(test)] mod tests { use crate::{ runtime::Program, diff --git a/examples/poseidon_bn254/.gitignore b/examples/poseidon_bn254/.gitignore new file mode 100644 index 0000000000..0be6e7269a --- /dev/null +++ b/examples/poseidon_bn254/.gitignore @@ -0,0 +1,16 @@ +# Cargo build +**/target + +# Cargo config +.cargo + +# Profile-guided optimization +/tmp +pgo-data.profdata + +# MacOS nuisances +.DS_Store + +# Proofs +**/proof-with-pis.json +**/proof-with-io.json diff --git a/examples/poseidon_bn254/program/Cargo.lock b/examples/poseidon_bn254/program/Cargo.lock new file mode 100644 index 0000000000..e968ccb59d --- /dev/null +++ b/examples/poseidon_bn254/program/Cargo.lock @@ -0,0 +1,1043 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "anyhow" +version = "1.0.83" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "25bdb32cbbdce2b519a9cd7df3a678443100e265d5e25ca763b7572a5104f5f3" + +[[package]] +name = "arrayref" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6b4930d2cb77ce62f89ee5d5289b4ac049559b1c45539271f5ed4fdc7db34545" + +[[package]] +name = "arrayvec" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96d30a06541fbafbc7f82ed10c06164cfbd2c401138f6addd8404629c4b16711" + +[[package]] +name = "autocfg" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0" + +[[package]] +name = "base16ct" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c7f02d4ea65f2c1853089ffd8d2787bdbc63de2f0d29dedbcf8ccdfa0ccd4cf" + +[[package]] +name = "base64ct" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8c3c1a368f70d6cf7302d78f8f7093da241fb8e8807c05cc9e51a125895a6d5b" + +[[package]] +name = "bincode" +version = "1.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1f45e9417d87227c7a56d22e471c6206462cba514c7590c09aff4cf6d1ddcad" +dependencies = [ + "serde", +] + +[[package]] +name = "bitvec" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bc2832c24239b0141d5674bb9174f9d68a8b5b3f2753311927c172ca46f7e9c" +dependencies = [ + "funty", + "radium", + "tap", + "wyz", +] + +[[package]] +name = "blake2b_simd" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23285ad32269793932e830392f2fe2f83e26488fd3ec778883a93c8323735780" +dependencies = [ + "arrayref", + "arrayvec", + "constant_time_eq", +] + +[[package]] +name = "block-buffer" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" +dependencies = [ + "generic-array", +] + +[[package]] +name = "byte-slice-cast" +version = "1.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3ac9f8b63eca6fd385229b3675f6cc0dc5c8a5c8a54a59d4f52ffd670d87b0c" + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "const-oid" +version = "0.9.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8" + +[[package]] +name = "constant_time_eq" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f7144d30dcf0fafbce74250a3963025d8d52177934239851c917d29f1df280c2" + +[[package]] +name = "cpufeatures" +version = "0.2.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53fe5e26ff1b7aef8bca9c6080520cfb8d9333c7568e1829cef191a9723e5504" +dependencies = [ + "libc", +] + +[[package]] +name = "crypto-bigint" +version = "0.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0dc92fb57ca44df6db8059111ab3af99a63d5d0f8375d9972e319a379c6bab76" +dependencies = [ + "generic-array", + "rand_core", + "subtle", + "zeroize", +] + +[[package]] +name = "crypto-common" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" +dependencies = [ + "generic-array", + "typenum", +] + +[[package]] +name = "der" +version = "0.7.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f55bf8e7b65898637379c1b74eb1551107c8294ed26d855ceb9fd1a09cfc9bc0" +dependencies = [ + "const-oid", + "zeroize", +] + +[[package]] +name = "derive_more" +version = "0.99.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fb810d30a7c1953f91334de7244731fc3f3c10d7fe163338a35b9f640960321" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "digest" +version = "0.10.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" +dependencies = [ + "block-buffer", + "const-oid", + "crypto-common", + "subtle", +] + +[[package]] +name = "ecdsa" +version = "0.16.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee27f32b5c5292967d2d4a9d7f1e0b0aed2c15daded5a60300e4abb9d8020bca" +dependencies = [ + "der", + "digest", + "elliptic-curve", + "rfc6979", + "signature", + "spki", +] + +[[package]] +name = "either" +version = "1.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a47c1c47d2f5964e29c61246e81db715514cd532db6b5116a25ea3c03d6780a2" + +[[package]] +name = "elliptic-curve" +version = "0.13.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5e6043086bf7973472e0c7dff2142ea0b680d30e18d9cc40f267efbf222bd47" +dependencies = [ + "base16ct", + "crypto-bigint", + "digest", + "ff", + "generic-array", + "group", + "pkcs8", + "rand_core", + "sec1", + "subtle", + "tap", + "zeroize", +] + +[[package]] +name = "equivalent" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" + +[[package]] +name = "ff" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ded41244b729663b1e574f1b4fb731469f69f79c17667b5d776b16cda0479449" +dependencies = [ + "bitvec", + "rand_core", + "subtle", +] + +[[package]] +name = "funty" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c" + +[[package]] +name = "gcd" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d758ba1b47b00caf47f24925c0074ecb20d6dfcffe7f6d53395c0465674841a" + +[[package]] +name = "generic-array" +version = "0.14.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" +dependencies = [ + "typenum", + "version_check", + "zeroize", +] + +[[package]] +name = "getrandom" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" +dependencies = [ + "cfg-if", + "libc", + "wasi", +] + +[[package]] +name = "group" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0f9ef7462f7c099f518d754361858f86d8a07af53ba9af0fe635bbccb151a63" +dependencies = [ + "ff", + "rand_core", + "subtle", +] + +[[package]] +name = "halo2curves" +version = "0.3.3" +source = "git+https://github.com/kunxian-xia/halo2curves.git?branch=feat/sp1#bdcf288396c9bd8eb76d81f25b98615abe3afb20" +dependencies = [ + "ff", + "group", + "lazy_static", + "num-bigint", + "num-traits", + "pasta_curves", + "paste", + "rand", + "rand_core", + "serde", + "static_assertions", + "subtle", +] + +[[package]] +name = "hashbrown" +version = "0.14.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" + +[[package]] +name = "hex" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" + +[[package]] +name = "hmac" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e" +dependencies = [ + "digest", +] + +[[package]] +name = "impl-trait-for-tuples" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "11d7a9f6330b71fea57921c9b61c47ee6e84f72d394754eff6163ae67e7395eb" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "indexmap" +version = "2.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "168fb715dda47215e360912c096649d23d58bf392ac62f73919e831745e40f26" +dependencies = [ + "equivalent", + "hashbrown", +] + +[[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" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba291022dbbd398a455acf126c1e341954079855bc60dfdda641363bd6922569" +dependencies = [ + "either", +] + +[[package]] +name = "k256" +version = "0.13.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "956ff9b67e26e1a6a866cb758f12c6f8746208489e3e4a4b5580802f2f0a587b" +dependencies = [ + "cfg-if", + "ecdsa", + "elliptic-curve", + "once_cell", + "sha2", + "signature", +] + +[[package]] +name = "lazy_static" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" +dependencies = [ + "spin", +] + +[[package]] +name = "libc" +version = "0.2.154" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae743338b92ff9146ce83992f766a31066a91a8c84a45e0e9f21e7cf6de6d346" + +[[package]] +name = "libm" +version = "0.2.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ec2a862134d2a7d32d7983ddcdd1c4923530833c9f2ea1a44fc5fa473989058" + +[[package]] +name = "memchr" +version = "2.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c8640c5d730cb13ebd907d8d04b52f55ac9a2eec55b440c8892f40d56c76c1d" + +[[package]] +name = "num" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3135b08af27d103b0a51f2ae0f8632117b7b185ccf931445affa8df530576a41" +dependencies = [ + "num-bigint", + "num-complex", + "num-integer", + "num-iter", + "num-rational", + "num-traits", +] + +[[package]] +name = "num-bigint" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c165a9ab64cf766f73521c0dd2cfdff64f488b8f0b3e621face3462d3db536d7" +dependencies = [ + "num-integer", + "num-traits", +] + +[[package]] +name = "num-complex" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23c6602fda94a57c990fe0df199a035d83576b496aa29f4e634a8ac6004e68a6" +dependencies = [ + "num-traits", +] + +[[package]] +name = "num-integer" +version = "0.1.46" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" +dependencies = [ + "num-traits", +] + +[[package]] +name = "num-iter" +version = "0.1.45" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1429034a0490724d0075ebb2bc9e875d6503c3cf69e235a8941aa757d83ef5bf" +dependencies = [ + "autocfg", + "num-integer", + "num-traits", +] + +[[package]] +name = "num-rational" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0638a1c9d0a3c0914158145bc76cff373a75a627e6ecbfb71cbe6f453a5a19b0" +dependencies = [ + "autocfg", + "num-bigint", + "num-integer", + "num-traits", +] + +[[package]] +name = "num-traits" +version = "0.2.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" +dependencies = [ + "autocfg", +] + +[[package]] +name = "once_cell" +version = "1.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" + +[[package]] +name = "p3-baby-bear" +version = "0.1.0" +source = "git+https://github.com/Plonky3/Plonky3.git?branch=sp1#d379375a75417ddfd0a059ce7db63e162ec52c69" +dependencies = [ + "num-bigint", + "p3-field", + "p3-mds", + "p3-poseidon2", + "p3-symmetric", + "rand", + "serde", +] + +[[package]] +name = "p3-dft" +version = "0.1.0" +source = "git+https://github.com/Plonky3/Plonky3.git?branch=sp1#d379375a75417ddfd0a059ce7db63e162ec52c69" +dependencies = [ + "p3-field", + "p3-matrix", + "p3-maybe-rayon", + "p3-util", + "tracing", +] + +[[package]] +name = "p3-field" +version = "0.1.0" +source = "git+https://github.com/Plonky3/Plonky3.git?branch=sp1#d379375a75417ddfd0a059ce7db63e162ec52c69" +dependencies = [ + "itertools 0.12.1", + "num-bigint", + "num-traits", + "p3-util", + "rand", + "serde", +] + +[[package]] +name = "p3-matrix" +version = "0.1.0" +source = "git+https://github.com/Plonky3/Plonky3.git?branch=sp1#d379375a75417ddfd0a059ce7db63e162ec52c69" +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/Plonky3/Plonky3.git?branch=sp1#d379375a75417ddfd0a059ce7db63e162ec52c69" + +[[package]] +name = "p3-mds" +version = "0.1.0" +source = "git+https://github.com/Plonky3/Plonky3.git?branch=sp1#d379375a75417ddfd0a059ce7db63e162ec52c69" +dependencies = [ + "itertools 0.11.0", + "p3-dft", + "p3-field", + "p3-matrix", + "p3-symmetric", + "p3-util", + "rand", +] + +[[package]] +name = "p3-poseidon2" +version = "0.1.0" +source = "git+https://github.com/Plonky3/Plonky3.git?branch=sp1#d379375a75417ddfd0a059ce7db63e162ec52c69" +dependencies = [ + "gcd", + "p3-field", + "p3-mds", + "p3-symmetric", + "rand", +] + +[[package]] +name = "p3-symmetric" +version = "0.1.0" +source = "git+https://github.com/Plonky3/Plonky3.git?branch=sp1#d379375a75417ddfd0a059ce7db63e162ec52c69" +dependencies = [ + "itertools 0.12.1", + "p3-field", + "serde", +] + +[[package]] +name = "p3-util" +version = "0.1.0" +source = "git+https://github.com/Plonky3/Plonky3.git?branch=sp1#d379375a75417ddfd0a059ce7db63e162ec52c69" +dependencies = [ + "serde", +] + +[[package]] +name = "parity-scale-codec" +version = "3.6.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "881331e34fa842a2fb61cc2db9643a8fedc615e47cfcc52597d1af0db9a7e8fe" +dependencies = [ + "arrayvec", + "byte-slice-cast", + "impl-trait-for-tuples", + "parity-scale-codec-derive", +] + +[[package]] +name = "parity-scale-codec-derive" +version = "3.6.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "be30eaf4b0a9fba5336683b38de57bb86d179a35862ba6bfcf57625d006bde5b" +dependencies = [ + "proc-macro-crate 2.0.2", + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "pasta_curves" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3e57598f73cc7e1b2ac63c79c517b31a0877cd7c402cdcaa311b5208de7a095" +dependencies = [ + "blake2b_simd", + "ff", + "group", + "lazy_static", + "rand", + "static_assertions", + "subtle", +] + +[[package]] +name = "paste" +version = "1.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" + +[[package]] +name = "pin-project-lite" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bda66fc9667c18cb2758a2ac84d1167245054bcf85d5d1aaa6923f45801bdd02" + +[[package]] +name = "pkcs8" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f950b2377845cebe5cf8b5165cb3cc1a5e0fa5cfa3e1f7f55707d8fd82e0a7b7" +dependencies = [ + "der", + "spki", +] + +[[package]] +name = "poseidon-base" +version = "0.1.0" +source = "git+https://github.com/scroll-tech/poseidon-circuit.git?branch=feat/sp1#ab45385dcbce698010b88395861e89a7726a57a3" +dependencies = [ + "bitvec", + "halo2curves", + "lazy_static", + "subtle", +] + +[[package]] +name = "poseidon_bn254-program" +version = "0.1.0" +dependencies = [ + "halo2curves", + "hex", + "poseidon-base", + "sp1-zkvm", +] + +[[package]] +name = "ppv-lite86" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" + +[[package]] +name = "proc-macro-crate" +version = "1.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f4c021e1093a56626774e81216a4ce732a735e5bad4868a03f3ed65ca0c3919" +dependencies = [ + "once_cell", + "toml_edit 0.19.15", +] + +[[package]] +name = "proc-macro-crate" +version = "2.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b00f26d3400549137f92511a46ac1cd8ce37cb5598a96d382381458b992a5d24" +dependencies = [ + "toml_datetime", + "toml_edit 0.20.2", +] + +[[package]] +name = "proc-macro2" +version = "1.0.82" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ad3d49ab951a01fbaafe34f2ec74122942fe18a3f9814c3268f1bb72042131b" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.36" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "radium" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc33ff2d4973d518d823d61aa239014831e521c75da58e3df4840d3f47749d09" + +[[package]] +name = "rand" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" +dependencies = [ + "libc", + "rand_chacha", + "rand_core", +] + +[[package]] +name = "rand_chacha" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" +dependencies = [ + "ppv-lite86", + "rand_core", +] + +[[package]] +name = "rand_core" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" +dependencies = [ + "getrandom", +] + +[[package]] +name = "rfc6979" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8dd2a808d456c4a54e300a23e9f5a67e122c3024119acbfd73e3bf664491cb2" +dependencies = [ + "hmac", + "subtle", +] + +[[package]] +name = "scale-info" +version = "2.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7c453e59a955f81fb62ee5d596b450383d699f152d350e9d23a0db2adb78e4c0" +dependencies = [ + "cfg-if", + "derive_more", + "parity-scale-codec", + "scale-info-derive", +] + +[[package]] +name = "scale-info-derive" +version = "2.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "18cf6c6447f813ef19eb450e985bcce6705f9ce7660db221b59093d15c79c4b7" +dependencies = [ + "proc-macro-crate 1.3.1", + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "sec1" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3e97a565f76233a6003f9f5c54be1d9c5bdfa3eccfb189469f11ec4901c47dc" +dependencies = [ + "base16ct", + "der", + "generic-array", + "pkcs8", + "subtle", + "zeroize", +] + +[[package]] +name = "serde" +version = "1.0.200" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ddc6f9cc94d67c0e21aaf7eda3a010fd3af78ebf6e096aa6e2e13c79749cce4f" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.200" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "856f046b9400cee3c8c94ed572ecdb752444c24528c035cd35882aad6f492bcb" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.61", +] + +[[package]] +name = "sha2" +version = "0.10.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest", +] + +[[package]] +name = "signature" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77549399552de45a898a580c1b41d445bf730df867cc44e6c0233bbc4b8329de" +dependencies = [ + "digest", + "rand_core", +] + +[[package]] +name = "snowbridge-amcl" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "460a9ed63cdf03c1b9847e8a12a5f5ba19c4efd5869e4a737e05be25d7c427e5" +dependencies = [ + "parity-scale-codec", + "scale-info", +] + +[[package]] +name = "sp1-precompiles" +version = "0.1.0" +dependencies = [ + "anyhow", + "bincode", + "cfg-if", + "getrandom", + "hex", + "k256", + "num", + "rand", + "serde", + "snowbridge-amcl", +] + +[[package]] +name = "sp1-primitives" +version = "0.1.0" +dependencies = [ + "itertools 0.12.1", + "lazy_static", + "p3-baby-bear", + "p3-field", + "p3-poseidon2", + "p3-symmetric", +] + +[[package]] +name = "sp1-zkvm" +version = "0.1.0" +dependencies = [ + "bincode", + "cfg-if", + "getrandom", + "k256", + "libm", + "once_cell", + "p3-baby-bear", + "p3-field", + "rand", + "serde", + "sha2", + "sp1-precompiles", + "sp1-primitives", +] + +[[package]] +name = "spin" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" + +[[package]] +name = "spki" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d91ed6c858b01f942cd56b37a94b3e0a1798290327d1236e4d9cf4eaca44d29d" +dependencies = [ + "base64ct", + "der", +] + +[[package]] +name = "static_assertions" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" + +[[package]] +name = "subtle" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "81cdd64d312baedb58e21336b31bc043b77e01cc99033ce76ef539f78e965ebc" + +[[package]] +name = "syn" +version = "1.0.109" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "syn" +version = "2.0.61" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c993ed8ccba56ae856363b1845da7266a7cb78e1d146c8a32d54b45a8b831fc9" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "tap" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" + +[[package]] +name = "toml_datetime" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7cda73e2f1397b1262d6dfdcef8aafae14d1de7748d66822d3bfeeb6d03e5e4b" + +[[package]] +name = "toml_edit" +version = "0.19.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b5bb770da30e5cbfde35a2d7b9b8a2c4b8ef89548a7a6aeab5c9a576e3e7421" +dependencies = [ + "indexmap", + "toml_datetime", + "winnow", +] + +[[package]] +name = "toml_edit" +version = "0.20.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "396e4d48bbb2b7554c944bde63101b5ae446cff6ec4a24227428f15eb72ef338" +dependencies = [ + "indexmap", + "toml_datetime", + "winnow", +] + +[[package]] +name = "tracing" +version = "0.1.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" +dependencies = [ + "pin-project-lite", + "tracing-attributes", + "tracing-core", +] + +[[package]] +name = "tracing-attributes" +version = "0.1.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.61", +] + +[[package]] +name = "tracing-core" +version = "0.1.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54" +dependencies = [ + "once_cell", +] + +[[package]] +name = "typenum" +version = "1.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" + +[[package]] +name = "unicode-ident" +version = "1.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" + +[[package]] +name = "version_check" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" + +[[package]] +name = "wasi" +version = "0.11.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" + +[[package]] +name = "winnow" +version = "0.5.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f593a95398737aeed53e489c785df13f3618e41dbcd6718c6addbf1395aa6876" +dependencies = [ + "memchr", +] + +[[package]] +name = "wyz" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05f360fc0b24296329c78fda852a1e9ae82de9cf7b27dae4b7f62f118f77b9ed" +dependencies = [ + "tap", +] + +[[package]] +name = "zeroize" +version = "1.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "525b4ec142c6b68a2d10f01f7bbf6755599ca3f81ea53b8431b7dd348f5fdb2d" diff --git a/examples/poseidon_bn254/program/Cargo.toml b/examples/poseidon_bn254/program/Cargo.toml new file mode 100644 index 0000000000..a83ce53e4a --- /dev/null +++ b/examples/poseidon_bn254/program/Cargo.toml @@ -0,0 +1,11 @@ +[workspace] +[package] +version = "0.1.0" +name = "poseidon_bn254-program" +edition = "2021" + +[dependencies] +sp1-zkvm = { path = "../../../zkvm/entrypoint" } +hex = "0.4" +halo2curves = { git = "https://github.com/kunxian-xia/halo2curves.git", branch = "feat/sp1" } +poseidon_base = { git = "https://github.com/scroll-tech/poseidon-circuit.git", package = "poseidon-base", branch = "feat/sp1" } \ No newline at end of file diff --git a/examples/poseidon_bn254/program/elf/riscv32im-succinct-zkvm-elf b/examples/poseidon_bn254/program/elf/riscv32im-succinct-zkvm-elf new file mode 100755 index 0000000000000000000000000000000000000000..fbad0899ffb23805bec35e060db97a55c406501f GIT binary patch literal 192100 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ⅆNb3?hEYq|D)`mzSM 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 0 { + results[0] + } else { + Fr::zero() + }; + + let mut c_le_bytes = c.to_repr().to_vec(); + c_le_bytes.reverse(); + + assert_eq!( + hex::encode(&c_le_bytes), + "115cc0f5e7d690413df64c6b9662e9cf2a3617f2743245519e19607a4417189a" + ); +} diff --git a/examples/poseidon_bn254/script/Cargo.lock b/examples/poseidon_bn254/script/Cargo.lock new file mode 100644 index 0000000000..b0bffe064b --- /dev/null +++ b/examples/poseidon_bn254/script/Cargo.lock @@ -0,0 +1,4699 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "addr2line" +version = "0.21.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb" +dependencies = [ + "gimli", +] + +[[package]] +name = "adler" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" + +[[package]] +name = "ahash" +version = "0.8.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011" +dependencies = [ + "cfg-if", + "once_cell", + "version_check", + "zerocopy", +] + +[[package]] +name = "aho-corasick" +version = "1.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" +dependencies = [ + "memchr", +] + +[[package]] +name = "allocator-api2" +version = "0.2.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c6cb57a04249c6480766f7f7cef5467412af1490f8d1e243141daddada3264f" + +[[package]] +name = "alloy" +version = "0.1.0" +source = "git+https://github.com/alloy-rs/alloy?rev=bfd0fda#bfd0fda492e560c3463d521958793c81bbeadfc1" +dependencies = [ + "alloy-contract", + "alloy-core", + "alloy-eips", + "alloy-genesis", + "alloy-provider", + "alloy-rpc-client", + "alloy-serde", + "alloy-signer", + "alloy-signer-wallet", + "alloy-transport-http", + "reqwest 0.12.4", +] + +[[package]] +name = "alloy-consensus" +version = "0.1.0" +source = "git+https://github.com/alloy-rs/alloy?rev=bfd0fda#bfd0fda492e560c3463d521958793c81bbeadfc1" +dependencies = [ + "alloy-eips", + "alloy-primitives", + "alloy-rlp", + "alloy-serde", + "serde", + "sha2", +] + +[[package]] +name = "alloy-contract" +version = "0.1.0" +source = "git+https://github.com/alloy-rs/alloy?rev=bfd0fda#bfd0fda492e560c3463d521958793c81bbeadfc1" +dependencies = [ + "alloy-dyn-abi", + "alloy-json-abi", + "alloy-network", + "alloy-primitives", + "alloy-provider", + "alloy-rpc-types", + "alloy-sol-types", + "alloy-transport", + "futures", + "futures-util", + "thiserror", +] + +[[package]] +name = "alloy-core" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e30b83573b348305b9629a094b5331093a030514cd5713433799495cb283fea1" +dependencies = [ + "alloy-dyn-abi", + "alloy-json-abi", + "alloy-primitives", + "alloy-sol-types", +] + +[[package]] +name = "alloy-dyn-abi" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "545885d9b0b2c30fd344ae291439b4bfe59e48dd62fbc862f8503d98088967dc" +dependencies = [ + "alloy-json-abi", + "alloy-primitives", + "alloy-sol-type-parser", + "alloy-sol-types", + "const-hex", + "itoa", + "serde", + "serde_json", + "winnow 0.6.8", +] + +[[package]] +name = "alloy-eips" +version = "0.1.0" +source = "git+https://github.com/alloy-rs/alloy?rev=bfd0fda#bfd0fda492e560c3463d521958793c81bbeadfc1" +dependencies = [ + "alloy-primitives", + "alloy-rlp", + "alloy-serde", + "c-kzg", + "once_cell", + "serde", +] + +[[package]] +name = "alloy-genesis" +version = "0.1.0" +source = "git+https://github.com/alloy-rs/alloy?rev=bfd0fda#bfd0fda492e560c3463d521958793c81bbeadfc1" +dependencies = [ + "alloy-primitives", + "alloy-serde", + "serde", +] + +[[package]] +name = "alloy-json-abi" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "786689872ec4e7d354810ab0dffd48bb40b838c047522eb031cbd47d15634849" +dependencies = [ + "alloy-primitives", + "alloy-sol-type-parser", + "serde", + "serde_json", +] + +[[package]] +name = "alloy-json-rpc" +version = "0.1.0" +source = "git+https://github.com/alloy-rs/alloy?rev=bfd0fda#bfd0fda492e560c3463d521958793c81bbeadfc1" +dependencies = [ + "alloy-primitives", + "serde", + "serde_json", + "thiserror", +] + +[[package]] +name = "alloy-network" +version = "0.1.0" +source = "git+https://github.com/alloy-rs/alloy?rev=bfd0fda#bfd0fda492e560c3463d521958793c81bbeadfc1" +dependencies = [ + "alloy-consensus", + "alloy-eips", + "alloy-json-rpc", + "alloy-primitives", + "alloy-rpc-types", + "alloy-signer", + "async-trait", + "futures-utils-wasm", + "serde", + "thiserror", +] + +[[package]] +name = "alloy-primitives" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "525448f6afc1b70dd0f9d0a8145631bf2f5e434678ab23ab18409ca264cae6b3" +dependencies = [ + "alloy-rlp", + "bytes", + "cfg-if", + "const-hex", + "derive_more", + "hex-literal", + "itoa", + "k256", + "keccak-asm", + "proptest", + "rand", + "ruint", + "serde", + "tiny-keccak", +] + +[[package]] +name = "alloy-provider" +version = "0.1.0" +source = "git+https://github.com/alloy-rs/alloy?rev=bfd0fda#bfd0fda492e560c3463d521958793c81bbeadfc1" +dependencies = [ + "alloy-json-rpc", + "alloy-network", + "alloy-primitives", + "alloy-rpc-client", + "alloy-rpc-types", + "alloy-rpc-types-trace", + "alloy-transport", + "alloy-transport-http", + "async-stream", + "async-trait", + "auto_impl", + "dashmap", + "futures", + "lru", + "reqwest 0.12.4", + "serde_json", + "tokio", + "tracing", + "url", +] + +[[package]] +name = "alloy-rlp" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8d58d9f5da7b40e9bfff0b7e7816700be4019db97d4b6359fe7f94a9e22e42ac" +dependencies = [ + "alloy-rlp-derive", + "arrayvec", + "bytes", +] + +[[package]] +name = "alloy-rlp-derive" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a047897373be4bbb0224c1afdabca92648dc57a9c9ef6e7b0be3aff7a859c83" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.61", +] + +[[package]] +name = "alloy-rpc-client" +version = "0.1.0" +source = "git+https://github.com/alloy-rs/alloy?rev=bfd0fda#bfd0fda492e560c3463d521958793c81bbeadfc1" +dependencies = [ + "alloy-json-rpc", + "alloy-transport", + "alloy-transport-http", + "futures", + "pin-project", + "reqwest 0.12.4", + "serde", + "serde_json", + "tokio", + "tokio-stream", + "tower", + "tracing", + "url", +] + +[[package]] +name = "alloy-rpc-types" +version = "0.1.0" +source = "git+https://github.com/alloy-rs/alloy?rev=bfd0fda#bfd0fda492e560c3463d521958793c81bbeadfc1" +dependencies = [ + "alloy-consensus", + "alloy-eips", + "alloy-genesis", + "alloy-primitives", + "alloy-rlp", + "alloy-serde", + "alloy-sol-types", + "itertools 0.12.1", + "serde", + "serde_json", + "thiserror", +] + +[[package]] +name = "alloy-rpc-types-trace" +version = "0.1.0" +source = "git+https://github.com/alloy-rs/alloy?rev=bfd0fda#bfd0fda492e560c3463d521958793c81bbeadfc1" +dependencies = [ + "alloy-primitives", + "alloy-rpc-types", + "alloy-serde", + "serde", + "serde_json", +] + +[[package]] +name = "alloy-serde" +version = "0.1.0" +source = "git+https://github.com/alloy-rs/alloy?rev=bfd0fda#bfd0fda492e560c3463d521958793c81bbeadfc1" +dependencies = [ + "alloy-primitives", + "serde", + "serde_json", +] + +[[package]] +name = "alloy-signer" +version = "0.1.0" +source = "git+https://github.com/alloy-rs/alloy?rev=bfd0fda#bfd0fda492e560c3463d521958793c81bbeadfc1" +dependencies = [ + "alloy-primitives", + "async-trait", + "auto_impl", + "elliptic-curve", + "k256", + "thiserror", +] + +[[package]] +name = "alloy-signer-wallet" +version = "0.1.0" +source = "git+https://github.com/alloy-rs/alloy?rev=bfd0fda#bfd0fda492e560c3463d521958793c81bbeadfc1" +dependencies = [ + "alloy-consensus", + "alloy-network", + "alloy-primitives", + "alloy-signer", + "async-trait", + "k256", + "rand", + "thiserror", +] + +[[package]] +name = "alloy-sol-macro" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "89c80a2cb97e7aa48611cbb63950336f9824a174cdf670527cc6465078a26ea1" +dependencies = [ + "alloy-json-abi", + "alloy-sol-macro-input", + "const-hex", + "heck 0.4.1", + "indexmap 2.2.6", + "proc-macro-error", + "proc-macro2", + "quote", + "syn 2.0.61", + "syn-solidity", + "tiny-keccak", +] + +[[package]] +name = "alloy-sol-macro-input" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c58894b58ac50979eeac6249661991ac40b9d541830d9a725f7714cc9ef08c23" +dependencies = [ + "alloy-json-abi", + "const-hex", + "dunce", + "heck 0.5.0", + "proc-macro2", + "quote", + "serde_json", + "syn 2.0.61", + "syn-solidity", +] + +[[package]] +name = "alloy-sol-type-parser" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7da8e71ea68e780cc203919e03f69f59e7afe92d2696fb1dcb6662f61e4031b6" +dependencies = [ + "winnow 0.6.8", +] + +[[package]] +name = "alloy-sol-types" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "399287f68d1081ed8b1f4903c49687658b95b142207d7cb4ae2f4813915343ef" +dependencies = [ + "alloy-json-abi", + "alloy-primitives", + "alloy-sol-macro", + "const-hex", + "serde", +] + +[[package]] +name = "alloy-transport" +version = "0.1.0" +source = "git+https://github.com/alloy-rs/alloy?rev=bfd0fda#bfd0fda492e560c3463d521958793c81bbeadfc1" +dependencies = [ + "alloy-json-rpc", + "base64 0.22.1", + "futures-util", + "futures-utils-wasm", + "serde", + "serde_json", + "thiserror", + "tokio", + "tower", + "url", + "wasm-bindgen-futures", +] + +[[package]] +name = "alloy-transport-http" +version = "0.1.0" +source = "git+https://github.com/alloy-rs/alloy?rev=bfd0fda#bfd0fda492e560c3463d521958793c81bbeadfc1" +dependencies = [ + "alloy-json-rpc", + "alloy-transport", + "reqwest 0.12.4", + "serde_json", + "tower", + "url", +] + +[[package]] +name = "android-tzdata" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e999941b234f3131b00bc13c22d06e8c5ff726d1b6318ac7eb276997bbb4fef0" + +[[package]] +name = "android_system_properties" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311" +dependencies = [ + "libc", +] + +[[package]] +name = "ansi_term" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d52a9bb7ec0cf484c551830a7ce27bd20d67eac647e1befb56b0be4ee39a55d2" +dependencies = [ + "winapi", +] + +[[package]] +name = "anyhow" +version = "1.0.83" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "25bdb32cbbdce2b519a9cd7df3a678443100e265d5e25ca763b7572a5104f5f3" + +[[package]] +name = "ark-ff" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6b3235cc41ee7a12aaaf2c575a2ad7b46713a8a50bda2fc3b003a04845c05dd6" +dependencies = [ + "ark-ff-asm 0.3.0", + "ark-ff-macros 0.3.0", + "ark-serialize 0.3.0", + "ark-std 0.3.0", + "derivative", + "num-bigint", + "num-traits", + "paste", + "rustc_version 0.3.3", + "zeroize", +] + +[[package]] +name = "ark-ff" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec847af850f44ad29048935519032c33da8aa03340876d351dfab5660d2966ba" +dependencies = [ + "ark-ff-asm 0.4.2", + "ark-ff-macros 0.4.2", + "ark-serialize 0.4.2", + "ark-std 0.4.0", + "derivative", + "digest 0.10.7", + "itertools 0.10.5", + "num-bigint", + "num-traits", + "paste", + "rustc_version 0.4.0", + "zeroize", +] + +[[package]] +name = "ark-ff-asm" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db02d390bf6643fb404d3d22d31aee1c4bc4459600aef9113833d17e786c6e44" +dependencies = [ + "quote", + "syn 1.0.109", +] + +[[package]] +name = "ark-ff-asm" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3ed4aa4fe255d0bc6d79373f7e31d2ea147bcf486cba1be5ba7ea85abdb92348" +dependencies = [ + "quote", + "syn 1.0.109", +] + +[[package]] +name = "ark-ff-macros" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db2fd794a08ccb318058009eefdf15bcaaaaf6f8161eb3345f907222bac38b20" +dependencies = [ + "num-bigint", + "num-traits", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "ark-ff-macros" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7abe79b0e4288889c4574159ab790824d0033b9fdcb2a112a3182fac2e514565" +dependencies = [ + "num-bigint", + "num-traits", + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "ark-serialize" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d6c2b318ee6e10f8c2853e73a83adc0ccb88995aa978d8a3408d492ab2ee671" +dependencies = [ + "ark-std 0.3.0", + "digest 0.9.0", +] + +[[package]] +name = "ark-serialize" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "adb7b85a02b83d2f22f89bd5cac66c9c89474240cb6207cb1efc16d098e822a5" +dependencies = [ + "ark-std 0.4.0", + "digest 0.10.7", + "num-bigint", +] + +[[package]] +name = "ark-std" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1df2c09229cbc5a028b1d70e00fdb2acee28b1055dfb5ca73eea49c5a25c4e7c" +dependencies = [ + "num-traits", + "rand", +] + +[[package]] +name = "ark-std" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94893f1e0c6eeab764ade8dc4c0db24caf4fe7cbbaafc0eba0a9030f447b5185" +dependencies = [ + "num-traits", + "rand", +] + +[[package]] +name = "arrayref" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6b4930d2cb77ce62f89ee5d5289b4ac049559b1c45539271f5ed4fdc7db34545" + +[[package]] +name = "arrayvec" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96d30a06541fbafbc7f82ed10c06164cfbd2c401138f6addd8404629c4b16711" + +[[package]] +name = "async-stream" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd56dd203fef61ac097dd65721a419ddccb106b2d2b70ba60a6b529f03961a51" +dependencies = [ + "async-stream-impl", + "futures-core", + "pin-project-lite", +] + +[[package]] +name = "async-stream-impl" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "16e62a023e7c117e27523144c5d2459f4397fcc3cab0085af8e2224f643a0193" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.61", +] + +[[package]] +name = "async-trait" +version = "0.1.80" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c6fa2087f2753a7da8cc1c0dbfcf89579dd57458e36769de5ac750b4671737ca" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.61", +] + +[[package]] +name = "auto_impl" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c87f3f15e7794432337fc718554eaa4dc8f04c9677a950ffe366f20a162ae42" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.61", +] + +[[package]] +name = "autocfg" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0" + +[[package]] +name = "axum" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1236b4b292f6c4d6dc34604bb5120d85c3fe1d1aa596bd5cc52ca054d13e7b9e" +dependencies = [ + "async-trait", + "axum-core", + "bytes", + "futures-util", + "http 1.1.0", + "http-body 1.0.0", + "http-body-util", + "hyper 1.3.1", + "hyper-util", + "itoa", + "matchit", + "memchr", + "mime", + "percent-encoding", + "pin-project-lite", + "rustversion", + "serde", + "serde_json", + "serde_path_to_error", + "serde_urlencoded", + "sync_wrapper", + "tokio", + "tower", + "tower-layer", + "tower-service", + "tracing", +] + +[[package]] +name = "axum-core" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a15c63fd72d41492dc4f497196f5da1fb04fb7529e631d73630d1b491e47a2e3" +dependencies = [ + "async-trait", + "bytes", + "futures-util", + "http 1.1.0", + "http-body 1.0.0", + "http-body-util", + "mime", + "pin-project-lite", + "rustversion", + "sync_wrapper", + "tower-layer", + "tower-service", + "tracing", +] + +[[package]] +name = "backtrace" +version = "0.3.71" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26b05800d2e817c8b3b4b54abd461726265fa9789ae34330622f2db9ee696f9d" +dependencies = [ + "addr2line", + "cc", + "cfg-if", + "libc", + "miniz_oxide", + "object", + "rustc-demangle", +] + +[[package]] +name = "base16ct" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c7f02d4ea65f2c1853089ffd8d2787bdbc63de2f0d29dedbcf8ccdfa0ccd4cf" + +[[package]] +name = "base64" +version = "0.21.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567" + +[[package]] +name = "base64" +version = "0.22.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" + +[[package]] +name = "base64ct" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8c3c1a368f70d6cf7302d78f8f7093da241fb8e8807c05cc9e51a125895a6d5b" + +[[package]] +name = "bincode" +version = "1.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1f45e9417d87227c7a56d22e471c6206462cba514c7590c09aff4cf6d1ddcad" +dependencies = [ + "serde", +] + +[[package]] +name = "bit-set" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0700ddab506f33b20a03b13996eccd309a48e5ff77d0d95926aa0210fb4e95f1" +dependencies = [ + "bit-vec", +] + +[[package]] +name = "bit-vec" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "349f9b6a179ed607305526ca489b34ad0a41aed5f7980fa90eb03160b69598fb" + +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + +[[package]] +name = "bitflags" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf4b9d6a944f767f8e5e0db018570623c85f3d925ac718db4e06d0187adb21c1" + +[[package]] +name = "bitvec" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bc2832c24239b0141d5674bb9174f9d68a8b5b3f2753311927c172ca46f7e9c" +dependencies = [ + "funty", + "radium", + "tap", + "wyz", +] + +[[package]] +name = "blake3" +version = "1.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "30cca6d3674597c30ddf2c587bf8d9d65c9a84d2326d941cc79c9842dfe0ef52" +dependencies = [ + "arrayref", + "arrayvec", + "cc", + "cfg-if", + "constant_time_eq", + "rayon", +] + +[[package]] +name = "blake3-zkvm" +version = "0.1.0" +source = "git+https://github.com/sp1-patches/BLAKE3.git?branch=patch-blake3_zkvm/v.1.0.0#bac2d59f9122b07a4d91475560b4c3214ae62444" + +[[package]] +name = "block-buffer" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" +dependencies = [ + "generic-array 0.14.7", +] + +[[package]] +name = "blst" +version = "0.3.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c94087b935a822949d3291a9989ad2b2051ea141eda0fd4e478a75f6aa3e604b" +dependencies = [ + "cc", + "glob", + "threadpool", + "zeroize", +] + +[[package]] +name = "bumpalo" +version = "3.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c" + +[[package]] +name = "byte-slice-cast" +version = "1.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3ac9f8b63eca6fd385229b3675f6cc0dc5c8a5c8a54a59d4f52ffd670d87b0c" + +[[package]] +name = "byteorder" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" + +[[package]] +name = "bytes" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "514de17de45fdb8dc022b1a7975556c53c86f9f0aa5f534b98977b171857c2c9" +dependencies = [ + "serde", +] + +[[package]] +name = "c-kzg" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3130f3d8717cc02e668a896af24984d5d5d4e8bf12e278e982e0f1bd88a0f9af" +dependencies = [ + "blst", + "cc", + "glob", + "hex", + "libc", + "serde", +] + +[[package]] +name = "camino" +version = "1.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c59e92b5a388f549b863a7bea62612c09f24c8393560709a54558a9abdfb3b9c" +dependencies = [ + "serde", +] + +[[package]] +name = "cargo-platform" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24b1f0365a6c6bb4020cd05806fd0d33c44d38046b8bd7f0e40814b9763cabfc" +dependencies = [ + "serde", +] + +[[package]] +name = "cargo_metadata" +version = "0.18.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2d886547e41f740c616ae73108f6eb70afe6d940c7bc697cb30f13daec073037" +dependencies = [ + "camino", + "cargo-platform", + "semver 1.0.23", + "serde", + "serde_json", + "thiserror", +] + +[[package]] +name = "cc" +version = "1.0.97" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "099a5357d84c4c61eb35fc8eafa9a79a902c2f76911e5747ced4e032edd8d9b4" + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "chrono" +version = "0.4.38" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a21f936df1771bf62b77f047b726c4625ff2e8aa607c01ec06e5a05bd8463401" +dependencies = [ + "android-tzdata", + "iana-time-zone", + "num-traits", + "serde", + "windows-targets 0.52.5", +] + +[[package]] +name = "console" +version = "0.15.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0e1f83fc076bd6dd27517eacdf25fef6c4dfe5f1d7448bafaaf3a26f13b5e4eb" +dependencies = [ + "encode_unicode", + "lazy_static", + "libc", + "unicode-width", + "windows-sys 0.52.0", +] + +[[package]] +name = "const-hex" +version = "1.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ba00838774b4ab0233e355d26710fbfc8327a05c017f6dc4873f876d1f79f78" +dependencies = [ + "cfg-if", + "cpufeatures", + "hex", + "proptest", + "serde", +] + +[[package]] +name = "const-oid" +version = "0.9.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8" + +[[package]] +name = "constant_time_eq" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f7144d30dcf0fafbce74250a3963025d8d52177934239851c917d29f1df280c2" + +[[package]] +name = "convert_case" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6245d59a3e82a7fc217c5828a6692dbc6dfb63a0c8c90495621f7b9d79704a0e" + +[[package]] +name = "core-foundation" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91e195e091a93c46f7102ec7818a2aa394e1e1771c3ab4825963fa03e45afb8f" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "core-foundation-sys" +version = "0.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06ea2b9bc92be3c2baa9334a323ebca2d6f074ff852cd1d7b11064035cd3868f" + +[[package]] +name = "cpufeatures" +version = "0.2.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53fe5e26ff1b7aef8bca9c6080520cfb8d9333c7568e1829cef191a9723e5504" +dependencies = [ + "libc", +] + +[[package]] +name = "crossbeam-deque" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "613f8cc01fe9cf1a3eb3d7f488fd2fa8388403e97039e2f73692932e291a770d" +dependencies = [ + "crossbeam-epoch", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-epoch" +version = "0.9.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e" +dependencies = [ + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-utils" +version = "0.8.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "248e3bacc7dc6baa3b21e405ee045c3047101a49145e7e9eca583ab4c2ca5345" + +[[package]] +name = "crunchy" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" + +[[package]] +name = "crypto-bigint" +version = "0.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0dc92fb57ca44df6db8059111ab3af99a63d5d0f8375d9972e319a379c6bab76" +dependencies = [ + "generic-array 0.14.7", + "rand_core", + "subtle", + "zeroize", +] + +[[package]] +name = "crypto-common" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" +dependencies = [ + "generic-array 0.14.7", + "typenum", +] + +[[package]] +name = "curve25519-dalek" +version = "4.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0a677b8922c94e01bdbb12126b0bc852f00447528dee1782229af9c720c3f348" +dependencies = [ + "cfg-if", + "cpufeatures", + "curve25519-dalek-derive", + "fiat-crypto", + "platforms", + "rustc_version 0.4.0", + "subtle", + "zeroize", +] + +[[package]] +name = "curve25519-dalek-derive" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f46882e17999c6cc590af592290432be3bce0428cb0d5f8b6715e4dc7b383eb3" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.61", +] + +[[package]] +name = "darling" +version = "0.20.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "54e36fcd13ed84ffdfda6f5be89b31287cbb80c439841fe69e04841435464391" +dependencies = [ + "darling_core", + "darling_macro", +] + +[[package]] +name = "darling_core" +version = "0.20.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c2cf1c23a687a1feeb728783b993c4e1ad83d99f351801977dd809b48d0a70f" +dependencies = [ + "fnv", + "ident_case", + "proc-macro2", + "quote", + "strsim", + "syn 2.0.61", +] + +[[package]] +name = "darling_macro" +version = "0.20.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a668eda54683121533a393014d8692171709ff57a7d61f187b6e782719f8933f" +dependencies = [ + "darling_core", + "quote", + "syn 2.0.61", +] + +[[package]] +name = "dashmap" +version = "5.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "978747c1d849a7d2ee5e8adc0159961c48fb7e5db2f06af6723b80123bb53856" +dependencies = [ + "cfg-if", + "hashbrown 0.14.5", + "lock_api", + "once_cell", + "parking_lot_core", +] + +[[package]] +name = "data-encoding" +version = "2.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e8566979429cf69b49a5c740c60791108e86440e8be149bbea4fe54d2c32d6e2" + +[[package]] +name = "der" +version = "0.7.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f55bf8e7b65898637379c1b74eb1551107c8294ed26d855ceb9fd1a09cfc9bc0" +dependencies = [ + "const-oid", + "zeroize", +] + +[[package]] +name = "deranged" +version = "0.3.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b42b6fa04a440b495c8b04d0e71b707c585f83cb9cb28cf8cd0d976c315e31b4" +dependencies = [ + "powerfmt", + "serde", +] + +[[package]] +name = "derivative" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fcc3dd5e9e9c0b295d6e1e4d811fb6f157d5ffd784b8d202fc62eac8035a770b" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "derive_more" +version = "0.99.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fb810d30a7c1953f91334de7244731fc3f3c10d7fe163338a35b9f640960321" +dependencies = [ + "convert_case", + "proc-macro2", + "quote", + "rustc_version 0.4.0", + "syn 1.0.109", +] + +[[package]] +name = "digest" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3dd60d1080a57a05ab032377049e0591415d2b31afd7028356dbf3cc6dcb066" +dependencies = [ + "generic-array 0.14.7", +] + +[[package]] +name = "digest" +version = "0.10.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" +dependencies = [ + "block-buffer", + "const-oid", + "crypto-common", + "subtle", +] + +[[package]] +name = "dotenv" +version = "0.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77c90badedccf4105eca100756a0b1289e191f6fcbdadd3cee1d2f614f97da8f" + +[[package]] +name = "downcast-rs" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75b325c5dbd37f80359721ad39aca5a29fb04c89279657cffdda8736d0c0b9d2" + +[[package]] +name = "dunce" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56ce8c6da7551ec6c462cbaf3bfbc75131ebbfa1c944aeaa9dab51ca1c5f0c3b" + +[[package]] +name = "ecdsa" +version = "0.16.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee27f32b5c5292967d2d4a9d7f1e0b0aed2c15daded5a60300e4abb9d8020bca" +dependencies = [ + "der", + "digest 0.10.7", + "elliptic-curve", + "rfc6979", + "signature", + "spki", +] + +[[package]] +name = "either" +version = "1.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a47c1c47d2f5964e29c61246e81db715514cd532db6b5116a25ea3c03d6780a2" + +[[package]] +name = "elf" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4445909572dbd556c457c849c4ca58623d84b27c8fff1e74b0b4227d8b90d17b" + +[[package]] +name = "elliptic-curve" +version = "0.13.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5e6043086bf7973472e0c7dff2142ea0b680d30e18d9cc40f267efbf222bd47" +dependencies = [ + "base16ct", + "crypto-bigint", + "digest 0.10.7", + "ff", + "generic-array 0.14.7", + "group", + "pkcs8", + "rand_core", + "sec1", + "subtle", + "zeroize", +] + +[[package]] +name = "encode_unicode" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a357d28ed41a50f9c765dbfe56cbc04a64e53e5fc58ba79fbc34c10ef3df831f" + +[[package]] +name = "encoding_rs" +version = "0.8.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b45de904aa0b010bce2ab45264d0631681847fa7b6f2eaa7dab7619943bc4f59" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "enum-as-inner" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ffccbb6966c05b32ef8fbac435df276c4ae4d3dc55a8cd0eb9745e6c12f546a" +dependencies = [ + "heck 0.4.1", + "proc-macro2", + "quote", + "syn 2.0.61", +] + +[[package]] +name = "equivalent" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" + +[[package]] +name = "errno" +version = "0.3.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a258e46cdc063eb8519c00b9fc845fc47bcfca4130e2f08e88665ceda8474245" +dependencies = [ + "libc", + "windows-sys 0.52.0", +] + +[[package]] +name = "fastrand" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9fc0510504f03c51ada170672ac806f1f105a88aa97a5281117e1ddc3368e51a" + +[[package]] +name = "fastrlp" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "139834ddba373bbdd213dffe02c8d110508dcf1726c2be27e8d1f7d7e1856418" +dependencies = [ + "arrayvec", + "auto_impl", + "bytes", +] + +[[package]] +name = "ff" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ded41244b729663b1e574f1b4fb731469f69f79c17667b5d776b16cda0479449" +dependencies = [ + "rand_core", + "subtle", +] + +[[package]] +name = "fiat-crypto" +version = "0.2.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38793c55593b33412e3ae40c2c9781ffaa6f438f6f8c10f24e71846fbd7ae01e" + +[[package]] +name = "fixed-hash" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "835c052cb0c08c1acf6ffd71c022172e18723949c8282f2b9f27efbc51e64534" +dependencies = [ + "byteorder", + "rand", + "rustc-hex", + "static_assertions", +] + +[[package]] +name = "fnv" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" + +[[package]] +name = "foreign-types" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" +dependencies = [ + "foreign-types-shared", +] + +[[package]] +name = "foreign-types-shared" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" + +[[package]] +name = "form_urlencoded" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456" +dependencies = [ + "percent-encoding", +] + +[[package]] +name = "funty" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c" + +[[package]] +name = "futures" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "645c6916888f6cb6350d2550b80fb63e734897a8498abe35cfb732b6487804b0" +dependencies = [ + "futures-channel", + "futures-core", + "futures-executor", + "futures-io", + "futures-sink", + "futures-task", + "futures-util", +] + +[[package]] +name = "futures-channel" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eac8f7d7865dcb88bd4373ab671c8cf4508703796caa2b1985a9ca867b3fcb78" +dependencies = [ + "futures-core", + "futures-sink", +] + +[[package]] +name = "futures-core" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dfc6580bb841c5a68e9ef15c77ccc837b40a7504914d52e47b8b0e9bbda25a1d" + +[[package]] +name = "futures-executor" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a576fc72ae164fca6b9db127eaa9a9dda0d61316034f33a0a0d4eda41f02b01d" +dependencies = [ + "futures-core", + "futures-task", + "futures-util", +] + +[[package]] +name = "futures-io" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a44623e20b9681a318efdd71c299b6b222ed6f231972bfe2f224ebad6311f0c1" + +[[package]] +name = "futures-macro" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.61", +] + +[[package]] +name = "futures-sink" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9fb8e00e87438d937621c1c6269e53f536c14d3fbd6a042bb24879e57d474fb5" + +[[package]] +name = "futures-task" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38d84fa142264698cdce1a9f9172cf383a0c82de1bddcf3092901442c4097004" + +[[package]] +name = "futures-util" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d6401deb83407ab3da39eba7e33987a73c3df0c82b4bb5813ee871c19c41d48" +dependencies = [ + "futures-channel", + "futures-core", + "futures-io", + "futures-macro", + "futures-sink", + "futures-task", + "memchr", + "pin-project-lite", + "pin-utils", + "slab", +] + +[[package]] +name = "futures-utils-wasm" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42012b0f064e01aa58b545fe3727f90f7dd4020f4a3ea735b50344965f5a57e9" + +[[package]] +name = "gcd" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d758ba1b47b00caf47f24925c0074ecb20d6dfcffe7f6d53395c0465674841a" + +[[package]] +name = "generic-array" +version = "0.14.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" +dependencies = [ + "typenum", + "version_check", + "zeroize", +] + +[[package]] +name = "generic-array" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fe739944a5406424e080edccb6add95685130b9f160d5407c639c7df0c5836b0" +dependencies = [ + "serde", + "typenum", +] + +[[package]] +name = "getrandom" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" +dependencies = [ + "cfg-if", + "libc", + "wasi", +] + +[[package]] +name = "gimli" +version = "0.28.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" + +[[package]] +name = "glob" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b" + +[[package]] +name = "group" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0f9ef7462f7c099f518d754361858f86d8a07af53ba9af0fe635bbccb151a63" +dependencies = [ + "ff", + "rand_core", + "subtle", +] + +[[package]] +name = "h2" +version = "0.3.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "81fe527a889e1532da5c525686d96d4c2e74cdd345badf8dfef9f6b39dd5f5e8" +dependencies = [ + "bytes", + "fnv", + "futures-core", + "futures-sink", + "futures-util", + "http 0.2.12", + "indexmap 2.2.6", + "slab", + "tokio", + "tokio-util", + "tracing", +] + +[[package]] +name = "h2" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "816ec7294445779408f36fe57bc5b7fc1cf59664059096c65f905c1c61f58069" +dependencies = [ + "bytes", + "fnv", + "futures-core", + "futures-sink", + "futures-util", + "http 1.1.0", + "indexmap 2.2.6", + "slab", + "tokio", + "tokio-util", + "tracing", +] + +[[package]] +name = "hashbrown" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" + +[[package]] +name = "hashbrown" +version = "0.14.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" +dependencies = [ + "ahash", + "allocator-api2", +] + +[[package]] +name = "heck" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" + +[[package]] +name = "heck" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" + +[[package]] +name = "hermit-abi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" + +[[package]] +name = "hex" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" +dependencies = [ + "serde", +] + +[[package]] +name = "hex-literal" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6fe2267d4ed49bc07b63801559be28c718ea06c4738b7a03c94df7386d2cde46" + +[[package]] +name = "hickory-proto" +version = "0.24.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07698b8420e2f0d6447a436ba999ec85d8fbf2a398bbd737b82cac4a2e96e512" +dependencies = [ + "async-trait", + "cfg-if", + "data-encoding", + "enum-as-inner", + "futures-channel", + "futures-io", + "futures-util", + "idna 0.4.0", + "ipnet", + "once_cell", + "rand", + "thiserror", + "tinyvec", + "tokio", + "tracing", + "url", +] + +[[package]] +name = "hickory-resolver" +version = "0.24.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "28757f23aa75c98f254cf0405e6d8c25b831b32921b050a66692427679b1f243" +dependencies = [ + "cfg-if", + "futures-util", + "hickory-proto", + "ipconfig", + "lru-cache", + "once_cell", + "parking_lot", + "rand", + "resolv-conf", + "smallvec", + "thiserror", + "tokio", + "tracing", +] + +[[package]] +name = "hmac" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e" +dependencies = [ + "digest 0.10.7", +] + +[[package]] +name = "hostname" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c731c3e10504cc8ed35cfe2f1db4c9274c3d35fa486e3b31df46f068ef3e867" +dependencies = [ + "libc", + "match_cfg", + "winapi", +] + +[[package]] +name = "http" +version = "0.2.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "601cbb57e577e2f5ef5be8e7b83f0f63994f25aa94d673e54a92d5c516d101f1" +dependencies = [ + "bytes", + "fnv", + "itoa", +] + +[[package]] +name = "http" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "21b9ddb458710bc376481b842f5da65cdf31522de232c1ca8146abce2a358258" +dependencies = [ + "bytes", + "fnv", + "itoa", +] + +[[package]] +name = "http-body" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ceab25649e9960c0311ea418d17bee82c0dcec1bd053b5f9a66e265a693bed2" +dependencies = [ + "bytes", + "http 0.2.12", + "pin-project-lite", +] + +[[package]] +name = "http-body" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1cac85db508abc24a2e48553ba12a996e87244a0395ce011e62b37158745d643" +dependencies = [ + "bytes", + "http 1.1.0", +] + +[[package]] +name = "http-body-util" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0475f8b2ac86659c21b64320d5d653f9efe42acd2a4e560073ec61a155a34f1d" +dependencies = [ + "bytes", + "futures-core", + "http 1.1.0", + "http-body 1.0.0", + "pin-project-lite", +] + +[[package]] +name = "httparse" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d897f394bad6a705d5f4104762e116a75639e470d80901eed05a860a95cb1904" + +[[package]] +name = "httpdate" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" + +[[package]] +name = "hyper" +version = "0.14.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf96e135eb83a2a8ddf766e426a841d8ddd7449d5f00d34ea02b41d2f19eef80" +dependencies = [ + "bytes", + "futures-channel", + "futures-core", + "futures-util", + "h2 0.3.26", + "http 0.2.12", + "http-body 0.4.6", + "httparse", + "httpdate", + "itoa", + "pin-project-lite", + "socket2", + "tokio", + "tower-service", + "tracing", + "want", +] + +[[package]] +name = "hyper" +version = "1.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fe575dd17d0862a9a33781c8c4696a55c320909004a67a00fb286ba8b1bc496d" +dependencies = [ + "bytes", + "futures-channel", + "futures-util", + "h2 0.4.4", + "http 1.1.0", + "http-body 1.0.0", + "httparse", + "httpdate", + "itoa", + "pin-project-lite", + "smallvec", + "tokio", + "want", +] + +[[package]] +name = "hyper-rustls" +version = "0.24.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec3efd23720e2049821a693cbc7e65ea87c72f1c58ff2f9522ff332b1491e590" +dependencies = [ + "futures-util", + "http 0.2.12", + "hyper 0.14.28", + "rustls", + "tokio", + "tokio-rustls", +] + +[[package]] +name = "hyper-tls" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d6183ddfa99b85da61a140bea0efc93fdf56ceaa041b37d553518030827f9905" +dependencies = [ + "bytes", + "hyper 0.14.28", + "native-tls", + "tokio", + "tokio-native-tls", +] + +[[package]] +name = "hyper-tls" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70206fc6890eaca9fde8a0bf71caa2ddfc9fe045ac9e5c70df101a7dbde866e0" +dependencies = [ + "bytes", + "http-body-util", + "hyper 1.3.1", + "hyper-util", + "native-tls", + "tokio", + "tokio-native-tls", + "tower-service", +] + +[[package]] +name = "hyper-util" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca38ef113da30126bbff9cd1705f9273e15d45498615d138b0c20279ac7a76aa" +dependencies = [ + "bytes", + "futures-channel", + "futures-util", + "http 1.1.0", + "http-body 1.0.0", + "hyper 1.3.1", + "pin-project-lite", + "socket2", + "tokio", + "tower", + "tower-service", + "tracing", +] + +[[package]] +name = "iana-time-zone" +version = "0.1.60" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7ffbb5a1b541ea2561f8c41c087286cc091e21e556a4f09a8f6cbf17b69b141" +dependencies = [ + "android_system_properties", + "core-foundation-sys", + "iana-time-zone-haiku", + "js-sys", + "wasm-bindgen", + "windows-core", +] + +[[package]] +name = "iana-time-zone-haiku" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f" +dependencies = [ + "cc", +] + +[[package]] +name = "ident_case" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" + +[[package]] +name = "idna" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d20d6b07bfbc108882d88ed8e37d39636dcc260e15e30c45e6ba089610b917c" +dependencies = [ + "unicode-bidi", + "unicode-normalization", +] + +[[package]] +name = "idna" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "634d9b1461af396cad843f47fdba5597a4f9e6ddd4bfb6ff5d85028c25cb12f6" +dependencies = [ + "unicode-bidi", + "unicode-normalization", +] + +[[package]] +name = "impl-codec" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba6a270039626615617f3f36d15fc827041df3b78c439da2cadfa47455a77f2f" +dependencies = [ + "parity-scale-codec", +] + +[[package]] +name = "impl-trait-for-tuples" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "11d7a9f6330b71fea57921c9b61c47ee6e84f72d394754eff6163ae67e7395eb" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "indexmap" +version = "1.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" +dependencies = [ + "autocfg", + "hashbrown 0.12.3", + "serde", +] + +[[package]] +name = "indexmap" +version = "2.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "168fb715dda47215e360912c096649d23d58bf392ac62f73919e831745e40f26" +dependencies = [ + "equivalent", + "hashbrown 0.14.5", + "serde", +] + +[[package]] +name = "indicatif" +version = "0.17.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "763a5a8f45087d6bcea4222e7b72c291a054edf80e4ef6efd2a4979878c7bea3" +dependencies = [ + "console", + "instant", + "number_prefix", + "portable-atomic", + "unicode-width", +] + +[[package]] +name = "instant" +version = "0.1.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "ipconfig" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b58db92f96b720de98181bbbe63c831e87005ab460c1bf306eb2622b4707997f" +dependencies = [ + "socket2", + "widestring", + "windows-sys 0.48.0", + "winreg 0.50.0", +] + +[[package]] +name = "ipnet" +version = "2.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f518f335dce6725a761382244631d86cf0ccb2863413590b31338feb467f9c3" + +[[package]] +name = "itertools" +version = "0.10.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473" +dependencies = [ + "either", +] + +[[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" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba291022dbbd398a455acf126c1e341954079855bc60dfdda641363bd6922569" +dependencies = [ + "either", +] + +[[package]] +name = "itoa" +version = "1.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" + +[[package]] +name = "js-sys" +version = "0.3.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29c15563dc2726973df627357ce0c9ddddbea194836909d655df6a75d2cf296d" +dependencies = [ + "wasm-bindgen", +] + +[[package]] +name = "k256" +version = "0.13.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "956ff9b67e26e1a6a866cb758f12c6f8746208489e3e4a4b5580802f2f0a587b" +dependencies = [ + "cfg-if", + "ecdsa", + "elliptic-curve", + "once_cell", + "sha2", + "signature", +] + +[[package]] +name = "keccak-asm" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb8515fff80ed850aea4a1595f2e519c003e2a00a82fe168ebf5269196caf444" +dependencies = [ + "digest 0.10.7", + "sha3-asm", +] + +[[package]] +name = "lazy_static" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" + +[[package]] +name = "libc" +version = "0.2.154" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae743338b92ff9146ce83992f766a31066a91a8c84a45e0e9f21e7cf6de6d346" + +[[package]] +name = "libm" +version = "0.2.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ec2a862134d2a7d32d7983ddcdd1c4923530833c9f2ea1a44fc5fa473989058" + +[[package]] +name = "linked-hash-map" +version = "0.5.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0717cef1bc8b636c6e1c1bbdefc09e6322da8a9321966e8928ef80d20f7f770f" + +[[package]] +name = "linux-raw-sys" +version = "0.4.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "01cda141df6706de531b6c46c3a33ecca755538219bd484262fa09410c13539c" + +[[package]] +name = "lock_api" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17" +dependencies = [ + "autocfg", + "scopeguard", +] + +[[package]] +name = "log" +version = "0.4.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90ed8c1e510134f979dbc4f070f87d4313098b704861a105fe34231c70a3901c" + +[[package]] +name = "lru" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3262e75e648fce39813cb56ac41f3c3e3f65217ebf3844d818d1f9398cfb0dc" +dependencies = [ + "hashbrown 0.14.5", +] + +[[package]] +name = "lru-cache" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "31e24f1ad8321ca0e8a1e0ac13f23cb668e6f5466c2c57319f6a5cf1cc8e3b1c" +dependencies = [ + "linked-hash-map", +] + +[[package]] +name = "match_cfg" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ffbee8634e0d45d258acb448e7eaab3fce7a0a467395d4d9f228e3c1f01fb2e4" + +[[package]] +name = "matchers" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8263075bb86c5a1b1427b5ae862e8889656f126e9f77c484496e8b47cf5c5558" +dependencies = [ + "regex-automata 0.1.10", +] + +[[package]] +name = "matchit" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0e7465ac9959cc2b1404e8e2367b43684a6d13790fe23056cc8c6c5a6b7bcb94" + +[[package]] +name = "memchr" +version = "2.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c8640c5d730cb13ebd907d8d04b52f55ac9a2eec55b440c8892f40d56c76c1d" + +[[package]] +name = "mime" +version = "0.3.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" + +[[package]] +name = "mime_guess" +version = "2.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4192263c238a5f0d0c6bfd21f336a313a4ce1c450542449ca191bb657b4642ef" +dependencies = [ + "mime", + "unicase", +] + +[[package]] +name = "miniz_oxide" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d811f3e15f28568be3407c8e7fdb6514c1cda3cb30683f15b6a1a1dc4ea14a7" +dependencies = [ + "adler", +] + +[[package]] +name = "mio" +version = "0.8.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4a650543ca06a924e8b371db273b2756685faae30f8487da1b56505a8f78b0c" +dependencies = [ + "libc", + "wasi", + "windows-sys 0.48.0", +] + +[[package]] +name = "native-tls" +version = "0.2.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07226173c32f2926027b63cce4bcd8076c3552846cbe7925f3aaffeac0a3b92e" +dependencies = [ + "lazy_static", + "libc", + "log", + "openssl", + "openssl-probe", + "openssl-sys", + "schannel", + "security-framework", + "security-framework-sys", + "tempfile", +] + +[[package]] +name = "nohash-hasher" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2bf50223579dc7cdcfb3bfcacf7069ff68243f8c363f62ffa99cf000a6b9c451" + +[[package]] +name = "nu-ansi-term" +version = "0.46.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77a8165726e8236064dbb45459242600304b42a5ea24ee2948e18e023bf7ba84" +dependencies = [ + "overload", + "winapi", +] + +[[package]] +name = "num" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3135b08af27d103b0a51f2ae0f8632117b7b185ccf931445affa8df530576a41" +dependencies = [ + "num-bigint", + "num-complex", + "num-integer", + "num-iter", + "num-rational", + "num-traits", +] + +[[package]] +name = "num-bigint" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c165a9ab64cf766f73521c0dd2cfdff64f488b8f0b3e621face3462d3db536d7" +dependencies = [ + "num-integer", + "num-traits", +] + +[[package]] +name = "num-complex" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23c6602fda94a57c990fe0df199a035d83576b496aa29f4e634a8ac6004e68a6" +dependencies = [ + "num-traits", +] + +[[package]] +name = "num-conv" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9" + +[[package]] +name = "num-integer" +version = "0.1.46" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" +dependencies = [ + "num-traits", +] + +[[package]] +name = "num-iter" +version = "0.1.45" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1429034a0490724d0075ebb2bc9e875d6503c3cf69e235a8941aa757d83ef5bf" +dependencies = [ + "autocfg", + "num-integer", + "num-traits", +] + +[[package]] +name = "num-rational" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0638a1c9d0a3c0914158145bc76cff373a75a627e6ecbfb71cbe6f453a5a19b0" +dependencies = [ + "autocfg", + "num-bigint", + "num-integer", + "num-traits", +] + +[[package]] +name = "num-traits" +version = "0.2.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" +dependencies = [ + "autocfg", + "libm", +] + +[[package]] +name = "num_cpus" +version = "1.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43" +dependencies = [ + "hermit-abi", + "libc", +] + +[[package]] +name = "num_enum" +version = "0.5.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f646caf906c20226733ed5b1374287eb97e3c2a5c227ce668c1f2ce20ae57c9" +dependencies = [ + "num_enum_derive", +] + +[[package]] +name = "num_enum_derive" +version = "0.5.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dcbff9bc912032c62bf65ef1d5aea88983b420f4f839db1e9b0c281a25c9c799" +dependencies = [ + "proc-macro-crate 1.3.1", + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "number_prefix" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "830b246a0e5f20af87141b25c173cd1b609bd7779a4617d6ec582abaf90870f3" + +[[package]] +name = "object" +version = "0.32.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a6a622008b6e321afc04970976f62ee297fdbaa6f95318ca343e3eebb9648441" +dependencies = [ + "memchr", +] + +[[package]] +name = "once_cell" +version = "1.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" + +[[package]] +name = "openssl" +version = "0.10.64" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95a0481286a310808298130d22dd1fef0fa571e05a8f44ec801801e84b216b1f" +dependencies = [ + "bitflags 2.5.0", + "cfg-if", + "foreign-types", + "libc", + "once_cell", + "openssl-macros", + "openssl-sys", +] + +[[package]] +name = "openssl-macros" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.61", +] + +[[package]] +name = "openssl-probe" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" + +[[package]] +name = "openssl-sys" +version = "0.9.102" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c597637d56fbc83893a35eb0dd04b2b8e7a50c91e64e9493e398b5df4fb45fa2" +dependencies = [ + "cc", + "libc", + "pkg-config", + "vcpkg", +] + +[[package]] +name = "overload" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39" + +[[package]] +name = "p3-air" +version = "0.1.0" +source = "git+https://github.com/Plonky3/Plonky3.git?branch=sp1#d379375a75417ddfd0a059ce7db63e162ec52c69" +dependencies = [ + "p3-field", + "p3-matrix", +] + +[[package]] +name = "p3-baby-bear" +version = "0.1.0" +source = "git+https://github.com/Plonky3/Plonky3.git?branch=sp1#d379375a75417ddfd0a059ce7db63e162ec52c69" +dependencies = [ + "num-bigint", + "p3-field", + "p3-mds", + "p3-poseidon2", + "p3-symmetric", + "rand", + "serde", +] + +[[package]] +name = "p3-blake3" +version = "0.1.0" +source = "git+https://github.com/Plonky3/Plonky3.git?branch=sp1#d379375a75417ddfd0a059ce7db63e162ec52c69" +dependencies = [ + "blake3", + "p3-symmetric", +] + +[[package]] +name = "p3-challenger" +version = "0.1.0" +source = "git+https://github.com/Plonky3/Plonky3.git?branch=sp1#d379375a75417ddfd0a059ce7db63e162ec52c69" +dependencies = [ + "p3-field", + "p3-maybe-rayon", + "p3-symmetric", + "p3-util", + "tracing", +] + +[[package]] +name = "p3-commit" +version = "0.1.0" +source = "git+https://github.com/Plonky3/Plonky3.git?branch=sp1#d379375a75417ddfd0a059ce7db63e162ec52c69" +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/Plonky3/Plonky3.git?branch=sp1#d379375a75417ddfd0a059ce7db63e162ec52c69" +dependencies = [ + "p3-field", + "p3-matrix", + "p3-maybe-rayon", + "p3-util", + "tracing", +] + +[[package]] +name = "p3-field" +version = "0.1.0" +source = "git+https://github.com/Plonky3/Plonky3.git?branch=sp1#d379375a75417ddfd0a059ce7db63e162ec52c69" +dependencies = [ + "itertools 0.12.1", + "num-bigint", + "num-traits", + "p3-util", + "rand", + "serde", +] + +[[package]] +name = "p3-fri" +version = "0.1.0" +source = "git+https://github.com/Plonky3/Plonky3.git?branch=sp1#d379375a75417ddfd0a059ce7db63e162ec52c69" +dependencies = [ + "itertools 0.12.1", + "p3-challenger", + "p3-commit", + "p3-dft", + "p3-field", + "p3-interpolation", + "p3-matrix", + "p3-maybe-rayon", + "p3-util", + "serde", + "tracing", +] + +[[package]] +name = "p3-interpolation" +version = "0.1.0" +source = "git+https://github.com/Plonky3/Plonky3.git?branch=sp1#d379375a75417ddfd0a059ce7db63e162ec52c69" +dependencies = [ + "p3-field", + "p3-matrix", + "p3-util", +] + +[[package]] +name = "p3-keccak" +version = "0.1.0" +source = "git+https://github.com/Plonky3/Plonky3.git?branch=sp1#d379375a75417ddfd0a059ce7db63e162ec52c69" +dependencies = [ + "p3-symmetric", + "tiny-keccak", +] + +[[package]] +name = "p3-keccak-air" +version = "0.1.0" +source = "git+https://github.com/Plonky3/Plonky3.git?branch=sp1#d379375a75417ddfd0a059ce7db63e162ec52c69" +dependencies = [ + "p3-air", + "p3-field", + "p3-matrix", + "p3-util", + "tracing", +] + +[[package]] +name = "p3-matrix" +version = "0.1.0" +source = "git+https://github.com/Plonky3/Plonky3.git?branch=sp1#d379375a75417ddfd0a059ce7db63e162ec52c69" +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/Plonky3/Plonky3.git?branch=sp1#d379375a75417ddfd0a059ce7db63e162ec52c69" +dependencies = [ + "rayon", +] + +[[package]] +name = "p3-mds" +version = "0.1.0" +source = "git+https://github.com/Plonky3/Plonky3.git?branch=sp1#d379375a75417ddfd0a059ce7db63e162ec52c69" +dependencies = [ + "itertools 0.11.0", + "p3-dft", + "p3-field", + "p3-matrix", + "p3-symmetric", + "p3-util", + "rand", +] + +[[package]] +name = "p3-merkle-tree" +version = "0.1.0" +source = "git+https://github.com/Plonky3/Plonky3.git?branch=sp1#d379375a75417ddfd0a059ce7db63e162ec52c69" +dependencies = [ + "itertools 0.12.1", + "p3-commit", + "p3-field", + "p3-matrix", + "p3-maybe-rayon", + "p3-symmetric", + "p3-util", + "serde", + "tracing", +] + +[[package]] +name = "p3-poseidon2" +version = "0.1.0" +source = "git+https://github.com/Plonky3/Plonky3.git?branch=sp1#d379375a75417ddfd0a059ce7db63e162ec52c69" +dependencies = [ + "gcd", + "p3-field", + "p3-mds", + "p3-symmetric", + "rand", +] + +[[package]] +name = "p3-symmetric" +version = "0.1.0" +source = "git+https://github.com/Plonky3/Plonky3.git?branch=sp1#d379375a75417ddfd0a059ce7db63e162ec52c69" +dependencies = [ + "itertools 0.12.1", + "p3-field", + "serde", +] + +[[package]] +name = "p3-uni-stark" +version = "0.1.0" +source = "git+https://github.com/Plonky3/Plonky3.git?branch=sp1#d379375a75417ddfd0a059ce7db63e162ec52c69" +dependencies = [ + "itertools 0.12.1", + "p3-air", + "p3-challenger", + "p3-commit", + "p3-dft", + "p3-field", + "p3-matrix", + "p3-maybe-rayon", + "p3-util", + "serde", + "tracing", +] + +[[package]] +name = "p3-util" +version = "0.1.0" +source = "git+https://github.com/Plonky3/Plonky3.git?branch=sp1#d379375a75417ddfd0a059ce7db63e162ec52c69" +dependencies = [ + "serde", +] + +[[package]] +name = "parity-scale-codec" +version = "3.6.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "881331e34fa842a2fb61cc2db9643a8fedc615e47cfcc52597d1af0db9a7e8fe" +dependencies = [ + "arrayvec", + "bitvec", + "byte-slice-cast", + "impl-trait-for-tuples", + "parity-scale-codec-derive", + "serde", +] + +[[package]] +name = "parity-scale-codec-derive" +version = "3.6.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "be30eaf4b0a9fba5336683b38de57bb86d179a35862ba6bfcf57625d006bde5b" +dependencies = [ + "proc-macro-crate 2.0.2", + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "parking_lot" +version = "0.12.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7e4af0ca4f6caed20e900d564c242b8e5d4903fdacf31d3daf527b66fe6f42fb" +dependencies = [ + "lock_api", + "parking_lot_core", +] + +[[package]] +name = "parking_lot_core" +version = "0.9.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8" +dependencies = [ + "cfg-if", + "libc", + "redox_syscall", + "smallvec", + "windows-targets 0.52.5", +] + +[[package]] +name = "paste" +version = "1.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" + +[[package]] +name = "percent-encoding" +version = "2.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" + +[[package]] +name = "pest" +version = "2.7.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "560131c633294438da9f7c4b08189194b20946c8274c6b9e38881a7874dc8ee8" +dependencies = [ + "memchr", + "thiserror", + "ucd-trie", +] + +[[package]] +name = "pin-project" +version = "1.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6bf43b791c5b9e34c3d182969b4abb522f9343702850a2e57f460d00d09b4b3" +dependencies = [ + "pin-project-internal", +] + +[[package]] +name = "pin-project-internal" +version = "1.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2f38a4412a78282e09a2cf38d195ea5420d15ba0602cb375210efbc877243965" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.61", +] + +[[package]] +name = "pin-project-lite" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bda66fc9667c18cb2758a2ac84d1167245054bcf85d5d1aaa6923f45801bdd02" + +[[package]] +name = "pin-utils" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" + +[[package]] +name = "pkcs8" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f950b2377845cebe5cf8b5165cb3cc1a5e0fa5cfa3e1f7f55707d8fd82e0a7b7" +dependencies = [ + "der", + "spki", +] + +[[package]] +name = "pkg-config" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d231b230927b5e4ad203db57bbcbee2802f6bce620b1e4a9024a07d94e2907ec" + +[[package]] +name = "platforms" +version = "3.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db23d408679286588f4d4644f965003d056e3dd5abcaaa938116871d7ce2fee7" + +[[package]] +name = "portable-atomic" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7170ef9988bc169ba16dd36a7fa041e5c4cbeb6a35b76d4c03daded371eae7c0" + +[[package]] +name = "poseidon_bn254-script" +version = "0.1.0" +dependencies = [ + "sp1-helper", + "sp1-sdk", +] + +[[package]] +name = "powerfmt" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" + +[[package]] +name = "ppv-lite86" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" + +[[package]] +name = "primitive-types" +version = "0.12.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b34d9fd68ae0b74a41b21c03c2f62847aa0ffea044eee893b4c140b37e244e2" +dependencies = [ + "fixed-hash", + "impl-codec", + "uint", +] + +[[package]] +name = "proc-macro-crate" +version = "1.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f4c021e1093a56626774e81216a4ce732a735e5bad4868a03f3ed65ca0c3919" +dependencies = [ + "once_cell", + "toml_edit 0.19.15", +] + +[[package]] +name = "proc-macro-crate" +version = "2.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b00f26d3400549137f92511a46ac1cd8ce37cb5598a96d382381458b992a5d24" +dependencies = [ + "toml_datetime", + "toml_edit 0.20.2", +] + +[[package]] +name = "proc-macro-error" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" +dependencies = [ + "proc-macro-error-attr", + "proc-macro2", + "quote", + "syn 1.0.109", + "version_check", +] + +[[package]] +name = "proc-macro-error-attr" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" +dependencies = [ + "proc-macro2", + "quote", + "version_check", +] + +[[package]] +name = "proc-macro2" +version = "1.0.82" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ad3d49ab951a01fbaafe34f2ec74122942fe18a3f9814c3268f1bb72042131b" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "proptest" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "31b476131c3c86cb68032fdc5cb6d5a1045e3e42d96b69fa599fd77701e1f5bf" +dependencies = [ + "bit-set", + "bit-vec", + "bitflags 2.5.0", + "lazy_static", + "num-traits", + "rand", + "rand_chacha", + "rand_xorshift", + "regex-syntax 0.8.3", + "rusty-fork", + "tempfile", + "unarray", +] + +[[package]] +name = "prost" +version = "0.12.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d0f5d036824e4761737860779c906171497f6d55681139d8312388f8fe398922" +dependencies = [ + "bytes", + "prost-derive", +] + +[[package]] +name = "prost-derive" +version = "0.12.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19de2de2a00075bf566bee3bd4db014b11587e84184d3f7a791bc17f1a8e9e48" +dependencies = [ + "anyhow", + "itertools 0.12.1", + "proc-macro2", + "quote", + "syn 2.0.61", +] + +[[package]] +name = "prost-types" +version = "0.12.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3235c33eb02c1f1e212abdbe34c78b264b038fb58ca612664343271e36e55ffe" +dependencies = [ + "prost", +] + +[[package]] +name = "quick-error" +version = "1.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0" + +[[package]] +name = "quote" +version = "1.0.36" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "radium" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc33ff2d4973d518d823d61aa239014831e521c75da58e3df4840d3f47749d09" + +[[package]] +name = "rand" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" +dependencies = [ + "libc", + "rand_chacha", + "rand_core", +] + +[[package]] +name = "rand_chacha" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" +dependencies = [ + "ppv-lite86", + "rand_core", +] + +[[package]] +name = "rand_core" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" +dependencies = [ + "getrandom", +] + +[[package]] +name = "rand_xorshift" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d25bf25ec5ae4a3f1b92f929810509a2f53d7dca2f50b794ff57e3face536c8f" +dependencies = [ + "rand_core", +] + +[[package]] +name = "rayon" +version = "1.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b418a60154510ca1a002a752ca9714984e21e4241e804d32555251faf8b78ffa" +dependencies = [ + "either", + "rayon-core", +] + +[[package]] +name = "rayon-core" +version = "1.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1465873a3dfdaa8ae7cb14b4383657caab0b3e8a0aa9ae8e04b044854c8dfce2" +dependencies = [ + "crossbeam-deque", + "crossbeam-utils", +] + +[[package]] +name = "rayon-scan" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f87cc11a0140b4b0da0ffc889885760c61b13672d80a908920b2c0df078fa14" +dependencies = [ + "rayon", +] + +[[package]] +name = "redox_syscall" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "469052894dcb553421e483e4209ee581a45100d31b4018de03e5a7ad86374a7e" +dependencies = [ + "bitflags 2.5.0", +] + +[[package]] +name = "regex" +version = "1.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c117dbdfde9c8308975b6a18d71f3f385c89461f7b3fb054288ecf2a2058ba4c" +dependencies = [ + "aho-corasick", + "memchr", + "regex-automata 0.4.6", + "regex-syntax 0.8.3", +] + +[[package]] +name = "regex-automata" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132" +dependencies = [ + "regex-syntax 0.6.29", +] + +[[package]] +name = "regex-automata" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "86b83b8b9847f9bf95ef68afb0b8e6cdb80f498442f5179a29fad448fcc1eaea" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax 0.8.3", +] + +[[package]] +name = "regex-syntax" +version = "0.6.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1" + +[[package]] +name = "regex-syntax" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "adad44e29e4c806119491a7f06f03de4d1af22c3a680dd47f1e6e179439d1f56" + +[[package]] +name = "reqwest" +version = "0.11.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd67538700a17451e7cba03ac727fb961abb7607553461627b97de0b89cf4a62" +dependencies = [ + "base64 0.21.7", + "bytes", + "encoding_rs", + "futures-core", + "futures-util", + "h2 0.3.26", + "hickory-resolver", + "http 0.2.12", + "http-body 0.4.6", + "hyper 0.14.28", + "hyper-rustls", + "hyper-tls 0.5.0", + "ipnet", + "js-sys", + "log", + "mime", + "mime_guess", + "native-tls", + "once_cell", + "percent-encoding", + "pin-project-lite", + "rustls", + "rustls-pemfile 1.0.4", + "serde", + "serde_json", + "serde_urlencoded", + "sync_wrapper", + "system-configuration", + "tokio", + "tokio-native-tls", + "tokio-rustls", + "tower-service", + "url", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", + "webpki-roots", + "winreg 0.50.0", +] + +[[package]] +name = "reqwest" +version = "0.12.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "566cafdd92868e0939d3fb961bd0dc25fcfaaed179291093b3d43e6b3150ea10" +dependencies = [ + "base64 0.22.1", + "bytes", + "futures-core", + "futures-util", + "http 1.1.0", + "http-body 1.0.0", + "http-body-util", + "hyper 1.3.1", + "hyper-tls 0.6.0", + "hyper-util", + "ipnet", + "js-sys", + "log", + "mime", + "native-tls", + "once_cell", + "percent-encoding", + "pin-project-lite", + "rustls-pemfile 2.1.2", + "serde", + "serde_json", + "serde_urlencoded", + "sync_wrapper", + "tokio", + "tokio-native-tls", + "tower-service", + "url", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", + "winreg 0.52.0", +] + +[[package]] +name = "reqwest-middleware" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a735987236a8e238bf0296c7e351b999c188ccc11477f311b82b55c93984216" +dependencies = [ + "anyhow", + "async-trait", + "http 0.2.12", + "reqwest 0.11.27", + "serde", + "task-local-extensions", + "thiserror", +] + +[[package]] +name = "resolv-conf" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "52e44394d2086d010551b14b53b1f24e31647570cd1deb0379e2c21b329aba00" +dependencies = [ + "hostname", + "quick-error", +] + +[[package]] +name = "rfc6979" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8dd2a808d456c4a54e300a23e9f5a67e122c3024119acbfd73e3bf664491cb2" +dependencies = [ + "hmac", + "subtle", +] + +[[package]] +name = "ring" +version = "0.17.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c17fa4cb658e3583423e915b9f3acc01cceaee1860e33d59ebae66adc3a2dc0d" +dependencies = [ + "cc", + "cfg-if", + "getrandom", + "libc", + "spin", + "untrusted", + "windows-sys 0.52.0", +] + +[[package]] +name = "rlp" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb919243f34364b6bd2fc10ef797edbfa75f33c252e7998527479c6d6b47e1ec" +dependencies = [ + "bytes", + "rustc-hex", +] + +[[package]] +name = "rrs-lib" +version = "0.1.0" +source = "git+https://github.com/GregAC/rrs.git#b23afc16b4e6a1fb5c4a73eb1e337e9400816507" +dependencies = [ + "downcast-rs", + "num_enum", + "paste", +] + +[[package]] +name = "ruint" +version = "1.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f308135fef9fc398342da5472ce7c484529df23743fb7c734e0f3d472971e62" +dependencies = [ + "alloy-rlp", + "ark-ff 0.3.0", + "ark-ff 0.4.2", + "bytes", + "fastrlp", + "num-bigint", + "num-traits", + "parity-scale-codec", + "primitive-types", + "proptest", + "rand", + "rlp", + "ruint-macro", + "serde", + "valuable", + "zeroize", +] + +[[package]] +name = "ruint-macro" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f86854cf50259291520509879a5c294c3c9a4c334e9ff65071c51e42ef1e2343" + +[[package]] +name = "rustc-demangle" +version = "0.1.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" + +[[package]] +name = "rustc-hex" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3e75f6a532d0fd9f7f13144f392b6ad56a32696bfcd9c78f797f16bbb6f072d6" + +[[package]] +name = "rustc_version" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0dfe2087c51c460008730de8b57e6a320782fbfb312e1f4d520e6c6fae155ee" +dependencies = [ + "semver 0.11.0", +] + +[[package]] +name = "rustc_version" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" +dependencies = [ + "semver 1.0.23", +] + +[[package]] +name = "rustix" +version = "0.38.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70dc5ec042f7a43c4a73241207cecc9873a06d45debb38b329f8541d85c2730f" +dependencies = [ + "bitflags 2.5.0", + "errno", + "libc", + "linux-raw-sys", + "windows-sys 0.52.0", +] + +[[package]] +name = "rustls" +version = "0.21.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f56a14d1f48b391359b22f731fd4bd7e43c97f3c50eee276f3aa09c94784d3e" +dependencies = [ + "log", + "ring", + "rustls-webpki", + "sct", +] + +[[package]] +name = "rustls-pemfile" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1c74cae0a4cf6ccbbf5f359f08efdf8ee7e1dc532573bf0db71968cb56b1448c" +dependencies = [ + "base64 0.21.7", +] + +[[package]] +name = "rustls-pemfile" +version = "2.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29993a25686778eb88d4189742cd713c9bce943bc54251a33509dc63cbacf73d" +dependencies = [ + "base64 0.22.1", + "rustls-pki-types", +] + +[[package]] +name = "rustls-pki-types" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "51f344d206c5e1b010eec27349b815a4805f70a778895959d70b74b9b529b30a" + +[[package]] +name = "rustls-webpki" +version = "0.101.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b6275d1ee7a1cd780b64aca7726599a1dbc893b1e64144529e55c3c2f745765" +dependencies = [ + "ring", + "untrusted", +] + +[[package]] +name = "rustversion" +version = "1.0.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "092474d1a01ea8278f69e6a358998405fae5b8b963ddaeb2b0b04a128bf1dfb0" + +[[package]] +name = "rusty-fork" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb3dcc6e454c328bb824492db107ab7c0ae8fcffe4ad210136ef014458c1bc4f" +dependencies = [ + "fnv", + "quick-error", + "tempfile", + "wait-timeout", +] + +[[package]] +name = "ryu" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" + +[[package]] +name = "scale-info" +version = "2.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7c453e59a955f81fb62ee5d596b450383d699f152d350e9d23a0db2adb78e4c0" +dependencies = [ + "cfg-if", + "derive_more", + "parity-scale-codec", + "scale-info-derive", +] + +[[package]] +name = "scale-info-derive" +version = "2.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "18cf6c6447f813ef19eb450e985bcce6705f9ce7660db221b59093d15c79c4b7" +dependencies = [ + "proc-macro-crate 1.3.1", + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "schannel" +version = "0.1.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fbc91545643bcf3a0bbb6569265615222618bdf33ce4ffbbd13c4bbd4c093534" +dependencies = [ + "windows-sys 0.52.0", +] + +[[package]] +name = "scopeguard" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" + +[[package]] +name = "sct" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da046153aa2352493d6cb7da4b6e5c0c057d8a1d0a9aa8560baffdd945acd414" +dependencies = [ + "ring", + "untrusted", +] + +[[package]] +name = "sec1" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3e97a565f76233a6003f9f5c54be1d9c5bdfa3eccfb189469f11ec4901c47dc" +dependencies = [ + "base16ct", + "der", + "generic-array 0.14.7", + "pkcs8", + "subtle", + "zeroize", +] + +[[package]] +name = "security-framework" +version = "2.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c627723fd09706bacdb5cf41499e95098555af3c3c29d014dc3c458ef6be11c0" +dependencies = [ + "bitflags 2.5.0", + "core-foundation", + "core-foundation-sys", + "libc", + "security-framework-sys", +] + +[[package]] +name = "security-framework-sys" +version = "2.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "317936bbbd05227752583946b9e66d7ce3b489f84e11a94a510b4437fef407d7" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "semver" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f301af10236f6df4160f7c3f04eec6dbc70ace82d23326abad5edee88801c6b6" +dependencies = [ + "semver-parser", +] + +[[package]] +name = "semver" +version = "1.0.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61697e0a1c7e512e84a621326239844a24d8207b4669b41bc18b32ea5cbf988b" +dependencies = [ + "serde", +] + +[[package]] +name = "semver-parser" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "00b0bef5b7f9e0df16536d3961cfb6e84331c065b4066afb39768d0e319411f7" +dependencies = [ + "pest", +] + +[[package]] +name = "serde" +version = "1.0.200" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ddc6f9cc94d67c0e21aaf7eda3a010fd3af78ebf6e096aa6e2e13c79749cce4f" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.200" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "856f046b9400cee3c8c94ed572ecdb752444c24528c035cd35882aad6f492bcb" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.61", +] + +[[package]] +name = "serde_json" +version = "1.0.116" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3e17db7126d17feb94eb3fad46bf1a96b034e8aacbc2e775fe81505f8b0b2813" +dependencies = [ + "itoa", + "ryu", + "serde", +] + +[[package]] +name = "serde_path_to_error" +version = "0.1.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af99884400da37c88f5e9146b7f1fd0fbcae8f6eec4e9da38b67d05486f814a6" +dependencies = [ + "itoa", + "serde", +] + +[[package]] +name = "serde_urlencoded" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" +dependencies = [ + "form_urlencoded", + "itoa", + "ryu", + "serde", +] + +[[package]] +name = "serde_with" +version = "3.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ad483d2ab0149d5a5ebcd9972a3852711e0153d863bf5a5d0391d28883c4a20" +dependencies = [ + "base64 0.22.1", + "chrono", + "hex", + "indexmap 1.9.3", + "indexmap 2.2.6", + "serde", + "serde_derive", + "serde_json", + "serde_with_macros", + "time", +] + +[[package]] +name = "serde_with_macros" +version = "3.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "65569b702f41443e8bc8bbb1c5779bd0450bbe723b56198980e80ec45780bce2" +dependencies = [ + "darling", + "proc-macro2", + "quote", + "syn 2.0.61", +] + +[[package]] +name = "sha2" +version = "0.10.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest 0.10.7", +] + +[[package]] +name = "sha3-asm" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bac61da6b35ad76b195eb4771210f947734321a8d81d7738e1580d953bc7a15e" +dependencies = [ + "cc", + "cfg-if", +] + +[[package]] +name = "sharded-slab" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f40ca3c46823713e0d4209592e8d6e826aa57e928f09752619fc696c499637f6" +dependencies = [ + "lazy_static", +] + +[[package]] +name = "signal-hook-registry" +version = "1.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a9e9e0b4211b72e7b8b6e85c807d36c212bdb33ea8587f7569562a84df5465b1" +dependencies = [ + "libc", +] + +[[package]] +name = "signature" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77549399552de45a898a580c1b41d445bf730df867cc44e6c0233bbc4b8329de" +dependencies = [ + "digest 0.10.7", + "rand_core", +] + +[[package]] +name = "size" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9fed904c7fb2856d868b92464fc8fa597fce366edea1a9cbfaa8cb5fe080bd6d" + +[[package]] +name = "slab" +version = "0.4.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" +dependencies = [ + "autocfg", +] + +[[package]] +name = "smallvec" +version = "1.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" + +[[package]] +name = "snowbridge-amcl" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "460a9ed63cdf03c1b9847e8a12a5f5ba19c4efd5869e4a737e05be25d7c427e5" +dependencies = [ + "parity-scale-codec", + "scale-info", +] + +[[package]] +name = "socket2" +version = "0.5.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce305eb0b4296696835b71df73eb912e0f1ffd2556a501fcede6e0c50349191c" +dependencies = [ + "libc", + "windows-sys 0.52.0", +] + +[[package]] +name = "sp1-core" +version = "0.1.0" +dependencies = [ + "anyhow", + "arrayref", + "bincode", + "blake3", + "blake3-zkvm", + "cfg-if", + "curve25519-dalek", + "elf", + "elliptic-curve", + "generic-array 1.0.0", + "hex", + "itertools 0.12.1", + "k256", + "log", + "nohash-hasher", + "num", + "num_cpus", + "p3-air", + "p3-baby-bear", + "p3-blake3", + "p3-challenger", + "p3-commit", + "p3-dft", + "p3-field", + "p3-fri", + "p3-keccak", + "p3-keccak-air", + "p3-matrix", + "p3-maybe-rayon", + "p3-merkle-tree", + "p3-poseidon2", + "p3-symmetric", + "p3-uni-stark", + "p3-util", + "rayon-scan", + "rrs-lib", + "serde", + "serde_with", + "size", + "snowbridge-amcl", + "sp1-derive", + "sp1-primitives", + "strum", + "strum_macros", + "tempfile", + "tracing", + "tracing-forest", + "tracing-subscriber", + "typenum", + "web-time", +] + +[[package]] +name = "sp1-derive" +version = "0.1.0" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "sp1-helper" +version = "0.1.0" +dependencies = [ + "cargo_metadata", + "chrono", +] + +[[package]] +name = "sp1-primitives" +version = "0.1.0" +dependencies = [ + "itertools 0.12.1", + "lazy_static", + "p3-baby-bear", + "p3-field", + "p3-poseidon2", + "p3-symmetric", +] + +[[package]] +name = "sp1-sdk" +version = "0.1.0" +dependencies = [ + "alloy", + "anyhow", + "async-trait", + "axum", + "bincode", + "dotenv", + "futures", + "hex", + "indicatif", + "log", + "p3-commit", + "p3-field", + "p3-matrix", + "prost", + "prost-types", + "reqwest 0.11.27", + "reqwest-middleware", + "serde", + "serde_json", + "sha2", + "sp1-core", + "tokio", + "tracing", + "twirp", +] + +[[package]] +name = "spin" +version = "0.9.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" + +[[package]] +name = "spki" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d91ed6c858b01f942cd56b37a94b3e0a1798290327d1236e4d9cf4eaca44d29d" +dependencies = [ + "base64ct", + "der", +] + +[[package]] +name = "static_assertions" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" + +[[package]] +name = "strsim" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" + +[[package]] +name = "strum" +version = "0.26.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d8cec3501a5194c432b2b7976db6b7d10ec95c253208b45f83f7136aa985e29" + +[[package]] +name = "strum_macros" +version = "0.26.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c6cf59daf282c0a494ba14fd21610a0325f9f90ec9d1231dea26bcb1d696c946" +dependencies = [ + "heck 0.4.1", + "proc-macro2", + "quote", + "rustversion", + "syn 2.0.61", +] + +[[package]] +name = "subtle" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "81cdd64d312baedb58e21336b31bc043b77e01cc99033ce76ef539f78e965ebc" + +[[package]] +name = "syn" +version = "1.0.109" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "syn" +version = "2.0.61" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c993ed8ccba56ae856363b1845da7266a7cb78e1d146c8a32d54b45a8b831fc9" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "syn-solidity" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5aa0cefd02f532035d83cfec82647c6eb53140b0485220760e669f4bad489e36" +dependencies = [ + "paste", + "proc-macro2", + "quote", + "syn 2.0.61", +] + +[[package]] +name = "sync_wrapper" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2047c6ded9c721764247e62cd3b03c09ffc529b2ba5b10ec482ae507a4a70160" + +[[package]] +name = "system-configuration" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba3a3adc5c275d719af8cb4272ea1c4a6d668a777f37e115f6d11ddbc1c8e0e7" +dependencies = [ + "bitflags 1.3.2", + "core-foundation", + "system-configuration-sys", +] + +[[package]] +name = "system-configuration-sys" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a75fb188eb626b924683e3b95e3a48e63551fcfb51949de2f06a9d91dbee93c9" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "tap" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" + +[[package]] +name = "task-local-extensions" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba323866e5d033818e3240feeb9f7db2c4296674e4d9e16b97b7bf8f490434e8" +dependencies = [ + "pin-utils", +] + +[[package]] +name = "tempfile" +version = "3.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85b77fafb263dd9d05cbeac119526425676db3784113aa9295c88498cbf8bff1" +dependencies = [ + "cfg-if", + "fastrand", + "rustix", + "windows-sys 0.52.0", +] + +[[package]] +name = "thiserror" +version = "1.0.60" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "579e9083ca58dd9dcf91a9923bb9054071b9ebbd800b342194c9feb0ee89fc18" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.60" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2470041c06ec3ac1ab38d0356a6119054dedaea53e12fbefc0de730a1c08524" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.61", +] + +[[package]] +name = "thread_local" +version = "1.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b9ef9bad013ada3808854ceac7b46812a6465ba368859a37e2100283d2d719c" +dependencies = [ + "cfg-if", + "once_cell", +] + +[[package]] +name = "threadpool" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d050e60b33d41c19108b32cea32164033a9013fe3b46cbd4457559bfbf77afaa" +dependencies = [ + "num_cpus", +] + +[[package]] +name = "time" +version = "0.3.36" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5dfd88e563464686c916c7e46e623e520ddc6d79fa6641390f2e3fa86e83e885" +dependencies = [ + "deranged", + "itoa", + "num-conv", + "powerfmt", + "serde", + "time-core", + "time-macros", +] + +[[package]] +name = "time-core" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3" + +[[package]] +name = "time-macros" +version = "0.2.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f252a68540fde3a3877aeea552b832b40ab9a69e318efd078774a01ddee1ccf" +dependencies = [ + "num-conv", + "time-core", +] + +[[package]] +name = "tiny-keccak" +version = "2.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2c9d3793400a45f954c52e73d068316d76b6f4e36977e3fcebb13a2721e80237" +dependencies = [ + "crunchy", +] + +[[package]] +name = "tinyvec" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50" +dependencies = [ + "tinyvec_macros", +] + +[[package]] +name = "tinyvec_macros" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" + +[[package]] +name = "tokio" +version = "1.37.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1adbebffeca75fcfd058afa480fb6c0b81e165a0323f9c9d39c9697e37c46787" +dependencies = [ + "backtrace", + "bytes", + "libc", + "mio", + "num_cpus", + "parking_lot", + "pin-project-lite", + "signal-hook-registry", + "socket2", + "tokio-macros", + "windows-sys 0.48.0", +] + +[[package]] +name = "tokio-macros" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.61", +] + +[[package]] +name = "tokio-native-tls" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbae76ab933c85776efabc971569dd6119c580d8f5d448769dec1764bf796ef2" +dependencies = [ + "native-tls", + "tokio", +] + +[[package]] +name = "tokio-rustls" +version = "0.24.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c28327cf380ac148141087fbfb9de9d7bd4e84ab5d2c28fbc911d753de8a7081" +dependencies = [ + "rustls", + "tokio", +] + +[[package]] +name = "tokio-stream" +version = "0.1.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "267ac89e0bec6e691e5813911606935d77c476ff49024f98abcea3e7b15e37af" +dependencies = [ + "futures-core", + "pin-project-lite", + "tokio", + "tokio-util", +] + +[[package]] +name = "tokio-util" +version = "0.7.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9cf6b47b3771c49ac75ad09a6162f53ad4b8088b76ac60e8ec1455b31a189fe1" +dependencies = [ + "bytes", + "futures-core", + "futures-sink", + "pin-project-lite", + "tokio", +] + +[[package]] +name = "toml_datetime" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7cda73e2f1397b1262d6dfdcef8aafae14d1de7748d66822d3bfeeb6d03e5e4b" + +[[package]] +name = "toml_edit" +version = "0.19.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b5bb770da30e5cbfde35a2d7b9b8a2c4b8ef89548a7a6aeab5c9a576e3e7421" +dependencies = [ + "indexmap 2.2.6", + "toml_datetime", + "winnow 0.5.40", +] + +[[package]] +name = "toml_edit" +version = "0.20.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "396e4d48bbb2b7554c944bde63101b5ae446cff6ec4a24227428f15eb72ef338" +dependencies = [ + "indexmap 2.2.6", + "toml_datetime", + "winnow 0.5.40", +] + +[[package]] +name = "tower" +version = "0.4.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8fa9be0de6cf49e536ce1851f987bd21a43b771b09473c3549a6c853db37c1c" +dependencies = [ + "futures-core", + "futures-util", + "pin-project", + "pin-project-lite", + "tokio", + "tower-layer", + "tower-service", + "tracing", +] + +[[package]] +name = "tower-layer" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c20c8dbed6283a09604c3e69b4b7eeb54e298b8a600d4d5ecb5ad39de609f1d0" + +[[package]] +name = "tower-service" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6bc1c9ce2b5135ac7f93c72918fc37feb872bdc6a5533a8b85eb4b86bfdae52" + +[[package]] +name = "tracing" +version = "0.1.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" +dependencies = [ + "log", + "pin-project-lite", + "tracing-attributes", + "tracing-core", +] + +[[package]] +name = "tracing-attributes" +version = "0.1.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.61", +] + +[[package]] +name = "tracing-core" +version = "0.1.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54" +dependencies = [ + "once_cell", + "valuable", +] + +[[package]] +name = "tracing-forest" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee40835db14ddd1e3ba414292272eddde9dad04d3d4b65509656414d1c42592f" +dependencies = [ + "ansi_term", + "smallvec", + "thiserror", + "tracing", + "tracing-subscriber", +] + +[[package]] +name = "tracing-log" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee855f1f400bd0e5c02d150ae5de3840039a3f54b025156404e34c23c03f47c3" +dependencies = [ + "log", + "once_cell", + "tracing-core", +] + +[[package]] +name = "tracing-subscriber" +version = "0.3.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ad0f048c97dbd9faa9b7df56362b8ebcaa52adb06b498c050d2f4e32f90a7a8b" +dependencies = [ + "matchers", + "nu-ansi-term", + "once_cell", + "regex", + "sharded-slab", + "smallvec", + "thread_local", + "tracing", + "tracing-core", + "tracing-log", +] + +[[package]] +name = "try-lock" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" + +[[package]] +name = "twirp" +version = "0.3.0" +source = "git+https://github.com/github/twirp-rs.git#aacdd3971e52735b64476ec1dcc56fb3d7f2771e" +dependencies = [ + "async-trait", + "axum", + "bytes", + "futures", + "http 1.1.0", + "http-body-util", + "hyper 1.3.1", + "prost", + "reqwest 0.11.27", + "serde", + "serde_json", + "thiserror", + "tokio", + "tower", + "url", +] + +[[package]] +name = "typenum" +version = "1.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" + +[[package]] +name = "ucd-trie" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed646292ffc8188ef8ea4d1e0e0150fb15a5c2e12ad9b8fc191ae7a8a7f3c4b9" + +[[package]] +name = "uint" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76f64bba2c53b04fcab63c01a7d7427eadc821e3bc48c34dc9ba29c501164b52" +dependencies = [ + "byteorder", + "crunchy", + "hex", + "static_assertions", +] + +[[package]] +name = "unarray" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eaea85b334db583fe3274d12b4cd1880032beab409c0d774be044d4480ab9a94" + +[[package]] +name = "unicase" +version = "2.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f7d2d4dafb69621809a81864c9c1b864479e1235c0dd4e199924b9742439ed89" +dependencies = [ + "version_check", +] + +[[package]] +name = "unicode-bidi" +version = "0.3.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08f95100a766bf4f8f28f90d77e0a5461bbdb219042e7679bebe79004fed8d75" + +[[package]] +name = "unicode-ident" +version = "1.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" + +[[package]] +name = "unicode-normalization" +version = "0.1.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a56d1686db2308d901306f92a263857ef59ea39678a5458e7cb17f01415101f5" +dependencies = [ + "tinyvec", +] + +[[package]] +name = "unicode-width" +version = "0.1.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68f5e5f3158ecfd4b8ff6fe086db7c8467a2dfdac97fe420f2b7c4aa97af66d6" + +[[package]] +name = "untrusted" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" + +[[package]] +name = "url" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "31e6302e3bb753d46e83516cae55ae196fc0c309407cf11ab35cc51a4c2a4633" +dependencies = [ + "form_urlencoded", + "idna 0.5.0", + "percent-encoding", +] + +[[package]] +name = "valuable" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d" + +[[package]] +name = "vcpkg" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" + +[[package]] +name = "version_check" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" + +[[package]] +name = "wait-timeout" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f200f5b12eb75f8c1ed65abd4b2db8a6e1b138a20de009dacee265a2498f3f6" +dependencies = [ + "libc", +] + +[[package]] +name = "want" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfa7760aed19e106de2c7c0b581b509f2f25d3dacaf737cb82ac61bc6d760b0e" +dependencies = [ + "try-lock", +] + +[[package]] +name = "wasi" +version = "0.11.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" + +[[package]] +name = "wasm-bindgen" +version = "0.2.92" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4be2531df63900aeb2bca0daaaddec08491ee64ceecbee5076636a3b026795a8" +dependencies = [ + "cfg-if", + "wasm-bindgen-macro", +] + +[[package]] +name = "wasm-bindgen-backend" +version = "0.2.92" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "614d787b966d3989fa7bb98a654e369c762374fd3213d212cfc0251257e747da" +dependencies = [ + "bumpalo", + "log", + "once_cell", + "proc-macro2", + "quote", + "syn 2.0.61", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-futures" +version = "0.4.42" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76bc14366121efc8dbb487ab05bcc9d346b3b5ec0eaa76e46594cabbe51762c0" +dependencies = [ + "cfg-if", + "js-sys", + "wasm-bindgen", + "web-sys", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.92" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1f8823de937b71b9460c0c34e25f3da88250760bec0ebac694b49997550d726" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.92" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.61", + "wasm-bindgen-backend", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.92" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af190c94f2773fdb3729c55b007a722abb5384da03bc0986df4c289bf5567e96" + +[[package]] +name = "web-sys" +version = "0.3.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77afa9a11836342370f4817622a2f0f418b134426d91a82dfb48f532d2ec13ef" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "web-time" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a6580f308b1fad9207618087a65c04e7a10bc77e02c8e84e9b00dd4b12fa0bb" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "webpki-roots" +version = "0.25.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f20c57d8d7db6d3b86154206ae5d8fba62dd39573114de97c2cb0578251f8e1" + +[[package]] +name = "widestring" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7219d36b6eac893fa81e84ebe06485e7dcbb616177469b142df14f1f4deb1311" + +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + +[[package]] +name = "windows-core" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" +dependencies = [ + "windows-targets 0.52.5", +] + +[[package]] +name = "windows-sys" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" +dependencies = [ + "windows-targets 0.48.5", +] + +[[package]] +name = "windows-sys" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" +dependencies = [ + "windows-targets 0.52.5", +] + +[[package]] +name = "windows-targets" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" +dependencies = [ + "windows_aarch64_gnullvm 0.48.5", + "windows_aarch64_msvc 0.48.5", + "windows_i686_gnu 0.48.5", + "windows_i686_msvc 0.48.5", + "windows_x86_64_gnu 0.48.5", + "windows_x86_64_gnullvm 0.48.5", + "windows_x86_64_msvc 0.48.5", +] + +[[package]] +name = "windows-targets" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f0713a46559409d202e70e28227288446bf7841d3211583a4b53e3f6d96e7eb" +dependencies = [ + "windows_aarch64_gnullvm 0.52.5", + "windows_aarch64_msvc 0.52.5", + "windows_i686_gnu 0.52.5", + "windows_i686_gnullvm", + "windows_i686_msvc 0.52.5", + "windows_x86_64_gnu 0.52.5", + "windows_x86_64_gnullvm 0.52.5", + "windows_x86_64_msvc 0.52.5", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7088eed71e8b8dda258ecc8bac5fb1153c5cffaf2578fc8ff5d61e23578d3263" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9985fd1504e250c615ca5f281c3f7a6da76213ebd5ccc9561496568a2752afb6" + +[[package]] +name = "windows_i686_gnu" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" + +[[package]] +name = "windows_i686_gnu" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "88ba073cf16d5372720ec942a8ccbf61626074c6d4dd2e745299726ce8b89670" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87f4261229030a858f36b459e748ae97545d6f1ec60e5e0d6a3d32e0dc232ee9" + +[[package]] +name = "windows_i686_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" + +[[package]] +name = "windows_i686_msvc" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db3c2bf3d13d5b658be73463284eaf12830ac9a26a90c717b7f771dfe97487bf" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4e4246f76bdeff09eb48875a0fd3e2af6aada79d409d33011886d3e1581517d9" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "852298e482cd67c356ddd9570386e2862b5673c85bd5f88df9ab6802b334c596" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bec47e5bfd1bff0eeaf6d8b485cc1074891a197ab4225d504cb7a1ab88b02bf0" + +[[package]] +name = "winnow" +version = "0.5.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f593a95398737aeed53e489c785df13f3618e41dbcd6718c6addbf1395aa6876" +dependencies = [ + "memchr", +] + +[[package]] +name = "winnow" +version = "0.6.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3c52e9c97a68071b23e836c9380edae937f17b9c4667bd021973efc689f618d" +dependencies = [ + "memchr", +] + +[[package]] +name = "winreg" +version = "0.50.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "524e57b2c537c0f9b1e69f1965311ec12182b4122e45035b1508cd24d2adadb1" +dependencies = [ + "cfg-if", + "windows-sys 0.48.0", +] + +[[package]] +name = "winreg" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a277a57398d4bfa075df44f501a17cfdf8542d224f0d36095a2adc7aee4ef0a5" +dependencies = [ + "cfg-if", + "windows-sys 0.48.0", +] + +[[package]] +name = "wyz" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05f360fc0b24296329c78fda852a1e9ae82de9cf7b27dae4b7f62f118f77b9ed" +dependencies = [ + "tap", +] + +[[package]] +name = "zerocopy" +version = "0.7.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae87e3fcd617500e5d106f0380cf7b77f3c6092aae37191433159dda23cfb087" +dependencies = [ + "zerocopy-derive", +] + +[[package]] +name = "zerocopy-derive" +version = "0.7.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "15e934569e47891f7d9411f1a451d947a60e000ab3bd24fbb970f000387d1b3b" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.61", +] + +[[package]] +name = "zeroize" +version = "1.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "525b4ec142c6b68a2d10f01f7bbf6755599ca3f81ea53b8431b7dd348f5fdb2d" +dependencies = [ + "zeroize_derive", +] + +[[package]] +name = "zeroize_derive" +version = "1.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.61", +] diff --git a/examples/poseidon_bn254/script/Cargo.toml b/examples/poseidon_bn254/script/Cargo.toml new file mode 100644 index 0000000000..712d15d1e1 --- /dev/null +++ b/examples/poseidon_bn254/script/Cargo.toml @@ -0,0 +1,11 @@ +[workspace] +[package] +version = "0.1.0" +name = "poseidon_bn254-script" +edition = "2021" + +[dependencies] +sp1-sdk = { path = "../../../sdk" } + +[build-dependencies] +sp1-helper = { path = "../../../helper" } \ No newline at end of file diff --git a/examples/poseidon_bn254/script/build.rs b/examples/poseidon_bn254/script/build.rs new file mode 100644 index 0000000000..32b99273cd --- /dev/null +++ b/examples/poseidon_bn254/script/build.rs @@ -0,0 +1,5 @@ +use sp1_helper::build_program; + +fn main() { + build_program("../program") +} diff --git a/examples/poseidon_bn254/script/src/main.rs b/examples/poseidon_bn254/script/src/main.rs new file mode 100644 index 0000000000..bc4fdc74fa --- /dev/null +++ b/examples/poseidon_bn254/script/src/main.rs @@ -0,0 +1,25 @@ +//! A simple script to generate and verify the proof of a given program. +// use sp1_core::{SP1Prover, SP1Stdin, SP1Verifier}; +use sp1_sdk::{utils, ProverClient, SP1Stdin}; + +const ELF: &[u8] = include_bytes!("../../program/elf/riscv32im-succinct-zkvm-elf"); + +fn main() { + utils::setup_tracer(); + + // Generate proof. + let mut stdin = SP1Stdin::new(); + + let client = ProverClient::new(); + let mut proof = client.prove(ELF, stdin).expect("proving failed"); + + // Verify proof. + client.verify(ELF, &proof).expect("verification failed"); + + // Save proof. + proof + .save("proof-with-io.json") + .expect("saving proof failed"); + + println!("successfully generated and verified proof for the program!") +} From e769fb464f139b84b8bf28a234eec8076048337e Mon Sep 17 00:00:00 2001 From: kunxian-xia Date: Thu, 16 May 2024 15:21:20 +0800 Subject: [PATCH 09/34] handle bn254 scalar add and mul separately --- core/src/runtime/syscall.rs | 27 +- core/src/stark/air.rs | 15 +- .../syscall/precompiles/bn254_scalar/add.rs | 208 +++++++++++ .../syscall/precompiles/bn254_scalar/mod.rs | 334 +++++------------- .../syscall/precompiles/bn254_scalar/mul.rs | 208 +++++++++++ .../elf/riscv32im-succinct-zkvm-elf | Bin 114700 -> 98036 bytes tests/bn254-scalar-arith/src/main.rs | 23 +- zkvm/entrypoint/src/syscalls/bn254.rs | 25 +- zkvm/entrypoint/src/syscalls/mod.rs | 6 +- zkvm/precompiles/src/lib.rs | 3 +- 10 files changed, 566 insertions(+), 283 deletions(-) create mode 100644 core/src/syscall/precompiles/bn254_scalar/add.rs create mode 100644 core/src/syscall/precompiles/bn254_scalar/mul.rs diff --git a/core/src/runtime/syscall.rs b/core/src/runtime/syscall.rs index b953d03599..59a0e527f3 100644 --- a/core/src/runtime/syscall.rs +++ b/core/src/runtime/syscall.rs @@ -5,7 +5,7 @@ use strum_macros::EnumIter; use crate::runtime::{Register, Runtime}; use crate::stark::Blake3CompressInnerChip; -use crate::syscall::precompiles::bn254_scalar::Bn254ScalarArithChip; +use crate::syscall::precompiles::bn254_scalar::{Bn254ScalarAddChip, Bn254ScalarMulChip}; use crate::syscall::precompiles::edwards::EdAddAssignChip; use crate::syscall::precompiles::edwards::EdDecompressChip; use crate::syscall::precompiles::keccak256::KeccakPermuteChip; @@ -104,8 +104,11 @@ pub enum SyscallCode { /// Executes the `BLS12381_DOUBLE` precompile. BLS12381_DOUBLE = 0x00_00_01_1F, - /// Executes the `BN254_SCALAR_ARITH` precompile. - BN254_SCALAR_ARITH = 0x00_00_01_20, + /// Executes the `BN254_SCALAR_Add` precompile. + BN254_SCALAR_ADD = 0x00_01_01_20, + + /// Execute the `BN254_SCALAR_MUL` precompile. + BN254_SCALAR_MUL = 0x00_01_01_21, } impl SyscallCode { @@ -136,7 +139,8 @@ impl SyscallCode { 0x00_00_00_F1 => SyscallCode::HINT_READ, 0x00_00_01_1D => SyscallCode::UINT256_MUL, 0x00_00_01_1C => SyscallCode::BLS12381_DECOMPRESS, - 0x00_00_01_20 => SyscallCode::BN254_SCALAR_ARITH, + 0x00_01_01_20 => SyscallCode::BN254_SCALAR_ADD, + 0x00_01_01_21 => SyscallCode::BN254_SCALAR_MUL, _ => panic!("invalid syscall number: {}", value), } } @@ -342,8 +346,12 @@ pub fn default_syscall_map() -> HashMap> { ); syscall_map.insert(SyscallCode::UINT256_MUL, Rc::new(Uint256MulChip::new())); syscall_map.insert( - SyscallCode::BN254_SCALAR_ARITH, - Rc::new(Bn254ScalarArithChip::new()), + SyscallCode::BN254_SCALAR_ADD, + Rc::new(Bn254ScalarAddChip::new()), + ); + syscall_map.insert( + SyscallCode::BN254_SCALAR_MUL, + Rc::new(Bn254ScalarMulChip::new()), ); syscall_map @@ -442,8 +450,11 @@ mod tests { SyscallCode::BLS12381_DECOMPRESS => { assert_eq!(code as u32, sp1_zkvm::syscalls::BLS12381_DECOMPRESS) } - SyscallCode::BN254_SCALAR_ARITH => { - assert_eq!(code as u32, sp1_zkvm::syscalls::BN254_SCALAR_ARITH) + SyscallCode::BN254_SCALAR_ADD => { + assert_eq!(code as u32, sp1_zkvm::syscalls::BN254_SCALAR_ADD) + } + SyscallCode::BN254_SCALAR_MUL => { + assert_eq!(code as u32, sp1_zkvm::syscalls::BN254_SCALAR_MUL) } } } diff --git a/core/src/stark/air.rs b/core/src/stark/air.rs index 9eae9b1820..a51b0cc58e 100644 --- a/core/src/stark/air.rs +++ b/core/src/stark/air.rs @@ -3,6 +3,7 @@ pub use crate::air::SP1AirBuilder; use crate::air::{MachineAir, SP1_PROOF_NUM_PV_ELTS}; use crate::memory::{MemoryChipType, MemoryProgramChip}; use crate::stark::Chip; +use crate::syscall::precompiles::bn254_scalar::Bn254ScalarMulChip; use crate::StarkGenericConfig; use p3_field::PrimeField32; pub use riscv_chips::*; @@ -21,7 +22,7 @@ pub(crate) mod riscv_chips { pub use crate::memory::MemoryChip; pub use crate::program::ProgramChip; pub use crate::syscall::precompiles::blake3::Blake3CompressInnerChip; - pub use crate::syscall::precompiles::bn254_scalar::Bn254ScalarArithChip; + pub use crate::syscall::precompiles::bn254_scalar::Bn254ScalarAddChip; pub use crate::syscall::precompiles::edwards::EdAddAssignChip; pub use crate::syscall::precompiles::edwards::EdDecompressChip; pub use crate::syscall::precompiles::keccak256::KeccakPermuteChip; @@ -100,8 +101,10 @@ pub enum RiscvAir { Bls12381Double(WeierstrassDoubleAssignChip>), /// A precompile for uint256 mul. Uint256Mul(Uint256MulChip), - /// A precompile for bn254 scalar field arithmetic. - Bn254ScalarArith(Bn254ScalarArithChip), + /// A precompile for bn254 scalar addition. + Bn254ScalarAdd(Bn254ScalarAddChip), + /// A precompile for bn254 scalar multiplication. + Bn254ScalarMul(Bn254ScalarMulChip), /// A precompile for decompressing a point on the BLS12-381 curve. Bls12381Decompress(WeierstrassDecompressChip>), } @@ -151,8 +154,10 @@ impl RiscvAir { chips.push(RiscvAir::Bls12381Double(bls12381_double)); let uint256_mul = Uint256MulChip::default(); chips.push(RiscvAir::Uint256Mul(uint256_mul)); - let bn254_scalar_arith = Bn254ScalarArithChip::new(); - chips.push(RiscvAir::Bn254ScalarArith(bn254_scalar_arith)); + let bn254_scalar_add = Bn254ScalarAddChip::new(); + chips.push(RiscvAir::Bn254ScalarAdd(bn254_scalar_add)); + let bn254_scalar_mul = Bn254ScalarMulChip::new(); + chips.push(RiscvAir::Bn254ScalarMul(bn254_scalar_mul)); let bls12381_decompress = WeierstrassDecompressChip::>::new(); chips.push(RiscvAir::Bls12381Decompress(bls12381_decompress)); let add = AddSubChip::default(); diff --git a/core/src/syscall/precompiles/bn254_scalar/add.rs b/core/src/syscall/precompiles/bn254_scalar/add.rs new file mode 100644 index 0000000000..abb4dc6ca6 --- /dev/null +++ b/core/src/syscall/precompiles/bn254_scalar/add.rs @@ -0,0 +1,208 @@ +use std::borrow::{Borrow, BorrowMut}; + +use num::BigUint; +use num::Zero; +use p3_air::{Air, AirBuilder, BaseAir}; +use p3_field::AbstractField; +use p3_field::{Field, PrimeField32}; +use p3_matrix::{dense::RowMajorMatrix, Matrix}; +use sp1_derive::AlignedBorrow; + +use crate::{ + air::MachineAir, + memory::{MemoryCols, MemoryReadCols, MemoryWriteCols}, + operations::field::field_op::{FieldOpCols, FieldOperation}, + runtime::{ExecutionRecord, Program, Syscall, SyscallCode}, + stark::SP1AirBuilder, + syscall::precompiles::bn254_scalar::Limbs, + utils::{ + ec::{ + field::{FieldParameters, NumLimbs}, + weierstrass::bn254::Bn254ScalarField, + }, + limbs_from_prev_access, pad_rows, + }, +}; + +use super::{create_bn254_scalar_arith_event, NUM_WORDS_PER_FE}; + +const NUM_COLS: usize = core::mem::size_of::>(); +const OP: FieldOperation = FieldOperation::Add; + +#[derive(Debug, Clone, AlignedBorrow)] +#[repr(C)] +pub struct Bn254ScalarAddCols { + is_real: T, + shard: T, + clk: T, + p_ptr: T, + q_ptr: T, + p_access: [MemoryWriteCols; NUM_WORDS_PER_FE], + q_access: [MemoryReadCols; NUM_WORDS_PER_FE], + eval: FieldOpCols, +} + +pub struct Bn254ScalarAddChip; + +impl Bn254ScalarAddChip { + pub fn new() -> Self { + Self + } +} + +impl Syscall for Bn254ScalarAddChip { + fn execute( + &self, + rt: &mut crate::runtime::SyscallContext, + arg1: u32, + arg2: u32, + ) -> Option { + let event = create_bn254_scalar_arith_event(rt, arg1, arg2, OP); + rt.record_mut().bn254_scalar_arith_events.push(event); + + None + } + + fn num_extra_cycles(&self) -> u32 { + 1 + } +} + +impl MachineAir for Bn254ScalarAddChip { + type Record = ExecutionRecord; + + type Program = Program; + + fn name(&self) -> String { + "Bn254ScalarAdd".to_string() + } + + fn generate_trace(&self, input: &Self::Record, output: &mut Self::Record) -> RowMajorMatrix { + let mut rows = vec![]; + let mut new_byte_lookup_events = vec![]; + + for event in input + .bn254_scalar_arith_events + .iter() + .filter(|e| e.op == OP) + { + let mut row = [F::zero(); NUM_COLS]; + let cols: &mut Bn254ScalarAddCols = row.as_mut_slice().borrow_mut(); + + let p = BigUint::from_bytes_le( + event + .p + .iter() + .flat_map(|p| p.to_le_bytes()) + .collect::>() + .as_slice(), + ); + let q = BigUint::from_bytes_le( + event + .q + .iter() + .flat_map(|q| q.to_le_bytes()) + .collect::>() + .as_slice(), + ); + + cols.is_real = F::one(); + cols.shard = F::from_canonical_u32(event.shard); + cols.clk = F::from_canonical_u32(event.clk); + cols.p_ptr = F::from_canonical_u32(event.p_ptr); + cols.q_ptr = F::from_canonical_u32(event.q_ptr); + + cols.eval.populate(&p, &q, OP); + + for i in 0..cols.p_access.len() { + cols.p_access[i].populate(event.p_memory_records[i], &mut new_byte_lookup_events); + } + for i in 0..cols.q_access.len() { + cols.q_access[i].populate(event.q_memory_records[i], &mut new_byte_lookup_events); + } + + rows.push(row); + } + output.add_byte_lookup_events(new_byte_lookup_events); + + pad_rows(&mut rows, || { + let mut row = [F::zero(); NUM_COLS]; + let cols: &mut Bn254ScalarAddCols = row.as_mut_slice().borrow_mut(); + + let zero = BigUint::zero(); + cols.eval.populate(&zero, &zero, OP); + + row + }); + + RowMajorMatrix::new(rows.into_iter().flatten().collect::>(), NUM_COLS) + } + + fn included(&self, shard: &Self::Record) -> bool { + shard + .bn254_scalar_arith_events + .iter() + .filter(|e| e.op == OP) + .count() + != 0 + } +} + +impl BaseAir for Bn254ScalarAddChip { + fn width(&self) -> usize { + NUM_COLS + } +} + +impl Air for Bn254ScalarAddChip +where + AB: SP1AirBuilder, + // AB::Expr: Copy, +{ + fn eval(&self, builder: &mut AB) { + let main = builder.main(); + let row = main.row_slice(0); + let row: &Bn254ScalarAddCols = (*row).borrow(); + + builder.assert_bool(row.is_real); + + let p: Limbs<::Var, ::Limbs> = + limbs_from_prev_access(&row.p_access); + let q: Limbs<::Var, ::Limbs> = + limbs_from_prev_access(&row.q_access); + + row.eval.eval(builder, &p, &q, OP); + + for i in 0..Bn254ScalarField::NB_LIMBS { + builder + .when(row.is_real) + .assert_eq(row.eval.result[i], row.p_access[i / 4].value()[i % 4]); + } + + builder.eval_memory_access_slice( + row.shard, + row.clk.into(), + row.q_ptr, + &row.q_access, + row.is_real, + ); + + builder.eval_memory_access_slice( + row.shard, + row.clk.into(), + row.p_ptr, + &row.p_access, + row.is_real, + ); + + let syscall_id = AB::F::from_canonical_u32(SyscallCode::BN254_SCALAR_ADD.syscall_id()); + builder.receive_syscall( + row.shard, + row.clk, + syscall_id, + row.p_ptr, + row.q_ptr, + row.is_real, + ); + } +} diff --git a/core/src/syscall/precompiles/bn254_scalar/mod.rs b/core/src/syscall/precompiles/bn254_scalar/mod.rs index 1e67379aa6..3c279378a3 100644 --- a/core/src/syscall/precompiles/bn254_scalar/mod.rs +++ b/core/src/syscall/precompiles/bn254_scalar/mod.rs @@ -1,38 +1,24 @@ -mod general_field_op; +mod add; +mod mul; +// mod general_field_op; -use num::Zero; -use std::borrow::{Borrow, BorrowMut}; +pub use add::Bn254ScalarAddChip; +pub use mul::Bn254ScalarMulChip; use crate::{ - air::MachineAir, - memory::{MemoryCols, MemoryReadCols, MemoryWriteCols}, operations::field::{field_op::FieldOperation, params::Limbs}, - runtime::{ - ExecutionRecord, MemoryReadRecord, MemoryWriteRecord, Program, Syscall, SyscallCode, - }, - stark::SP1AirBuilder, - utils::{ - ec::{ - field::{FieldParameters, NumLimbs, NumWords}, - weierstrass::bn254::Bn254ScalarField, - }, - limbs_from_prev_access, pad_rows, + runtime::{MemoryReadRecord, MemoryWriteRecord, SyscallContext}, + utils::ec::{ + field::{FieldParameters, NumWords}, + weierstrass::bn254::Bn254ScalarField, }, }; use num::BigUint; -use p3_air::{Air, AirBuilder, BaseAir}; -use p3_field::{AbstractField, Field, PrimeField32}; -use p3_matrix::dense::RowMajorMatrix; -use p3_matrix::Matrix; -use sp1_derive::AlignedBorrow; use typenum::Unsigned; use serde::{Deserialize, Serialize}; -use self::general_field_op::GeneralFieldOpCols; - -const NUM_WORDS_PER_FE: usize = 8; -const NUM_COLS: usize = core::mem::size_of::>(); +pub(crate) const NUM_WORDS_PER_FE: usize = 8; #[derive(Clone, Debug, Serialize, Deserialize)] pub struct FieldArithEvent { @@ -41,238 +27,77 @@ pub struct FieldArithEvent { pub op: FieldOperation, pub p: Vec, pub q: Vec, - pub pq_ptr: u32, + pub p_ptr: u32, + pub q_ptr: u32, pub p_memory_records: Vec, pub q_memory_records: Vec, } -#[derive(Debug, Clone, AlignedBorrow)] -#[repr(C)] -pub struct Bn254ScalarArithAssignCols { - is_real: T, - shard: T, - clk: T, - op: T, - pq_ptr: T, - p_access: [MemoryWriteCols; NUM_WORDS_PER_FE], - q_access: [MemoryReadCols; NUM_WORDS_PER_FE], - eval: GeneralFieldOpCols, -} - -pub struct Bn254ScalarArithChip; - -impl Bn254ScalarArithChip { - pub fn new() -> Self { - Self - } -} - -impl Syscall for Bn254ScalarArithChip { - fn execute( - &self, - rt: &mut crate::runtime::SyscallContext, - arg1: u32, - arg2: u32, - ) -> Option { - // layout of input to this syscall - // | p (8 words) | q (8 words) | type (1 word) | - let start_clk = rt.clk; - - let pq_ptr = arg1; - if pq_ptr % 4 != 0 { - panic!(); - } - let op = arg2; - - let nw_per_fe = ::WordsFieldElement::USIZE; - debug_assert_eq!(nw_per_fe, NUM_WORDS_PER_FE); - - let p: Vec = rt.slice_unsafe(pq_ptr, nw_per_fe); - - let (q_memory_records, q) = rt.mr_slice(pq_ptr + 4 * (nw_per_fe as u32), nw_per_fe); - - let bn_p = BigUint::from_bytes_le( - &p.iter() - .cloned() - .flat_map(|word| word.to_le_bytes()) - .collect::>(), - ); - let bn_q = BigUint::from_bytes_le( - &q.iter() - .cloned() - .flat_map(|word| word.to_le_bytes()) - .collect::>(), - ); - - let modulus = Bn254ScalarField::modulus(); - let (r, op) = match op { - 0x00 => ((&bn_p + &bn_q) % modulus, FieldOperation::Add), - 0x01 => ((&bn_p - &bn_q) % modulus, FieldOperation::Sub), - 0x02 => ((&bn_p * &bn_q) % modulus, FieldOperation::Mul), - // TODO: how to handle q == 0? - 0x03 => ((&bn_p / &bn_q) % modulus, FieldOperation::Div), - _ => unreachable!("type {} not supported", op), - }; - log::trace!( - "shard: {}, clk: {}, bn_p: {:?}, bn_q: {:?}, r: {:?}", - rt.current_shard(), - rt.clk, - bn_p, - bn_q, - r - ); - - let mut result_words = r.to_u32_digits(); - result_words.resize(nw_per_fe, 0); - - let p_memory_records = rt.mw_slice(pq_ptr, &result_words); - - let shard = rt.current_shard(); - rt.record_mut() - .bn254_scalar_arith_events - .push(FieldArithEvent { - shard, - clk: start_clk, - op, - p, - q, - pq_ptr, - p_memory_records, - q_memory_records, - }); - - None - } -} - -impl MachineAir for Bn254ScalarArithChip { - type Record = ExecutionRecord; - - type Program = Program; - - fn name(&self) -> String { - "Bn254ScalarArith".to_string() - } - - fn generate_trace(&self, input: &Self::Record, output: &mut Self::Record) -> RowMajorMatrix { - let mut rows = vec![]; - let mut new_byte_lookup_events = vec![]; - - for event in input.bn254_scalar_arith_events.iter() { - let mut row = [F::zero(); NUM_COLS]; - let cols: &mut Bn254ScalarArithAssignCols = row.as_mut_slice().borrow_mut(); - - let p = BigUint::from_bytes_le( - event - .p - .iter() - .flat_map(|p| p.to_le_bytes()) - .collect::>() - .as_slice(), - ); - let q = BigUint::from_bytes_le( - event - .q - .iter() - .flat_map(|q| q.to_le_bytes()) - .collect::>() - .as_slice(), - ); - - cols.is_real = F::one(); - cols.shard = F::from_canonical_u32(event.shard); - cols.clk = F::from_canonical_u32(event.clk); - cols.pq_ptr = F::from_canonical_u32(event.pq_ptr); - cols.op = F::from_canonical_u32(event.op as u32); - - cols.eval.populate(&p, &q, event.op); - - for i in 0..cols.p_access.len() { - cols.p_access[i].populate(event.p_memory_records[i], &mut new_byte_lookup_events); - } - for i in 0..cols.q_access.len() { - cols.q_access[i].populate(event.q_memory_records[i], &mut new_byte_lookup_events); - } - - rows.push(row); - } - output.add_byte_lookup_events(new_byte_lookup_events); - - pad_rows(&mut rows, || { - let mut row = [F::zero(); NUM_COLS]; - let cols: &mut Bn254ScalarArithAssignCols = row.as_mut_slice().borrow_mut(); - - let zero = BigUint::zero(); - let op = FieldOperation::Add; - cols.eval.populate(&zero, &zero, op); - - row - }); - - RowMajorMatrix::new(rows.into_iter().flatten().collect::>(), NUM_COLS) - } - - fn included(&self, shard: &Self::Record) -> bool { - !shard.bn254_scalar_arith_events.is_empty() - } -} - -impl BaseAir for Bn254ScalarArithChip { - fn width(&self) -> usize { - NUM_COLS - } -} - -impl Air for Bn254ScalarArithChip -where - AB: SP1AirBuilder, - // AB::Expr: Copy, -{ - fn eval(&self, builder: &mut AB) { - let main = builder.main(); - let row = main.row_slice(0); - let row: &Bn254ScalarArithAssignCols = (*row).borrow(); - - builder.assert_bool(row.is_real); - - let p: Limbs<::Var, ::Limbs> = - limbs_from_prev_access(&row.p_access); - let q: Limbs<::Var, ::Limbs> = - limbs_from_prev_access(&row.q_access); - - row.eval.eval(builder, &p, &q, row.op); - - for i in 0..Bn254ScalarField::NB_LIMBS { - builder - .when(row.is_real) - .assert_eq(row.eval.cols.result[i], row.p_access[i / 4].value()[i % 4]); - } - - builder.eval_memory_access_slice( - row.shard, - row.clk.into(), - row.pq_ptr + AB::F::from_canonical_u32(4 * NUM_WORDS_PER_FE as u32), - &row.q_access, - row.is_real, - ); - - builder.eval_memory_access_slice( - row.shard, - row.clk.into(), - row.pq_ptr, - &row.p_access, - row.is_real, - ); - - let syscall_id = AB::F::from_canonical_u32(SyscallCode::BN254_SCALAR_ARITH.syscall_id()); - builder.receive_syscall( - row.shard, - row.clk, - syscall_id, - row.pq_ptr, - row.op, - row.is_real, - ); +pub fn create_bn254_scalar_arith_event( + rt: &mut SyscallContext, + arg1: u32, + arg2: u32, + op: FieldOperation, +) -> FieldArithEvent { + let start_clk = rt.clk; + let p_ptr = arg1; + let q_ptr = arg2; + + assert_eq!(p_ptr % 4, 0, "p_ptr({:x}) is not aligned", p_ptr); + assert_eq!(q_ptr % 4, 0, "q_ptr({:x}) is not aligned", q_ptr); + + let nw_per_fe = ::WordsFieldElement::USIZE; + debug_assert_eq!(nw_per_fe, NUM_WORDS_PER_FE); + + let p: Vec = rt.slice_unsafe(p_ptr, nw_per_fe); + let (q_memory_records, q) = rt.mr_slice(q_ptr, nw_per_fe); + + let bn_p = BigUint::from_bytes_le( + &p.iter() + .cloned() + .flat_map(|word| word.to_le_bytes()) + .collect::>(), + ); + let bn_q = BigUint::from_bytes_le( + &q.iter() + .cloned() + .flat_map(|word| word.to_le_bytes()) + .collect::>(), + ); + + let modulus = Bn254ScalarField::modulus(); + + let r = match op { + FieldOperation::Add => (&bn_p + &bn_q) % modulus, + FieldOperation::Mul => (&bn_p * &bn_q) % modulus, + _ => unimplemented!("not supported"), + }; + log::trace!( + "shard: {}, clk: {}, op: {:?}, bn_p: {:?}, bn_q: {:?}, r: {:?}", + rt.current_shard(), + rt.clk, + op, + bn_p, + bn_q, + r + ); + + let mut result_words = r.to_u32_digits(); + result_words.resize(nw_per_fe, 0); + + let p_memory_records = rt.mw_slice(p_ptr, &result_words); + + let shard = rt.current_shard(); + FieldArithEvent { + shard, + clk: start_clk, + op, + p, + q, + p_ptr, + q_ptr, + p_memory_records, + q_memory_records, } } @@ -280,6 +105,7 @@ where mod tests { use crate::{ runtime::Program, + runtime::Runtime, utils::{run_test, setup_logger, tests::BN254_SCALAR_ARITH_ELF}, }; @@ -287,6 +113,8 @@ mod tests { fn test_bn254_scalar_arith_simple() { setup_logger(); let program = Program::from(BN254_SCALAR_ARITH_ELF); - run_test(program).unwrap(); + let mut rt = Runtime::new(program); + rt.run(); + // run_test(program).unwrap(); } } diff --git a/core/src/syscall/precompiles/bn254_scalar/mul.rs b/core/src/syscall/precompiles/bn254_scalar/mul.rs new file mode 100644 index 0000000000..8cb1da2651 --- /dev/null +++ b/core/src/syscall/precompiles/bn254_scalar/mul.rs @@ -0,0 +1,208 @@ +use std::borrow::{Borrow, BorrowMut}; + +use num::BigUint; +use num::Zero; +use p3_air::{Air, AirBuilder, BaseAir}; +use p3_field::AbstractField; +use p3_field::{Field, PrimeField32}; +use p3_matrix::{dense::RowMajorMatrix, Matrix}; +use sp1_derive::AlignedBorrow; + +use crate::{ + air::MachineAir, + memory::{MemoryCols, MemoryReadCols, MemoryWriteCols}, + operations::field::field_op::{FieldOpCols, FieldOperation}, + runtime::{ExecutionRecord, Program, Syscall, SyscallCode}, + stark::SP1AirBuilder, + syscall::precompiles::bn254_scalar::Limbs, + utils::{ + ec::{ + field::{FieldParameters, NumLimbs}, + weierstrass::bn254::Bn254ScalarField, + }, + limbs_from_prev_access, pad_rows, + }, +}; + +use super::{create_bn254_scalar_arith_event, NUM_WORDS_PER_FE}; + +const NUM_COLS: usize = core::mem::size_of::>(); +const OP: FieldOperation = FieldOperation::Mul; + +#[derive(Debug, Clone, AlignedBorrow)] +#[repr(C)] +pub struct Bn254ScalarMulCols { + is_real: T, + shard: T, + clk: T, + p_ptr: T, + q_ptr: T, + p_access: [MemoryWriteCols; NUM_WORDS_PER_FE], + q_access: [MemoryReadCols; NUM_WORDS_PER_FE], + eval: FieldOpCols, +} + +pub struct Bn254ScalarMulChip; + +impl Bn254ScalarMulChip { + pub fn new() -> Self { + Self + } +} + +impl Syscall for Bn254ScalarMulChip { + fn execute( + &self, + rt: &mut crate::runtime::SyscallContext, + arg1: u32, + arg2: u32, + ) -> Option { + let event = create_bn254_scalar_arith_event(rt, arg1, arg2, OP); + rt.record_mut().bn254_scalar_arith_events.push(event); + + None + } + + fn num_extra_cycles(&self) -> u32 { + 1 + } +} + +impl MachineAir for Bn254ScalarMulChip { + type Record = ExecutionRecord; + + type Program = Program; + + fn name(&self) -> String { + "Bn254ScalarMul".to_string() + } + + fn generate_trace(&self, input: &Self::Record, output: &mut Self::Record) -> RowMajorMatrix { + let mut rows = vec![]; + let mut new_byte_lookup_events = vec![]; + + for event in input + .bn254_scalar_arith_events + .iter() + .filter(|e| e.op == OP) + { + let mut row = [F::zero(); NUM_COLS]; + let cols: &mut Bn254ScalarMulCols = row.as_mut_slice().borrow_mut(); + + let p = BigUint::from_bytes_le( + event + .p + .iter() + .flat_map(|p| p.to_le_bytes()) + .collect::>() + .as_slice(), + ); + let q = BigUint::from_bytes_le( + event + .q + .iter() + .flat_map(|q| q.to_le_bytes()) + .collect::>() + .as_slice(), + ); + + cols.is_real = F::one(); + cols.shard = F::from_canonical_u32(event.shard); + cols.clk = F::from_canonical_u32(event.clk); + cols.p_ptr = F::from_canonical_u32(event.p_ptr); + cols.q_ptr = F::from_canonical_u32(event.q_ptr); + + cols.eval.populate(&p, &q, OP); + + for i in 0..cols.p_access.len() { + cols.p_access[i].populate(event.p_memory_records[i], &mut new_byte_lookup_events); + } + for i in 0..cols.q_access.len() { + cols.q_access[i].populate(event.q_memory_records[i], &mut new_byte_lookup_events); + } + + rows.push(row); + } + output.add_byte_lookup_events(new_byte_lookup_events); + + pad_rows(&mut rows, || { + let mut row = [F::zero(); NUM_COLS]; + let cols: &mut Bn254ScalarMulCols = row.as_mut_slice().borrow_mut(); + + let zero = BigUint::zero(); + cols.eval.populate(&zero, &zero, OP); + + row + }); + + RowMajorMatrix::new(rows.into_iter().flatten().collect::>(), NUM_COLS) + } + + fn included(&self, shard: &Self::Record) -> bool { + shard + .bn254_scalar_arith_events + .iter() + .filter(|e| e.op == OP) + .count() + != 0 + } +} + +impl BaseAir for Bn254ScalarMulChip { + fn width(&self) -> usize { + NUM_COLS + } +} + +impl Air for Bn254ScalarMulChip +where + AB: SP1AirBuilder, + // AB::Expr: Copy, +{ + fn eval(&self, builder: &mut AB) { + let main = builder.main(); + let row = main.row_slice(0); + let row: &Bn254ScalarMulCols = (*row).borrow(); + + builder.assert_bool(row.is_real); + + let p: Limbs<::Var, ::Limbs> = + limbs_from_prev_access(&row.p_access); + let q: Limbs<::Var, ::Limbs> = + limbs_from_prev_access(&row.q_access); + + row.eval.eval(builder, &p, &q, OP); + + for i in 0..Bn254ScalarField::NB_LIMBS { + builder + .when(row.is_real) + .assert_eq(row.eval.result[i], row.p_access[i / 4].value()[i % 4]); + } + + builder.eval_memory_access_slice( + row.shard, + row.clk.into(), + row.q_ptr, + &row.q_access, + row.is_real, + ); + + builder.eval_memory_access_slice( + row.shard, + row.clk.into(), + row.p_ptr, + &row.p_access, + row.is_real, + ); + + let syscall_id = AB::F::from_canonical_u32(SyscallCode::BN254_SCALAR_MUL.syscall_id()); + builder.receive_syscall( + row.shard, + row.clk, + syscall_id, + row.p_ptr, + row.q_ptr, + row.is_real, + ); + } +} diff --git a/tests/bn254-scalar-arith/elf/riscv32im-succinct-zkvm-elf b/tests/bn254-scalar-arith/elf/riscv32im-succinct-zkvm-elf index 681964662373ec207a7c7864d533738d2be5b5c0..b97a2360493a2070b298275cbf97143a5714b0f0 100755 GIT binary patch delta 26749 zcmbt-4OmrG*8e_-d+xm=B6?8)zYbnhL?uKNHFK^BlQm{kR!*6rh+>0^ie+WpYjDld z9CTaPN()2N94kx>n{n!@;71>ZrD;Wl>6BAe+E}k|+3^3Zz0ZNe5t@0Q|9+n9KEJir zUVE*z*Zw#k)bfDq!mnCcT;%HRI?G^;#Xh*Q*VOC_I~k*&1`3N|OriP>{0{5l=kCE6 z{TxI$`0hH;F6rWzOyre^u2A2p+xBx$mw!8BGuW7?x^SvX{v_*&1s+BDw>Px|^A1?d zyeTVLNs`7q+F}+eXY8v$V3ap`CCfafGmk^7Cpy;@#p86aP^I9Ll^i7^aL-oBIoi-(?Z$-{`2Jvr&7x)tK zZ-o~=&C}YN_MbxhTaojfMEqOf1wKdoTj7O2<>hTVT`AMEj+b75+{zYG+V`=T8bU67 zzC_=nL?kU%N|Ht^d{I<)KTQ*-c2Z0icg+`^ri*hA^f2aeIgKe5o;g2;g*}RL5!24; z(Q+JKm8MTvtw7DSb8Wp5+gL?}f;PI_>o^ITuT6zx8|rXduSRucWQC|}BfL&v*EzMq zd7k;XmZo`KBv9|DK<#k`+IZc2NP)Y;4Z718X>%kNW!&Bg{Z@BZ(D(* zD@0xI@66YBFdvHoKsNeMtEI*y70BHa8Vs@=XF!9s}-WI)x2#8v*-%c-pCtO zu9j;Rq7J}o!fEjOM%5doM0nh}X(D%5S@6-9a@AmgreVvIG9yUgKrP<<}40<~9L@9=0b z7~k~{uX7Ksb*;ilG@s⁢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 IVHTnP2a^NX&j0`b delta 39801 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 gXSg-|Z9ZT0i$=&rvLx| diff --git a/tests/bn254-scalar-arith/src/main.rs b/tests/bn254-scalar-arith/src/main.rs index 09c77394fb..bbda639665 100644 --- a/tests/bn254-scalar-arith/src/main.rs +++ b/tests/bn254-scalar-arith/src/main.rs @@ -2,29 +2,30 @@ sp1_zkvm::entrypoint!(main); extern "C" { - fn syscall_bn254_scalar_arith(pq: *mut u32, op: u32); + fn syscall_bn254_scalar_add(p: *mut u32, q: *const u32); + fn syscall_bn254_scalar_mul(p: *mut u32, q: *const u32); } fn main() { - let mut pq: [u8; 64] = [ + let mut p: [u8; 32] = [ 69, 44, 191, 0, 130, 148, 188, 171, 61, 47, 83, 78, 152, 132, 196, 72, 209, 29, 140, 237, - 126, 75, 223, 58, 115, 139, 235, 236, 200, 47, 2, 28, 169, 1, 76, 216, 163, 152, 124, 133, - 147, 234, 54, 244, 220, 34, 93, 224, 147, 90, 136, 227, 1, 70, 214, 130, 142, 119, 53, 203, - 16, 160, 133, 43, + 126, 75, 223, 58, 115, 139, 235, 236, 200, 47, 2, 28, + ]; + let q: [u8; 32] = [ + 169, 1, 76, 216, 163, 152, 124, 133, 147, 234, 54, 244, 220, 34, 93, 224, 147, 90, 136, + 227, 1, 70, 214, 130, 142, 119, 53, 203, 16, 160, 133, 43, ]; - // multiplication - let op = 2u32; let c: [u8; 32] = [ 43, 132, 167, 109, 73, 175, 44, 161, 152, 82, 20, 126, 173, 132, 9, 50, 112, 242, 217, 141, 87, 50, 0, 64, 74, 105, 9, 124, 167, 37, 39, 37, ]; - println!("cycle-tracker-start: bn254_scalar_arith"); + // println!("cycle-tracker-start: bn254_scalar_mul"); unsafe { - syscall_bn254_scalar_arith(pq.as_mut_ptr() as *mut u32, op); + syscall_bn254_scalar_mul(p.as_mut_ptr() as *mut u32, q.as_ptr() as *const u32); } - println!("cycle-tracker-end: bn254_scalar_arith"); + // println!("cycle-tracker-end: bn254_scalar_mul"); - assert_eq!(&pq[0..32], &c); + assert_eq!(p, c); } diff --git a/zkvm/entrypoint/src/syscalls/bn254.rs b/zkvm/entrypoint/src/syscalls/bn254.rs index 618fd5aa15..27de19f02b 100644 --- a/zkvm/entrypoint/src/syscalls/bn254.rs +++ b/zkvm/entrypoint/src/syscalls/bn254.rs @@ -43,14 +43,31 @@ pub extern "C" fn syscall_bn254_double(p: *mut u32) { #[allow(unused_variables)] #[no_mangle] -pub extern "C" fn syscall_bn254_scalar_arith(pq: *mut u32, op: u32) { +pub extern "C" fn syscall_bn254_scalar_add(p: *mut u32, q: *const u32) { #[cfg(target_os = "zkvm")] unsafe { asm!( "ecall", - in("t0") crate::syscalls::BN254_SCALAR_ARITH, - in("a0") pq, - in("a1") op, + in("t0") crate::syscalls::BN254_SCALAR_ADD, + in("a0") p, + in("a1") q, + ); + } + + #[cfg(not(target_os = "zkvm"))] + unreachable!() +} + +#[allow(unused_variables)] +#[no_mangle] +pub extern "C" fn syscall_bn254_scalar_mul(p: *mut u32, q: *const u32) { + #[cfg(target_os = "zkvm")] + unsafe { + asm!( + "ecall", + in("t0") crate::syscalls::BN254_SCALAR_MUL, + in("a0") p, + in("a1") q, ); } diff --git a/zkvm/entrypoint/src/syscalls/mod.rs b/zkvm/entrypoint/src/syscalls/mod.rs index 9225c73144..0d62694d48 100644 --- a/zkvm/entrypoint/src/syscalls/mod.rs +++ b/zkvm/entrypoint/src/syscalls/mod.rs @@ -104,4 +104,8 @@ pub const BLS12381_ADD: u32 = 0x00_01_01_1E; /// Executes the `BLS12381_DOUBLE` precompile. pub const BLS12381_DOUBLE: u32 = 0x00_00_01_1F; -pub const BN254_SCALAR_ARITH: u32 = 0x00_00_01_20; +/// Executes the `BN254_SCALAR_ADD` precompile +pub const BN254_SCALAR_ADD: u32 = 0x00_01_01_20; + +/// Executes the `BN254_SCALAR_MUL` precompile +pub const BN254_SCALAR_MUL: u32 = 0x00_01_01_21; diff --git a/zkvm/precompiles/src/lib.rs b/zkvm/precompiles/src/lib.rs index 60296b989b..a176e5066f 100644 --- a/zkvm/precompiles/src/lib.rs +++ b/zkvm/precompiles/src/lib.rs @@ -33,5 +33,6 @@ extern "C" { pub fn syscall_hint_read(ptr: *mut u8, len: usize); pub fn sys_alloc_aligned(bytes: usize, align: usize) -> *mut u8; pub fn syscall_bls12381_decompress(point: &mut [u8; 96], is_odd: bool); - pub fn syscall_bn254_scalar_arith(pq: *mut u32, op: u32); + pub fn syscall_bn254_scalar_add(p: *mut u32, q: *const u32); + pub fn syscall_bn254_scalar_mul(p: *mut u32, q: *const u32); } From 89e1ec8a4370b598c16dc99f2acf8d7686c82f11 Mon Sep 17 00:00:00 2001 From: kunxian-xia Date: Thu, 16 May 2024 17:18:11 +0800 Subject: [PATCH 10/34] chore: update poseidon-base dep --- examples/poseidon_bn254/program/Cargo.lock | 4 ++-- .../program/elf/riscv32im-succinct-zkvm-elf | Bin 192100 -> 189468 bytes examples/poseidon_bn254/script/src/main.rs | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/examples/poseidon_bn254/program/Cargo.lock b/examples/poseidon_bn254/program/Cargo.lock index e968ccb59d..10450238f7 100644 --- a/examples/poseidon_bn254/program/Cargo.lock +++ b/examples/poseidon_bn254/program/Cargo.lock @@ -272,7 +272,7 @@ dependencies = [ [[package]] name = "halo2curves" version = "0.3.3" -source = "git+https://github.com/kunxian-xia/halo2curves.git?branch=feat/sp1#bdcf288396c9bd8eb76d81f25b98615abe3afb20" +source = "git+https://github.com/kunxian-xia/halo2curves.git?branch=feat/sp1#9e05f40e6a19c125e831deaa59a9631b7ca048fb" dependencies = [ "ff", "group", @@ -635,7 +635,7 @@ dependencies = [ [[package]] name = "poseidon-base" version = "0.1.0" -source = "git+https://github.com/scroll-tech/poseidon-circuit.git?branch=feat/sp1#ab45385dcbce698010b88395861e89a7726a57a3" +source = "git+https://github.com/scroll-tech/poseidon-circuit.git?branch=feat/sp1#77bd4482555a16b58e04055ec61976262ad3c3e2" dependencies = [ "bitvec", "halo2curves", diff --git a/examples/poseidon_bn254/program/elf/riscv32im-succinct-zkvm-elf b/examples/poseidon_bn254/program/elf/riscv32im-succinct-zkvm-elf index fbad0899ffb23805bec35e060db97a55c406501f..96b0c28c1641894bbe34b7c3848324313be74b8c 100755 GIT binary patch delta 56145 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 delta 57860 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 diff --git a/examples/poseidon_bn254/script/src/main.rs b/examples/poseidon_bn254/script/src/main.rs index bc4fdc74fa..9695b48e88 100644 --- a/examples/poseidon_bn254/script/src/main.rs +++ b/examples/poseidon_bn254/script/src/main.rs @@ -5,7 +5,7 @@ use sp1_sdk::{utils, ProverClient, SP1Stdin}; const ELF: &[u8] = include_bytes!("../../program/elf/riscv32im-succinct-zkvm-elf"); fn main() { - utils::setup_tracer(); + utils::setup_logger(); // Generate proof. let mut stdin = SP1Stdin::new(); From eb0fdddd25499c6ec70ce93a1129fc54a64fd948 Mon Sep 17 00:00:00 2001 From: kunxian-xia Date: Fri, 17 May 2024 14:15:18 +0800 Subject: [PATCH 11/34] reduce total cycles from 2M to 1.4M --- examples/poseidon_bn254/program/Cargo.lock | 4 ++-- .../program/elf/riscv32im-succinct-zkvm-elf | Bin 189468 -> 173448 bytes 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/poseidon_bn254/program/Cargo.lock b/examples/poseidon_bn254/program/Cargo.lock index 10450238f7..d258341fcf 100644 --- a/examples/poseidon_bn254/program/Cargo.lock +++ b/examples/poseidon_bn254/program/Cargo.lock @@ -272,7 +272,7 @@ dependencies = [ [[package]] name = "halo2curves" version = "0.3.3" -source = "git+https://github.com/kunxian-xia/halo2curves.git?branch=feat/sp1#9e05f40e6a19c125e831deaa59a9631b7ca048fb" +source = "git+https://github.com/kunxian-xia/halo2curves.git?branch=feat/sp1#1b714c346fa61a9c433d06340d9a410b03fbc8c9" dependencies = [ "ff", "group", @@ -635,7 +635,7 @@ dependencies = [ [[package]] name = "poseidon-base" version = "0.1.0" -source = "git+https://github.com/scroll-tech/poseidon-circuit.git?branch=feat/sp1#77bd4482555a16b58e04055ec61976262ad3c3e2" +source = "git+https://github.com/scroll-tech/poseidon-circuit.git?branch=feat/sp1#fce99ee35181bdb5e43467637e40b11a4bb43e85" dependencies = [ "bitvec", "halo2curves", diff --git a/examples/poseidon_bn254/program/elf/riscv32im-succinct-zkvm-elf b/examples/poseidon_bn254/program/elf/riscv32im-succinct-zkvm-elf index 96b0c28c1641894bbe34b7c3848324313be74b8c..9ba4376733b66a582e40cf8707172de5c95ad527 100755 GIT binary patch delta 62666 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 delta 79166 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

|R6@{Bx29`74L3Pry5134tjY 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 Date: Tue, 21 May 2024 11:02:25 +0800 Subject: [PATCH 12/34] reduce total cycles from 1.4M to 1M --- examples/poseidon_bn254/program/Cargo.lock | 4 ++-- .../program/elf/riscv32im-succinct-zkvm-elf | Bin 173448 -> 171972 bytes 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/poseidon_bn254/program/Cargo.lock b/examples/poseidon_bn254/program/Cargo.lock index d258341fcf..be78ab24d1 100644 --- a/examples/poseidon_bn254/program/Cargo.lock +++ b/examples/poseidon_bn254/program/Cargo.lock @@ -272,7 +272,7 @@ dependencies = [ [[package]] name = "halo2curves" version = "0.3.3" -source = "git+https://github.com/kunxian-xia/halo2curves.git?branch=feat/sp1#1b714c346fa61a9c433d06340d9a410b03fbc8c9" +source = "git+https://github.com/kunxian-xia/halo2curves.git?branch=feat/sp1#da9ff1b096e7067659d6c7f8c1f0cb78cf6d13f3" dependencies = [ "ff", "group", @@ -635,7 +635,7 @@ dependencies = [ [[package]] name = "poseidon-base" version = "0.1.0" -source = "git+https://github.com/scroll-tech/poseidon-circuit.git?branch=feat/sp1#fce99ee35181bdb5e43467637e40b11a4bb43e85" +source = "git+https://github.com/scroll-tech/poseidon-circuit.git?branch=feat/sp1#23620d9cbe2584686e0f6ac8a9be65db2382761f" dependencies = [ "bitvec", "halo2curves", diff --git a/examples/poseidon_bn254/program/elf/riscv32im-succinct-zkvm-elf b/examples/poseidon_bn254/program/elf/riscv32im-succinct-zkvm-elf index 9ba4376733b66a582e40cf8707172de5c95ad527..491201918ba0d54162174b13f327868dcc261034 100755 GIT binary patch delta 26741 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

jH_LT*!re%+g&QcAw= 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 Date: Tue, 21 May 2024 11:11:37 +0800 Subject: [PATCH 13/34] add log in runtime execution --- core/src/runtime/mod.rs | 30 ++++++++++++++++++++++++++++++ core/src/runtime/utils.rs | 7 +++++++ 2 files changed, 37 insertions(+) diff --git a/core/src/runtime/mod.rs b/core/src/runtime/mod.rs index e1c8b21fc8..be379e6235 100644 --- a/core/src/runtime/mod.rs +++ b/core/src/runtime/mod.rs @@ -574,6 +574,10 @@ impl Runtime { let value = (memory_read_value).to_le_bytes()[(addr % 4) as usize]; a = ((value as i8) as i32) as u32; memory_store_value = Some(memory_read_value); + println!( + "[clk: {}, pc: 0x{:x}] LB: {:?} <- {:x}", + self.state.global_clk, self.state.pc, rd, a + ); self.rw(rd, a); } Opcode::LH => { @@ -586,6 +590,10 @@ impl Runtime { }; a = ((value as i16) as i32) as u32; memory_store_value = Some(memory_read_value); + println!( + "[clk: {}, pc: 0x{:x}] LH: {:?} <- {:x}", + self.state.global_clk, self.state.pc, rd, a + ); self.rw(rd, a); } Opcode::LW => { @@ -593,6 +601,10 @@ impl Runtime { assert_eq!(addr % 4, 0, "addr is not aligned"); a = memory_read_value; memory_store_value = Some(memory_read_value); + println!( + "[clk: {}, pc: 0x{:x}] LW: {:?} <- {}", + self.state.global_clk, self.state.pc, rd, a + ); self.rw(rd, a); } Opcode::LBU => { @@ -626,6 +638,10 @@ impl Runtime { _ => unreachable!(), }; memory_store_value = Some(value); + println!( + "[clk: {}, pc: 0x{:x}] SB 0x{:x} <- 0x{:x}", + self.state.global_clk, pc, addr, value + ); self.mw_cpu(align(addr), value, MemoryAccessPosition::Memory); } Opcode::SH => { @@ -637,6 +653,10 @@ impl Runtime { _ => unreachable!(), }; memory_store_value = Some(value); + println!( + "[clk: {}, pc: 0x{:x}] SH 0x{:x} <- 0x{:x}", + self.state.global_clk, pc, addr, value + ); self.mw_cpu(align(addr), value, MemoryAccessPosition::Memory); } Opcode::SW => { @@ -644,6 +664,10 @@ impl Runtime { assert_eq!(addr % 4, 0, "addr is not aligned"); let value = a; memory_store_value = Some(value); + println!( + "[clk: {}, pc: 0x{:x}] SW 0x{:x} <- 0x{:x}", + self.state.global_clk, pc, addr, value + ); self.mw_cpu(align(addr), value, MemoryAccessPosition::Memory); } @@ -719,9 +743,15 @@ impl Runtime { b = self.rr(Register::X10, MemoryAccessPosition::B); let syscall = SyscallCode::from_u32(syscall_id); + let global_clk = self.state.global_clk; + let syscall_impl = self.get_syscall(syscall).cloned(); let mut precompile_rt = SyscallContext::new(self); + println!( + "[clk: {}, pc: 0x{:x}] ecall syscall_id=0x{:x}, b: 0x{:x}, c: 0x{:x}", + global_clk, pc, syscall_id, b, c, + ); let (precompile_next_pc, precompile_cycles, returned_exit_code) = if let Some(syscall_impl) = syscall_impl { // Executing a syscall optionally returns a value to write to the t0 register. diff --git a/core/src/runtime/utils.rs b/core/src/runtime/utils.rs index 6f4feab738..3ed4c222b3 100644 --- a/core/src/runtime/utils.rs +++ b/core/src/runtime/utils.rs @@ -68,6 +68,13 @@ impl Runtime { self.register(Register::X18), ); + log::trace!( + "[clk: {}, pc: 0x{:x}] {:?}", + self.state.global_clk, + self.state.pc, + instruction, + ); + if !self.unconstrained && self.state.global_clk % 10_000_000 == 0 { log::info!( "clk = {} pc = 0x{:x?}", From a293b1b9e75afdfca9fc0dda8b7ae09a102ef0de Mon Sep 17 00:00:00 2001 From: lightsing Date: Tue, 21 May 2024 16:27:09 +0800 Subject: [PATCH 14/34] add mac --- core/src/runtime/syscall.rs | 10 ++- .../syscall/precompiles/bn254_scalar/mac.rs | 71 ++++++++++++++++++ .../syscall/precompiles/bn254_scalar/mod.rs | 2 + examples/poseidon_bn254/program/Cargo.lock | 7 +- examples/poseidon_bn254/program/Cargo.toml | 12 ++- .../program/elf/riscv32im-succinct-zkvm-elf | Bin 171972 -> 0 bytes zkvm/entrypoint/src/syscalls/bn254.rs | 20 +++++ zkvm/entrypoint/src/syscalls/mod.rs | 3 + 8 files changed, 119 insertions(+), 6 deletions(-) create mode 100644 core/src/syscall/precompiles/bn254_scalar/mac.rs delete mode 100755 examples/poseidon_bn254/program/elf/riscv32im-succinct-zkvm-elf diff --git a/core/src/runtime/syscall.rs b/core/src/runtime/syscall.rs index 59a0e527f3..9e9d980568 100644 --- a/core/src/runtime/syscall.rs +++ b/core/src/runtime/syscall.rs @@ -5,7 +5,7 @@ use strum_macros::EnumIter; use crate::runtime::{Register, Runtime}; use crate::stark::Blake3CompressInnerChip; -use crate::syscall::precompiles::bn254_scalar::{Bn254ScalarAddChip, Bn254ScalarMulChip}; +use crate::syscall::precompiles::bn254_scalar::{Bn254ScalarAddChip, Bn254ScalarMulChip, Bn254ScalarMacChip}; use crate::syscall::precompiles::edwards::EdAddAssignChip; use crate::syscall::precompiles::edwards::EdDecompressChip; use crate::syscall::precompiles::keccak256::KeccakPermuteChip; @@ -109,6 +109,9 @@ pub enum SyscallCode { /// Execute the `BN254_SCALAR_MUL` precompile. BN254_SCALAR_MUL = 0x00_01_01_21, + + /// Execute the `BN254_SCALAR_MAC` precompile. + BN254_SCALAR_MAC = 0x00_01_01_22, } impl SyscallCode { @@ -141,6 +144,7 @@ impl SyscallCode { 0x00_00_01_1C => SyscallCode::BLS12381_DECOMPRESS, 0x00_01_01_20 => SyscallCode::BN254_SCALAR_ADD, 0x00_01_01_21 => SyscallCode::BN254_SCALAR_MUL, + 0x00_01_01_22 => SyscallCode::BN254_SCALAR_MAC, _ => panic!("invalid syscall number: {}", value), } } @@ -353,6 +357,10 @@ pub fn default_syscall_map() -> HashMap> { SyscallCode::BN254_SCALAR_MUL, Rc::new(Bn254ScalarMulChip::new()), ); + syscall_map.insert( + SyscallCode::BN254_SCALAR_MAC, + Rc::new(Bn254ScalarMacChip::new()), + ); syscall_map } diff --git a/core/src/syscall/precompiles/bn254_scalar/mac.rs b/core/src/syscall/precompiles/bn254_scalar/mac.rs new file mode 100644 index 0000000000..6ddbcf1c38 --- /dev/null +++ b/core/src/syscall/precompiles/bn254_scalar/mac.rs @@ -0,0 +1,71 @@ +use crate::runtime::Syscall; +use crate::syscall::precompiles::bn254_scalar::NUM_WORDS_PER_FE; +use crate::utils::ec::field::{FieldParameters, NumWords}; +use crate::utils::ec::weierstrass::bn254::Bn254ScalarField; +use num::BigUint; +use typenum::Unsigned; + +pub struct Bn254ScalarMacChip; + +impl Bn254ScalarMacChip { + pub fn new() -> Self { + Self + } +} + +impl Syscall for Bn254ScalarMacChip { + fn execute( + &self, + rt: &mut crate::runtime::SyscallContext, + arg1: u32, + arg2: u32, + ) -> Option { + let p_ptr = arg1; + let q_ptr = arg2; + + assert_eq!(p_ptr % 4, 0, "p_ptr({:x}) is not aligned", p_ptr); + assert_eq!(q_ptr % 4, 0, "q_ptr({:x}) is not aligned", q_ptr); + + let nw_per_fe = ::WordsFieldElement::USIZE; + debug_assert_eq!(nw_per_fe, NUM_WORDS_PER_FE); + + let ret_in = rt.slice_unsafe(arg1, nw_per_fe); + let ptr = rt.slice_unsafe(arg2, 2); + let a = rt.slice_unsafe(ptr[0], nw_per_fe); + let b = rt.slice_unsafe(ptr[1], nw_per_fe); + + let bn_ret_in = BigUint::from_bytes_le( + &ret_in + .iter() + .copied() + .flat_map(|word| word.to_le_bytes()) + .collect::>(), + ); + let bn_a = BigUint::from_bytes_le( + &a.iter() + .copied() + .flat_map(|word| word.to_le_bytes()) + .collect::>(), + ); + let bn_b = BigUint::from_bytes_le( + &b.iter() + .copied() + .flat_map(|word| word.to_le_bytes()) + .collect::>(), + ); + + let modulus = Bn254ScalarField::modulus(); + + let bn_ret_out = ((bn_a * bn_b) % modulus.clone() + bn_ret_in) % modulus; + let mut result_words = bn_ret_out.to_u32_digits(); + result_words.resize(nw_per_fe, 0); + + let _p_memory_records = rt.mw_slice(p_ptr, &result_words); + + None + } + + fn num_extra_cycles(&self) -> u32 { + 1 + } +} diff --git a/core/src/syscall/precompiles/bn254_scalar/mod.rs b/core/src/syscall/precompiles/bn254_scalar/mod.rs index 3c279378a3..935c6f504f 100644 --- a/core/src/syscall/precompiles/bn254_scalar/mod.rs +++ b/core/src/syscall/precompiles/bn254_scalar/mod.rs @@ -1,9 +1,11 @@ mod add; mod mul; +mod mac; // mod general_field_op; pub use add::Bn254ScalarAddChip; pub use mul::Bn254ScalarMulChip; +pub use mac::Bn254ScalarMacChip; use crate::{ operations::field::{field_op::FieldOperation, params::Limbs}, diff --git a/examples/poseidon_bn254/program/Cargo.lock b/examples/poseidon_bn254/program/Cargo.lock index be78ab24d1..e9a2f26674 100644 --- a/examples/poseidon_bn254/program/Cargo.lock +++ b/examples/poseidon_bn254/program/Cargo.lock @@ -216,8 +216,7 @@ checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" [[package]] name = "ff" version = "0.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ded41244b729663b1e574f1b4fb731469f69f79c17667b5d776b16cda0479449" +source = "git+https://github.com/scroll-tech/ff?rev=7e94aa6#7e94aa6726837138b1b8346ec55b6ce6b593dc96" dependencies = [ "bitvec", "rand_core", @@ -272,7 +271,7 @@ dependencies = [ [[package]] name = "halo2curves" version = "0.3.3" -source = "git+https://github.com/kunxian-xia/halo2curves.git?branch=feat/sp1#da9ff1b096e7067659d6c7f8c1f0cb78cf6d13f3" +source = "git+https://github.com/lightsing/halo2curves.git?branch=feat/sp1#bade656dfc358b3dd587caf1f7756210f4edca6f" dependencies = [ "ff", "group", @@ -635,7 +634,7 @@ dependencies = [ [[package]] name = "poseidon-base" version = "0.1.0" -source = "git+https://github.com/scroll-tech/poseidon-circuit.git?branch=feat/sp1#23620d9cbe2584686e0f6ac8a9be65db2382761f" +source = "git+https://github.com/scroll-tech/poseidon-circuit.git?branch=feat/sp1#eb4126462778084e0a19df6ef22e8a8dd6fea187" dependencies = [ "bitvec", "halo2curves", diff --git a/examples/poseidon_bn254/program/Cargo.toml b/examples/poseidon_bn254/program/Cargo.toml index a83ce53e4a..93f0771080 100644 --- a/examples/poseidon_bn254/program/Cargo.toml +++ b/examples/poseidon_bn254/program/Cargo.toml @@ -8,4 +8,14 @@ edition = "2021" sp1-zkvm = { path = "../../../zkvm/entrypoint" } hex = "0.4" halo2curves = { git = "https://github.com/kunxian-xia/halo2curves.git", branch = "feat/sp1" } -poseidon_base = { git = "https://github.com/scroll-tech/poseidon-circuit.git", package = "poseidon-base", branch = "feat/sp1" } \ No newline at end of file +poseidon_base = { git = "https://github.com/scroll-tech/poseidon-circuit.git", package = "poseidon-base", branch = "feat/sp1" } + +#halo2curves = { path = "../../../../halo2curves" } +#poseidon_base = { path = "../../../../poseidon-circuit/poseidon-base", package = "poseidon-base" } + +[patch.crates-io] +ff = { git = "https://github.com/scroll-tech/ff", rev = "7e94aa6" } +#[patch."https://github.com/kunxian-xia/halo2curves.git"] +#halo2curves = { path = "../../../../halo2curves" } +[patch."https://github.com/kunxian-xia/halo2curves.git"] +halo2curves = { git = "https://github.com/lightsing/halo2curves.git", branch = "feat/sp1" } \ No newline at end of file diff --git a/examples/poseidon_bn254/program/elf/riscv32im-succinct-zkvm-elf b/examples/poseidon_bn254/program/elf/riscv32im-succinct-zkvm-elf deleted file mode 100755 index 491201918ba0d54162174b13f327868dcc261034..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 171972 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Í+VwR5huXj$eL+6zApZ~=qGzj`Y-ZT;M?JA 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 diff --git a/zkvm/entrypoint/src/syscalls/bn254.rs b/zkvm/entrypoint/src/syscalls/bn254.rs index 27de19f02b..e080bdbf87 100644 --- a/zkvm/entrypoint/src/syscalls/bn254.rs +++ b/zkvm/entrypoint/src/syscalls/bn254.rs @@ -74,3 +74,23 @@ pub extern "C" fn syscall_bn254_scalar_mul(p: *mut u32, q: *const u32) { #[cfg(not(target_os = "zkvm"))] unreachable!() } + +#[allow(unused_variables)] +#[no_mangle] +pub extern "C" fn syscall_bn254_scalar_mac(ret: *mut u32, a: *const u32, b: *const u32) { + let q = &[a, b]; + let q_ptr = q.as_ptr() as *const u32; + #[cfg(target_os = "zkvm")] + unsafe { + asm!( + "ecall", + in("t0") crate::syscalls::BN254_SCALAR_MAC, + in("a0") ret, + in("a1") q_ptr, + + ); + } + + #[cfg(not(target_os = "zkvm"))] + unreachable!() +} diff --git a/zkvm/entrypoint/src/syscalls/mod.rs b/zkvm/entrypoint/src/syscalls/mod.rs index 0d62694d48..f9d3faeeff 100644 --- a/zkvm/entrypoint/src/syscalls/mod.rs +++ b/zkvm/entrypoint/src/syscalls/mod.rs @@ -109,3 +109,6 @@ pub const BN254_SCALAR_ADD: u32 = 0x00_01_01_20; /// Executes the `BN254_SCALAR_MUL` precompile pub const BN254_SCALAR_MUL: u32 = 0x00_01_01_21; + +/// Executes the `BN254_SCALAR_MAC` precompile +pub const BN254_SCALAR_MAC: u32 = 0x00_01_01_22; From fb1c13feac64c3d79dc21abe1050a77c843b3ccb Mon Sep 17 00:00:00 2001 From: lightsing Date: Wed, 22 May 2024 16:41:32 +0800 Subject: [PATCH 15/34] add chip --- core/src/runtime/record.rs | 4 +- .../syscall/precompiles/bn254_scalar/add.rs | 38 +-- .../syscall/precompiles/bn254_scalar/mac.rs | 247 ++++++++++++++---- .../syscall/precompiles/bn254_scalar/mod.rs | 140 +++++++--- .../syscall/precompiles/bn254_scalar/mul.rs | 36 +-- 5 files changed, 326 insertions(+), 139 deletions(-) diff --git a/core/src/runtime/record.rs b/core/src/runtime/record.rs index af2501f2ef..ad58ba02fb 100644 --- a/core/src/runtime/record.rs +++ b/core/src/runtime/record.rs @@ -17,7 +17,7 @@ use crate::runtime::MemoryInitializeFinalizeEvent; use crate::runtime::MemoryRecordEnum; use crate::stark::MachineRecord; use crate::syscall::precompiles::blake3::Blake3CompressInnerEvent; -use crate::syscall::precompiles::bn254_scalar::FieldArithEvent; +use crate::syscall::precompiles::bn254_scalar::Bn254FieldArithEvent; use crate::syscall::precompiles::edwards::EdDecompressEvent; use crate::syscall::precompiles::keccak256::KeccakPermuteEvent; use crate::syscall::precompiles::sha256::{ShaCompressEvent, ShaExtendEvent}; @@ -85,7 +85,7 @@ pub struct ExecutionRecord { pub bn254_double_events: Vec, - pub bn254_scalar_arith_events: Vec, + pub bn254_scalar_arith_events: Vec, pub k256_decompress_events: Vec, diff --git a/core/src/syscall/precompiles/bn254_scalar/add.rs b/core/src/syscall/precompiles/bn254_scalar/add.rs index abb4dc6ca6..0eeb248f1f 100644 --- a/core/src/syscall/precompiles/bn254_scalar/add.rs +++ b/core/src/syscall/precompiles/bn254_scalar/add.rs @@ -11,7 +11,7 @@ use sp1_derive::AlignedBorrow; use crate::{ air::MachineAir, memory::{MemoryCols, MemoryReadCols, MemoryWriteCols}, - operations::field::field_op::{FieldOpCols, FieldOperation}, + operations::field::field_op::{FieldOpCols}, runtime::{ExecutionRecord, Program, Syscall, SyscallCode}, stark::SP1AirBuilder, syscall::precompiles::bn254_scalar::Limbs, @@ -24,10 +24,10 @@ use crate::{ }, }; -use super::{create_bn254_scalar_arith_event, NUM_WORDS_PER_FE}; +use super::{create_bn254_scalar_arith_event, NUM_WORDS_PER_FE, Bn254FieldOperation}; const NUM_COLS: usize = core::mem::size_of::>(); -const OP: FieldOperation = FieldOperation::Add; +const OP: Bn254FieldOperation = Bn254FieldOperation::Add; #[derive(Debug, Clone, AlignedBorrow)] #[repr(C)] @@ -89,36 +89,22 @@ impl MachineAir for Bn254ScalarAddChip { let mut row = [F::zero(); NUM_COLS]; let cols: &mut Bn254ScalarAddCols = row.as_mut_slice().borrow_mut(); - let p = BigUint::from_bytes_le( - event - .p - .iter() - .flat_map(|p| p.to_le_bytes()) - .collect::>() - .as_slice(), - ); - let q = BigUint::from_bytes_le( - event - .q - .iter() - .flat_map(|q| q.to_le_bytes()) - .collect::>() - .as_slice(), - ); + let p = event.arg1.as_biguint(); + let q = event.arg2.as_biguint(); cols.is_real = F::one(); cols.shard = F::from_canonical_u32(event.shard); cols.clk = F::from_canonical_u32(event.clk); - cols.p_ptr = F::from_canonical_u32(event.p_ptr); - cols.q_ptr = F::from_canonical_u32(event.q_ptr); + cols.p_ptr = F::from_canonical_u32(event.arg1.ptr); + cols.q_ptr = F::from_canonical_u32(event.arg2.ptr); - cols.eval.populate(&p, &q, OP); + cols.eval.populate(&p, &q, OP.to_field_operation()); for i in 0..cols.p_access.len() { - cols.p_access[i].populate(event.p_memory_records[i], &mut new_byte_lookup_events); + cols.p_access[i].populate(event.arg1.memory_records[i], &mut new_byte_lookup_events); } for i in 0..cols.q_access.len() { - cols.q_access[i].populate(event.q_memory_records[i], &mut new_byte_lookup_events); + cols.q_access[i].populate(event.arg2.memory_records[i], &mut new_byte_lookup_events); } rows.push(row); @@ -130,7 +116,7 @@ impl MachineAir for Bn254ScalarAddChip { let cols: &mut Bn254ScalarAddCols = row.as_mut_slice().borrow_mut(); let zero = BigUint::zero(); - cols.eval.populate(&zero, &zero, OP); + cols.eval.populate(&zero, &zero, OP.to_field_operation()); row }); @@ -171,7 +157,7 @@ where let q: Limbs<::Var, ::Limbs> = limbs_from_prev_access(&row.q_access); - row.eval.eval(builder, &p, &q, OP); + row.eval.eval(builder, &p, &q, OP.to_field_operation()); for i in 0..Bn254ScalarField::NB_LIMBS { builder diff --git a/core/src/syscall/precompiles/bn254_scalar/mac.rs b/core/src/syscall/precompiles/bn254_scalar/mac.rs index 6ddbcf1c38..f56fa728f8 100644 --- a/core/src/syscall/precompiles/bn254_scalar/mac.rs +++ b/core/src/syscall/precompiles/bn254_scalar/mac.rs @@ -1,9 +1,50 @@ -use crate::runtime::Syscall; -use crate::syscall::precompiles::bn254_scalar::NUM_WORDS_PER_FE; -use crate::utils::ec::field::{FieldParameters, NumWords}; -use crate::utils::ec::weierstrass::bn254::Bn254ScalarField; +use std::borrow::{Borrow, BorrowMut}; + use num::BigUint; -use typenum::Unsigned; +use num::Zero; +use p3_air::{Air, AirBuilder, BaseAir}; +use p3_field::AbstractField; +use p3_field::{Field, PrimeField32}; +use p3_matrix::{dense::RowMajorMatrix, Matrix}; +use typenum::U2; +use sp1_derive::AlignedBorrow; + +use crate::{ + air::MachineAir, + memory::{MemoryCols, MemoryReadCols, MemoryWriteCols}, + operations::field::field_op::{FieldOpCols, FieldOperation}, + runtime::{ExecutionRecord, Program, Syscall, SyscallCode}, + stark::SP1AirBuilder, + syscall::precompiles::bn254_scalar::Limbs, + utils::{ + ec::{ + field::{FieldParameters, NumLimbs}, + weierstrass::bn254::Bn254ScalarField, + }, + limbs_from_prev_access, pad_rows, + }, +}; + +use super::{create_bn254_scalar_arith_event, NUM_WORDS_PER_FE, Bn254FieldOperation}; + +const NUM_COLS: usize = core::mem::size_of::>(); +const OP: Bn254FieldOperation = Bn254FieldOperation::Mac; + +#[derive(Debug, Clone, AlignedBorrow)] +#[repr(C)] +pub struct Bn254ScalarMacCols { + is_real: T, + shard: T, + clk: T, + arg1_ptr: T, + arg2_ptr: T, + arg1_access: [MemoryWriteCols; NUM_WORDS_PER_FE], + arg2_access: [MemoryReadCols; 2], + a_access: [MemoryReadCols; NUM_WORDS_PER_FE], + b_access: [MemoryReadCols; NUM_WORDS_PER_FE], + mul_eval: FieldOpCols, + add_eval: FieldOpCols, +} pub struct Bn254ScalarMacChip; @@ -20,47 +61,8 @@ impl Syscall for Bn254ScalarMacChip { arg1: u32, arg2: u32, ) -> Option { - let p_ptr = arg1; - let q_ptr = arg2; - - assert_eq!(p_ptr % 4, 0, "p_ptr({:x}) is not aligned", p_ptr); - assert_eq!(q_ptr % 4, 0, "q_ptr({:x}) is not aligned", q_ptr); - - let nw_per_fe = ::WordsFieldElement::USIZE; - debug_assert_eq!(nw_per_fe, NUM_WORDS_PER_FE); - - let ret_in = rt.slice_unsafe(arg1, nw_per_fe); - let ptr = rt.slice_unsafe(arg2, 2); - let a = rt.slice_unsafe(ptr[0], nw_per_fe); - let b = rt.slice_unsafe(ptr[1], nw_per_fe); - - let bn_ret_in = BigUint::from_bytes_le( - &ret_in - .iter() - .copied() - .flat_map(|word| word.to_le_bytes()) - .collect::>(), - ); - let bn_a = BigUint::from_bytes_le( - &a.iter() - .copied() - .flat_map(|word| word.to_le_bytes()) - .collect::>(), - ); - let bn_b = BigUint::from_bytes_le( - &b.iter() - .copied() - .flat_map(|word| word.to_le_bytes()) - .collect::>(), - ); - - let modulus = Bn254ScalarField::modulus(); - - let bn_ret_out = ((bn_a * bn_b) % modulus.clone() + bn_ret_in) % modulus; - let mut result_words = bn_ret_out.to_u32_digits(); - result_words.resize(nw_per_fe, 0); - - let _p_memory_records = rt.mw_slice(p_ptr, &result_words); + let event = create_bn254_scalar_arith_event(rt, arg1, arg2, OP); + rt.record_mut().bn254_scalar_arith_events.push(event); None } @@ -69,3 +71,156 @@ impl Syscall for Bn254ScalarMacChip { 1 } } + +impl MachineAir for Bn254ScalarMacChip { + type Record = ExecutionRecord; + + type Program = Program; + + fn name(&self) -> String { + "Bn254ScalarMac".to_string() + } + + fn generate_trace(&self, input: &Self::Record, output: &mut Self::Record) -> RowMajorMatrix { + let mut rows = vec![]; + let mut new_byte_lookup_events = vec![]; + + for event in input + .bn254_scalar_arith_events + .iter() + .filter(|e| e.op == OP) + { + let mut row = [F::zero(); NUM_COLS]; + let cols: &mut Bn254ScalarMacCols = row.as_mut_slice().borrow_mut(); + + let arg1 = event.arg1.as_biguint(); + let a = event.a.as_ref().unwrap().as_biguint(); + let b = event.b.as_ref().unwrap().as_biguint(); + + cols.is_real = F::one(); + cols.shard = F::from_canonical_u32(event.shard); + cols.clk = F::from_canonical_u32(event.clk); + cols.arg1_ptr = F::from_canonical_u32(event.arg1.ptr); + cols.arg2_ptr = F::from_canonical_u32(event.arg2.ptr); + + let mul = cols.mul_eval.populate(&a, &b, FieldOperation::Mul); + cols.add_eval.populate(&arg1, &mul, FieldOperation::Add); + + for i in 0..cols.arg1_access.len() { + cols.arg1_access[i].populate(event.arg1.memory_records[i], &mut new_byte_lookup_events); + } + for i in 0..cols.arg2_access.len() { + cols.arg2_access[i].populate(event.arg2.memory_records[i], &mut new_byte_lookup_events); + } + for i in 0..cols.a_access.len() { + cols.a_access[i].populate(event.a.as_ref().unwrap().memory_records[i], &mut new_byte_lookup_events); + } + for i in 0..cols.b_access.len() { + cols.b_access[i].populate(event.b.as_ref().unwrap().memory_records[i], &mut new_byte_lookup_events); + } + + rows.push(row); + } + output.add_byte_lookup_events(new_byte_lookup_events); + + pad_rows(&mut rows, || { + let mut row = [F::zero(); NUM_COLS]; + let cols: &mut Bn254ScalarMacCols = row.as_mut_slice().borrow_mut(); + + let zero = BigUint::zero(); + cols.mul_eval.populate(&zero, &zero, FieldOperation::Mul); + cols.add_eval.populate(&zero, &zero, FieldOperation::Add); + + row + }); + + RowMajorMatrix::new(rows.into_iter().flatten().collect::>(), NUM_COLS) + } + + fn included(&self, shard: &Self::Record) -> bool { + shard + .bn254_scalar_arith_events + .iter() + .filter(|e| e.op == OP) + .count() + != 0 + } +} + +impl BaseAir for Bn254ScalarMacChip { + fn width(&self) -> usize { + NUM_COLS + } +} + +impl Air for Bn254ScalarMacChip +where + AB: SP1AirBuilder, +{ + fn eval(&self, builder: &mut AB) { + let main = builder.main(); + let row = main.row_slice(0); + let row: &Bn254ScalarMacCols = (*row).borrow(); + + builder.assert_bool(row.is_real); + + let arg1: Limbs<::Var, ::Limbs> = + limbs_from_prev_access(&row.arg1_access); + let arg2: Limbs<::Var, U2> = limbs_from_prev_access(&row.arg2_access); + let a: Limbs<::Var, ::Limbs> = + limbs_from_prev_access(&row.a_access); + let b: Limbs<::Var, ::Limbs> = + limbs_from_prev_access(&row.b_access); + + row.mul_eval.eval(builder, &a, &b, FieldOperation::Mul); + row.add_eval.eval(builder, &arg1, &row.mul_eval.result, FieldOperation::Add); + + for i in 0..Bn254ScalarField::NB_LIMBS { + builder + .when(row.is_real) + .assert_eq(row.add_eval.result[i], row.arg1_access[i / 4].value()[i % 4]); + } + + builder.eval_memory_access_slice( + row.shard, + row.clk.into(), + row.arg1_ptr, + &row.arg1_access, + row.is_real, + ); + + builder.eval_memory_access_slice( + row.shard, + row.clk.into(), + row.arg2_ptr, + &row.arg2_access, + row.is_real, + ); + + builder.eval_memory_access_slice( + row.shard, + row.clk.into(), + arg2[0], + &row.a_access, + row.is_real, + ); + + builder.eval_memory_access_slice( + row.shard, + row.clk.into(), + arg2[0], + &row.b_access, + row.is_real, + ); + + let syscall_id = AB::F::from_canonical_u32(SyscallCode::BN254_SCALAR_MAC.syscall_id()); + builder.receive_syscall( + row.shard, + row.clk, + syscall_id, + row.arg1_ptr, + row.arg2_ptr, + row.is_real, + ); + } +} \ No newline at end of file diff --git a/core/src/syscall/precompiles/bn254_scalar/mod.rs b/core/src/syscall/precompiles/bn254_scalar/mod.rs index 935c6f504f..070e1e1a86 100644 --- a/core/src/syscall/precompiles/bn254_scalar/mod.rs +++ b/core/src/syscall/precompiles/bn254_scalar/mod.rs @@ -9,7 +9,7 @@ pub use mac::Bn254ScalarMacChip; use crate::{ operations::field::{field_op::FieldOperation, params::Limbs}, - runtime::{MemoryReadRecord, MemoryWriteRecord, SyscallContext}, + runtime::{MemoryReadRecord, MemoryWriteRecord, SyscallContext, MemoryRecordEnum}, utils::ec::{ field::{FieldParameters, NumWords}, weierstrass::bn254::Bn254ScalarField, @@ -23,24 +23,75 @@ use serde::{Deserialize, Serialize}; pub(crate) const NUM_WORDS_PER_FE: usize = 8; #[derive(Clone, Debug, Serialize, Deserialize)] -pub struct FieldArithEvent { +pub struct FieldArithMemoryAccess { + pub ptr: u32, + pub memory_records: Vec +} + +impl FieldArithMemoryAccess { + pub fn read(rt: &mut SyscallContext, ptr: u32, len: usize) -> Self { + let (memory_records, _) = rt.mr_slice(ptr, len); + Self { ptr, memory_records } + } + + pub fn as_biguint(&self) -> BigUint { + BigUint::from_bytes_le( + &self.memory_records.iter() + .flat_map(|word| word.value.to_le_bytes()) + .collect::>(), + ) + } +} + +impl FieldArithMemoryAccess { + pub fn write(rt: &mut SyscallContext, ptr: u32, values: &[u32]) -> Self { + Self { ptr, memory_records: rt.mw_slice(ptr, &values) } + } + + + pub fn as_biguint(&self) -> BigUint { + BigUint::from_bytes_le( + &self.memory_records.iter() + .flat_map(|word| word.value.to_le_bytes()) + .collect::>(), + ) + } +} + +#[derive(PartialEq, Copy, Clone, Debug, Serialize, Deserialize)] +pub enum Bn254FieldOperation { + Add = 0, + Mul = 2, + Mac = 4, +} + +impl Bn254FieldOperation { + pub const fn to_field_operation(&self) -> FieldOperation { + match self { + Bn254FieldOperation::Add => FieldOperation::Add, + Bn254FieldOperation::Mul => FieldOperation::Mul, + Bn254FieldOperation::Mac => panic!("not supported"), + } + } +} + +#[derive(Clone, Debug, Serialize, Deserialize)] +pub struct Bn254FieldArithEvent { pub shard: u32, pub clk: u32, - pub op: FieldOperation, - pub p: Vec, - pub q: Vec, - pub p_ptr: u32, - pub q_ptr: u32, - pub p_memory_records: Vec, - pub q_memory_records: Vec, + pub op: Bn254FieldOperation, + pub arg1: FieldArithMemoryAccess, + pub arg2: FieldArithMemoryAccess, + pub a: Option>, + pub b: Option> } pub fn create_bn254_scalar_arith_event( rt: &mut SyscallContext, arg1: u32, arg2: u32, - op: FieldOperation, -) -> FieldArithEvent { + op: Bn254FieldOperation, +) -> Bn254FieldArithEvent { let start_clk = rt.clk; let p_ptr = arg1; let q_ptr = arg2; @@ -51,55 +102,64 @@ pub fn create_bn254_scalar_arith_event( let nw_per_fe = ::WordsFieldElement::USIZE; debug_assert_eq!(nw_per_fe, NUM_WORDS_PER_FE); - let p: Vec = rt.slice_unsafe(p_ptr, nw_per_fe); - let (q_memory_records, q) = rt.mr_slice(q_ptr, nw_per_fe); + let arg1: Vec = rt.slice_unsafe(p_ptr, nw_per_fe); + let arg2 = match op { + Bn254FieldOperation::Mac => FieldArithMemoryAccess::read(rt, arg2, 2), + _ => FieldArithMemoryAccess::read(rt, arg2, nw_per_fe) + }; - let bn_p = BigUint::from_bytes_le( - &p.iter() - .cloned() - .flat_map(|word| word.to_le_bytes()) - .collect::>(), - ); - let bn_q = BigUint::from_bytes_le( - &q.iter() - .cloned() + let bn_arg1 = BigUint::from_bytes_le( + &arg1.iter().copied() .flat_map(|word| word.to_le_bytes()) .collect::>(), ); - let modulus = Bn254ScalarField::modulus(); - let r = match op { - FieldOperation::Add => (&bn_p + &bn_q) % modulus, - FieldOperation::Mul => (&bn_p * &bn_q) % modulus, - _ => unimplemented!("not supported"), + let (a, b, bn_arg1_out) = if matches!(op, Bn254FieldOperation::Mac) { + let a = FieldArithMemoryAccess::read(rt, arg2.memory_records[0].value, nw_per_fe); + let b = FieldArithMemoryAccess::read(rt, arg2.memory_records[1].value, nw_per_fe); + + let bn_a = a.as_biguint(); + let bn_b = b.as_biguint(); + let bn_arg1_out = (&bn_a * &bn_b + &bn_arg1) % modulus; + + (Some(a), Some(b), bn_arg1_out) + } else { + let bn_arg2 = arg2.as_biguint(); + + let bn_arg1_out = match op { + Bn254FieldOperation::Add => (&bn_arg1 + &bn_arg2) % modulus, + Bn254FieldOperation::Mul => (&bn_arg1 * &bn_arg2) % modulus, + _ => unimplemented!("not supported"), + }; + (None, None, bn_arg1_out) }; + log::trace!( - "shard: {}, clk: {}, op: {:?}, bn_p: {:?}, bn_q: {:?}, r: {:?}", + "shard: {}, clk: {}, op: {:?}, arg1: {:?}, arg2: {:?}, a: {:?}, b: {:?}", rt.current_shard(), rt.clk, op, - bn_p, - bn_q, - r + arg1, + arg2, + a, + b ); - let mut result_words = r.to_u32_digits(); + let mut result_words = bn_arg1_out.to_u32_digits(); result_words.resize(nw_per_fe, 0); - let p_memory_records = rt.mw_slice(p_ptr, &result_words); + let arg1 = FieldArithMemoryAccess::write(rt, p_ptr, &result_words); let shard = rt.current_shard(); - FieldArithEvent { + Bn254FieldArithEvent { shard, clk: start_clk, op, - p, - q, - p_ptr, - q_ptr, - p_memory_records, - q_memory_records, + arg1, + arg2, + a, + b } } diff --git a/core/src/syscall/precompiles/bn254_scalar/mul.rs b/core/src/syscall/precompiles/bn254_scalar/mul.rs index 8cb1da2651..8fc156e5ba 100644 --- a/core/src/syscall/precompiles/bn254_scalar/mul.rs +++ b/core/src/syscall/precompiles/bn254_scalar/mul.rs @@ -24,10 +24,10 @@ use crate::{ }, }; -use super::{create_bn254_scalar_arith_event, NUM_WORDS_PER_FE}; +use super::{create_bn254_scalar_arith_event, NUM_WORDS_PER_FE, Bn254FieldOperation}; const NUM_COLS: usize = core::mem::size_of::>(); -const OP: FieldOperation = FieldOperation::Mul; +const OP: Bn254FieldOperation = Bn254FieldOperation::Mul; #[derive(Debug, Clone, AlignedBorrow)] #[repr(C)] @@ -89,36 +89,22 @@ impl MachineAir for Bn254ScalarMulChip { let mut row = [F::zero(); NUM_COLS]; let cols: &mut Bn254ScalarMulCols = row.as_mut_slice().borrow_mut(); - let p = BigUint::from_bytes_le( - event - .p - .iter() - .flat_map(|p| p.to_le_bytes()) - .collect::>() - .as_slice(), - ); - let q = BigUint::from_bytes_le( - event - .q - .iter() - .flat_map(|q| q.to_le_bytes()) - .collect::>() - .as_slice(), - ); + let p = event.arg1.as_biguint(); + let q = event.arg2.as_biguint(); cols.is_real = F::one(); cols.shard = F::from_canonical_u32(event.shard); cols.clk = F::from_canonical_u32(event.clk); - cols.p_ptr = F::from_canonical_u32(event.p_ptr); - cols.q_ptr = F::from_canonical_u32(event.q_ptr); + cols.p_ptr = F::from_canonical_u32(event.arg1.ptr); + cols.q_ptr = F::from_canonical_u32(event.arg2.ptr); - cols.eval.populate(&p, &q, OP); + cols.eval.populate(&p, &q, OP.to_field_operation()); for i in 0..cols.p_access.len() { - cols.p_access[i].populate(event.p_memory_records[i], &mut new_byte_lookup_events); + cols.p_access[i].populate(event.arg1.memory_records[i], &mut new_byte_lookup_events); } for i in 0..cols.q_access.len() { - cols.q_access[i].populate(event.q_memory_records[i], &mut new_byte_lookup_events); + cols.q_access[i].populate(event.arg2.memory_records[i], &mut new_byte_lookup_events); } rows.push(row); @@ -130,7 +116,7 @@ impl MachineAir for Bn254ScalarMulChip { let cols: &mut Bn254ScalarMulCols = row.as_mut_slice().borrow_mut(); let zero = BigUint::zero(); - cols.eval.populate(&zero, &zero, OP); + cols.eval.populate(&zero, &zero, OP.to_field_operation()); row }); @@ -171,7 +157,7 @@ where let q: Limbs<::Var, ::Limbs> = limbs_from_prev_access(&row.q_access); - row.eval.eval(builder, &p, &q, OP); + row.eval.eval(builder, &p, &q, OP.to_field_operation()); for i in 0..Bn254ScalarField::NB_LIMBS { builder From 15114bf9cb57bb1913abd0ca2676909fb28795e7 Mon Sep 17 00:00:00 2001 From: lightsing Date: Wed, 22 May 2024 16:54:26 +0800 Subject: [PATCH 16/34] fix --- core/src/syscall/precompiles/bn254_scalar/add.rs | 4 ++-- core/src/syscall/precompiles/bn254_scalar/mac.rs | 6 +++--- core/src/syscall/precompiles/bn254_scalar/mod.rs | 12 ++++++------ core/src/syscall/precompiles/bn254_scalar/mul.rs | 4 ++-- 4 files changed, 13 insertions(+), 13 deletions(-) diff --git a/core/src/syscall/precompiles/bn254_scalar/add.rs b/core/src/syscall/precompiles/bn254_scalar/add.rs index 0eeb248f1f..0babd22189 100644 --- a/core/src/syscall/precompiles/bn254_scalar/add.rs +++ b/core/src/syscall/precompiles/bn254_scalar/add.rs @@ -89,8 +89,8 @@ impl MachineAir for Bn254ScalarAddChip { let mut row = [F::zero(); NUM_COLS]; let cols: &mut Bn254ScalarAddCols = row.as_mut_slice().borrow_mut(); - let p = event.arg1.as_biguint(); - let q = event.arg2.as_biguint(); + let p = event.arg1.prev_value_as_biguint(); + let q = event.arg2.value_as_biguint(); cols.is_real = F::one(); cols.shard = F::from_canonical_u32(event.shard); diff --git a/core/src/syscall/precompiles/bn254_scalar/mac.rs b/core/src/syscall/precompiles/bn254_scalar/mac.rs index f56fa728f8..5f9419c015 100644 --- a/core/src/syscall/precompiles/bn254_scalar/mac.rs +++ b/core/src/syscall/precompiles/bn254_scalar/mac.rs @@ -93,9 +93,9 @@ impl MachineAir for Bn254ScalarMacChip { let mut row = [F::zero(); NUM_COLS]; let cols: &mut Bn254ScalarMacCols = row.as_mut_slice().borrow_mut(); - let arg1 = event.arg1.as_biguint(); - let a = event.a.as_ref().unwrap().as_biguint(); - let b = event.b.as_ref().unwrap().as_biguint(); + let arg1 = event.arg1.prev_value_as_biguint(); + let a = event.a.as_ref().unwrap().value_as_biguint(); + let b = event.b.as_ref().unwrap().value_as_biguint(); cols.is_real = F::one(); cols.shard = F::from_canonical_u32(event.shard); diff --git a/core/src/syscall/precompiles/bn254_scalar/mod.rs b/core/src/syscall/precompiles/bn254_scalar/mod.rs index 070e1e1a86..4558fc9cdb 100644 --- a/core/src/syscall/precompiles/bn254_scalar/mod.rs +++ b/core/src/syscall/precompiles/bn254_scalar/mod.rs @@ -34,7 +34,7 @@ impl FieldArithMemoryAccess { Self { ptr, memory_records } } - pub fn as_biguint(&self) -> BigUint { + pub fn value_as_biguint(&self) -> BigUint { BigUint::from_bytes_le( &self.memory_records.iter() .flat_map(|word| word.value.to_le_bytes()) @@ -49,10 +49,10 @@ impl FieldArithMemoryAccess { } - pub fn as_biguint(&self) -> BigUint { + pub fn prev_value_as_biguint(&self) -> BigUint { BigUint::from_bytes_le( &self.memory_records.iter() - .flat_map(|word| word.value.to_le_bytes()) + .flat_map(|word| word.prev_value.to_le_bytes()) .collect::>(), ) } @@ -119,13 +119,13 @@ pub fn create_bn254_scalar_arith_event( let a = FieldArithMemoryAccess::read(rt, arg2.memory_records[0].value, nw_per_fe); let b = FieldArithMemoryAccess::read(rt, arg2.memory_records[1].value, nw_per_fe); - let bn_a = a.as_biguint(); - let bn_b = b.as_biguint(); + let bn_a = a.value_as_biguint(); + let bn_b = b.value_as_biguint(); let bn_arg1_out = (&bn_a * &bn_b + &bn_arg1) % modulus; (Some(a), Some(b), bn_arg1_out) } else { - let bn_arg2 = arg2.as_biguint(); + let bn_arg2 = arg2.value_as_biguint(); let bn_arg1_out = match op { Bn254FieldOperation::Add => (&bn_arg1 + &bn_arg2) % modulus, diff --git a/core/src/syscall/precompiles/bn254_scalar/mul.rs b/core/src/syscall/precompiles/bn254_scalar/mul.rs index 8fc156e5ba..118aaff129 100644 --- a/core/src/syscall/precompiles/bn254_scalar/mul.rs +++ b/core/src/syscall/precompiles/bn254_scalar/mul.rs @@ -89,8 +89,8 @@ impl MachineAir for Bn254ScalarMulChip { let mut row = [F::zero(); NUM_COLS]; let cols: &mut Bn254ScalarMulCols = row.as_mut_slice().borrow_mut(); - let p = event.arg1.as_biguint(); - let q = event.arg2.as_biguint(); + let p = event.arg1.prev_value_as_biguint(); + let q = event.arg2.value_as_biguint(); cols.is_real = F::one(); cols.shard = F::from_canonical_u32(event.shard); From c4e0ac3cdc7ef85185b55f853d12af8ccb9b85ef Mon Sep 17 00:00:00 2001 From: lightsing Date: Wed, 22 May 2024 17:50:18 +0800 Subject: [PATCH 17/34] fix & fmt --- cli/src/build.rs | 6 +- core/src/runtime/syscall.rs | 4 +- core/src/stark/air.rs | 9 ++- .../syscall/precompiles/bn254_scalar/add.rs | 10 ++-- .../syscall/precompiles/bn254_scalar/mac.rs | 56 ++++++++++++++----- .../syscall/precompiles/bn254_scalar/mod.rs | 37 +++++++----- .../syscall/precompiles/bn254_scalar/mul.rs | 8 ++- zkvm/precompiles/src/lib.rs | 1 + 8 files changed, 89 insertions(+), 42 deletions(-) diff --git a/cli/src/build.rs b/cli/src/build.rs index c88e3bf1ec..0efb75926f 100644 --- a/cli/src/build.rs +++ b/cli/src/build.rs @@ -23,11 +23,7 @@ pub(crate) struct BuildArgs { env = "SP1_DOCKER" )] pub(crate) docker: bool, - #[clap( - long, - action, - help = "Ignore Rust version check.", - )] + #[clap(long, action, help = "Ignore Rust version check.")] pub(crate) ignore_rust_version: bool, } diff --git a/core/src/runtime/syscall.rs b/core/src/runtime/syscall.rs index 9e9d980568..36890c550e 100644 --- a/core/src/runtime/syscall.rs +++ b/core/src/runtime/syscall.rs @@ -5,7 +5,9 @@ use strum_macros::EnumIter; use crate::runtime::{Register, Runtime}; use crate::stark::Blake3CompressInnerChip; -use crate::syscall::precompiles::bn254_scalar::{Bn254ScalarAddChip, Bn254ScalarMulChip, Bn254ScalarMacChip}; +use crate::syscall::precompiles::bn254_scalar::{ + Bn254ScalarAddChip, Bn254ScalarMacChip, Bn254ScalarMulChip, +}; use crate::syscall::precompiles::edwards::EdAddAssignChip; use crate::syscall::precompiles::edwards::EdDecompressChip; use crate::syscall::precompiles::keccak256::KeccakPermuteChip; diff --git a/core/src/stark/air.rs b/core/src/stark/air.rs index a51b0cc58e..4879241c8f 100644 --- a/core/src/stark/air.rs +++ b/core/src/stark/air.rs @@ -3,7 +3,6 @@ pub use crate::air::SP1AirBuilder; use crate::air::{MachineAir, SP1_PROOF_NUM_PV_ELTS}; use crate::memory::{MemoryChipType, MemoryProgramChip}; use crate::stark::Chip; -use crate::syscall::precompiles::bn254_scalar::Bn254ScalarMulChip; use crate::StarkGenericConfig; use p3_field::PrimeField32; pub use riscv_chips::*; @@ -22,7 +21,9 @@ pub(crate) mod riscv_chips { pub use crate::memory::MemoryChip; pub use crate::program::ProgramChip; pub use crate::syscall::precompiles::blake3::Blake3CompressInnerChip; - pub use crate::syscall::precompiles::bn254_scalar::Bn254ScalarAddChip; + pub use crate::syscall::precompiles::bn254_scalar::{ + Bn254ScalarAddChip, Bn254ScalarMacChip, Bn254ScalarMulChip, + }; pub use crate::syscall::precompiles::edwards::EdAddAssignChip; pub use crate::syscall::precompiles::edwards::EdDecompressChip; pub use crate::syscall::precompiles::keccak256::KeccakPermuteChip; @@ -105,6 +106,8 @@ pub enum RiscvAir { Bn254ScalarAdd(Bn254ScalarAddChip), /// A precompile for bn254 scalar multiplication. Bn254ScalarMul(Bn254ScalarMulChip), + /// A precompile for bn254 scalar mul-add + Bn254ScalarMac(Bn254ScalarMacChip), /// A precompile for decompressing a point on the BLS12-381 curve. Bls12381Decompress(WeierstrassDecompressChip>), } @@ -158,6 +161,8 @@ impl RiscvAir { chips.push(RiscvAir::Bn254ScalarAdd(bn254_scalar_add)); let bn254_scalar_mul = Bn254ScalarMulChip::new(); chips.push(RiscvAir::Bn254ScalarMul(bn254_scalar_mul)); + let bn254_scalar_mac = Bn254ScalarMacChip::new(); + chips.push(RiscvAir::Bn254ScalarMac(bn254_scalar_mac)); let bls12381_decompress = WeierstrassDecompressChip::>::new(); chips.push(RiscvAir::Bls12381Decompress(bls12381_decompress)); let add = AddSubChip::default(); diff --git a/core/src/syscall/precompiles/bn254_scalar/add.rs b/core/src/syscall/precompiles/bn254_scalar/add.rs index 0babd22189..ffd0b7969e 100644 --- a/core/src/syscall/precompiles/bn254_scalar/add.rs +++ b/core/src/syscall/precompiles/bn254_scalar/add.rs @@ -11,7 +11,7 @@ use sp1_derive::AlignedBorrow; use crate::{ air::MachineAir, memory::{MemoryCols, MemoryReadCols, MemoryWriteCols}, - operations::field::field_op::{FieldOpCols}, + operations::field::field_op::FieldOpCols, runtime::{ExecutionRecord, Program, Syscall, SyscallCode}, stark::SP1AirBuilder, syscall::precompiles::bn254_scalar::Limbs, @@ -24,7 +24,7 @@ use crate::{ }, }; -use super::{create_bn254_scalar_arith_event, NUM_WORDS_PER_FE, Bn254FieldOperation}; +use super::{create_bn254_scalar_arith_event, Bn254FieldOperation, NUM_WORDS_PER_FE}; const NUM_COLS: usize = core::mem::size_of::>(); const OP: Bn254FieldOperation = Bn254FieldOperation::Add; @@ -101,10 +101,12 @@ impl MachineAir for Bn254ScalarAddChip { cols.eval.populate(&p, &q, OP.to_field_operation()); for i in 0..cols.p_access.len() { - cols.p_access[i].populate(event.arg1.memory_records[i], &mut new_byte_lookup_events); + cols.p_access[i] + .populate(event.arg1.memory_records[i], &mut new_byte_lookup_events); } for i in 0..cols.q_access.len() { - cols.q_access[i].populate(event.arg2.memory_records[i], &mut new_byte_lookup_events); + cols.q_access[i] + .populate(event.arg2.memory_records[i], &mut new_byte_lookup_events); } rows.push(row); diff --git a/core/src/syscall/precompiles/bn254_scalar/mac.rs b/core/src/syscall/precompiles/bn254_scalar/mac.rs index 5f9419c015..e663d2a731 100644 --- a/core/src/syscall/precompiles/bn254_scalar/mac.rs +++ b/core/src/syscall/precompiles/bn254_scalar/mac.rs @@ -6,8 +6,8 @@ use p3_air::{Air, AirBuilder, BaseAir}; use p3_field::AbstractField; use p3_field::{Field, PrimeField32}; use p3_matrix::{dense::RowMajorMatrix, Matrix}; -use typenum::U2; use sp1_derive::AlignedBorrow; +use typenum::{U4, U8}; use crate::{ air::MachineAir, @@ -25,7 +25,7 @@ use crate::{ }, }; -use super::{create_bn254_scalar_arith_event, NUM_WORDS_PER_FE, Bn254FieldOperation}; +use super::{create_bn254_scalar_arith_event, Bn254FieldOperation, NUM_WORDS_PER_FE}; const NUM_COLS: usize = core::mem::size_of::>(); const OP: Bn254FieldOperation = Bn254FieldOperation::Mac; @@ -107,16 +107,24 @@ impl MachineAir for Bn254ScalarMacChip { cols.add_eval.populate(&arg1, &mul, FieldOperation::Add); for i in 0..cols.arg1_access.len() { - cols.arg1_access[i].populate(event.arg1.memory_records[i], &mut new_byte_lookup_events); + cols.arg1_access[i] + .populate(event.arg1.memory_records[i], &mut new_byte_lookup_events); } for i in 0..cols.arg2_access.len() { - cols.arg2_access[i].populate(event.arg2.memory_records[i], &mut new_byte_lookup_events); + cols.arg2_access[i] + .populate(event.arg2.memory_records[i], &mut new_byte_lookup_events); } for i in 0..cols.a_access.len() { - cols.a_access[i].populate(event.a.as_ref().unwrap().memory_records[i], &mut new_byte_lookup_events); + cols.a_access[i].populate( + event.a.as_ref().unwrap().memory_records[i], + &mut new_byte_lookup_events, + ); } for i in 0..cols.b_access.len() { - cols.b_access[i].populate(event.b.as_ref().unwrap().memory_records[i], &mut new_byte_lookup_events); + cols.b_access[i].populate( + event.b.as_ref().unwrap().memory_records[i], + &mut new_byte_lookup_events, + ); } rows.push(row); @@ -166,19 +174,21 @@ where let arg1: Limbs<::Var, ::Limbs> = limbs_from_prev_access(&row.arg1_access); - let arg2: Limbs<::Var, U2> = limbs_from_prev_access(&row.arg2_access); + let arg2: Limbs<::Var, U8> = limbs_from_prev_access(&row.arg2_access); let a: Limbs<::Var, ::Limbs> = limbs_from_prev_access(&row.a_access); let b: Limbs<::Var, ::Limbs> = limbs_from_prev_access(&row.b_access); row.mul_eval.eval(builder, &a, &b, FieldOperation::Mul); - row.add_eval.eval(builder, &arg1, &row.mul_eval.result, FieldOperation::Add); + row.add_eval + .eval(builder, &arg1, &row.mul_eval.result, FieldOperation::Add); for i in 0..Bn254ScalarField::NB_LIMBS { - builder - .when(row.is_real) - .assert_eq(row.add_eval.result[i], row.arg1_access[i / 4].value()[i % 4]); + builder.when(row.is_real).assert_eq( + row.add_eval.result[i], + row.arg1_access[i / 4].value()[i % 4], + ); } builder.eval_memory_access_slice( @@ -197,10 +207,28 @@ where row.is_real, ); + let a_ptr = arg2.0[0..4] + .iter() + .rev() + .cloned() + .map(|v| v.into()) + .fold(AB::Expr::zero(), |acc, b| { + acc * AB::Expr::from_canonical_u16(0x100) + b + }); + + let b_ptr = arg2.0[4..8] + .iter() + .rev() + .cloned() + .map(|v| v.into()) + .fold(AB::Expr::zero(), |acc, b| { + acc * AB::Expr::from_canonical_u16(0x100) + b + }); + builder.eval_memory_access_slice( row.shard, row.clk.into(), - arg2[0], + a_ptr, &row.a_access, row.is_real, ); @@ -208,7 +236,7 @@ where builder.eval_memory_access_slice( row.shard, row.clk.into(), - arg2[0], + b_ptr, &row.b_access, row.is_real, ); @@ -223,4 +251,4 @@ where row.is_real, ); } -} \ No newline at end of file +} diff --git a/core/src/syscall/precompiles/bn254_scalar/mod.rs b/core/src/syscall/precompiles/bn254_scalar/mod.rs index 4558fc9cdb..d1903d4f38 100644 --- a/core/src/syscall/precompiles/bn254_scalar/mod.rs +++ b/core/src/syscall/precompiles/bn254_scalar/mod.rs @@ -1,15 +1,15 @@ mod add; -mod mul; mod mac; +mod mul; // mod general_field_op; pub use add::Bn254ScalarAddChip; -pub use mul::Bn254ScalarMulChip; pub use mac::Bn254ScalarMacChip; +pub use mul::Bn254ScalarMulChip; use crate::{ operations::field::{field_op::FieldOperation, params::Limbs}, - runtime::{MemoryReadRecord, MemoryWriteRecord, SyscallContext, MemoryRecordEnum}, + runtime::{MemoryReadRecord, MemoryRecordEnum, MemoryWriteRecord, SyscallContext}, utils::ec::{ field::{FieldParameters, NumWords}, weierstrass::bn254::Bn254ScalarField, @@ -25,18 +25,23 @@ pub(crate) const NUM_WORDS_PER_FE: usize = 8; #[derive(Clone, Debug, Serialize, Deserialize)] pub struct FieldArithMemoryAccess { pub ptr: u32, - pub memory_records: Vec + pub memory_records: Vec, } impl FieldArithMemoryAccess { pub fn read(rt: &mut SyscallContext, ptr: u32, len: usize) -> Self { let (memory_records, _) = rt.mr_slice(ptr, len); - Self { ptr, memory_records } + Self { + ptr, + memory_records, + } } pub fn value_as_biguint(&self) -> BigUint { BigUint::from_bytes_le( - &self.memory_records.iter() + &self + .memory_records + .iter() .flat_map(|word| word.value.to_le_bytes()) .collect::>(), ) @@ -45,13 +50,17 @@ impl FieldArithMemoryAccess { impl FieldArithMemoryAccess { pub fn write(rt: &mut SyscallContext, ptr: u32, values: &[u32]) -> Self { - Self { ptr, memory_records: rt.mw_slice(ptr, &values) } + Self { + ptr, + memory_records: rt.mw_slice(ptr, &values), + } } - pub fn prev_value_as_biguint(&self) -> BigUint { BigUint::from_bytes_le( - &self.memory_records.iter() + &self + .memory_records + .iter() .flat_map(|word| word.prev_value.to_le_bytes()) .collect::>(), ) @@ -83,7 +92,7 @@ pub struct Bn254FieldArithEvent { pub arg1: FieldArithMemoryAccess, pub arg2: FieldArithMemoryAccess, pub a: Option>, - pub b: Option> + pub b: Option>, } pub fn create_bn254_scalar_arith_event( @@ -105,11 +114,13 @@ pub fn create_bn254_scalar_arith_event( let arg1: Vec = rt.slice_unsafe(p_ptr, nw_per_fe); let arg2 = match op { Bn254FieldOperation::Mac => FieldArithMemoryAccess::read(rt, arg2, 2), - _ => FieldArithMemoryAccess::read(rt, arg2, nw_per_fe) + _ => FieldArithMemoryAccess::read(rt, arg2, nw_per_fe), }; let bn_arg1 = BigUint::from_bytes_le( - &arg1.iter().copied() + &arg1 + .iter() + .copied() .flat_map(|word| word.to_le_bytes()) .collect::>(), ); @@ -159,7 +170,7 @@ pub fn create_bn254_scalar_arith_event( arg1, arg2, a, - b + b, } } diff --git a/core/src/syscall/precompiles/bn254_scalar/mul.rs b/core/src/syscall/precompiles/bn254_scalar/mul.rs index 118aaff129..8f8ce32252 100644 --- a/core/src/syscall/precompiles/bn254_scalar/mul.rs +++ b/core/src/syscall/precompiles/bn254_scalar/mul.rs @@ -24,7 +24,7 @@ use crate::{ }, }; -use super::{create_bn254_scalar_arith_event, NUM_WORDS_PER_FE, Bn254FieldOperation}; +use super::{create_bn254_scalar_arith_event, Bn254FieldOperation, NUM_WORDS_PER_FE}; const NUM_COLS: usize = core::mem::size_of::>(); const OP: Bn254FieldOperation = Bn254FieldOperation::Mul; @@ -101,10 +101,12 @@ impl MachineAir for Bn254ScalarMulChip { cols.eval.populate(&p, &q, OP.to_field_operation()); for i in 0..cols.p_access.len() { - cols.p_access[i].populate(event.arg1.memory_records[i], &mut new_byte_lookup_events); + cols.p_access[i] + .populate(event.arg1.memory_records[i], &mut new_byte_lookup_events); } for i in 0..cols.q_access.len() { - cols.q_access[i].populate(event.arg2.memory_records[i], &mut new_byte_lookup_events); + cols.q_access[i] + .populate(event.arg2.memory_records[i], &mut new_byte_lookup_events); } rows.push(row); diff --git a/zkvm/precompiles/src/lib.rs b/zkvm/precompiles/src/lib.rs index a176e5066f..fe3ba5a0dc 100644 --- a/zkvm/precompiles/src/lib.rs +++ b/zkvm/precompiles/src/lib.rs @@ -35,4 +35,5 @@ extern "C" { pub fn syscall_bls12381_decompress(point: &mut [u8; 96], is_odd: bool); pub fn syscall_bn254_scalar_add(p: *mut u32, q: *const u32); pub fn syscall_bn254_scalar_mul(p: *mut u32, q: *const u32); + pub fn syscall_bn254_scalar_mac(ret: *mut u32, a: *const u32, b: *const u32); } From ee578f8fd21a6ec9336db03c64b1a6ceb0bd852a Mon Sep 17 00:00:00 2001 From: lightsing Date: Wed, 22 May 2024 17:56:26 +0800 Subject: [PATCH 18/34] fix p3-baby-bear dep --- Cargo.lock | 52 ++++++++++-------------- core/src/utils/config.rs | 6 +-- core/src/utils/prove.rs | 6 +-- primitives/src/lib.rs | 12 +++--- recursion/circuit/src/constraints.rs | 4 +- recursion/circuit/src/stark.rs | 6 +-- recursion/core/src/poseidon2/external.rs | 4 +- recursion/program/src/reduce.rs | 4 +- 8 files changed, 43 insertions(+), 51 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 5c7647b656..32ab13bcec 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2424,15 +2424,6 @@ dependencies = [ "either", ] -[[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" @@ -2938,7 +2929,7 @@ checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39" [[package]] name = "p3-air" version = "0.1.0" -source = "git+https://github.com/Plonky3/Plonky3.git?branch=sp1#d379375a75417ddfd0a059ce7db63e162ec52c69" +source = "git+https://github.com/Plonky3/Plonky3.git?branch=sp1#da0489b75025ec17f1100952694d8b7879c2b43e" dependencies = [ "p3-field", "p3-matrix", @@ -2947,7 +2938,7 @@ dependencies = [ [[package]] name = "p3-baby-bear" version = "0.1.0" -source = "git+https://github.com/Plonky3/Plonky3.git?branch=sp1#d379375a75417ddfd0a059ce7db63e162ec52c69" +source = "git+https://github.com/Plonky3/Plonky3.git?branch=sp1#da0489b75025ec17f1100952694d8b7879c2b43e" dependencies = [ "num-bigint 0.4.4", "p3-field", @@ -2961,7 +2952,7 @@ dependencies = [ [[package]] name = "p3-blake3" version = "0.1.0" -source = "git+https://github.com/Plonky3/Plonky3.git?branch=sp1#d379375a75417ddfd0a059ce7db63e162ec52c69" +source = "git+https://github.com/Plonky3/Plonky3.git?branch=sp1#da0489b75025ec17f1100952694d8b7879c2b43e" dependencies = [ "blake3", "p3-symmetric", @@ -2970,7 +2961,7 @@ dependencies = [ [[package]] name = "p3-bn254-fr" version = "0.1.0" -source = "git+https://github.com/Plonky3/Plonky3.git?branch=sp1#d379375a75417ddfd0a059ce7db63e162ec52c69" +source = "git+https://github.com/Plonky3/Plonky3.git?branch=sp1#da0489b75025ec17f1100952694d8b7879c2b43e" dependencies = [ "ff 0.13.0", "num-bigint 0.4.4", @@ -2984,7 +2975,7 @@ dependencies = [ [[package]] name = "p3-challenger" version = "0.1.0" -source = "git+https://github.com/Plonky3/Plonky3.git?branch=sp1#d379375a75417ddfd0a059ce7db63e162ec52c69" +source = "git+https://github.com/Plonky3/Plonky3.git?branch=sp1#da0489b75025ec17f1100952694d8b7879c2b43e" dependencies = [ "p3-field", "p3-maybe-rayon", @@ -2996,7 +2987,7 @@ dependencies = [ [[package]] name = "p3-commit" version = "0.1.0" -source = "git+https://github.com/Plonky3/Plonky3.git?branch=sp1#d379375a75417ddfd0a059ce7db63e162ec52c69" +source = "git+https://github.com/Plonky3/Plonky3.git?branch=sp1#da0489b75025ec17f1100952694d8b7879c2b43e" dependencies = [ "itertools 0.12.1", "p3-challenger", @@ -3009,7 +3000,7 @@ dependencies = [ [[package]] name = "p3-dft" version = "0.1.0" -source = "git+https://github.com/Plonky3/Plonky3.git?branch=sp1#d379375a75417ddfd0a059ce7db63e162ec52c69" +source = "git+https://github.com/Plonky3/Plonky3.git?branch=sp1#da0489b75025ec17f1100952694d8b7879c2b43e" dependencies = [ "p3-field", "p3-matrix", @@ -3021,7 +3012,7 @@ dependencies = [ [[package]] name = "p3-field" version = "0.1.0" -source = "git+https://github.com/Plonky3/Plonky3.git?branch=sp1#d379375a75417ddfd0a059ce7db63e162ec52c69" +source = "git+https://github.com/Plonky3/Plonky3.git?branch=sp1#da0489b75025ec17f1100952694d8b7879c2b43e" dependencies = [ "itertools 0.12.1", "num-bigint 0.4.4", @@ -3034,7 +3025,7 @@ dependencies = [ [[package]] name = "p3-fri" version = "0.1.0" -source = "git+https://github.com/Plonky3/Plonky3.git?branch=sp1#d379375a75417ddfd0a059ce7db63e162ec52c69" +source = "git+https://github.com/Plonky3/Plonky3.git?branch=sp1#da0489b75025ec17f1100952694d8b7879c2b43e" dependencies = [ "itertools 0.12.1", "p3-challenger", @@ -3052,7 +3043,7 @@ dependencies = [ [[package]] name = "p3-interpolation" version = "0.1.0" -source = "git+https://github.com/Plonky3/Plonky3.git?branch=sp1#d379375a75417ddfd0a059ce7db63e162ec52c69" +source = "git+https://github.com/Plonky3/Plonky3.git?branch=sp1#da0489b75025ec17f1100952694d8b7879c2b43e" dependencies = [ "p3-field", "p3-matrix", @@ -3062,7 +3053,7 @@ dependencies = [ [[package]] name = "p3-keccak" version = "0.1.0" -source = "git+https://github.com/Plonky3/Plonky3.git?branch=sp1#d379375a75417ddfd0a059ce7db63e162ec52c69" +source = "git+https://github.com/Plonky3/Plonky3.git?branch=sp1#da0489b75025ec17f1100952694d8b7879c2b43e" dependencies = [ "p3-symmetric", "tiny-keccak", @@ -3071,11 +3062,12 @@ dependencies = [ [[package]] name = "p3-keccak-air" version = "0.1.0" -source = "git+https://github.com/Plonky3/Plonky3.git?branch=sp1#d379375a75417ddfd0a059ce7db63e162ec52c69" +source = "git+https://github.com/Plonky3/Plonky3.git?branch=sp1#da0489b75025ec17f1100952694d8b7879c2b43e" dependencies = [ "p3-air", "p3-field", "p3-matrix", + "p3-maybe-rayon", "p3-util", "tracing", ] @@ -3083,7 +3075,7 @@ dependencies = [ [[package]] name = "p3-matrix" version = "0.1.0" -source = "git+https://github.com/Plonky3/Plonky3.git?branch=sp1#d379375a75417ddfd0a059ce7db63e162ec52c69" +source = "git+https://github.com/Plonky3/Plonky3.git?branch=sp1#da0489b75025ec17f1100952694d8b7879c2b43e" dependencies = [ "itertools 0.12.1", "p3-field", @@ -3097,7 +3089,7 @@ dependencies = [ [[package]] name = "p3-maybe-rayon" version = "0.1.0" -source = "git+https://github.com/Plonky3/Plonky3.git?branch=sp1#d379375a75417ddfd0a059ce7db63e162ec52c69" +source = "git+https://github.com/Plonky3/Plonky3.git?branch=sp1#da0489b75025ec17f1100952694d8b7879c2b43e" dependencies = [ "rayon", ] @@ -3105,9 +3097,9 @@ dependencies = [ [[package]] name = "p3-mds" version = "0.1.0" -source = "git+https://github.com/Plonky3/Plonky3.git?branch=sp1#d379375a75417ddfd0a059ce7db63e162ec52c69" +source = "git+https://github.com/Plonky3/Plonky3.git?branch=sp1#da0489b75025ec17f1100952694d8b7879c2b43e" dependencies = [ - "itertools 0.11.0", + "itertools 0.12.1", "p3-dft", "p3-field", "p3-matrix", @@ -3119,7 +3111,7 @@ dependencies = [ [[package]] name = "p3-merkle-tree" version = "0.1.0" -source = "git+https://github.com/Plonky3/Plonky3.git?branch=sp1#d379375a75417ddfd0a059ce7db63e162ec52c69" +source = "git+https://github.com/Plonky3/Plonky3.git?branch=sp1#da0489b75025ec17f1100952694d8b7879c2b43e" dependencies = [ "itertools 0.12.1", "p3-commit", @@ -3135,7 +3127,7 @@ dependencies = [ [[package]] name = "p3-poseidon2" version = "0.1.0" -source = "git+https://github.com/Plonky3/Plonky3.git?branch=sp1#d379375a75417ddfd0a059ce7db63e162ec52c69" +source = "git+https://github.com/Plonky3/Plonky3.git?branch=sp1#da0489b75025ec17f1100952694d8b7879c2b43e" dependencies = [ "gcd", "p3-field", @@ -3147,7 +3139,7 @@ dependencies = [ [[package]] name = "p3-symmetric" version = "0.1.0" -source = "git+https://github.com/Plonky3/Plonky3.git?branch=sp1#d379375a75417ddfd0a059ce7db63e162ec52c69" +source = "git+https://github.com/Plonky3/Plonky3.git?branch=sp1#da0489b75025ec17f1100952694d8b7879c2b43e" dependencies = [ "itertools 0.12.1", "p3-field", @@ -3157,7 +3149,7 @@ dependencies = [ [[package]] name = "p3-uni-stark" version = "0.1.0" -source = "git+https://github.com/Plonky3/Plonky3.git?branch=sp1#d379375a75417ddfd0a059ce7db63e162ec52c69" +source = "git+https://github.com/Plonky3/Plonky3.git?branch=sp1#da0489b75025ec17f1100952694d8b7879c2b43e" dependencies = [ "itertools 0.12.1", "p3-air", @@ -3175,7 +3167,7 @@ dependencies = [ [[package]] name = "p3-util" version = "0.1.0" -source = "git+https://github.com/Plonky3/Plonky3.git?branch=sp1#d379375a75417ddfd0a059ce7db63e162ec52c69" +source = "git+https://github.com/Plonky3/Plonky3.git?branch=sp1#da0489b75025ec17f1100952694d8b7879c2b43e" dependencies = [ "serde", ] diff --git a/core/src/utils/config.rs b/core/src/utils/config.rs index 21fee965fc..b63258a9f6 100644 --- a/core/src/utils/config.rs +++ b/core/src/utils/config.rs @@ -1,5 +1,5 @@ use crate::stark::StarkGenericConfig; -use p3_baby_bear::{BabyBear, DiffusionMatrixBabybear}; +use p3_baby_bear::{BabyBear, DiffusionMatrixBabyBear}; use p3_challenger::DuplexChallenger; use p3_commit::ExtensionMmcs; use p3_dft::Radix2DitParallel; @@ -23,7 +23,7 @@ const DIGEST_SIZE: usize = 8; pub type InnerVal = BabyBear; pub type InnerChallenge = BinomialExtensionField; pub type InnerPerm = - Poseidon2; + Poseidon2; pub type InnerHash = PaddingFreeSponge; pub type InnerDigestHash = Hash; pub type InnerDigest = [InnerVal; DIGEST_SIZE]; @@ -64,7 +64,7 @@ pub fn inner_perm() -> InnerPerm { Poseidon2ExternalMatrixGeneral, ROUNDS_P, internal_round_constants, - DiffusionMatrixBabybear, + DiffusionMatrixBabyBear, ) } diff --git a/core/src/utils/prove.rs b/core/src/utils/prove.rs index 1d84f093f5..918b0c2ab6 100644 --- a/core/src/utils/prove.rs +++ b/core/src/utils/prove.rs @@ -342,7 +342,7 @@ use p3_uni_stark::Proof; pub mod baby_bear_poseidon2 { - use p3_baby_bear::{BabyBear, DiffusionMatrixBabybear}; + use p3_baby_bear::{BabyBear, DiffusionMatrixBabyBear}; use p3_challenger::DuplexChallenger; use p3_commit::ExtensionMmcs; use p3_dft::Radix2DitParallel; @@ -361,7 +361,7 @@ pub mod baby_bear_poseidon2 { pub type Challenge = BinomialExtensionField; - pub type Perm = Poseidon2; + pub type Perm = Poseidon2; pub type MyHash = PaddingFreeSponge; pub type MyCompress = TruncatedPermutation; @@ -428,7 +428,7 @@ pub mod baby_bear_poseidon2 { Poseidon2ExternalMatrixGeneral, ROUNDS_P, internal_round_constants, - DiffusionMatrixBabybear, + DiffusionMatrixBabyBear, ); let hash = MyHash::new(perm.clone()); diff --git a/primitives/src/lib.rs b/primitives/src/lib.rs index 0637a075e4..0ffcea1ec3 100644 --- a/primitives/src/lib.rs +++ b/primitives/src/lib.rs @@ -2,7 +2,7 @@ //! Because it is imported in the zkvm entrypoint, it should be kept minimal. use lazy_static::lazy_static; -use p3_baby_bear::{BabyBear, DiffusionMatrixBabybear}; +use p3_baby_bear::{BabyBear, DiffusionMatrixBabyBear}; use p3_field::AbstractField; use p3_poseidon2::{Poseidon2, Poseidon2ExternalMatrixGeneral}; @@ -1100,7 +1100,7 @@ lazy_static! { } pub fn poseidon2_init( -) -> Poseidon2 { +) -> Poseidon2 { const ROUNDS_F: usize = 8; const ROUNDS_P: usize = 22; let mut round_constants = RC_16_30.to_vec(); @@ -1117,7 +1117,7 @@ pub fn poseidon2_init( Poseidon2ExternalMatrixGeneral, ROUNDS_P, internal_round_constants, - DiffusionMatrixBabybear, + DiffusionMatrixBabyBear, ) } @@ -1128,14 +1128,14 @@ pub fn poseidon2_hash(input: Vec) -> [BabyBear; 8] { } pub fn poseidon2_hasher() -> PaddingFreeSponge< - Poseidon2, + Poseidon2, 16, 8, 8, > { let hasher = poseidon2_init(); PaddingFreeSponge::< - Poseidon2, + Poseidon2, 16, 8, 8, @@ -1144,7 +1144,7 @@ pub fn poseidon2_hasher() -> PaddingFreeSponge< lazy_static! { pub static ref POSEIDON2_HASHER: PaddingFreeSponge::< - Poseidon2, + Poseidon2, 16, 8, 8, diff --git a/recursion/circuit/src/constraints.rs b/recursion/circuit/src/constraints.rs index bab344a67d..222130f5ba 100644 --- a/recursion/circuit/src/constraints.rs +++ b/recursion/circuit/src/constraints.rs @@ -165,7 +165,7 @@ where mod tests { use itertools::{izip, Itertools}; - use p3_baby_bear::DiffusionMatrixBabybear; + use p3_baby_bear::DiffusionMatrixBabyBear; use p3_challenger::{CanObserve, FieldChallenger}; use p3_commit::{Pcs, PolynomialSpace}; use serde::{de::DeserializeOwned, Serialize}; @@ -292,7 +292,7 @@ mod tests { sp1_core::utils::setup_logger(); let program = basic_program::(); let config = SC::new(); - let mut runtime = Runtime::::new_no_perm(&program); + let mut runtime = Runtime::::new_no_perm(&program); runtime.run(); let machine = A::machine(config); let (pk, vk) = machine.setup(&program); diff --git a/recursion/circuit/src/stark.rs b/recursion/circuit/src/stark.rs index fc128c4310..b8fd340ae8 100644 --- a/recursion/circuit/src/stark.rs +++ b/recursion/circuit/src/stark.rs @@ -296,7 +296,7 @@ pub(crate) mod tests { use crate::stark::build_wrap_circuit; use crate::witness::Witnessable; - use p3_baby_bear::DiffusionMatrixBabybear; + use p3_baby_bear::DiffusionMatrixBabyBear; use p3_field::PrimeField32; use serial_test::serial; use sp1_core::stark::{LocalProver, StarkGenericConfig}; @@ -339,7 +339,7 @@ pub(crate) mod tests { sp1_core::utils::setup_logger(); let program = basic_program::(); let config = SC::new(); - let mut runtime = Runtime::::new_no_perm(&program); + let mut runtime = Runtime::::new_no_perm(&program); runtime.run(); let machine = A::machine(config); let (pk, vk) = machine.setup(&program); @@ -348,7 +348,7 @@ pub(crate) mod tests { .prove::>(&pk, runtime.record, &mut challenger) .shard_proofs; - let mut runtime = Runtime::::new_no_perm(&program); + let mut runtime = Runtime::::new_no_perm(&program); runtime.run(); let mut witness = Witness::default(); diff --git a/recursion/core/src/poseidon2/external.rs b/recursion/core/src/poseidon2/external.rs index e7a331f9e8..f0434d41d7 100644 --- a/recursion/core/src/poseidon2/external.rs +++ b/recursion/core/src/poseidon2/external.rs @@ -333,7 +333,7 @@ mod tests { use std::time::Instant; use p3_baby_bear::BabyBear; - use p3_baby_bear::DiffusionMatrixBabybear; + use p3_baby_bear::DiffusionMatrixBabyBear; use p3_field::AbstractField; use p3_matrix::dense::RowMajorMatrix; use p3_poseidon2::Poseidon2; @@ -376,7 +376,7 @@ mod tests { let gt: Poseidon2< BabyBear, Poseidon2ExternalMatrixGeneral, - DiffusionMatrixBabybear, + DiffusionMatrixBabyBear, 16, 7, > = inner_perm(); diff --git a/recursion/program/src/reduce.rs b/recursion/program/src/reduce.rs index 05a0332476..9426cf9031 100644 --- a/recursion/program/src/reduce.rs +++ b/recursion/program/src/reduce.rs @@ -10,7 +10,7 @@ use crate::stark::StarkVerifier; use crate::types::ShardProofVariable; use crate::types::VerifyingKeyVariable; use p3_baby_bear::BabyBear; -use p3_baby_bear::DiffusionMatrixBabybear; +use p3_baby_bear::DiffusionMatrixBabyBear; use p3_challenger::DuplexChallenger; use p3_commit::ExtensionMmcs; use p3_commit::TwoAdicMultiplicativeCoset; @@ -53,7 +53,7 @@ type C = AsmConfig; type Val = BabyBear; type Challenge = BinomialExtensionField; -type Perm = Poseidon2; +type Perm = Poseidon2; type Hash = PaddingFreeSponge; type Compress = TruncatedPermutation; type ValMmcs = From 6aaec72d94947f5ef686b8d8f8b131c3ea6b2901 Mon Sep 17 00:00:00 2001 From: lightsing Date: Wed, 22 May 2024 18:21:27 +0800 Subject: [PATCH 19/34] remove add --- core/src/runtime/syscall.rs | 26 +-- core/src/stark/air.rs | 8 +- .../syscall/precompiles/bn254_scalar/add.rs | 196 ------------------ .../syscall/precompiles/bn254_scalar/mac.rs | 2 +- .../syscall/precompiles/bn254_scalar/mod.rs | 7 +- .../syscall/precompiles/bn254_scalar/mul.rs | 2 +- examples/poseidon_bn254/program/Cargo.lock | 44 ++-- examples/poseidon_bn254/script/Cargo.lock | 52 ++--- tests/bn254-scalar-arith/src/main.rs | 1 - zkvm/entrypoint/src/syscalls/bn254.rs | 17 -- zkvm/entrypoint/src/syscalls/mod.rs | 7 +- zkvm/precompiles/src/lib.rs | 1 - 12 files changed, 53 insertions(+), 310 deletions(-) delete mode 100644 core/src/syscall/precompiles/bn254_scalar/add.rs diff --git a/core/src/runtime/syscall.rs b/core/src/runtime/syscall.rs index 36890c550e..652da6c76b 100644 --- a/core/src/runtime/syscall.rs +++ b/core/src/runtime/syscall.rs @@ -5,9 +5,7 @@ use strum_macros::EnumIter; use crate::runtime::{Register, Runtime}; use crate::stark::Blake3CompressInnerChip; -use crate::syscall::precompiles::bn254_scalar::{ - Bn254ScalarAddChip, Bn254ScalarMacChip, Bn254ScalarMulChip, -}; +use crate::syscall::precompiles::bn254_scalar::{Bn254ScalarMacChip, Bn254ScalarMulChip}; use crate::syscall::precompiles::edwards::EdAddAssignChip; use crate::syscall::precompiles::edwards::EdDecompressChip; use crate::syscall::precompiles::keccak256::KeccakPermuteChip; @@ -106,14 +104,11 @@ pub enum SyscallCode { /// Executes the `BLS12381_DOUBLE` precompile. BLS12381_DOUBLE = 0x00_00_01_1F, - /// Executes the `BN254_SCALAR_Add` precompile. - BN254_SCALAR_ADD = 0x00_01_01_20, - /// Execute the `BN254_SCALAR_MUL` precompile. - BN254_SCALAR_MUL = 0x00_01_01_21, + BN254_SCALAR_MUL = 0x00_01_01_20, /// Execute the `BN254_SCALAR_MAC` precompile. - BN254_SCALAR_MAC = 0x00_01_01_22, + BN254_SCALAR_MAC = 0x00_01_01_21, } impl SyscallCode { @@ -144,9 +139,8 @@ impl SyscallCode { 0x00_00_00_F1 => SyscallCode::HINT_READ, 0x00_00_01_1D => SyscallCode::UINT256_MUL, 0x00_00_01_1C => SyscallCode::BLS12381_DECOMPRESS, - 0x00_01_01_20 => SyscallCode::BN254_SCALAR_ADD, - 0x00_01_01_21 => SyscallCode::BN254_SCALAR_MUL, - 0x00_01_01_22 => SyscallCode::BN254_SCALAR_MAC, + 0x00_01_01_20 => SyscallCode::BN254_SCALAR_MUL, + 0x00_01_01_21 => SyscallCode::BN254_SCALAR_MAC, _ => panic!("invalid syscall number: {}", value), } } @@ -351,10 +345,6 @@ pub fn default_syscall_map() -> HashMap> { Rc::new(WeierstrassDecompressChip::::new()), ); syscall_map.insert(SyscallCode::UINT256_MUL, Rc::new(Uint256MulChip::new())); - syscall_map.insert( - SyscallCode::BN254_SCALAR_ADD, - Rc::new(Bn254ScalarAddChip::new()), - ); syscall_map.insert( SyscallCode::BN254_SCALAR_MUL, Rc::new(Bn254ScalarMulChip::new()), @@ -460,12 +450,12 @@ mod tests { SyscallCode::BLS12381_DECOMPRESS => { assert_eq!(code as u32, sp1_zkvm::syscalls::BLS12381_DECOMPRESS) } - SyscallCode::BN254_SCALAR_ADD => { - assert_eq!(code as u32, sp1_zkvm::syscalls::BN254_SCALAR_ADD) - } SyscallCode::BN254_SCALAR_MUL => { assert_eq!(code as u32, sp1_zkvm::syscalls::BN254_SCALAR_MUL) } + SyscallCode::BN254_SCALAR_MAC => { + assert_eq!(code as u32, sp1_zkvm::syscalls::BN254_SCALAR_MAC) + } } } } diff --git a/core/src/stark/air.rs b/core/src/stark/air.rs index 4879241c8f..c849df8dc4 100644 --- a/core/src/stark/air.rs +++ b/core/src/stark/air.rs @@ -21,9 +21,7 @@ pub(crate) mod riscv_chips { pub use crate::memory::MemoryChip; pub use crate::program::ProgramChip; pub use crate::syscall::precompiles::blake3::Blake3CompressInnerChip; - pub use crate::syscall::precompiles::bn254_scalar::{ - Bn254ScalarAddChip, Bn254ScalarMacChip, Bn254ScalarMulChip, - }; + pub use crate::syscall::precompiles::bn254_scalar::{Bn254ScalarMacChip, Bn254ScalarMulChip}; pub use crate::syscall::precompiles::edwards::EdAddAssignChip; pub use crate::syscall::precompiles::edwards::EdDecompressChip; pub use crate::syscall::precompiles::keccak256::KeccakPermuteChip; @@ -102,8 +100,6 @@ pub enum RiscvAir { Bls12381Double(WeierstrassDoubleAssignChip>), /// A precompile for uint256 mul. Uint256Mul(Uint256MulChip), - /// A precompile for bn254 scalar addition. - Bn254ScalarAdd(Bn254ScalarAddChip), /// A precompile for bn254 scalar multiplication. Bn254ScalarMul(Bn254ScalarMulChip), /// A precompile for bn254 scalar mul-add @@ -157,8 +153,6 @@ impl RiscvAir { chips.push(RiscvAir::Bls12381Double(bls12381_double)); let uint256_mul = Uint256MulChip::default(); chips.push(RiscvAir::Uint256Mul(uint256_mul)); - let bn254_scalar_add = Bn254ScalarAddChip::new(); - chips.push(RiscvAir::Bn254ScalarAdd(bn254_scalar_add)); let bn254_scalar_mul = Bn254ScalarMulChip::new(); chips.push(RiscvAir::Bn254ScalarMul(bn254_scalar_mul)); let bn254_scalar_mac = Bn254ScalarMacChip::new(); diff --git a/core/src/syscall/precompiles/bn254_scalar/add.rs b/core/src/syscall/precompiles/bn254_scalar/add.rs deleted file mode 100644 index ffd0b7969e..0000000000 --- a/core/src/syscall/precompiles/bn254_scalar/add.rs +++ /dev/null @@ -1,196 +0,0 @@ -use std::borrow::{Borrow, BorrowMut}; - -use num::BigUint; -use num::Zero; -use p3_air::{Air, AirBuilder, BaseAir}; -use p3_field::AbstractField; -use p3_field::{Field, PrimeField32}; -use p3_matrix::{dense::RowMajorMatrix, Matrix}; -use sp1_derive::AlignedBorrow; - -use crate::{ - air::MachineAir, - memory::{MemoryCols, MemoryReadCols, MemoryWriteCols}, - operations::field::field_op::FieldOpCols, - runtime::{ExecutionRecord, Program, Syscall, SyscallCode}, - stark::SP1AirBuilder, - syscall::precompiles::bn254_scalar::Limbs, - utils::{ - ec::{ - field::{FieldParameters, NumLimbs}, - weierstrass::bn254::Bn254ScalarField, - }, - limbs_from_prev_access, pad_rows, - }, -}; - -use super::{create_bn254_scalar_arith_event, Bn254FieldOperation, NUM_WORDS_PER_FE}; - -const NUM_COLS: usize = core::mem::size_of::>(); -const OP: Bn254FieldOperation = Bn254FieldOperation::Add; - -#[derive(Debug, Clone, AlignedBorrow)] -#[repr(C)] -pub struct Bn254ScalarAddCols { - is_real: T, - shard: T, - clk: T, - p_ptr: T, - q_ptr: T, - p_access: [MemoryWriteCols; NUM_WORDS_PER_FE], - q_access: [MemoryReadCols; NUM_WORDS_PER_FE], - eval: FieldOpCols, -} - -pub struct Bn254ScalarAddChip; - -impl Bn254ScalarAddChip { - pub fn new() -> Self { - Self - } -} - -impl Syscall for Bn254ScalarAddChip { - fn execute( - &self, - rt: &mut crate::runtime::SyscallContext, - arg1: u32, - arg2: u32, - ) -> Option { - let event = create_bn254_scalar_arith_event(rt, arg1, arg2, OP); - rt.record_mut().bn254_scalar_arith_events.push(event); - - None - } - - fn num_extra_cycles(&self) -> u32 { - 1 - } -} - -impl MachineAir for Bn254ScalarAddChip { - type Record = ExecutionRecord; - - type Program = Program; - - fn name(&self) -> String { - "Bn254ScalarAdd".to_string() - } - - fn generate_trace(&self, input: &Self::Record, output: &mut Self::Record) -> RowMajorMatrix { - let mut rows = vec![]; - let mut new_byte_lookup_events = vec![]; - - for event in input - .bn254_scalar_arith_events - .iter() - .filter(|e| e.op == OP) - { - let mut row = [F::zero(); NUM_COLS]; - let cols: &mut Bn254ScalarAddCols = row.as_mut_slice().borrow_mut(); - - let p = event.arg1.prev_value_as_biguint(); - let q = event.arg2.value_as_biguint(); - - cols.is_real = F::one(); - cols.shard = F::from_canonical_u32(event.shard); - cols.clk = F::from_canonical_u32(event.clk); - cols.p_ptr = F::from_canonical_u32(event.arg1.ptr); - cols.q_ptr = F::from_canonical_u32(event.arg2.ptr); - - cols.eval.populate(&p, &q, OP.to_field_operation()); - - for i in 0..cols.p_access.len() { - cols.p_access[i] - .populate(event.arg1.memory_records[i], &mut new_byte_lookup_events); - } - for i in 0..cols.q_access.len() { - cols.q_access[i] - .populate(event.arg2.memory_records[i], &mut new_byte_lookup_events); - } - - rows.push(row); - } - output.add_byte_lookup_events(new_byte_lookup_events); - - pad_rows(&mut rows, || { - let mut row = [F::zero(); NUM_COLS]; - let cols: &mut Bn254ScalarAddCols = row.as_mut_slice().borrow_mut(); - - let zero = BigUint::zero(); - cols.eval.populate(&zero, &zero, OP.to_field_operation()); - - row - }); - - RowMajorMatrix::new(rows.into_iter().flatten().collect::>(), NUM_COLS) - } - - fn included(&self, shard: &Self::Record) -> bool { - shard - .bn254_scalar_arith_events - .iter() - .filter(|e| e.op == OP) - .count() - != 0 - } -} - -impl BaseAir for Bn254ScalarAddChip { - fn width(&self) -> usize { - NUM_COLS - } -} - -impl Air for Bn254ScalarAddChip -where - AB: SP1AirBuilder, - // AB::Expr: Copy, -{ - fn eval(&self, builder: &mut AB) { - let main = builder.main(); - let row = main.row_slice(0); - let row: &Bn254ScalarAddCols = (*row).borrow(); - - builder.assert_bool(row.is_real); - - let p: Limbs<::Var, ::Limbs> = - limbs_from_prev_access(&row.p_access); - let q: Limbs<::Var, ::Limbs> = - limbs_from_prev_access(&row.q_access); - - row.eval.eval(builder, &p, &q, OP.to_field_operation()); - - for i in 0..Bn254ScalarField::NB_LIMBS { - builder - .when(row.is_real) - .assert_eq(row.eval.result[i], row.p_access[i / 4].value()[i % 4]); - } - - builder.eval_memory_access_slice( - row.shard, - row.clk.into(), - row.q_ptr, - &row.q_access, - row.is_real, - ); - - builder.eval_memory_access_slice( - row.shard, - row.clk.into(), - row.p_ptr, - &row.p_access, - row.is_real, - ); - - let syscall_id = AB::F::from_canonical_u32(SyscallCode::BN254_SCALAR_ADD.syscall_id()); - builder.receive_syscall( - row.shard, - row.clk, - syscall_id, - row.p_ptr, - row.q_ptr, - row.is_real, - ); - } -} diff --git a/core/src/syscall/precompiles/bn254_scalar/mac.rs b/core/src/syscall/precompiles/bn254_scalar/mac.rs index e663d2a731..f8fdec334f 100644 --- a/core/src/syscall/precompiles/bn254_scalar/mac.rs +++ b/core/src/syscall/precompiles/bn254_scalar/mac.rs @@ -7,7 +7,7 @@ use p3_field::AbstractField; use p3_field::{Field, PrimeField32}; use p3_matrix::{dense::RowMajorMatrix, Matrix}; use sp1_derive::AlignedBorrow; -use typenum::{U4, U8}; +use typenum::U8; use crate::{ air::MachineAir, diff --git a/core/src/syscall/precompiles/bn254_scalar/mod.rs b/core/src/syscall/precompiles/bn254_scalar/mod.rs index d1903d4f38..602b201bfa 100644 --- a/core/src/syscall/precompiles/bn254_scalar/mod.rs +++ b/core/src/syscall/precompiles/bn254_scalar/mod.rs @@ -1,15 +1,13 @@ -mod add; mod mac; mod mul; // mod general_field_op; -pub use add::Bn254ScalarAddChip; pub use mac::Bn254ScalarMacChip; pub use mul::Bn254ScalarMulChip; use crate::{ operations::field::{field_op::FieldOperation, params::Limbs}, - runtime::{MemoryReadRecord, MemoryRecordEnum, MemoryWriteRecord, SyscallContext}, + runtime::{MemoryReadRecord, MemoryWriteRecord, SyscallContext}, utils::ec::{ field::{FieldParameters, NumWords}, weierstrass::bn254::Bn254ScalarField, @@ -69,7 +67,6 @@ impl FieldArithMemoryAccess { #[derive(PartialEq, Copy, Clone, Debug, Serialize, Deserialize)] pub enum Bn254FieldOperation { - Add = 0, Mul = 2, Mac = 4, } @@ -77,7 +74,6 @@ pub enum Bn254FieldOperation { impl Bn254FieldOperation { pub const fn to_field_operation(&self) -> FieldOperation { match self { - Bn254FieldOperation::Add => FieldOperation::Add, Bn254FieldOperation::Mul => FieldOperation::Mul, Bn254FieldOperation::Mac => panic!("not supported"), } @@ -139,7 +135,6 @@ pub fn create_bn254_scalar_arith_event( let bn_arg2 = arg2.value_as_biguint(); let bn_arg1_out = match op { - Bn254FieldOperation::Add => (&bn_arg1 + &bn_arg2) % modulus, Bn254FieldOperation::Mul => (&bn_arg1 * &bn_arg2) % modulus, _ => unimplemented!("not supported"), }; diff --git a/core/src/syscall/precompiles/bn254_scalar/mul.rs b/core/src/syscall/precompiles/bn254_scalar/mul.rs index 8f8ce32252..2cd7d1d373 100644 --- a/core/src/syscall/precompiles/bn254_scalar/mul.rs +++ b/core/src/syscall/precompiles/bn254_scalar/mul.rs @@ -11,7 +11,7 @@ use sp1_derive::AlignedBorrow; use crate::{ air::MachineAir, memory::{MemoryCols, MemoryReadCols, MemoryWriteCols}, - operations::field::field_op::{FieldOpCols, FieldOperation}, + operations::field::field_op::FieldOpCols, runtime::{ExecutionRecord, Program, Syscall, SyscallCode}, stark::SP1AirBuilder, syscall::precompiles::bn254_scalar::Limbs, diff --git a/examples/poseidon_bn254/program/Cargo.lock b/examples/poseidon_bn254/program/Cargo.lock index e9a2f26674..1e808ebc16 100644 --- a/examples/poseidon_bn254/program/Cargo.lock +++ b/examples/poseidon_bn254/program/Cargo.lock @@ -216,7 +216,7 @@ checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" [[package]] name = "ff" version = "0.13.0" -source = "git+https://github.com/scroll-tech/ff?rev=7e94aa6#7e94aa6726837138b1b8346ec55b6ce6b593dc96" +source = "git+https://github.com/scroll-tech/ff?branch=feat/sp1#7e94aa6726837138b1b8346ec55b6ce6b593dc96" dependencies = [ "bitvec", "rand_core", @@ -271,7 +271,7 @@ dependencies = [ [[package]] name = "halo2curves" version = "0.3.3" -source = "git+https://github.com/lightsing/halo2curves.git?branch=feat/sp1#bade656dfc358b3dd587caf1f7756210f4edca6f" +source = "git+https://github.com/scroll-tech/halo2curves.git?branch=feat/sp1#366a78b34dbf3ebaed78435f8f16e033a7bcecfa" dependencies = [ "ff", "group", @@ -282,7 +282,6 @@ dependencies = [ "paste", "rand", "rand_core", - "serde", "static_assertions", "subtle", ] @@ -329,15 +328,6 @@ dependencies = [ "hashbrown", ] -[[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" @@ -471,7 +461,7 @@ checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" [[package]] name = "p3-baby-bear" version = "0.1.0" -source = "git+https://github.com/Plonky3/Plonky3.git?branch=sp1#d379375a75417ddfd0a059ce7db63e162ec52c69" +source = "git+https://github.com/Plonky3/Plonky3.git?branch=sp1#da0489b75025ec17f1100952694d8b7879c2b43e" dependencies = [ "num-bigint", "p3-field", @@ -485,7 +475,7 @@ dependencies = [ [[package]] name = "p3-dft" version = "0.1.0" -source = "git+https://github.com/Plonky3/Plonky3.git?branch=sp1#d379375a75417ddfd0a059ce7db63e162ec52c69" +source = "git+https://github.com/Plonky3/Plonky3.git?branch=sp1#da0489b75025ec17f1100952694d8b7879c2b43e" dependencies = [ "p3-field", "p3-matrix", @@ -497,9 +487,9 @@ dependencies = [ [[package]] name = "p3-field" version = "0.1.0" -source = "git+https://github.com/Plonky3/Plonky3.git?branch=sp1#d379375a75417ddfd0a059ce7db63e162ec52c69" +source = "git+https://github.com/Plonky3/Plonky3.git?branch=sp1#da0489b75025ec17f1100952694d8b7879c2b43e" dependencies = [ - "itertools 0.12.1", + "itertools", "num-bigint", "num-traits", "p3-util", @@ -510,9 +500,9 @@ dependencies = [ [[package]] name = "p3-matrix" version = "0.1.0" -source = "git+https://github.com/Plonky3/Plonky3.git?branch=sp1#d379375a75417ddfd0a059ce7db63e162ec52c69" +source = "git+https://github.com/Plonky3/Plonky3.git?branch=sp1#da0489b75025ec17f1100952694d8b7879c2b43e" dependencies = [ - "itertools 0.12.1", + "itertools", "p3-field", "p3-maybe-rayon", "p3-util", @@ -524,14 +514,14 @@ dependencies = [ [[package]] name = "p3-maybe-rayon" version = "0.1.0" -source = "git+https://github.com/Plonky3/Plonky3.git?branch=sp1#d379375a75417ddfd0a059ce7db63e162ec52c69" +source = "git+https://github.com/Plonky3/Plonky3.git?branch=sp1#da0489b75025ec17f1100952694d8b7879c2b43e" [[package]] name = "p3-mds" version = "0.1.0" -source = "git+https://github.com/Plonky3/Plonky3.git?branch=sp1#d379375a75417ddfd0a059ce7db63e162ec52c69" +source = "git+https://github.com/Plonky3/Plonky3.git?branch=sp1#da0489b75025ec17f1100952694d8b7879c2b43e" dependencies = [ - "itertools 0.11.0", + "itertools", "p3-dft", "p3-field", "p3-matrix", @@ -543,7 +533,7 @@ dependencies = [ [[package]] name = "p3-poseidon2" version = "0.1.0" -source = "git+https://github.com/Plonky3/Plonky3.git?branch=sp1#d379375a75417ddfd0a059ce7db63e162ec52c69" +source = "git+https://github.com/Plonky3/Plonky3.git?branch=sp1#da0489b75025ec17f1100952694d8b7879c2b43e" dependencies = [ "gcd", "p3-field", @@ -555,9 +545,9 @@ dependencies = [ [[package]] name = "p3-symmetric" version = "0.1.0" -source = "git+https://github.com/Plonky3/Plonky3.git?branch=sp1#d379375a75417ddfd0a059ce7db63e162ec52c69" +source = "git+https://github.com/Plonky3/Plonky3.git?branch=sp1#da0489b75025ec17f1100952694d8b7879c2b43e" dependencies = [ - "itertools 0.12.1", + "itertools", "p3-field", "serde", ] @@ -565,7 +555,7 @@ dependencies = [ [[package]] name = "p3-util" version = "0.1.0" -source = "git+https://github.com/Plonky3/Plonky3.git?branch=sp1#d379375a75417ddfd0a059ce7db63e162ec52c69" +source = "git+https://github.com/Plonky3/Plonky3.git?branch=sp1#da0489b75025ec17f1100952694d8b7879c2b43e" dependencies = [ "serde", ] @@ -634,7 +624,7 @@ dependencies = [ [[package]] name = "poseidon-base" version = "0.1.0" -source = "git+https://github.com/scroll-tech/poseidon-circuit.git?branch=feat/sp1#eb4126462778084e0a19df6ef22e8a8dd6fea187" +source = "git+https://github.com/scroll-tech/poseidon-circuit.git?branch=feat/sp1#5509d2e5f9b9868bb14fe6b51fe6a9dc77289c26" dependencies = [ "bitvec", "halo2curves", @@ -851,7 +841,7 @@ dependencies = [ name = "sp1-primitives" version = "0.1.0" dependencies = [ - "itertools 0.12.1", + "itertools", "lazy_static", "p3-baby-bear", "p3-field", diff --git a/examples/poseidon_bn254/script/Cargo.lock b/examples/poseidon_bn254/script/Cargo.lock index b0bffe064b..7f5252662d 100644 --- a/examples/poseidon_bn254/script/Cargo.lock +++ b/examples/poseidon_bn254/script/Cargo.lock @@ -2007,15 +2007,6 @@ dependencies = [ "either", ] -[[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" @@ -2411,7 +2402,7 @@ checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39" [[package]] name = "p3-air" version = "0.1.0" -source = "git+https://github.com/Plonky3/Plonky3.git?branch=sp1#d379375a75417ddfd0a059ce7db63e162ec52c69" +source = "git+https://github.com/Plonky3/Plonky3.git?branch=sp1#da0489b75025ec17f1100952694d8b7879c2b43e" dependencies = [ "p3-field", "p3-matrix", @@ -2420,7 +2411,7 @@ dependencies = [ [[package]] name = "p3-baby-bear" version = "0.1.0" -source = "git+https://github.com/Plonky3/Plonky3.git?branch=sp1#d379375a75417ddfd0a059ce7db63e162ec52c69" +source = "git+https://github.com/Plonky3/Plonky3.git?branch=sp1#da0489b75025ec17f1100952694d8b7879c2b43e" dependencies = [ "num-bigint", "p3-field", @@ -2434,7 +2425,7 @@ dependencies = [ [[package]] name = "p3-blake3" version = "0.1.0" -source = "git+https://github.com/Plonky3/Plonky3.git?branch=sp1#d379375a75417ddfd0a059ce7db63e162ec52c69" +source = "git+https://github.com/Plonky3/Plonky3.git?branch=sp1#da0489b75025ec17f1100952694d8b7879c2b43e" dependencies = [ "blake3", "p3-symmetric", @@ -2443,7 +2434,7 @@ dependencies = [ [[package]] name = "p3-challenger" version = "0.1.0" -source = "git+https://github.com/Plonky3/Plonky3.git?branch=sp1#d379375a75417ddfd0a059ce7db63e162ec52c69" +source = "git+https://github.com/Plonky3/Plonky3.git?branch=sp1#da0489b75025ec17f1100952694d8b7879c2b43e" dependencies = [ "p3-field", "p3-maybe-rayon", @@ -2455,7 +2446,7 @@ dependencies = [ [[package]] name = "p3-commit" version = "0.1.0" -source = "git+https://github.com/Plonky3/Plonky3.git?branch=sp1#d379375a75417ddfd0a059ce7db63e162ec52c69" +source = "git+https://github.com/Plonky3/Plonky3.git?branch=sp1#da0489b75025ec17f1100952694d8b7879c2b43e" dependencies = [ "itertools 0.12.1", "p3-challenger", @@ -2468,7 +2459,7 @@ dependencies = [ [[package]] name = "p3-dft" version = "0.1.0" -source = "git+https://github.com/Plonky3/Plonky3.git?branch=sp1#d379375a75417ddfd0a059ce7db63e162ec52c69" +source = "git+https://github.com/Plonky3/Plonky3.git?branch=sp1#da0489b75025ec17f1100952694d8b7879c2b43e" dependencies = [ "p3-field", "p3-matrix", @@ -2480,7 +2471,7 @@ dependencies = [ [[package]] name = "p3-field" version = "0.1.0" -source = "git+https://github.com/Plonky3/Plonky3.git?branch=sp1#d379375a75417ddfd0a059ce7db63e162ec52c69" +source = "git+https://github.com/Plonky3/Plonky3.git?branch=sp1#da0489b75025ec17f1100952694d8b7879c2b43e" dependencies = [ "itertools 0.12.1", "num-bigint", @@ -2493,7 +2484,7 @@ dependencies = [ [[package]] name = "p3-fri" version = "0.1.0" -source = "git+https://github.com/Plonky3/Plonky3.git?branch=sp1#d379375a75417ddfd0a059ce7db63e162ec52c69" +source = "git+https://github.com/Plonky3/Plonky3.git?branch=sp1#da0489b75025ec17f1100952694d8b7879c2b43e" dependencies = [ "itertools 0.12.1", "p3-challenger", @@ -2511,7 +2502,7 @@ dependencies = [ [[package]] name = "p3-interpolation" version = "0.1.0" -source = "git+https://github.com/Plonky3/Plonky3.git?branch=sp1#d379375a75417ddfd0a059ce7db63e162ec52c69" +source = "git+https://github.com/Plonky3/Plonky3.git?branch=sp1#da0489b75025ec17f1100952694d8b7879c2b43e" dependencies = [ "p3-field", "p3-matrix", @@ -2521,7 +2512,7 @@ dependencies = [ [[package]] name = "p3-keccak" version = "0.1.0" -source = "git+https://github.com/Plonky3/Plonky3.git?branch=sp1#d379375a75417ddfd0a059ce7db63e162ec52c69" +source = "git+https://github.com/Plonky3/Plonky3.git?branch=sp1#da0489b75025ec17f1100952694d8b7879c2b43e" dependencies = [ "p3-symmetric", "tiny-keccak", @@ -2530,11 +2521,12 @@ dependencies = [ [[package]] name = "p3-keccak-air" version = "0.1.0" -source = "git+https://github.com/Plonky3/Plonky3.git?branch=sp1#d379375a75417ddfd0a059ce7db63e162ec52c69" +source = "git+https://github.com/Plonky3/Plonky3.git?branch=sp1#da0489b75025ec17f1100952694d8b7879c2b43e" dependencies = [ "p3-air", "p3-field", "p3-matrix", + "p3-maybe-rayon", "p3-util", "tracing", ] @@ -2542,7 +2534,7 @@ dependencies = [ [[package]] name = "p3-matrix" version = "0.1.0" -source = "git+https://github.com/Plonky3/Plonky3.git?branch=sp1#d379375a75417ddfd0a059ce7db63e162ec52c69" +source = "git+https://github.com/Plonky3/Plonky3.git?branch=sp1#da0489b75025ec17f1100952694d8b7879c2b43e" dependencies = [ "itertools 0.12.1", "p3-field", @@ -2556,7 +2548,7 @@ dependencies = [ [[package]] name = "p3-maybe-rayon" version = "0.1.0" -source = "git+https://github.com/Plonky3/Plonky3.git?branch=sp1#d379375a75417ddfd0a059ce7db63e162ec52c69" +source = "git+https://github.com/Plonky3/Plonky3.git?branch=sp1#da0489b75025ec17f1100952694d8b7879c2b43e" dependencies = [ "rayon", ] @@ -2564,9 +2556,9 @@ dependencies = [ [[package]] name = "p3-mds" version = "0.1.0" -source = "git+https://github.com/Plonky3/Plonky3.git?branch=sp1#d379375a75417ddfd0a059ce7db63e162ec52c69" +source = "git+https://github.com/Plonky3/Plonky3.git?branch=sp1#da0489b75025ec17f1100952694d8b7879c2b43e" dependencies = [ - "itertools 0.11.0", + "itertools 0.12.1", "p3-dft", "p3-field", "p3-matrix", @@ -2578,7 +2570,7 @@ dependencies = [ [[package]] name = "p3-merkle-tree" version = "0.1.0" -source = "git+https://github.com/Plonky3/Plonky3.git?branch=sp1#d379375a75417ddfd0a059ce7db63e162ec52c69" +source = "git+https://github.com/Plonky3/Plonky3.git?branch=sp1#da0489b75025ec17f1100952694d8b7879c2b43e" dependencies = [ "itertools 0.12.1", "p3-commit", @@ -2594,7 +2586,7 @@ dependencies = [ [[package]] name = "p3-poseidon2" version = "0.1.0" -source = "git+https://github.com/Plonky3/Plonky3.git?branch=sp1#d379375a75417ddfd0a059ce7db63e162ec52c69" +source = "git+https://github.com/Plonky3/Plonky3.git?branch=sp1#da0489b75025ec17f1100952694d8b7879c2b43e" dependencies = [ "gcd", "p3-field", @@ -2606,7 +2598,7 @@ dependencies = [ [[package]] name = "p3-symmetric" version = "0.1.0" -source = "git+https://github.com/Plonky3/Plonky3.git?branch=sp1#d379375a75417ddfd0a059ce7db63e162ec52c69" +source = "git+https://github.com/Plonky3/Plonky3.git?branch=sp1#da0489b75025ec17f1100952694d8b7879c2b43e" dependencies = [ "itertools 0.12.1", "p3-field", @@ -2616,7 +2608,7 @@ dependencies = [ [[package]] name = "p3-uni-stark" version = "0.1.0" -source = "git+https://github.com/Plonky3/Plonky3.git?branch=sp1#d379375a75417ddfd0a059ce7db63e162ec52c69" +source = "git+https://github.com/Plonky3/Plonky3.git?branch=sp1#da0489b75025ec17f1100952694d8b7879c2b43e" dependencies = [ "itertools 0.12.1", "p3-air", @@ -2634,7 +2626,7 @@ dependencies = [ [[package]] name = "p3-util" version = "0.1.0" -source = "git+https://github.com/Plonky3/Plonky3.git?branch=sp1#d379375a75417ddfd0a059ce7db63e162ec52c69" +source = "git+https://github.com/Plonky3/Plonky3.git?branch=sp1#da0489b75025ec17f1100952694d8b7879c2b43e" dependencies = [ "serde", ] @@ -2892,7 +2884,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "19de2de2a00075bf566bee3bd4db014b11587e84184d3f7a791bc17f1a8e9e48" dependencies = [ "anyhow", - "itertools 0.12.1", + "itertools 0.10.5", "proc-macro2", "quote", "syn 2.0.61", diff --git a/tests/bn254-scalar-arith/src/main.rs b/tests/bn254-scalar-arith/src/main.rs index bbda639665..6adc9e0cc4 100644 --- a/tests/bn254-scalar-arith/src/main.rs +++ b/tests/bn254-scalar-arith/src/main.rs @@ -2,7 +2,6 @@ sp1_zkvm::entrypoint!(main); extern "C" { - fn syscall_bn254_scalar_add(p: *mut u32, q: *const u32); fn syscall_bn254_scalar_mul(p: *mut u32, q: *const u32); } diff --git a/zkvm/entrypoint/src/syscalls/bn254.rs b/zkvm/entrypoint/src/syscalls/bn254.rs index e080bdbf87..e719a838d8 100644 --- a/zkvm/entrypoint/src/syscalls/bn254.rs +++ b/zkvm/entrypoint/src/syscalls/bn254.rs @@ -41,23 +41,6 @@ pub extern "C" fn syscall_bn254_double(p: *mut u32) { unreachable!() } -#[allow(unused_variables)] -#[no_mangle] -pub extern "C" fn syscall_bn254_scalar_add(p: *mut u32, q: *const u32) { - #[cfg(target_os = "zkvm")] - unsafe { - asm!( - "ecall", - in("t0") crate::syscalls::BN254_SCALAR_ADD, - in("a0") p, - in("a1") q, - ); - } - - #[cfg(not(target_os = "zkvm"))] - unreachable!() -} - #[allow(unused_variables)] #[no_mangle] pub extern "C" fn syscall_bn254_scalar_mul(p: *mut u32, q: *const u32) { diff --git a/zkvm/entrypoint/src/syscalls/mod.rs b/zkvm/entrypoint/src/syscalls/mod.rs index f9d3faeeff..38ced33993 100644 --- a/zkvm/entrypoint/src/syscalls/mod.rs +++ b/zkvm/entrypoint/src/syscalls/mod.rs @@ -104,11 +104,8 @@ pub const BLS12381_ADD: u32 = 0x00_01_01_1E; /// Executes the `BLS12381_DOUBLE` precompile. pub const BLS12381_DOUBLE: u32 = 0x00_00_01_1F; -/// Executes the `BN254_SCALAR_ADD` precompile -pub const BN254_SCALAR_ADD: u32 = 0x00_01_01_20; - /// Executes the `BN254_SCALAR_MUL` precompile -pub const BN254_SCALAR_MUL: u32 = 0x00_01_01_21; +pub const BN254_SCALAR_MUL: u32 = 0x00_01_01_20; /// Executes the `BN254_SCALAR_MAC` precompile -pub const BN254_SCALAR_MAC: u32 = 0x00_01_01_22; +pub const BN254_SCALAR_MAC: u32 = 0x00_01_01_21; diff --git a/zkvm/precompiles/src/lib.rs b/zkvm/precompiles/src/lib.rs index fe3ba5a0dc..4fd568250f 100644 --- a/zkvm/precompiles/src/lib.rs +++ b/zkvm/precompiles/src/lib.rs @@ -33,7 +33,6 @@ extern "C" { pub fn syscall_hint_read(ptr: *mut u8, len: usize); pub fn sys_alloc_aligned(bytes: usize, align: usize) -> *mut u8; pub fn syscall_bls12381_decompress(point: &mut [u8; 96], is_odd: bool); - pub fn syscall_bn254_scalar_add(p: *mut u32, q: *const u32); pub fn syscall_bn254_scalar_mul(p: *mut u32, q: *const u32); pub fn syscall_bn254_scalar_mac(ret: *mut u32, a: *const u32, b: *const u32); } From 6397a7939667861e1c4ff13b93106cd2a4eaf672 Mon Sep 17 00:00:00 2001 From: lightsing Date: Wed, 22 May 2024 20:24:57 +0800 Subject: [PATCH 20/34] fix twirp & reqwest --- Cargo.lock | 283 +++++++++++++++---------------------------------- sdk/Cargo.toml | 4 +- 2 files changed, 89 insertions(+), 198 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 32ab13bcec..ab556d15d9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -729,7 +729,7 @@ dependencies = [ "http 1.1.0", "http-body 1.0.0", "http-body-util", - "hyper 1.2.0", + "hyper 1.3.1", "hyper-util", "itoa", "matchit", @@ -1375,12 +1375,6 @@ dependencies = [ "parking_lot_core", ] -[[package]] -name = "data-encoding" -version = "2.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e962a19be5cfc3f3bf6dd8f61eb50107f356ad6270fbb3ed41476571db78be5" - [[package]] name = "der" version = "0.7.9" @@ -1558,18 +1552,6 @@ dependencies = [ "cfg-if", ] -[[package]] -name = "enum-as-inner" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ffccbb6966c05b32ef8fbac435df276c4ae4d3dc55a8cd0eb9745e6c12f546a" -dependencies = [ - "heck 0.4.1", - "proc-macro2", - "quote", - "syn 2.0.59", -] - [[package]] name = "equivalent" version = "1.0.1" @@ -2020,51 +2002,6 @@ version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6fe2267d4ed49bc07b63801559be28c718ea06c4738b7a03c94df7386d2cde46" -[[package]] -name = "hickory-proto" -version = "0.24.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "091a6fbccf4860009355e3efc52ff4acf37a63489aad7435372d44ceeb6fbbcf" -dependencies = [ - "async-trait", - "cfg-if", - "data-encoding", - "enum-as-inner", - "futures-channel", - "futures-io", - "futures-util", - "idna 0.4.0", - "ipnet", - "once_cell", - "rand", - "thiserror", - "tinyvec", - "tokio", - "tracing", - "url", -] - -[[package]] -name = "hickory-resolver" -version = "0.24.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "35b8f021164e6a984c9030023544c57789c51760065cd510572fedcfb04164e8" -dependencies = [ - "cfg-if", - "futures-util", - "hickory-proto", - "ipconfig", - "lru-cache", - "once_cell", - "parking_lot", - "rand", - "resolv-conf", - "smallvec", - "thiserror", - "tokio", - "tracing", -] - [[package]] name = "hmac" version = "0.12.1" @@ -2074,17 +2011,6 @@ dependencies = [ "digest 0.10.7", ] -[[package]] -name = "hostname" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c731c3e10504cc8ed35cfe2f1db4c9274c3d35fa486e3b31df46f068ef3e867" -dependencies = [ - "libc", - "match_cfg", - "winapi", -] - [[package]] name = "http" version = "0.2.12" @@ -2179,9 +2105,9 @@ dependencies = [ [[package]] name = "hyper" -version = "1.2.0" +version = "1.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "186548d73ac615b32a73aafe38fb4f56c0d340e110e5a200bcadbaf2e199263a" +checksum = "fe575dd17d0862a9a33781c8c4696a55c320909004a67a00fb286ba8b1bc496d" dependencies = [ "bytes", "futures-channel", @@ -2207,22 +2133,26 @@ dependencies = [ "futures-util", "http 0.2.12", "hyper 0.14.28", - "rustls", + "rustls 0.21.10", "tokio", - "tokio-rustls", + "tokio-rustls 0.24.1", ] [[package]] -name = "hyper-tls" -version = "0.5.0" +name = "hyper-rustls" +version = "0.26.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d6183ddfa99b85da61a140bea0efc93fdf56ceaa041b37d553518030827f9905" +checksum = "a0bea761b46ae2b24eb4aef630d8d1c398157b6fc29e6350ecf090a0b70c952c" dependencies = [ - "bytes", - "hyper 0.14.28", - "native-tls", + "futures-util", + "http 1.1.0", + "hyper 1.3.1", + "hyper-util", + "rustls 0.22.4", + "rustls-pki-types", "tokio", - "tokio-native-tls", + "tokio-rustls 0.25.0", + "tower-service", ] [[package]] @@ -2233,7 +2163,7 @@ checksum = "70206fc6890eaca9fde8a0bf71caa2ddfc9fe045ac9e5c70df101a7dbde866e0" dependencies = [ "bytes", "http-body-util", - "hyper 1.2.0", + "hyper 1.3.1", "hyper-util", "native-tls", "tokio", @@ -2252,7 +2182,7 @@ dependencies = [ "futures-util", "http 1.1.0", "http-body 1.0.0", - "hyper 1.2.0", + "hyper 1.3.1", "pin-project-lite", "socket2", "tokio", @@ -2290,16 +2220,6 @@ version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" -[[package]] -name = "idna" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d20d6b07bfbc108882d88ed8e37d39636dcc260e15e30c45e6ba089610b917c" -dependencies = [ - "unicode-bidi", - "unicode-normalization", -] - [[package]] name = "idna" version = "0.5.0" @@ -2386,18 +2306,6 @@ dependencies = [ "cfg-if", ] -[[package]] -name = "ipconfig" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b58db92f96b720de98181bbbe63c831e87005ab460c1bf306eb2622b4707997f" -dependencies = [ - "socket2", - "widestring", - "windows-sys 0.48.0", - "winreg 0.50.0", -] - [[package]] name = "ipnet" version = "2.9.0" @@ -2559,12 +2467,6 @@ dependencies = [ "vcpkg", ] -[[package]] -name = "linked-hash-map" -version = "0.5.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0717cef1bc8b636c6e1c1bbdefc09e6322da8a9321966e8928ef80d20f7f770f" - [[package]] name = "linux-raw-sys" version = "0.4.13" @@ -2596,21 +2498,6 @@ dependencies = [ "hashbrown 0.14.3", ] -[[package]] -name = "lru-cache" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "31e24f1ad8321ca0e8a1e0ac13f23cb668e6f5466c2c57319f6a5cf1cc8e3b1c" -dependencies = [ - "linked-hash-map", -] - -[[package]] -name = "match_cfg" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ffbee8634e0d45d258acb448e7eaab3fce7a0a467395d4d9f228e3c1f01fb2e4" - [[package]] name = "matchers" version = "0.1.0" @@ -2644,16 +2531,6 @@ version = "0.3.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" -[[package]] -name = "mime_guess" -version = "2.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4192263c238a5f0d0c6bfd21f336a313a4ce1c450542449ca191bb657b4642ef" -dependencies = [ - "mime", - "unicase", -] - [[package]] name = "miniz_oxide" version = "0.7.2" @@ -3484,7 +3361,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "19de2de2a00075bf566bee3bd4db014b11587e84184d3f7a791bc17f1a8e9e48" dependencies = [ "anyhow", - "itertools 0.10.5", + "itertools 0.12.1", "proc-macro2", "quote", "syn 2.0.59", @@ -3664,22 +3541,18 @@ dependencies = [ "futures-core", "futures-util", "h2 0.3.26", - "hickory-resolver", "http 0.2.12", "http-body 0.4.6", "hyper 0.14.28", - "hyper-rustls", - "hyper-tls 0.5.0", + "hyper-rustls 0.24.2", "ipnet", "js-sys", "log", "mime", - "mime_guess", - "native-tls", "once_cell", "percent-encoding", "pin-project-lite", - "rustls", + "rustls 0.21.10", "rustls-pemfile 1.0.4", "serde", "serde_json", @@ -3687,8 +3560,7 @@ dependencies = [ "sync_wrapper", "system-configuration", "tokio", - "tokio-native-tls", - "tokio-rustls", + "tokio-rustls 0.24.1", "tokio-util", "tower-service", "url", @@ -3696,7 +3568,7 @@ dependencies = [ "wasm-bindgen-futures", "wasm-streams", "web-sys", - "webpki-roots", + "webpki-roots 0.25.4", "winreg 0.50.0", ] @@ -3708,13 +3580,16 @@ checksum = "3e6cc1e89e689536eb5aeede61520e874df5a4707df811cd5da4aa5fbb2aae19" dependencies = [ "base64 0.22.0", "bytes", + "encoding_rs", "futures-core", "futures-util", + "h2 0.4.4", "http 1.1.0", "http-body 1.0.0", "http-body-util", - "hyper 1.2.0", - "hyper-tls 0.6.0", + "hyper 1.3.1", + "hyper-rustls 0.26.0", + "hyper-tls", "hyper-util", "ipnet", "js-sys", @@ -3724,44 +3599,39 @@ dependencies = [ "once_cell", "percent-encoding", "pin-project-lite", + "rustls 0.22.4", "rustls-pemfile 2.1.2", + "rustls-pki-types", "serde", "serde_json", "serde_urlencoded", "sync_wrapper", + "system-configuration", "tokio", "tokio-native-tls", + "tokio-rustls 0.25.0", "tower-service", "url", "wasm-bindgen", "wasm-bindgen-futures", "web-sys", + "webpki-roots 0.26.1", "winreg 0.52.0", ] [[package]] name = "reqwest-middleware" -version = "0.2.5" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a735987236a8e238bf0296c7e351b999c188ccc11477f311b82b55c93984216" +checksum = "a45d100244a467870f6cb763c4484d010a6bed6bd610b3676e3825d93fb4cfbd" dependencies = [ "anyhow", "async-trait", - "http 0.2.12", - "reqwest 0.11.27", + "http 1.1.0", + "reqwest 0.12.3", "serde", - "task-local-extensions", "thiserror", -] - -[[package]] -name = "resolv-conf" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "52e44394d2086d010551b14b53b1f24e31647570cd1deb0379e2c21b329aba00" -dependencies = [ - "hostname", - "quick-error", + "tower-service", ] [[package]] @@ -3890,10 +3760,24 @@ checksum = "f9d5a6813c0759e4609cd494e8e725babae6a2ca7b62a5536a13daaec6fcb7ba" dependencies = [ "log", "ring", - "rustls-webpki", + "rustls-webpki 0.101.7", "sct", ] +[[package]] +name = "rustls" +version = "0.22.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf4ef73721ac7bcd79b2b315da7779d8fc09718c6b3d2d1b2d94850eb8c18432" +dependencies = [ + "log", + "ring", + "rustls-pki-types", + "rustls-webpki 0.102.3", + "subtle", + "zeroize", +] + [[package]] name = "rustls-pemfile" version = "1.0.4" @@ -3929,6 +3813,17 @@ dependencies = [ "untrusted", ] +[[package]] +name = "rustls-webpki" +version = "0.102.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f3bce581c0dd41bce533ce695a1437fa16a7ab5ac3ccfa99fe1a620a7885eabf" +dependencies = [ + "ring", + "rustls-pki-types", + "untrusted", +] + [[package]] name = "rustversion" version = "1.0.15" @@ -4589,7 +4484,7 @@ dependencies = [ "p3-matrix", "prost", "prost-types", - "reqwest 0.11.27", + "reqwest 0.12.3", "reqwest-middleware", "serde", "serde_json", @@ -4768,15 +4663,6 @@ version = "0.12.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e1fc403891a21bcfb7c37834ba66a547a8f402146eba7265b5a6d88059c9ff2f" -[[package]] -name = "task-local-extensions" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba323866e5d033818e3240feeb9f7db2c4296674e4d9e16b97b7bf8f490434e8" -dependencies = [ - "pin-utils", -] - [[package]] name = "tempfile" version = "3.10.1" @@ -4941,7 +4827,18 @@ version = "0.24.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c28327cf380ac148141087fbfb9de9d7bd4e84ab5d2c28fbc911d753de8a7081" dependencies = [ - "rustls", + "rustls 0.21.10", + "tokio", +] + +[[package]] +name = "tokio-rustls" +version = "0.25.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "775e0c0f0adb3a2f22a00c4745d728b479985fc15ee7ca6a2608388c5569860f" +dependencies = [ + "rustls 0.22.4", + "rustls-pki-types", "tokio", ] @@ -5111,7 +5008,7 @@ checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" [[package]] name = "twirp" version = "0.3.0" -source = "git+https://github.com/github/twirp-rs.git#90244e417d27bf9233e96de37bbab8121e983020" +source = "git+https://github.com/github/twirp-rs.git#c85f31f9c54957374e7dcb3534fc52cff0aa2dc5" dependencies = [ "async-trait", "axum", @@ -5119,9 +5016,9 @@ dependencies = [ "futures", "http 1.1.0", "http-body-util", - "hyper 1.2.0", + "hyper 1.3.1", "prost", - "reqwest 0.11.27", + "reqwest 0.12.3", "serde", "serde_json", "thiserror", @@ -5160,15 +5057,6 @@ version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "eaea85b334db583fe3274d12b4cd1880032beab409c0d774be044d4480ab9a94" -[[package]] -name = "unicase" -version = "2.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f7d2d4dafb69621809a81864c9c1b864479e1235c0dd4e199924b9742439ed89" -dependencies = [ - "version_check", -] - [[package]] name = "unicode-bidi" version = "0.3.15" @@ -5209,7 +5097,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "31e6302e3bb753d46e83516cae55ae196fc0c309407cf11ab35cc51a4c2a4633" dependencies = [ "form_urlencoded", - "idna 0.5.0", + "idna", "percent-encoding", ] @@ -5390,10 +5278,13 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5f20c57d8d7db6d3b86154206ae5d8fba62dd39573114de97c2cb0578251f8e1" [[package]] -name = "widestring" -version = "1.1.0" +name = "webpki-roots" +version = "0.26.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7219d36b6eac893fa81e84ebe06485e7dcbb616177469b142df14f1f4deb1311" +checksum = "b3de34ae270483955a94f4b21bdaaeb83d508bb84a01435f393818edb0012009" +dependencies = [ + "rustls-pki-types", +] [[package]] name = "winapi" diff --git a/sdk/Cargo.toml b/sdk/Cargo.toml index cec192bceb..3a99cf504e 100644 --- a/sdk/Cargo.toml +++ b/sdk/Cargo.toml @@ -12,8 +12,8 @@ serde = { version = "1.0.197", features = ["derive"] } serde_json = "1.0.114" twirp = { git = "https://github.com/github/twirp-rs.git" } async-trait = "0.1.77" -reqwest-middleware = "0.2.4" -reqwest = { version = "0.11.25", features = ["rustls-tls", "trust-dns"] } +reqwest-middleware = "0.3" +reqwest = { version = "0.12", features = ["rustls-tls", "trust-dns"] } anyhow = "1.0.80" sp1-core = { path = "../core" } futures = "0.3.30" From c228ae3bf9c214f517f1c031e60bb8353016c729 Mon Sep 17 00:00:00 2001 From: lightsing Date: Thu, 6 Jun 2024 15:32:35 +0800 Subject: [PATCH 21/34] add memcpy chip --- core/src/runtime/record.rs | 3 + core/src/runtime/syscall.rs | 16 +- core/src/stark/air.rs | 7 + core/src/syscall/memcpy.rs | 158 ++++ core/src/syscall/mod.rs | 2 + zkvm/entrypoint/src/memcpy.c | 142 ++++ zkvm/entrypoint/src/memcpy.s | 1137 ++++++++++++++++++++------- zkvm/entrypoint/src/syscalls/mod.rs | 6 + 8 files changed, 1177 insertions(+), 294 deletions(-) create mode 100644 core/src/syscall/memcpy.rs create mode 100644 zkvm/entrypoint/src/memcpy.c diff --git a/core/src/runtime/record.rs b/core/src/runtime/record.rs index ad58ba02fb..027a7d0846 100644 --- a/core/src/runtime/record.rs +++ b/core/src/runtime/record.rs @@ -24,6 +24,7 @@ use crate::syscall::precompiles::sha256::{ShaCompressEvent, ShaExtendEvent}; use crate::syscall::precompiles::uint256::Uint256MulEvent; use crate::syscall::precompiles::ECDecompressEvent; use crate::syscall::precompiles::{ECAddEvent, ECDoubleEvent}; +use crate::syscall::MemCopyEvent; use crate::utils::env; /// A record of the execution of a program. Contains event data for everything that happened during @@ -103,6 +104,8 @@ pub struct ExecutionRecord { pub bls12381_decompress_events: Vec, + pub memcpy_events: HashMap>, + /// The public values. pub public_values: PublicValues, } diff --git a/core/src/runtime/syscall.rs b/core/src/runtime/syscall.rs index 652da6c76b..2b205754c1 100644 --- a/core/src/runtime/syscall.rs +++ b/core/src/runtime/syscall.rs @@ -15,8 +15,9 @@ use crate::syscall::precompiles::weierstrass::WeierstrassAddAssignChip; use crate::syscall::precompiles::weierstrass::WeierstrassDecompressChip; use crate::syscall::precompiles::weierstrass::WeierstrassDoubleAssignChip; use crate::syscall::{ - SyscallCommit, SyscallCommitDeferred, SyscallEnterUnconstrained, SyscallExitUnconstrained, - SyscallHalt, SyscallHintLen, SyscallHintRead, SyscallVerifySP1Proof, SyscallWrite, + MemCopyChip, SyscallCommit, SyscallCommitDeferred, SyscallEnterUnconstrained, + SyscallExitUnconstrained, SyscallHalt, SyscallHintLen, SyscallHintRead, SyscallVerifySP1Proof, + SyscallWrite, }; use crate::utils::ec::edwards::ed25519::{Ed25519, Ed25519Parameters}; use crate::utils::ec::weierstrass::bls12_381::Bls12381; @@ -109,6 +110,12 @@ pub enum SyscallCode { /// Execute the `BN254_SCALAR_MAC` precompile. BN254_SCALAR_MAC = 0x00_01_01_21, + + /// Execute the `MEMCPY_32` precompile. + MEMCPY_32 = 0x00_00_01_30, + + /// Execute the `MEMCPY_64` precompile. + MEMCPY_64 = 0x00_00_01_31, } impl SyscallCode { @@ -141,6 +148,8 @@ impl SyscallCode { 0x00_00_01_1C => SyscallCode::BLS12381_DECOMPRESS, 0x00_01_01_20 => SyscallCode::BN254_SCALAR_MUL, 0x00_01_01_21 => SyscallCode::BN254_SCALAR_MAC, + 0x00_00_01_30 => SyscallCode::MEMCPY_32, + 0x00_00_01_31 => SyscallCode::MEMCPY_64, _ => panic!("invalid syscall number: {}", value), } } @@ -354,6 +363,9 @@ pub fn default_syscall_map() -> HashMap> { Rc::new(Bn254ScalarMacChip::new()), ); + syscall_map.insert(SyscallCode::MEMCPY_32, Rc::new(MemCopyChip::<8>::new())); + syscall_map.insert(SyscallCode::MEMCPY_64, Rc::new(MemCopyChip::<16>::new())); + syscall_map } diff --git a/core/src/stark/air.rs b/core/src/stark/air.rs index c849df8dc4..fa3a80cfda 100644 --- a/core/src/stark/air.rs +++ b/core/src/stark/air.rs @@ -31,6 +31,7 @@ pub(crate) mod riscv_chips { pub use crate::syscall::precompiles::weierstrass::WeierstrassAddAssignChip; pub use crate::syscall::precompiles::weierstrass::WeierstrassDecompressChip; pub use crate::syscall::precompiles::weierstrass::WeierstrassDoubleAssignChip; + pub use crate::syscall::MemCopyChip; pub use crate::utils::ec::edwards::ed25519::Ed25519Parameters; pub use crate::utils::ec::edwards::EdwardsCurve; pub use crate::utils::ec::weierstrass::bls12_381::Bls12381Parameters; @@ -106,6 +107,9 @@ pub enum RiscvAir { Bn254ScalarMac(Bn254ScalarMacChip), /// A precompile for decompressing a point on the BLS12-381 curve. Bls12381Decompress(WeierstrassDecompressChip>), + + MemCpy32(MemCopyChip<8>), + MemCpy64(MemCopyChip<16>), } impl RiscvAir { @@ -182,6 +186,9 @@ impl RiscvAir { let byte = ByteChip::default(); chips.push(RiscvAir::ByteLookup(byte)); + chips.push(RiscvAir::MemCpy32(MemCopyChip::<8>::new())); + chips.push(RiscvAir::MemCpy64(MemCopyChip::<16>::new())); + chips } } diff --git a/core/src/syscall/memcpy.rs b/core/src/syscall/memcpy.rs new file mode 100644 index 0000000000..5770cc949d --- /dev/null +++ b/core/src/syscall/memcpy.rs @@ -0,0 +1,158 @@ +use std::borrow::{Borrow, BorrowMut}; + +use p3_air::{Air, BaseAir}; +use p3_field::AbstractField; +use p3_field::{Field, PrimeField32}; +use p3_matrix::{dense::RowMajorMatrix, Matrix}; +use serde::{Deserialize, Serialize}; +use sp1_derive::AlignedBorrow; + +use crate::{ + air::MachineAir, + memory::{MemoryReadCols, MemoryWriteCols}, + runtime::{ + ExecutionRecord, MemoryReadRecord, MemoryWriteRecord, Program, Syscall, SyscallCode, + }, + stark::SP1AirBuilder, +}; + +#[derive(Clone, Debug, Serialize, Deserialize)] +pub struct MemCopyEvent { + pub shard: u32, + pub clk: u32, + pub src_ptr: u32, + pub dst_ptr: u32, + pub src_access: Vec, + pub dst_access: Vec, +} + +#[derive(Debug, Clone, AlignedBorrow)] +#[repr(C)] +pub struct MemCopyCols { + is_real: T, + shard: T, + clk: T, + src_ptr: T, + dst_ptr: T, + src_access: [MemoryReadCols; NUM_WORDS], + dst_access: [MemoryWriteCols; NUM_WORDS], +} + +pub struct MemCopyChip; + +impl MemCopyChip { + const NUM_COLS: usize = core::mem::size_of::>(); + + pub fn new() -> Self { + println!("MemCopyChip<{NUM_WORDS}> NUM_COLS = {}", Self::NUM_COLS); + Self + } + + pub fn syscall_id() -> u32 { + match NUM_WORDS { + 8 => SyscallCode::MEMCPY_32.syscall_id(), + 16 => SyscallCode::MEMCPY_64.syscall_id(), + _ => unreachable!(), + } + } +} + +impl Syscall for MemCopyChip { + fn execute(&self, ctx: &mut crate::runtime::SyscallContext, src: u32, dst: u32) -> Option { + let (read, read_bytes) = ctx.mr_slice(src, NUM_WORDS); + let write = ctx.mw_slice(dst, &read_bytes); + + let event = MemCopyEvent { + shard: ctx.current_shard(), + clk: ctx.clk, + src_ptr: src, + dst_ptr: dst, + src_access: read, + dst_access: write, + }; + ctx.record_mut() + .memcpy_events + .entry(NUM_WORDS) + .or_default() + .push(event); + + None + } +} + +impl MachineAir for MemCopyChip +where + [(); Self::NUM_COLS]:, +{ + type Record = ExecutionRecord; + + type Program = Program; + + fn name(&self) -> String { + format!("MemCopy{}Chip", NUM_WORDS) + } + + fn generate_trace(&self, input: &Self::Record, output: &mut Self::Record) -> RowMajorMatrix { + let mut rows = vec![]; + let mut new_byte_lookup_events = vec![]; + + for event in input.memcpy_events.get(&NUM_WORDS).unwrap_or(&vec![]) { + let mut row = [F::zero(); Self::NUM_COLS]; + let cols: &mut MemCopyCols = row.as_mut_slice().borrow_mut(); + + cols.is_real = F::one(); + cols.shard = F::from_canonical_u32(event.shard); + cols.clk = F::from_canonical_u32(event.clk); + cols.src_ptr = F::from_canonical_u32(event.src_ptr); + cols.dst_ptr = F::from_canonical_u32(event.dst_ptr); + + for i in 0..NUM_WORDS { + cols.src_access[i].populate(event.src_access[i], &mut new_byte_lookup_events); + } + for i in 0..NUM_WORDS { + cols.dst_access[i].populate(event.dst_access[i], &mut new_byte_lookup_events); + } + + rows.push(row); + } + output.add_byte_lookup_events(new_byte_lookup_events); + + RowMajorMatrix::new( + rows.into_iter().flatten().collect::>(), + Self::NUM_COLS, + ) + } + + fn included(&self, shard: &Self::Record) -> bool { + shard + .memcpy_events + .get(&NUM_WORDS) + .map(|events| !events.is_empty()) + .unwrap_or(false) + } +} + +impl BaseAir for MemCopyChip { + fn width(&self) -> usize { + Self::NUM_COLS + } +} + +impl Air for MemCopyChip { + fn eval(&self, builder: &mut AB) { + let main = builder.main(); + let row = main.row_slice(0); + let row: &MemCopyCols = (*row).borrow(); + + // TODO assert eq + + builder.receive_syscall( + row.shard, + row.clk, + AB::F::from_canonical_u32(Self::syscall_id()), + row.src_ptr, + row.dst_ptr, + row.is_real, + ); + } +} diff --git a/core/src/syscall/mod.rs b/core/src/syscall/mod.rs index a2f7950619..4b106fbbcd 100644 --- a/core/src/syscall/mod.rs +++ b/core/src/syscall/mod.rs @@ -1,6 +1,7 @@ mod commit; mod halt; mod hint; +mod memcpy; pub mod precompiles; mod unconstrained; mod verify; @@ -9,6 +10,7 @@ mod write; pub use commit::*; pub use halt::*; pub use hint::*; +pub use memcpy::*; pub use unconstrained::*; pub use verify::*; pub use write::*; diff --git a/zkvm/entrypoint/src/memcpy.c b/zkvm/entrypoint/src/memcpy.c new file mode 100644 index 0000000000..16f30bc2b8 --- /dev/null +++ b/zkvm/entrypoint/src/memcpy.c @@ -0,0 +1,142 @@ +#include +#include + +#define MEMCPY_32 0x00000130 +#define MEMCPY_64 0x00000131 + +void *memcpy(void *restrict dest, const void *restrict src, size_t n) +{ + unsigned char *d = dest; + const unsigned char *s = src; + +#ifdef __GNUC__ +#define LS >> +#define RS << + + typedef uint32_t __attribute__((__may_alias__)) u32; + uint32_t w, x; + + for (; (uintptr_t)s % 4 && n; n--) *d++ = *s++; + + if ((uintptr_t)d % 4 == 0) { + for (; n>=64; s+=64, d+=64, n-=64) { + asm volatile( + "mv t0, %0\n" + "mv a0, %1\n" + "mv a1, %2\n" + "ecall" + : // No output operands + : "r"(MEMCPY_64), "r"(s), "r"(d) + : "t0", "a0", "a1" // Clobbered registers + ); + } + for (; n>=32; s+=32, d+=32, n-=32) { + asm volatile( + "mv t0, %0\n" + "mv a0, %1\n" + "mv a1, %2\n" + "ecall" + : // No output operands + : "r"(MEMCPY_32), "r"(s), "r"(d) + : "t0", "a0", "a1" // Clobbered registers + ); + } + for (; n>=16; s+=16, d+=16, n-=16) { + *(u32 *)(d+0) = *(u32 *)(s+0); + *(u32 *)(d+4) = *(u32 *)(s+4); + *(u32 *)(d+8) = *(u32 *)(s+8); + *(u32 *)(d+12) = *(u32 *)(s+12); + } + if (n&8) { + *(u32 *)(d+0) = *(u32 *)(s+0); + *(u32 *)(d+4) = *(u32 *)(s+4); + d += 8; s += 8; + } + if (n&4) { + *(u32 *)(d+0) = *(u32 *)(s+0); + d += 4; s += 4; + } + if (n&2) { + *d++ = *s++; *d++ = *s++; + } + if (n&1) { + *d = *s; + } + return dest; + } + + if (n >= 32) switch ((uintptr_t)d % 4) { + case 1: + w = *(u32 *)s; + *d++ = *s++; + *d++ = *s++; + *d++ = *s++; + n -= 3; + for (; n>=17; s+=16, d+=16, n-=16) { + x = *(u32 *)(s+1); + *(u32 *)(d+0) = (w LS 24) | (x RS 8); + w = *(u32 *)(s+5); + *(u32 *)(d+4) = (x LS 24) | (w RS 8); + x = *(u32 *)(s+9); + *(u32 *)(d+8) = (w LS 24) | (x RS 8); + w = *(u32 *)(s+13); + *(u32 *)(d+12) = (x LS 24) | (w RS 8); + } + break; + case 2: + w = *(u32 *)s; + *d++ = *s++; + *d++ = *s++; + n -= 2; + for (; n>=18; s+=16, d+=16, n-=16) { + x = *(u32 *)(s+2); + *(u32 *)(d+0) = (w LS 16) | (x RS 16); + w = *(u32 *)(s+6); + *(u32 *)(d+4) = (x LS 16) | (w RS 16); + x = *(u32 *)(s+10); + *(u32 *)(d+8) = (w LS 16) | (x RS 16); + w = *(u32 *)(s+14); + *(u32 *)(d+12) = (x LS 16) | (w RS 16); + } + break; + case 3: + w = *(u32 *)s; + *d++ = *s++; + n -= 1; + for (; n>=19; s+=16, d+=16, n-=16) { + x = *(u32 *)(s+3); + *(u32 *)(d+0) = (w LS 8) | (x RS 24); + w = *(u32 *)(s+7); + *(u32 *)(d+4) = (x LS 8) | (w RS 24); + x = *(u32 *)(s+11); + *(u32 *)(d+8) = (w LS 8) | (x RS 24); + w = *(u32 *)(s+15); + *(u32 *)(d+12) = (x LS 8) | (w RS 24); + } + break; + } + if (n&16) { + *d++ = *s++; *d++ = *s++; *d++ = *s++; *d++ = *s++; + *d++ = *s++; *d++ = *s++; *d++ = *s++; *d++ = *s++; + *d++ = *s++; *d++ = *s++; *d++ = *s++; *d++ = *s++; + *d++ = *s++; *d++ = *s++; *d++ = *s++; *d++ = *s++; + } + if (n&8) { + *d++ = *s++; *d++ = *s++; *d++ = *s++; *d++ = *s++; + *d++ = *s++; *d++ = *s++; *d++ = *s++; *d++ = *s++; + } + if (n&4) { + *d++ = *s++; *d++ = *s++; *d++ = *s++; *d++ = *s++; + } + if (n&2) { + *d++ = *s++; *d++ = *s++; + } + if (n&1) { + *d = *s; + } + return dest; +#endif + + for (; n; n--) *d++ = *s++; + return dest; +} \ No newline at end of file diff --git a/zkvm/entrypoint/src/memcpy.s b/zkvm/entrypoint/src/memcpy.s index 1735cae5c7..1100370be3 100644 --- a/zkvm/entrypoint/src/memcpy.s +++ b/zkvm/entrypoint/src/memcpy.s @@ -201,298 +201,851 @@ // negated the permissions granted in the license. In the spirit of // permissive licensing, and of not having licensing issues being an // obstacle to adoption, that text has been removed. + .file "memcpy.c" + .option nopic + .attribute arch, "rv32im" + .attribute unaligned_access, 0 + .attribute stack_align, 16 .text - .attribute 4, 16 - .attribute 5, "rv32im" - .file "musl_memcpy.c" + .align 2 .globl memcpy - .p2align 2 - .type memcpy,@function + .type memcpy, @function memcpy: - andi a3, a1, 3 - seqz a3, a3 - seqz a4, a2 - or a3, a3, a4 - bnez a3, .LBBmemcpy0_11 - addi a5, a1, 1 - mv a6, a0 -.LBBmemcpy0_2: - lb a7, 0(a1) - addi a4, a1, 1 - addi a3, a6, 1 - sb a7, 0(a6) - addi a2, a2, -1 - andi a1, a5, 3 - snez a1, a1 - snez a6, a2 - and a7, a1, a6 - addi a5, a5, 1 - mv a1, a4 - mv a6, a3 - bnez a7, .LBBmemcpy0_2 - andi a1, a3, 3 - beqz a1, .LBBmemcpy0_12 -.LBBmemcpy0_4: - li a5, 32 - bltu a2, a5, .LBBmemcpy0_26 - li a5, 3 - beq a1, a5, .LBBmemcpy0_19 - li a5, 2 - beq a1, a5, .LBBmemcpy0_22 - li a5, 1 - bne a1, a5, .LBBmemcpy0_26 - lw a5, 0(a4) - sb a5, 0(a3) - srli a1, a5, 8 - sb a1, 1(a3) - srli a6, a5, 16 - addi a1, a3, 3 - sb a6, 2(a3) - addi a2, a2, -3 - addi a3, a4, 16 - li a4, 16 -.LBBmemcpy0_9: - lw a6, -12(a3) - srli a5, a5, 24 - slli a7, a6, 8 - lw t0, -8(a3) - or a5, a7, a5 - sw a5, 0(a1) - srli a5, a6, 24 - slli a6, t0, 8 - lw a7, -4(a3) - or a5, a6, a5 - sw a5, 4(a1) - srli a6, t0, 24 - slli t0, a7, 8 - lw a5, 0(a3) - or a6, t0, a6 - sw a6, 8(a1) - srli a6, a7, 24 - slli a7, a5, 8 - or a6, a7, a6 - sw a6, 12(a1) - addi a1, a1, 16 - addi a2, a2, -16 - addi a3, a3, 16 - bltu a4, a2, .LBBmemcpy0_9 - addi a4, a3, -13 - j .LBBmemcpy0_25 -.LBBmemcpy0_11: - mv a3, a0 - mv a4, a1 - andi a1, a3, 3 - bnez a1, .LBBmemcpy0_4 -.LBBmemcpy0_12: - li a1, 16 - bltu a2, a1, .LBBmemcpy0_15 - li a1, 15 -.LBBmemcpy0_14: - lw a5, 0(a4) - lw a6, 4(a4) - lw a7, 8(a4) - lw t0, 12(a4) - sw a5, 0(a3) - sw a6, 4(a3) - sw a7, 8(a3) - sw t0, 12(a3) - addi a4, a4, 16 - addi a2, a2, -16 - addi a3, a3, 16 - bltu a1, a2, .LBBmemcpy0_14 -.LBBmemcpy0_15: - andi a1, a2, 8 - beqz a1, .LBBmemcpy0_17 - lw a1, 0(a4) - lw a5, 4(a4) - sw a1, 0(a3) - sw a5, 4(a3) - addi a3, a3, 8 - addi a4, a4, 8 -.LBBmemcpy0_17: - andi a1, a2, 4 - beqz a1, .LBBmemcpy0_30 - lw a1, 0(a4) - sw a1, 0(a3) - addi a3, a3, 4 - addi a4, a4, 4 - j .LBBmemcpy0_30 -.LBBmemcpy0_19: - lw a5, 0(a4) - addi a1, a3, 1 - sb a5, 0(a3) - addi a2, a2, -1 - addi a3, a4, 16 - li a4, 18 -.LBBmemcpy0_20: - lw a6, -12(a3) - srli a5, a5, 8 - slli a7, a6, 24 - lw t0, -8(a3) - or a5, a7, a5 - sw a5, 0(a1) - srli a5, a6, 8 - slli a6, t0, 24 - lw a7, -4(a3) - or a5, a6, a5 - sw a5, 4(a1) - srli a6, t0, 8 - slli t0, a7, 24 - lw a5, 0(a3) - or a6, t0, a6 - sw a6, 8(a1) - srli a6, a7, 8 - slli a7, a5, 24 - or a6, a7, a6 - sw a6, 12(a1) - addi a1, a1, 16 - addi a2, a2, -16 - addi a3, a3, 16 - bltu a4, a2, .LBBmemcpy0_20 - addi a4, a3, -15 - j .LBBmemcpy0_25 -.LBBmemcpy0_22: - lw a5, 0(a4) - sb a5, 0(a3) - srli a6, a5, 8 - addi a1, a3, 2 - sb a6, 1(a3) - addi a2, a2, -2 - addi a3, a4, 16 - li a4, 17 -.LBBmemcpy0_23: - lw a6, -12(a3) - srli a5, a5, 16 - slli a7, a6, 16 - lw t0, -8(a3) - or a5, a7, a5 - sw a5, 0(a1) - srli a5, a6, 16 - slli a6, t0, 16 - lw a7, -4(a3) - or a5, a6, a5 - sw a5, 4(a1) - srli a6, t0, 16 - slli t0, a7, 16 - lw a5, 0(a3) - or a6, t0, a6 - sw a6, 8(a1) - srli a6, a7, 16 - slli a7, a5, 16 - or a6, a7, a6 - sw a6, 12(a1) - addi a1, a1, 16 - addi a2, a2, -16 - addi a3, a3, 16 - bltu a4, a2, .LBBmemcpy0_23 - addi a4, a3, -14 -.LBBmemcpy0_25: - mv a3, a1 -.LBBmemcpy0_26: - andi a1, a2, 16 - bnez a1, .LBBmemcpy0_35 - andi a1, a2, 8 - bnez a1, .LBBmemcpy0_36 -.LBBmemcpy0_28: - andi a1, a2, 4 - beqz a1, .LBBmemcpy0_30 -.LBBmemcpy0_29: - lb a1, 0(a4) - lb a5, 1(a4) - lb a6, 2(a4) - sb a1, 0(a3) - sb a5, 1(a3) - lb a1, 3(a4) - sb a6, 2(a3) - addi a4, a4, 4 - addi a5, a3, 4 - sb a1, 3(a3) - mv a3, a5 -.LBBmemcpy0_30: - andi a1, a2, 2 - bnez a1, .LBBmemcpy0_33 - andi a1, a2, 1 - bnez a1, .LBBmemcpy0_34 -.LBBmemcpy0_32: - ret -.LBBmemcpy0_33: - lb a1, 0(a4) - lb a5, 1(a4) - sb a1, 0(a3) - addi a4, a4, 2 - addi a1, a3, 2 - sb a5, 1(a3) - mv a3, a1 - andi a1, a2, 1 - beqz a1, .LBBmemcpy0_32 -.LBBmemcpy0_34: - lb a1, 0(a4) - sb a1, 0(a3) - ret -.LBBmemcpy0_35: - lb a1, 0(a4) - lb a5, 1(a4) - lb a6, 2(a4) - sb a1, 0(a3) - sb a5, 1(a3) - lb a1, 3(a4) - sb a6, 2(a3) - lb a5, 4(a4) - lb a6, 5(a4) - sb a1, 3(a3) - lb a1, 6(a4) - sb a5, 4(a3) - sb a6, 5(a3) - lb a5, 7(a4) - sb a1, 6(a3) - lb a1, 8(a4) - lb a6, 9(a4) - sb a5, 7(a3) - lb a5, 10(a4) - sb a1, 8(a3) - sb a6, 9(a3) - lb a1, 11(a4) - sb a5, 10(a3) - lb a5, 12(a4) - lb a6, 13(a4) - sb a1, 11(a3) - lb a1, 14(a4) - sb a5, 12(a3) - sb a6, 13(a3) - lb a5, 15(a4) - sb a1, 14(a3) - addi a4, a4, 16 - addi a1, a3, 16 - sb a5, 15(a3) - mv a3, a1 - andi a1, a2, 8 - beqz a1, .LBBmemcpy0_28 -.LBBmemcpy0_36: - lb a1, 0(a4) - lb a5, 1(a4) - lb a6, 2(a4) - sb a1, 0(a3) - sb a5, 1(a3) - lb a1, 3(a4) - sb a6, 2(a3) - lb a5, 4(a4) - lb a6, 5(a4) - sb a1, 3(a3) - lb a1, 6(a4) - sb a5, 4(a3) - sb a6, 5(a3) - lb a5, 7(a4) - sb a1, 6(a3) - addi a4, a4, 8 - addi a1, a3, 8 - sb a5, 7(a3) - mv a3, a1 - andi a1, a2, 4 - bnez a1, .LBBmemcpy0_29 - j .LBBmemcpy0_30 -.Lfuncmemcpy_end0: - .size memcpy, .Lfuncmemcpy_end0-memcpy - - .ident "Ubuntu clang version 14.0.6-++20220622053131+f28c006a5895-1~exp1~20220622173215.157" - .section ".note.GNU-stack","",@progbits - .addrsig \ No newline at end of file + andi a4,a1,3 + addi sp,sp,-32 + mv a5,a1 + mv a6,a0 + beq a4,zero,.L27 + beq a2,zero,.L40 + andi a3,a2,7 + mv a4,a0 + addi a0,a2,-1 + beq a3,zero,.L4 + li a1,1 + beq a3,a1,.L106 + li t0,2 + beq a3,t0,.L107 + li t1,3 + beq a3,t1,.L108 + li t2,4 + beq a3,t2,.L109 + li a7,5 + beq a3,a7,.L110 + li t3,6 + bne a3,t3,.L166 +.L111: + lbu t5,0(a5) + addi a5,a5,1 + andi t6,a5,3 + sb t5,0(a4) + addi a2,a2,-1 + addi a4,a4,1 + beq t6,zero,.L2 +.L110: + lbu a0,0(a5) + addi a5,a5,1 + andi a3,a5,3 + sb a0,0(a4) + addi a2,a2,-1 + addi a4,a4,1 + beq a3,zero,.L2 +.L109: + lbu a1,0(a5) + addi a5,a5,1 + andi t0,a5,3 + sb a1,0(a4) + addi a2,a2,-1 + addi a4,a4,1 + beq t0,zero,.L2 +.L108: + lbu t1,0(a5) + addi a5,a5,1 + andi t2,a5,3 + sb t1,0(a4) + addi a2,a2,-1 + addi a4,a4,1 + beq t2,zero,.L2 +.L107: + lbu a7,0(a5) + addi a5,a5,1 + andi t3,a5,3 + sb a7,0(a4) + addi a2,a2,-1 + addi a4,a4,1 + beq t3,zero,.L2 +.L106: + lbu t4,0(a5) + addi a5,a5,1 + andi t5,a5,3 + sb t4,0(a4) + addi a2,a2,-1 + addi a4,a4,1 + beq t5,zero,.L2 +.L163: + beq a2,zero,.L167 +.L4: + lbu a0,0(a5) + addi a5,a5,1 + addi a4,a4,1 + addi a2,a2,-1 + andi t0,a5,3 + sb a0,-1(a4) + mv a3,a5 + mv a1,a4 + mv t3,a2 + beq t0,zero,.L2 + lbu t1,0(a5) + addi a5,a5,1 + andi a7,a5,3 + sb t1,0(a4) + addi a2,a2,-1 + addi a4,a4,1 + beq a7,zero,.L2 + lbu a4,1(a3) + addi a5,a3,2 + andi t4,a5,3 + sb a4,1(a1) + addi a2,t3,-2 + addi a4,a1,2 + beq t4,zero,.L2 + lbu a2,2(a3) + addi a5,a3,3 + andi t5,a5,3 + sb a2,2(a1) + addi a4,a1,3 + addi a2,t3,-3 + beq t5,zero,.L2 + lbu t6,3(a3) + addi a4,a1,4 + addi a5,a3,4 + sb t6,-1(a4) + addi a2,t3,-4 + beq t0,zero,.L2 + lbu a0,4(a3) + addi a5,a3,5 + andi t0,a5,3 + sb a0,4(a1) + addi a4,a1,5 + addi a2,t3,-5 + beq t0,zero,.L2 + lbu t2,5(a3) + addi a5,a3,6 + andi t1,a5,3 + sb t2,5(a1) + addi a4,a1,6 + addi a2,t3,-6 + beq t1,zero,.L2 + lbu a7,6(a3) + addi a5,a3,7 + andi a3,a5,3 + sb a7,6(a1) + addi a4,a1,7 + addi a2,t3,-7 + bne a3,zero,.L163 +.L2: + andi a1,a4,3 + bne a1,zero,.L8 + li t5,63 + bleu a2,t5,.L29 + addi t4,a2,-64 + andi t3,t4,-64 + addi t2,t3,64 + addi t1,t2,-64 + srli a3,t1,6 + addi a7,a3,1 + andi a1,a7,7 + mv a3,a5 + add a7,a4,t2 + li t6,305 + beq a1,zero,.L10 + li t0,1 + beq a1,t0,.L112 + li a0,2 + beq a1,a0,.L113 + li t5,3 + beq a1,t5,.L114 + li t4,4 + beq a1,t4,.L115 + li t3,5 + beq a1,t3,.L116 + li t1,6 + bne a1,t1,.L168 +.L117: + #APP +# 23 "memcpy.c" 1 + mv t0, t6 +mv a0, a3 +mv a1, a4 +ecall +# 0 "" 2 + #NO_APP + addi a3,a3,64 + addi a4,a4,64 +.L116: + #APP +# 23 "memcpy.c" 1 + mv t0, t6 +mv a0, a3 +mv a1, a4 +ecall +# 0 "" 2 + #NO_APP + addi a3,a3,64 + addi a4,a4,64 +.L115: + #APP +# 23 "memcpy.c" 1 + mv t0, t6 +mv a0, a3 +mv a1, a4 +ecall +# 0 "" 2 + #NO_APP + addi a3,a3,64 + addi a4,a4,64 +.L114: + #APP +# 23 "memcpy.c" 1 + mv t0, t6 +mv a0, a3 +mv a1, a4 +ecall +# 0 "" 2 + #NO_APP + addi a3,a3,64 + addi a4,a4,64 +.L113: + #APP +# 23 "memcpy.c" 1 + mv t0, t6 +mv a0, a3 +mv a1, a4 +ecall +# 0 "" 2 + #NO_APP + addi a3,a3,64 + addi a4,a4,64 +.L112: + #APP +# 23 "memcpy.c" 1 + mv t0, t6 +mv a0, a3 +mv a1, a4 +ecall +# 0 "" 2 + #NO_APP + addi a4,a4,64 + addi a3,a3,64 + beq a4,a7,.L153 +.L10: + #APP +# 23 "memcpy.c" 1 + mv t0, t6 +mv a0, a3 +mv a1, a4 +ecall +# 0 "" 2 + #NO_APP + addi t4,a3,64 + addi t5,a4,64 + #APP +# 23 "memcpy.c" 1 + mv t0, t6 +mv a0, t4 +mv a1, t5 +ecall +# 0 "" 2 + #NO_APP + addi t3,a3,128 + addi t1,a4,128 + #APP +# 23 "memcpy.c" 1 + mv t0, t6 +mv a0, t3 +mv a1, t1 +ecall +# 0 "" 2 + #NO_APP + addi t4,a3,192 + addi t5,a4,192 + #APP +# 23 "memcpy.c" 1 + mv t0, t6 +mv a0, t4 +mv a1, t5 +ecall +# 0 "" 2 + #NO_APP + addi t3,a3,256 + addi t1,a4,256 + #APP +# 23 "memcpy.c" 1 + mv t0, t6 +mv a0, t3 +mv a1, t1 +ecall +# 0 "" 2 + #NO_APP + addi t4,a3,320 + addi t5,a4,320 + #APP +# 23 "memcpy.c" 1 + mv t0, t6 +mv a0, t4 +mv a1, t5 +ecall +# 0 "" 2 + #NO_APP + addi t3,a3,384 + addi t1,a4,384 + #APP +# 23 "memcpy.c" 1 + mv t0, t6 +mv a0, t3 +mv a1, t1 +ecall +# 0 "" 2 + #NO_APP + addi t4,a3,448 + addi t5,a4,448 + #APP +# 23 "memcpy.c" 1 + mv t0, t6 +mv a0, t4 +mv a1, t5 +ecall +# 0 "" 2 + #NO_APP + addi a4,a4,512 + addi a3,a3,512 + bne a4,a7,.L10 +.L153: + add a5,a5,t2 + andi t6,a2,63 +.L9: + li a4,31 + bleu t6,a4,.L11 + li a2,304 + #APP +# 34 "memcpy.c" 1 + mv t0, a2 +mv a0, a5 +mv a1, a7 +ecall +# 0 "" 2 + #NO_APP + addi a5,a5,32 + addi a7,a7,32 + andi t6,t6,31 +.L11: + li t2,15 + bleu t6,t2,.L12 + lw t0,4(a5) + lw a1,8(a5) + lw a0,12(a5) + lw a3,0(a5) + sw t0,4(a7) + sw a1,8(a7) + sw a3,0(a7) + sw a0,12(a7) + addi a5,a5,16 + addi a7,a7,16 + addi t6,t6,-16 +.L12: + andi t3,t6,8 + beq t3,zero,.L13 + lw t1,4(a5) + lw t4,0(a5) + addi a7,a7,8 + addi a5,a5,8 + sw t1,-4(a7) + sw t4,-8(a7) +.L13: + andi t5,t6,4 + beq t5,zero,.L6 + lw a4,0(a5) + addi a7,a7,4 + addi a5,a5,4 + sw a4,-4(a7) +.L6: + andi a2,t6,2 + beq a2,zero,.L14 + lbu t2,0(a5) + lbu t0,1(a5) + addi a7,a7,2 + sb t2,-2(a7) + sb t0,-1(a7) + addi a5,a5,2 +.L14: + andi t6,t6,1 + beq t6,zero,.L40 + lbu a5,0(a5) + sb a5,0(a7) +.L40: + mv a0,a6 + addi sp,sp,32 + jr ra +.L8: + sw s0,28(sp) + sw s1,24(sp) + sw s2,20(sp) + li s0,31 + bleu a2,s0,.L159 + li s1,2 + lbu s2,0(a5) + lw a3,0(a5) + beq a1,s1,.L18 + addi t4,a2,-20 + li t6,3 + andi t2,t4,-16 + beq a1,t6,.L19 + addi t0,t2,19 + addi t6,a4,3 + add t5,a4,t0 + lbu a0,1(a5) + lbu a1,2(a5) + sub s1,t5,t6 + addi s0,s1,-16 + srli a7,s0,4 + addi t0,a5,3 + sb a0,1(a4) + sb a1,2(a4) + sb s2,0(a4) + andi t3,a7,1 + srli t4,t4,4 + mv a1,t0 + mv a0,t6 + bne t3,zero,.L160 + lw s1,1(t0) + lw a0,5(t0) + lw a1,9(t0) + srli t1,a3,24 + lw a3,13(t0) + slli s2,s1,8 + srli a7,s1,24 + slli s0,a1,8 + slli s1,a0,8 + srli a1,a1,24 + srli a0,a0,24 + slli t3,a3,8 + or t1,t1,s2 + or s2,a7,s1 + or a7,a0,s0 + or s1,a1,t3 + sw t1,0(t6) + sw s2,4(t6) + sw a7,8(t6) + sw s1,12(t6) + addi a0,a4,19 + addi a1,a5,19 + beq a0,t5,.L154 +.L160: + sw s3,16(sp) + sw s4,12(sp) + sw s5,8(sp) + sw s6,4(sp) + sw s7,0(sp) +.L20: + lw s6,1(a1) + lw s5,5(a1) + lw s4,9(a1) + lw s3,13(a1) + lw a7,17(a1) + lw a4,21(a1) + lw a5,25(a1) + srli s2,a3,24 + lw a3,29(a1) + slli s7,s6,8 + srli s1,s6,24 + srli s0,s5,24 + slli s6,s5,8 + srli t3,s4,24 + slli s5,s4,8 + slli s4,s3,8 + srli t1,s3,24 + or s2,s2,s7 + slli s3,a7,8 + or s7,s1,s6 + srli a7,a7,24 + or s1,s0,s5 + or s6,t3,s4 + slli s5,a4,8 + slli t3,a5,8 + srli a4,a4,24 + srli a5,a5,24 + slli s4,a3,8 + or s0,t1,s3 + sw s2,0(a0) + or t1,a7,s5 + or s3,a4,t3 + or s2,a5,s4 + sw s7,4(a0) + sw s1,8(a0) + sw s6,12(a0) + sw s0,16(a0) + sw t1,20(a0) + sw s3,24(a0) + sw s2,28(a0) + addi a0,a0,32 + addi a1,a1,32 + bne a0,t5,.L20 + lw s3,16(sp) + lw s4,12(sp) + lw s5,8(sp) + lw s6,4(sp) + lw s7,0(sp) +.L154: + addi a3,t4,1 + slli t5,a3,4 + addi a2,a2,-19 + j .L164 +.L167: + andi t6,a4,3 + beq t6,zero,.L169 +.L17: + andi t2,a2,16 + andi a3,a2,8 + andi a7,a2,4 + andi a0,a2,2 + andi a2,a2,1 + beq t2,zero,.L23 + sw s0,28(sp) + sw s1,24(sp) + sw s2,20(sp) + sw s3,16(sp) + sw s4,12(sp) + sw s5,8(sp) + sw s6,4(sp) + sw s7,0(sp) + lbu s7,0(a5) + lbu s6,1(a5) + lbu s5,2(a5) + lbu s4,3(a5) + lbu s3,4(a5) + lbu s2,5(a5) + lbu s1,6(a5) + lbu s0,7(a5) + lbu t0,9(a5) + lbu t6,10(a5) + lbu t5,11(a5) + lbu t4,12(a5) + lbu t3,13(a5) + lbu t1,14(a5) + lbu a1,15(a5) + lbu t2,8(a5) + sb s7,0(a4) + sb s6,1(a4) + sb s5,2(a4) + sb s4,3(a4) + sb s3,4(a4) + sb s2,5(a4) + sb s1,6(a4) + sb s0,7(a4) + sb t2,8(a4) + sb t0,9(a4) + sb t6,10(a4) + sb t5,11(a4) + sb t4,12(a4) + sb t3,13(a4) + sb t1,14(a4) + sb a1,15(a4) + lw s0,28(sp) + lw s1,24(sp) + lw s2,20(sp) + lw s3,16(sp) + lw s4,12(sp) + lw s5,8(sp) + lw s6,4(sp) + lw s7,0(sp) + addi a5,a5,16 + addi a4,a4,16 +.L23: + beq a3,zero,.L24 + lbu t2,0(a5) + lbu t0,1(a5) + lbu t6,2(a5) + lbu t5,3(a5) + lbu t4,4(a5) + lbu t3,5(a5) + lbu t1,6(a5) + lbu a3,7(a5) + sb t2,0(a4) + sb t0,1(a4) + sb t6,2(a4) + sb t5,3(a4) + sb t4,4(a4) + sb t3,5(a4) + sb t1,6(a4) + sb a3,7(a4) + addi a5,a5,8 + addi a4,a4,8 +.L24: + beq a7,zero,.L25 + lbu t2,0(a5) + lbu a7,1(a5) + lbu a1,2(a5) + lbu t0,3(a5) + sb t2,0(a4) + sb a7,1(a4) + sb a1,2(a4) + sb t0,3(a4) + addi a5,a5,4 + addi a4,a4,4 +.L25: + beq a0,zero,.L7 + lbu a0,0(a5) + lbu t6,1(a5) + addi a4,a4,2 + sb a0,-2(a4) + sb t6,-1(a4) + addi a5,a5,2 +.L7: + beq a2,zero,.L40 + lbu a5,0(a5) + mv a0,a6 + sb a5,0(a4) + addi sp,sp,32 + jr ra +.L166: + lbu a2,0(a5) + addi a5,a5,1 + andi t4,a5,3 + sb a2,0(a6) + addi a4,a6,1 + mv a2,a0 + bne t4,zero,.L111 + j .L2 +.L19: + addi t0,t2,17 + addi t6,a4,1 + add t5,a4,t0 + sub a0,t5,t6 + addi a1,a0,-16 + srli s1,a1,4 + addi t0,a5,1 + sb s2,0(a4) + andi s0,s1,1 + srli t4,t4,4 + mv a1,t0 + mv a0,t6 + bne s0,zero,.L161 + lw t3,7(t0) + lw a7,3(t0) + lw a1,11(t0) + srli t1,a3,8 + lw a3,15(t0) + slli s2,a7,24 + slli s1,t3,24 + srli a0,t3,8 + srli a7,a7,8 + slli s0,a1,24 + slli t3,a3,24 + srli a1,a1,8 + or t1,t1,s2 + or s2,a7,s1 + or a7,a0,s0 + or s1,a1,t3 + sw t1,0(t6) + sw s2,4(t6) + sw a7,8(t6) + sw s1,12(t6) + addi a0,a4,17 + addi a1,a5,17 + beq a0,t5,.L155 +.L161: + sw s3,16(sp) + sw s4,12(sp) + sw s5,8(sp) + sw s6,4(sp) + sw s7,0(sp) +.L22: + lw s6,3(a1) + lw s5,7(a1) + lw s4,11(a1) + lw s3,15(a1) + lw a7,19(a1) + lw a4,23(a1) + lw a5,27(a1) + srli s2,a3,8 + lw a3,31(a1) + slli s7,s6,24 + srli s1,s6,8 + srli s0,s5,8 + slli s6,s5,24 + srli t3,s4,8 + slli s5,s4,24 + slli s4,s3,24 + srli t1,s3,8 + or s2,s2,s7 + slli s3,a7,24 + or s7,s1,s6 + srli a7,a7,8 + or s1,s0,s5 + or s6,t3,s4 + slli s5,a4,24 + slli t3,a5,24 + srli a4,a4,8 + srli a5,a5,8 + slli s4,a3,24 + or s0,t1,s3 + sw s2,0(a0) + or t1,a7,s5 + or s3,a4,t3 + or s2,a5,s4 + sw s7,4(a0) + sw s1,8(a0) + sw s6,12(a0) + sw s0,16(a0) + sw t1,20(a0) + sw s3,24(a0) + sw s2,28(a0) + addi a0,a0,32 + addi a1,a1,32 + bne a0,t5,.L22 + lw s3,16(sp) + lw s4,12(sp) + lw s5,8(sp) + lw s6,4(sp) + lw s7,0(sp) +.L155: + addi a3,t4,1 + slli t5,a3,4 + addi a2,a2,-17 +.L164: + lw s0,28(sp) + lw s1,24(sp) + lw s2,20(sp) + add a5,t0,t5 + add a4,t6,t5 + sub a2,a2,t2 + j .L17 +.L18: + addi t3,a2,-20 + andi t2,t3,-16 + addi t4,t2,18 + addi t6,a4,2 + add t5,a4,t4 + lbu a0,1(a5) + sub t0,t5,t6 + addi t1,t0,-16 + srli a7,t1,4 + addi t0,a5,2 + sb a0,1(a4) + sb s2,0(a4) + andi s0,a7,1 + srli t4,t3,4 + mv a1,t0 + mv a0,t6 + bne s0,zero,.L162 + lw s1,2(t0) + lw t3,6(t0) + lw a1,10(t0) + srli t1,a3,16 + lw a3,14(t0) + slli s2,s1,16 + srli a7,s1,16 + srli a0,t3,16 + slli s1,t3,16 + slli s0,a1,16 + slli t3,a3,16 + srli a1,a1,16 + or t1,t1,s2 + or s2,a7,s1 + or a7,a0,s0 + or s1,a1,t3 + sw t1,0(t6) + sw s2,4(t6) + sw a7,8(t6) + sw s1,12(t6) + addi a0,a4,18 + addi a1,a5,18 + beq a0,t5,.L156 +.L162: + sw s3,16(sp) + sw s4,12(sp) + sw s5,8(sp) + sw s6,4(sp) + sw s7,0(sp) +.L21: + lw s3,2(a1) + lw s4,6(a1) + lw t3,10(a1) + lw t1,14(a1) + lw a7,18(a1) + lw a4,22(a1) + lw a5,26(a1) + srli s2,a3,16 + lw a3,30(a1) + slli s7,s3,16 + srli s1,s3,16 + slli s6,s4,16 + srli s0,s4,16 + slli s5,t3,16 + slli s4,t1,16 + srli t3,t3,16 + slli s3,a7,16 + or s2,s2,s7 + srli t1,t1,16 + or s7,s1,s6 + srli a7,a7,16 + or s1,s0,s5 + or s6,t3,s4 + slli s5,a4,16 + slli t3,a5,16 + srli a4,a4,16 + srli a5,a5,16 + slli s4,a3,16 + or s0,t1,s3 + sw s2,0(a0) + or t1,a7,s5 + or s3,a4,t3 + or s2,a5,s4 + sw s7,4(a0) + sw s1,8(a0) + sw s6,12(a0) + sw s0,16(a0) + sw t1,20(a0) + sw s3,24(a0) + sw s2,28(a0) + addi a0,a0,32 + addi a1,a1,32 + bne a0,t5,.L21 + lw s3,16(sp) + lw s4,12(sp) + lw s5,8(sp) + lw s6,4(sp) + lw s7,0(sp) +.L156: + addi t5,t4,1 + slli t5,t5,4 + addi a2,a2,-18 + j .L164 +.L27: + mv a4,a0 + j .L2 +.L159: + lw s0,28(sp) + lw s1,24(sp) + lw s2,20(sp) + j .L17 +.L168: + #APP +# 23 "memcpy.c" 1 + mv t0, t6 +mv a0, a5 +mv a1, a4 +ecall +# 0 "" 2 + #NO_APP + addi a3,a5,64 + addi a4,a4,64 + j .L117 +.L169: + mv a7,a4 + j .L11 +.L29: + mv a7,a4 + mv t6,a2 + j .L9 + .size memcpy, .-memcpy + .ident "GCC: (gc891d8dc23e1) 13.2.0" diff --git a/zkvm/entrypoint/src/syscalls/mod.rs b/zkvm/entrypoint/src/syscalls/mod.rs index 38ced33993..869379632f 100644 --- a/zkvm/entrypoint/src/syscalls/mod.rs +++ b/zkvm/entrypoint/src/syscalls/mod.rs @@ -109,3 +109,9 @@ pub const BN254_SCALAR_MUL: u32 = 0x00_01_01_20; /// Executes the `BN254_SCALAR_MAC` precompile pub const BN254_SCALAR_MAC: u32 = 0x00_01_01_21; + +/// Executes the `MEMCPY_32` precompile +pub const MEMCPY_32: u32 = 0x00_00_01_30; + +/// Executes the `MEMCPY_64` precompile +pub const MEMCPY_64: u32 = 0x00_00_01_31; From 9ee89cd122d3a6fe7681a2ae8778656e269c68ad Mon Sep 17 00:00:00 2001 From: lightsing Date: Thu, 6 Jun 2024 16:16:46 +0800 Subject: [PATCH 22/34] add eval_memory_access_slice --- core/src/runtime/syscall.rs | 11 ++++- core/src/stark/air.rs | 9 ++-- core/src/syscall/memcpy.rs | 88 ++++++++++++++++++++++++++----------- 3 files changed, 77 insertions(+), 31 deletions(-) diff --git a/core/src/runtime/syscall.rs b/core/src/runtime/syscall.rs index 2b205754c1..ed82432117 100644 --- a/core/src/runtime/syscall.rs +++ b/core/src/runtime/syscall.rs @@ -2,6 +2,7 @@ use std::collections::HashMap; use std::rc::Rc; use strum_macros::EnumIter; +use typenum::{U16, U32, U64, U8}; use crate::runtime::{Register, Runtime}; use crate::stark::Blake3CompressInnerChip; @@ -363,8 +364,14 @@ pub fn default_syscall_map() -> HashMap> { Rc::new(Bn254ScalarMacChip::new()), ); - syscall_map.insert(SyscallCode::MEMCPY_32, Rc::new(MemCopyChip::<8>::new())); - syscall_map.insert(SyscallCode::MEMCPY_64, Rc::new(MemCopyChip::<16>::new())); + syscall_map.insert( + SyscallCode::MEMCPY_32, + Rc::new(MemCopyChip::::new()), + ); + syscall_map.insert( + SyscallCode::MEMCPY_64, + Rc::new(MemCopyChip::::new()), + ); syscall_map } diff --git a/core/src/stark/air.rs b/core/src/stark/air.rs index fa3a80cfda..e0deabbe89 100644 --- a/core/src/stark/air.rs +++ b/core/src/stark/air.rs @@ -6,6 +6,7 @@ use crate::stark::Chip; use crate::StarkGenericConfig; use p3_field::PrimeField32; pub use riscv_chips::*; +use typenum::{U16, U32, U64, U8}; /// A module for importing all the different RISC-V chips. pub(crate) mod riscv_chips { @@ -108,8 +109,8 @@ pub enum RiscvAir { /// A precompile for decompressing a point on the BLS12-381 curve. Bls12381Decompress(WeierstrassDecompressChip>), - MemCpy32(MemCopyChip<8>), - MemCpy64(MemCopyChip<16>), + MemCpy32(MemCopyChip), + MemCpy64(MemCopyChip), } impl RiscvAir { @@ -186,8 +187,8 @@ impl RiscvAir { let byte = ByteChip::default(); chips.push(RiscvAir::ByteLookup(byte)); - chips.push(RiscvAir::MemCpy32(MemCopyChip::<8>::new())); - chips.push(RiscvAir::MemCpy64(MemCopyChip::<16>::new())); + chips.push(RiscvAir::MemCpy32(MemCopyChip::new())); + chips.push(RiscvAir::MemCpy64(MemCopyChip::new())); chips } diff --git a/core/src/syscall/memcpy.rs b/core/src/syscall/memcpy.rs index 5770cc949d..70178a8574 100644 --- a/core/src/syscall/memcpy.rs +++ b/core/src/syscall/memcpy.rs @@ -1,12 +1,16 @@ +use generic_array::{ArrayLength, GenericArray}; use std::borrow::{Borrow, BorrowMut}; +use std::marker::PhantomData; -use p3_air::{Air, BaseAir}; +use p3_air::{Air, AirBuilder, BaseAir}; use p3_field::AbstractField; use p3_field::{Field, PrimeField32}; use p3_matrix::{dense::RowMajorMatrix, Matrix}; use serde::{Deserialize, Serialize}; use sp1_derive::AlignedBorrow; +use crate::operations::field::params::Limbs; +use crate::utils::{limbs_from_access, limbs_from_prev_access}; use crate::{ air::MachineAir, memory::{MemoryReadCols, MemoryWriteCols}, @@ -28,38 +32,49 @@ pub struct MemCopyEvent { #[derive(Debug, Clone, AlignedBorrow)] #[repr(C)] -pub struct MemCopyCols { +pub struct MemCopyCols { is_real: T, shard: T, clk: T, src_ptr: T, dst_ptr: T, - src_access: [MemoryReadCols; NUM_WORDS], - dst_access: [MemoryWriteCols; NUM_WORDS], + src_access: GenericArray, NumWords>, + dst_access: GenericArray, NumWords>, } -pub struct MemCopyChip; +pub struct MemCopyChip { + _marker: PhantomData<(NumWords, NumBytes)>, +} -impl MemCopyChip { - const NUM_COLS: usize = core::mem::size_of::>(); +impl MemCopyChip { + const NUM_COLS: usize = core::mem::size_of::>(); pub fn new() -> Self { - println!("MemCopyChip<{NUM_WORDS}> NUM_COLS = {}", Self::NUM_COLS); - Self + println!( + "MemCopyChip<{}> NUM_COLS = {}", + NumWords::USIZE, + Self::NUM_COLS + ); + assert_eq!(NumWords::USIZE * 4, NumBytes::USIZE); + Self { + _marker: PhantomData, + } } pub fn syscall_id() -> u32 { - match NUM_WORDS { - 8 => SyscallCode::MEMCPY_32.syscall_id(), - 16 => SyscallCode::MEMCPY_64.syscall_id(), + match NumBytes::USIZE { + 32 => SyscallCode::MEMCPY_32.syscall_id(), + 64 => SyscallCode::MEMCPY_64.syscall_id(), _ => unreachable!(), } } } -impl Syscall for MemCopyChip { +impl Syscall + for MemCopyChip +{ fn execute(&self, ctx: &mut crate::runtime::SyscallContext, src: u32, dst: u32) -> Option { - let (read, read_bytes) = ctx.mr_slice(src, NUM_WORDS); + let (read, read_bytes) = ctx.mr_slice(src, NumWords::USIZE); let write = ctx.mw_slice(dst, &read_bytes); let event = MemCopyEvent { @@ -72,7 +87,7 @@ impl Syscall for MemCopyChip { }; ctx.record_mut() .memcpy_events - .entry(NUM_WORDS) + .entry(NumWords::USIZE) .or_default() .push(event); @@ -80,7 +95,8 @@ impl Syscall for MemCopyChip { } } -impl MachineAir for MemCopyChip +impl MachineAir + for MemCopyChip where [(); Self::NUM_COLS]:, { @@ -89,16 +105,16 @@ where type Program = Program; fn name(&self) -> String { - format!("MemCopy{}Chip", NUM_WORDS) + format!("MemCopy{}Chip", NumWords::USIZE) } fn generate_trace(&self, input: &Self::Record, output: &mut Self::Record) -> RowMajorMatrix { let mut rows = vec![]; let mut new_byte_lookup_events = vec![]; - for event in input.memcpy_events.get(&NUM_WORDS).unwrap_or(&vec![]) { + for event in input.memcpy_events.get(&NumWords::USIZE).unwrap_or(&vec![]) { let mut row = [F::zero(); Self::NUM_COLS]; - let cols: &mut MemCopyCols = row.as_mut_slice().borrow_mut(); + let cols: &mut MemCopyCols = row.as_mut_slice().borrow_mut(); cols.is_real = F::one(); cols.shard = F::from_canonical_u32(event.shard); @@ -106,10 +122,10 @@ where cols.src_ptr = F::from_canonical_u32(event.src_ptr); cols.dst_ptr = F::from_canonical_u32(event.dst_ptr); - for i in 0..NUM_WORDS { + for i in 0..NumWords::USIZE { cols.src_access[i].populate(event.src_access[i], &mut new_byte_lookup_events); } - for i in 0..NUM_WORDS { + for i in 0..NumWords::USIZE { cols.dst_access[i].populate(event.dst_access[i], &mut new_byte_lookup_events); } @@ -126,26 +142,48 @@ where fn included(&self, shard: &Self::Record) -> bool { shard .memcpy_events - .get(&NUM_WORDS) + .get(&NumWords::USIZE) .map(|events| !events.is_empty()) .unwrap_or(false) } } -impl BaseAir for MemCopyChip { +impl BaseAir + for MemCopyChip +{ fn width(&self) -> usize { Self::NUM_COLS } } -impl Air for MemCopyChip { +impl Air + for MemCopyChip +{ fn eval(&self, builder: &mut AB) { let main = builder.main(); let row = main.row_slice(0); - let row: &MemCopyCols = (*row).borrow(); + let row: &MemCopyCols = (*row).borrow(); + + let src: Limbs<::Var, NumBytes> = limbs_from_prev_access(&row.src_access); + let dst: Limbs<::Var, NumBytes> = limbs_from_access(&row.dst_access); // TODO assert eq + builder.eval_memory_access_slice( + row.shard, + row.clk.into(), + row.src_ptr, + &row.src_access, + row.is_real, + ); + builder.eval_memory_access_slice( + row.shard, + row.clk.into(), + row.dst_ptr, + &row.dst_access, + row.is_real, + ); + builder.receive_syscall( row.shard, row.clk, From 61b3431dfe98063ee36a07f6172b75b34e45d138 Mon Sep 17 00:00:00 2001 From: lightsing Date: Thu, 13 Jun 2024 11:08:53 +0800 Subject: [PATCH 23/34] update Cargo.lock --- examples/poseidon_bn254/program/Cargo.lock | 125 ++-- examples/poseidon_bn254/script/Cargo.lock | 793 +++++++-------------- 2 files changed, 305 insertions(+), 613 deletions(-) diff --git a/examples/poseidon_bn254/program/Cargo.lock b/examples/poseidon_bn254/program/Cargo.lock index 1e808ebc16..7806435006 100644 --- a/examples/poseidon_bn254/program/Cargo.lock +++ b/examples/poseidon_bn254/program/Cargo.lock @@ -4,9 +4,9 @@ version = 3 [[package]] name = "anyhow" -version = "1.0.83" +version = "1.0.86" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25bdb32cbbdce2b519a9cd7df3a678443100e265d5e25ca763b7572a5104f5f3" +checksum = "b3d1d046238990b9cf5bcde22a3fb3584ee5cf65fb2765f454ed428c7a0063da" [[package]] name = "arrayref" @@ -183,9 +183,9 @@ dependencies = [ [[package]] name = "either" -version = "1.11.0" +version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a47c1c47d2f5964e29c61246e81db715514cd532db6b5116a25ea3c03d6780a2" +checksum = "3dca9240753cf90908d7e4aac30f630662b02aebaa1b58a3cadabdb23385b58b" [[package]] name = "elliptic-curve" @@ -362,9 +362,9 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.154" +version = "0.2.155" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae743338b92ff9146ce83992f766a31066a91a8c84a45e0e9f21e7cf6de6d346" +checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c" [[package]] name = "libm" @@ -380,9 +380,9 @@ checksum = "6c8640c5d730cb13ebd907d8d04b52f55ac9a2eec55b440c8892f40d56c76c1d" [[package]] name = "num" -version = "0.4.2" +version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3135b08af27d103b0a51f2ae0f8632117b7b185ccf931445affa8df530576a41" +checksum = "35bd024e8b2ff75562e5f34e7f4905839deb4b22955ef5e73d2fea1b9813cb23" dependencies = [ "num-bigint", "num-complex", @@ -404,9 +404,9 @@ dependencies = [ [[package]] name = "num-complex" -version = "0.4.5" +version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23c6602fda94a57c990fe0df199a035d83576b496aa29f4e634a8ac6004e68a6" +checksum = "73f88a1307638156682bada9d7604135552957b7818057dcef22705b4d509495" dependencies = [ "num-traits", ] @@ -433,11 +433,10 @@ dependencies = [ [[package]] name = "num-rational" -version = "0.4.1" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0638a1c9d0a3c0914158145bc76cff373a75a627e6ecbfb71cbe6f453a5a19b0" +checksum = "f83d14da390562dca69fc84082e73e548e1ad308d24accdedd2720017cb37824" dependencies = [ - "autocfg", "num-bigint", "num-integer", "num-traits", @@ -461,7 +460,7 @@ checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" [[package]] name = "p3-baby-bear" version = "0.1.0" -source = "git+https://github.com/Plonky3/Plonky3.git?branch=sp1#da0489b75025ec17f1100952694d8b7879c2b43e" +source = "git+https://github.com/Plonky3/Plonky3.git?branch=sp1#f535642f5bea6a2bfded8c4e51b1f2960b1f6da7" dependencies = [ "num-bigint", "p3-field", @@ -475,7 +474,7 @@ dependencies = [ [[package]] name = "p3-dft" version = "0.1.0" -source = "git+https://github.com/Plonky3/Plonky3.git?branch=sp1#da0489b75025ec17f1100952694d8b7879c2b43e" +source = "git+https://github.com/Plonky3/Plonky3.git?branch=sp1#f535642f5bea6a2bfded8c4e51b1f2960b1f6da7" dependencies = [ "p3-field", "p3-matrix", @@ -487,7 +486,7 @@ dependencies = [ [[package]] name = "p3-field" version = "0.1.0" -source = "git+https://github.com/Plonky3/Plonky3.git?branch=sp1#da0489b75025ec17f1100952694d8b7879c2b43e" +source = "git+https://github.com/Plonky3/Plonky3.git?branch=sp1#f535642f5bea6a2bfded8c4e51b1f2960b1f6da7" dependencies = [ "itertools", "num-bigint", @@ -500,7 +499,7 @@ dependencies = [ [[package]] name = "p3-matrix" version = "0.1.0" -source = "git+https://github.com/Plonky3/Plonky3.git?branch=sp1#da0489b75025ec17f1100952694d8b7879c2b43e" +source = "git+https://github.com/Plonky3/Plonky3.git?branch=sp1#f535642f5bea6a2bfded8c4e51b1f2960b1f6da7" dependencies = [ "itertools", "p3-field", @@ -514,12 +513,12 @@ dependencies = [ [[package]] name = "p3-maybe-rayon" version = "0.1.0" -source = "git+https://github.com/Plonky3/Plonky3.git?branch=sp1#da0489b75025ec17f1100952694d8b7879c2b43e" +source = "git+https://github.com/Plonky3/Plonky3.git?branch=sp1#f535642f5bea6a2bfded8c4e51b1f2960b1f6da7" [[package]] name = "p3-mds" version = "0.1.0" -source = "git+https://github.com/Plonky3/Plonky3.git?branch=sp1#da0489b75025ec17f1100952694d8b7879c2b43e" +source = "git+https://github.com/Plonky3/Plonky3.git?branch=sp1#f535642f5bea6a2bfded8c4e51b1f2960b1f6da7" dependencies = [ "itertools", "p3-dft", @@ -533,7 +532,7 @@ dependencies = [ [[package]] name = "p3-poseidon2" version = "0.1.0" -source = "git+https://github.com/Plonky3/Plonky3.git?branch=sp1#da0489b75025ec17f1100952694d8b7879c2b43e" +source = "git+https://github.com/Plonky3/Plonky3.git?branch=sp1#f535642f5bea6a2bfded8c4e51b1f2960b1f6da7" dependencies = [ "gcd", "p3-field", @@ -545,7 +544,7 @@ dependencies = [ [[package]] name = "p3-symmetric" version = "0.1.0" -source = "git+https://github.com/Plonky3/Plonky3.git?branch=sp1#da0489b75025ec17f1100952694d8b7879c2b43e" +source = "git+https://github.com/Plonky3/Plonky3.git?branch=sp1#f535642f5bea6a2bfded8c4e51b1f2960b1f6da7" dependencies = [ "itertools", "p3-field", @@ -555,16 +554,16 @@ dependencies = [ [[package]] name = "p3-util" version = "0.1.0" -source = "git+https://github.com/Plonky3/Plonky3.git?branch=sp1#da0489b75025ec17f1100952694d8b7879c2b43e" +source = "git+https://github.com/Plonky3/Plonky3.git?branch=sp1#f535642f5bea6a2bfded8c4e51b1f2960b1f6da7" dependencies = [ "serde", ] [[package]] name = "parity-scale-codec" -version = "3.6.9" +version = "3.6.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "881331e34fa842a2fb61cc2db9643a8fedc615e47cfcc52597d1af0db9a7e8fe" +checksum = "306800abfa29c7f16596b5970a588435e3d5b3149683d00c12b699cc19f895ee" dependencies = [ "arrayvec", "byte-slice-cast", @@ -574,11 +573,11 @@ dependencies = [ [[package]] name = "parity-scale-codec-derive" -version = "3.6.9" +version = "3.6.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be30eaf4b0a9fba5336683b38de57bb86d179a35862ba6bfcf57625d006bde5b" +checksum = "d830939c76d294956402033aee57a6da7b438f2294eb94864c37b0569053a42c" dependencies = [ - "proc-macro-crate 2.0.2", + "proc-macro-crate", "proc-macro2", "quote", "syn 1.0.109", @@ -624,7 +623,7 @@ dependencies = [ [[package]] name = "poseidon-base" version = "0.1.0" -source = "git+https://github.com/scroll-tech/poseidon-circuit.git?branch=feat/sp1#5509d2e5f9b9868bb14fe6b51fe6a9dc77289c26" +source = "git+https://github.com/scroll-tech/poseidon-circuit.git?branch=feat/sp1#30d40848eae359cf8086a061a4d3bb81bf458f63" dependencies = [ "bitvec", "halo2curves", @@ -650,29 +649,18 @@ checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" [[package]] name = "proc-macro-crate" -version = "1.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f4c021e1093a56626774e81216a4ce732a735e5bad4868a03f3ed65ca0c3919" -dependencies = [ - "once_cell", - "toml_edit 0.19.15", -] - -[[package]] -name = "proc-macro-crate" -version = "2.0.2" +version = "3.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b00f26d3400549137f92511a46ac1cd8ce37cb5598a96d382381458b992a5d24" +checksum = "6d37c51ca738a55da99dc0c4a34860fd675453b8b36209178c2249bb13651284" dependencies = [ - "toml_datetime", - "toml_edit 0.20.2", + "toml_edit", ] [[package]] name = "proc-macro2" -version = "1.0.82" +version = "1.0.84" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ad3d49ab951a01fbaafe34f2ec74122942fe18a3f9814c3268f1bb72042131b" +checksum = "ec96c6a92621310b51366f1e28d05ef11489516e93be030060e5fc12024a49d6" dependencies = [ "unicode-ident", ] @@ -734,9 +722,9 @@ dependencies = [ [[package]] name = "scale-info" -version = "2.11.2" +version = "2.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7c453e59a955f81fb62ee5d596b450383d699f152d350e9d23a0db2adb78e4c0" +checksum = "eca070c12893629e2cc820a9761bedf6ce1dcddc9852984d1dc734b8bd9bd024" dependencies = [ "cfg-if", "derive_more", @@ -746,11 +734,11 @@ dependencies = [ [[package]] name = "scale-info-derive" -version = "2.11.2" +version = "2.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "18cf6c6447f813ef19eb450e985bcce6705f9ce7660db221b59093d15c79c4b7" +checksum = "2d35494501194174bda522a32605929eefc9ecf7e0a326c26db1fdd85881eb62" dependencies = [ - "proc-macro-crate 1.3.1", + "proc-macro-crate", "proc-macro2", "quote", "syn 1.0.109", @@ -772,22 +760,22 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.200" +version = "1.0.203" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ddc6f9cc94d67c0e21aaf7eda3a010fd3af78ebf6e096aa6e2e13c79749cce4f" +checksum = "7253ab4de971e72fb7be983802300c30b5a7f0c2e56fab8abfc6a214307c0094" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.200" +version = "1.0.203" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "856f046b9400cee3c8c94ed572ecdb752444c24528c035cd35882aad6f492bcb" +checksum = "500cbc0ebeb6f46627f50f3f5811ccf6bf00643be300b4c3eabc0ef55dc5b5ba" dependencies = [ "proc-macro2", "quote", - "syn 2.0.61", + "syn 2.0.66", ] [[package]] @@ -909,9 +897,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.61" +version = "2.0.66" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c993ed8ccba56ae856363b1845da7266a7cb78e1d146c8a32d54b45a8b831fc9" +checksum = "c42f3f41a2de00b01c0aaad383c5a45241efc8b2d1eda5661812fda5f3cdcff5" dependencies = [ "proc-macro2", "quote", @@ -926,26 +914,15 @@ checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" [[package]] name = "toml_datetime" -version = "0.6.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7cda73e2f1397b1262d6dfdcef8aafae14d1de7748d66822d3bfeeb6d03e5e4b" - -[[package]] -name = "toml_edit" -version = "0.19.15" +version = "0.6.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b5bb770da30e5cbfde35a2d7b9b8a2c4b8ef89548a7a6aeab5c9a576e3e7421" -dependencies = [ - "indexmap", - "toml_datetime", - "winnow", -] +checksum = "4badfd56924ae69bcc9039335b2e017639ce3f9b001c393c1b2d1ef846ce2cbf" [[package]] name = "toml_edit" -version = "0.20.2" +version = "0.21.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "396e4d48bbb2b7554c944bde63101b5ae446cff6ec4a24227428f15eb72ef338" +checksum = "6a8534fd7f78b5405e860340ad6575217ce99f38d4d5c8f2442cb5ecb50090e1" dependencies = [ "indexmap", "toml_datetime", @@ -971,7 +948,7 @@ checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.61", + "syn 2.0.66", ] [[package]] @@ -1027,6 +1004,6 @@ dependencies = [ [[package]] name = "zeroize" -version = "1.7.0" +version = "1.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "525b4ec142c6b68a2d10f01f7bbf6755599ca3f81ea53b8431b7dd348f5fdb2d" +checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde" diff --git a/examples/poseidon_bn254/script/Cargo.lock b/examples/poseidon_bn254/script/Cargo.lock index 7f5252662d..7afd58c838 100644 --- a/examples/poseidon_bn254/script/Cargo.lock +++ b/examples/poseidon_bn254/script/Cargo.lock @@ -59,7 +59,7 @@ dependencies = [ "alloy-signer", "alloy-signer-wallet", "alloy-transport-http", - "reqwest 0.12.4", + "reqwest", ] [[package]] @@ -95,9 +95,9 @@ dependencies = [ [[package]] name = "alloy-core" -version = "0.7.2" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e30b83573b348305b9629a094b5331093a030514cd5713433799495cb283fea1" +checksum = "f7253846c7bf55147775fd66c334abc1dd0a41e97e6155577b3dc513c6e66ef2" dependencies = [ "alloy-dyn-abi", "alloy-json-abi", @@ -107,9 +107,9 @@ dependencies = [ [[package]] name = "alloy-dyn-abi" -version = "0.7.2" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "545885d9b0b2c30fd344ae291439b4bfe59e48dd62fbc862f8503d98088967dc" +checksum = "8425a283510106b1a6ad25dd4bb648ecde7da3fd2baeb9400a85ad62f51ec90b" dependencies = [ "alloy-json-abi", "alloy-primitives", @@ -147,9 +147,9 @@ dependencies = [ [[package]] name = "alloy-json-abi" -version = "0.7.2" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "786689872ec4e7d354810ab0dffd48bb40b838c047522eb031cbd47d15634849" +checksum = "7e30946aa6173020259055a44971f5cf40a7d76c931d209caeb51b333263df4f" dependencies = [ "alloy-primitives", "alloy-sol-type-parser", @@ -187,9 +187,9 @@ dependencies = [ [[package]] name = "alloy-primitives" -version = "0.7.2" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "525448f6afc1b70dd0f9d0a8145631bf2f5e434678ab23ab18409ca264cae6b3" +checksum = "db8aa973e647ec336810a9356af8aea787249c9d00b1525359f3db29a68d231b" dependencies = [ "alloy-rlp", "bytes", @@ -226,7 +226,7 @@ dependencies = [ "dashmap", "futures", "lru", - "reqwest 0.12.4", + "reqwest", "serde_json", "tokio", "tracing", @@ -235,9 +235,9 @@ dependencies = [ [[package]] name = "alloy-rlp" -version = "0.3.4" +version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d58d9f5da7b40e9bfff0b7e7816700be4019db97d4b6359fe7f94a9e22e42ac" +checksum = "b155716bab55763c95ba212806cf43d05bcc70e5f35b02bad20cf5ec7fe11fed" dependencies = [ "alloy-rlp-derive", "arrayvec", @@ -246,13 +246,13 @@ dependencies = [ [[package]] name = "alloy-rlp-derive" -version = "0.3.4" +version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a047897373be4bbb0224c1afdabca92648dc57a9c9ef6e7b0be3aff7a859c83" +checksum = "8037e03c7f462a063f28daec9fda285a9a89da003c552f8637a80b9c8fd96241" dependencies = [ "proc-macro2", "quote", - "syn 2.0.61", + "syn 2.0.66", ] [[package]] @@ -265,7 +265,7 @@ dependencies = [ "alloy-transport-http", "futures", "pin-project", - "reqwest 0.12.4", + "reqwest", "serde", "serde_json", "tokio", @@ -345,9 +345,23 @@ dependencies = [ [[package]] name = "alloy-sol-macro" -version = "0.7.2" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7dbd17d67f3e89478c8a634416358e539e577899666c927bc3d2b1328ee9b6ca" +dependencies = [ + "alloy-sol-macro-expander", + "alloy-sol-macro-input", + "proc-macro-error", + "proc-macro2", + "quote", + "syn 2.0.66", +] + +[[package]] +name = "alloy-sol-macro-expander" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89c80a2cb97e7aa48611cbb63950336f9824a174cdf670527cc6465078a26ea1" +checksum = "2c6da95adcf4760bb4b108fefa51d50096c5e5fdd29ee72fed3e86ee414f2e34" dependencies = [ "alloy-json-abi", "alloy-sol-macro-input", @@ -357,16 +371,16 @@ dependencies = [ "proc-macro-error", "proc-macro2", "quote", - "syn 2.0.61", + "syn 2.0.66", "syn-solidity", "tiny-keccak", ] [[package]] name = "alloy-sol-macro-input" -version = "0.7.2" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c58894b58ac50979eeac6249661991ac40b9d541830d9a725f7714cc9ef08c23" +checksum = "32c8da04c1343871fb6ce5a489218f9c85323c8340a36e9106b5fc98d4dd59d5" dependencies = [ "alloy-json-abi", "const-hex", @@ -375,24 +389,24 @@ dependencies = [ "proc-macro2", "quote", "serde_json", - "syn 2.0.61", + "syn 2.0.66", "syn-solidity", ] [[package]] name = "alloy-sol-type-parser" -version = "0.7.2" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7da8e71ea68e780cc203919e03f69f59e7afe92d2696fb1dcb6662f61e4031b6" +checksum = "368cae4dc052cad1d8f72eb2ae0c38027116933eeb49213c200a9e9875f208d7" dependencies = [ "winnow 0.6.8", ] [[package]] name = "alloy-sol-types" -version = "0.7.2" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "399287f68d1081ed8b1f4903c49687658b95b142207d7cb4ae2f4813915343ef" +checksum = "40a64d2d2395c1ac636b62419a7b17ec39031d6b2367e66e9acbf566e6055e9c" dependencies = [ "alloy-json-abi", "alloy-primitives", @@ -407,7 +421,7 @@ version = "0.1.0" source = "git+https://github.com/alloy-rs/alloy?rev=bfd0fda#bfd0fda492e560c3463d521958793c81bbeadfc1" dependencies = [ "alloy-json-rpc", - "base64 0.22.1", + "base64", "futures-util", "futures-utils-wasm", "serde", @@ -426,7 +440,7 @@ source = "git+https://github.com/alloy-rs/alloy?rev=bfd0fda#bfd0fda492e560c3463d dependencies = [ "alloy-json-rpc", "alloy-transport", - "reqwest 0.12.4", + "reqwest", "serde_json", "tower", "url", @@ -458,9 +472,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.83" +version = "1.0.86" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25bdb32cbbdce2b519a9cd7df3a678443100e265d5e25ca763b7572a5104f5f3" +checksum = "b3d1d046238990b9cf5bcde22a3fb3584ee5cf65fb2765f454ed428c7a0063da" [[package]] name = "ark-ff" @@ -617,7 +631,7 @@ checksum = "16e62a023e7c117e27523144c5d2459f4397fcc3cab0085af8e2224f643a0193" dependencies = [ "proc-macro2", "quote", - "syn 2.0.61", + "syn 2.0.66", ] [[package]] @@ -628,9 +642,15 @@ checksum = "c6fa2087f2753a7da8cc1c0dbfcf89579dd57458e36769de5ac750b4671737ca" dependencies = [ "proc-macro2", "quote", - "syn 2.0.61", + "syn 2.0.66", ] +[[package]] +name = "atomic-waker" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" + [[package]] name = "auto_impl" version = "1.2.0" @@ -639,7 +659,7 @@ checksum = "3c87f3f15e7794432337fc718554eaa4dc8f04c9677a950ffe366f20a162ae42" dependencies = [ "proc-macro2", "quote", - "syn 2.0.61", + "syn 2.0.66", ] [[package]] @@ -658,10 +678,10 @@ dependencies = [ "axum-core", "bytes", "futures-util", - "http 1.1.0", - "http-body 1.0.0", + "http", + "http-body", "http-body-util", - "hyper 1.3.1", + "hyper", "hyper-util", "itoa", "matchit", @@ -691,8 +711,8 @@ dependencies = [ "async-trait", "bytes", "futures-util", - "http 1.1.0", - "http-body 1.0.0", + "http", + "http-body", "http-body-util", "mime", "pin-project-lite", @@ -724,12 +744,6 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4c7f02d4ea65f2c1853089ffd8d2787bdbc63de2f0d29dedbcf8ccdfa0ccd4cf" -[[package]] -name = "base64" -version = "0.21.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567" - [[package]] name = "base64" version = "0.22.1" @@ -859,9 +873,9 @@ dependencies = [ [[package]] name = "c-kzg" -version = "1.0.0" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3130f3d8717cc02e668a896af24984d5d5d4e8bf12e278e982e0f1bd88a0f9af" +checksum = "cdf100c4cea8f207e883ff91ca886d621d8a166cb04971dfaa9bb8fd99ed95df" dependencies = [ "blst", "cc", @@ -873,9 +887,9 @@ dependencies = [ [[package]] name = "camino" -version = "1.1.6" +version = "1.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c59e92b5a388f549b863a7bea62612c09f24c8393560709a54558a9abdfb3b9c" +checksum = "e0ec6b951b160caa93cc0c7b209e5a3bff7aae9062213451ac99493cd844c239" dependencies = [ "serde", ] @@ -905,9 +919,9 @@ dependencies = [ [[package]] name = "cc" -version = "1.0.97" +version = "1.0.98" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "099a5357d84c4c61eb35fc8eafa9a79a902c2f76911e5747ced4e032edd8d9b4" +checksum = "41c270e7540d725e65ac7f1b212ac8ce349719624d7bcff99f8e2e488e8cf03f" [[package]] name = "cfg-if" @@ -943,9 +957,9 @@ dependencies = [ [[package]] name = "const-hex" -version = "1.11.3" +version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ba00838774b4ab0233e355d26710fbfc8327a05c017f6dc4873f876d1f79f78" +checksum = "94fb8a24a26d37e1ffd45343323dc9fe6654ceea44c12f2fcb3d7ac29e610bc6" dependencies = [ "cfg-if", "cpufeatures", @@ -1018,9 +1032,9 @@ dependencies = [ [[package]] name = "crossbeam-utils" -version = "0.8.19" +version = "0.8.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "248e3bacc7dc6baa3b21e405ee045c3047101a49145e7e9eca583ab4c2ca5345" +checksum = "22ec99545bb0ed0ea7bb9b8e1e9122ea386ff8a48c0922e43f36d45ab09e0e80" [[package]] name = "crunchy" @@ -1074,14 +1088,14 @@ checksum = "f46882e17999c6cc590af592290432be3bce0428cb0d5f8b6715e4dc7b383eb3" dependencies = [ "proc-macro2", "quote", - "syn 2.0.61", + "syn 2.0.66", ] [[package]] name = "darling" -version = "0.20.8" +version = "0.20.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "54e36fcd13ed84ffdfda6f5be89b31287cbb80c439841fe69e04841435464391" +checksum = "83b2eb4d90d12bdda5ed17de686c2acb4c57914f8f921b8da7e112b5a36f3fe1" dependencies = [ "darling_core", "darling_macro", @@ -1089,27 +1103,27 @@ dependencies = [ [[package]] name = "darling_core" -version = "0.20.8" +version = "0.20.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c2cf1c23a687a1feeb728783b993c4e1ad83d99f351801977dd809b48d0a70f" +checksum = "622687fe0bac72a04e5599029151f5796111b90f1baaa9b544d807a5e31cd120" dependencies = [ "fnv", "ident_case", "proc-macro2", "quote", "strsim", - "syn 2.0.61", + "syn 2.0.66", ] [[package]] name = "darling_macro" -version = "0.20.8" +version = "0.20.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a668eda54683121533a393014d8692171709ff57a7d61f187b6e782719f8933f" +checksum = "733cabb43482b1a1b53eee8583c2b9e8684d592215ea83efd305dd31bc2f0178" dependencies = [ "darling_core", "quote", - "syn 2.0.61", + "syn 2.0.66", ] [[package]] @@ -1125,12 +1139,6 @@ dependencies = [ "parking_lot_core", ] -[[package]] -name = "data-encoding" -version = "2.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8566979429cf69b49a5c740c60791108e86440e8be149bbea4fe54d2c32d6e2" - [[package]] name = "der" version = "0.7.9" @@ -1230,9 +1238,9 @@ dependencies = [ [[package]] name = "either" -version = "1.11.0" +version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a47c1c47d2f5964e29c61246e81db715514cd532db6b5116a25ea3c03d6780a2" +checksum = "3dca9240753cf90908d7e4aac30f630662b02aebaa1b58a3cadabdb23385b58b" [[package]] name = "elf" @@ -1274,18 +1282,6 @@ dependencies = [ "cfg-if", ] -[[package]] -name = "enum-as-inner" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ffccbb6966c05b32ef8fbac435df276c4ae4d3dc55a8cd0eb9745e6c12f546a" -dependencies = [ - "heck 0.4.1", - "proc-macro2", - "quote", - "syn 2.0.61", -] - [[package]] name = "equivalent" version = "1.0.1" @@ -1294,9 +1290,9 @@ checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" [[package]] name = "errno" -version = "0.3.8" +version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a258e46cdc063eb8519c00b9fc845fc47bcfca4130e2f08e88665ceda8474245" +checksum = "534c5cf6194dfab3db3242765c03bbe257cf92f22b38f6bc0c58d59108a820ba" dependencies = [ "libc", "windows-sys 0.52.0", @@ -1331,9 +1327,9 @@ dependencies = [ [[package]] name = "fiat-crypto" -version = "0.2.8" +version = "0.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38793c55593b33412e3ae40c2c9781ffaa6f438f6f8c10f24e71846fbd7ae01e" +checksum = "28dea519a9695b9977216879a3ebfddf92f1c08c05d984f8996aecd6ecdc811d" [[package]] name = "fixed-hash" @@ -1439,7 +1435,7 @@ checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" dependencies = [ "proc-macro2", "quote", - "syn 2.0.61", + "syn 2.0.66", ] [[package]] @@ -1541,35 +1537,16 @@ dependencies = [ [[package]] name = "h2" -version = "0.3.26" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81fe527a889e1532da5c525686d96d4c2e74cdd345badf8dfef9f6b39dd5f5e8" -dependencies = [ - "bytes", - "fnv", - "futures-core", - "futures-sink", - "futures-util", - "http 0.2.12", - "indexmap 2.2.6", - "slab", - "tokio", - "tokio-util", - "tracing", -] - -[[package]] -name = "h2" -version = "0.4.4" +version = "0.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "816ec7294445779408f36fe57bc5b7fc1cf59664059096c65f905c1c61f58069" +checksum = "fa82e28a107a8cc405f0839610bdc9b15f1e25ec7d696aa5cf173edbcb1486ab" dependencies = [ + "atomic-waker", "bytes", "fnv", "futures-core", "futures-sink", - "futures-util", - "http 1.1.0", + "http", "indexmap 2.2.6", "slab", "tokio", @@ -1626,51 +1603,6 @@ version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6fe2267d4ed49bc07b63801559be28c718ea06c4738b7a03c94df7386d2cde46" -[[package]] -name = "hickory-proto" -version = "0.24.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07698b8420e2f0d6447a436ba999ec85d8fbf2a398bbd737b82cac4a2e96e512" -dependencies = [ - "async-trait", - "cfg-if", - "data-encoding", - "enum-as-inner", - "futures-channel", - "futures-io", - "futures-util", - "idna 0.4.0", - "ipnet", - "once_cell", - "rand", - "thiserror", - "tinyvec", - "tokio", - "tracing", - "url", -] - -[[package]] -name = "hickory-resolver" -version = "0.24.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28757f23aa75c98f254cf0405e6d8c25b831b32921b050a66692427679b1f243" -dependencies = [ - "cfg-if", - "futures-util", - "hickory-proto", - "ipconfig", - "lru-cache", - "once_cell", - "parking_lot", - "rand", - "resolv-conf", - "smallvec", - "thiserror", - "tokio", - "tracing", -] - [[package]] name = "hmac" version = "0.12.1" @@ -1680,28 +1612,6 @@ dependencies = [ "digest 0.10.7", ] -[[package]] -name = "hostname" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c731c3e10504cc8ed35cfe2f1db4c9274c3d35fa486e3b31df46f068ef3e867" -dependencies = [ - "libc", - "match_cfg", - "winapi", -] - -[[package]] -name = "http" -version = "0.2.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "601cbb57e577e2f5ef5be8e7b83f0f63994f25aa94d673e54a92d5c516d101f1" -dependencies = [ - "bytes", - "fnv", - "itoa", -] - [[package]] name = "http" version = "1.1.0" @@ -1713,17 +1623,6 @@ dependencies = [ "itoa", ] -[[package]] -name = "http-body" -version = "0.4.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ceab25649e9960c0311ea418d17bee82c0dcec1bd053b5f9a66e265a693bed2" -dependencies = [ - "bytes", - "http 0.2.12", - "pin-project-lite", -] - [[package]] name = "http-body" version = "1.0.0" @@ -1731,7 +1630,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1cac85db508abc24a2e48553ba12a996e87244a0395ce011e62b37158745d643" dependencies = [ "bytes", - "http 1.1.0", + "http", ] [[package]] @@ -1742,8 +1641,8 @@ checksum = "0475f8b2ac86659c21b64320d5d653f9efe42acd2a4e560073ec61a155a34f1d" dependencies = [ "bytes", "futures-core", - "http 1.1.0", - "http-body 1.0.0", + "http", + "http-body", "pin-project-lite", ] @@ -1759,30 +1658,6 @@ version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" -[[package]] -name = "hyper" -version = "0.14.28" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf96e135eb83a2a8ddf766e426a841d8ddd7449d5f00d34ea02b41d2f19eef80" -dependencies = [ - "bytes", - "futures-channel", - "futures-core", - "futures-util", - "h2 0.3.26", - "http 0.2.12", - "http-body 0.4.6", - "httparse", - "httpdate", - "itoa", - "pin-project-lite", - "socket2", - "tokio", - "tower-service", - "tracing", - "want", -] - [[package]] name = "hyper" version = "1.3.1" @@ -1792,9 +1667,9 @@ dependencies = [ "bytes", "futures-channel", "futures-util", - "h2 0.4.4", - "http 1.1.0", - "http-body 1.0.0", + "h2", + "http", + "http-body", "httparse", "httpdate", "itoa", @@ -1806,29 +1681,19 @@ dependencies = [ [[package]] name = "hyper-rustls" -version = "0.24.2" +version = "0.26.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec3efd23720e2049821a693cbc7e65ea87c72f1c58ff2f9522ff332b1491e590" +checksum = "a0bea761b46ae2b24eb4aef630d8d1c398157b6fc29e6350ecf090a0b70c952c" dependencies = [ "futures-util", - "http 0.2.12", - "hyper 0.14.28", + "http", + "hyper", + "hyper-util", "rustls", + "rustls-pki-types", "tokio", "tokio-rustls", -] - -[[package]] -name = "hyper-tls" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d6183ddfa99b85da61a140bea0efc93fdf56ceaa041b37d553518030827f9905" -dependencies = [ - "bytes", - "hyper 0.14.28", - "native-tls", - "tokio", - "tokio-native-tls", + "tower-service", ] [[package]] @@ -1839,7 +1704,7 @@ checksum = "70206fc6890eaca9fde8a0bf71caa2ddfc9fe045ac9e5c70df101a7dbde866e0" dependencies = [ "bytes", "http-body-util", - "hyper 1.3.1", + "hyper", "hyper-util", "native-tls", "tokio", @@ -1849,16 +1714,16 @@ dependencies = [ [[package]] name = "hyper-util" -version = "0.1.3" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca38ef113da30126bbff9cd1705f9273e15d45498615d138b0c20279ac7a76aa" +checksum = "3d8d52be92d09acc2e01dddb7fde3ad983fc6489c7db4837e605bc3fca4cb63e" dependencies = [ "bytes", "futures-channel", "futures-util", - "http 1.1.0", - "http-body 1.0.0", - "hyper 1.3.1", + "http", + "http-body", + "hyper", "pin-project-lite", "socket2", "tokio", @@ -1896,16 +1761,6 @@ version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" -[[package]] -name = "idna" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d20d6b07bfbc108882d88ed8e37d39636dcc260e15e30c45e6ba089610b917c" -dependencies = [ - "unicode-bidi", - "unicode-normalization", -] - [[package]] name = "idna" version = "0.5.0" @@ -1973,25 +1828,13 @@ dependencies = [ [[package]] name = "instant" -version = "0.1.12" +version = "0.1.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c" +checksum = "e0242819d153cba4b4b05a5a8f2a7e9bbf97b6055b2a002b395c96b5ff3c0222" dependencies = [ "cfg-if", ] -[[package]] -name = "ipconfig" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b58db92f96b720de98181bbbe63c831e87005ab460c1bf306eb2622b4707997f" -dependencies = [ - "socket2", - "widestring", - "windows-sys 0.48.0", - "winreg 0.50.0", -] - [[package]] name = "ipnet" version = "2.9.0" @@ -2047,9 +1890,9 @@ dependencies = [ [[package]] name = "keccak-asm" -version = "0.1.0" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb8515fff80ed850aea4a1595f2e519c003e2a00a82fe168ebf5269196caf444" +checksum = "47a3633291834c4fbebf8673acbc1b04ec9d151418ff9b8e26dcd79129928758" dependencies = [ "digest 0.10.7", "sha3-asm", @@ -2063,9 +1906,9 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" [[package]] name = "libc" -version = "0.2.154" +version = "0.2.155" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae743338b92ff9146ce83992f766a31066a91a8c84a45e0e9f21e7cf6de6d346" +checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c" [[package]] name = "libm" @@ -2073,17 +1916,11 @@ version = "0.2.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4ec2a862134d2a7d32d7983ddcdd1c4923530833c9f2ea1a44fc5fa473989058" -[[package]] -name = "linked-hash-map" -version = "0.5.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0717cef1bc8b636c6e1c1bbdefc09e6322da8a9321966e8928ef80d20f7f770f" - [[package]] name = "linux-raw-sys" -version = "0.4.13" +version = "0.4.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "01cda141df6706de531b6c46c3a33ecca755538219bd484262fa09410c13539c" +checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89" [[package]] name = "lock_api" @@ -2110,21 +1947,6 @@ dependencies = [ "hashbrown 0.14.5", ] -[[package]] -name = "lru-cache" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "31e24f1ad8321ca0e8a1e0ac13f23cb668e6f5466c2c57319f6a5cf1cc8e3b1c" -dependencies = [ - "linked-hash-map", -] - -[[package]] -name = "match_cfg" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ffbee8634e0d45d258acb448e7eaab3fce7a0a467395d4d9f228e3c1f01fb2e4" - [[package]] name = "matchers" version = "0.1.0" @@ -2152,21 +1974,11 @@ version = "0.3.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" -[[package]] -name = "mime_guess" -version = "2.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4192263c238a5f0d0c6bfd21f336a313a4ce1c450542449ca191bb657b4642ef" -dependencies = [ - "mime", - "unicase", -] - [[package]] name = "miniz_oxide" -version = "0.7.2" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d811f3e15f28568be3407c8e7fdb6514c1cda3cb30683f15b6a1a1dc4ea14a7" +checksum = "87dfd01fe195c66b572b37921ad8803d010623c0aca821bea2302239d155cdae" dependencies = [ "adler", ] @@ -2184,11 +1996,10 @@ dependencies = [ [[package]] name = "native-tls" -version = "0.2.11" +version = "0.2.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07226173c32f2926027b63cce4bcd8076c3552846cbe7925f3aaffeac0a3b92e" +checksum = "a8614eb2c83d59d1c8cc974dd3f920198647674a0a035e1af1fa58707e317466" dependencies = [ - "lazy_static", "libc", "log", "openssl", @@ -2218,9 +2029,9 @@ dependencies = [ [[package]] name = "num" -version = "0.4.2" +version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3135b08af27d103b0a51f2ae0f8632117b7b185ccf931445affa8df530576a41" +checksum = "35bd024e8b2ff75562e5f34e7f4905839deb4b22955ef5e73d2fea1b9813cb23" dependencies = [ "num-bigint", "num-complex", @@ -2242,9 +2053,9 @@ dependencies = [ [[package]] name = "num-complex" -version = "0.4.5" +version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23c6602fda94a57c990fe0df199a035d83576b496aa29f4e634a8ac6004e68a6" +checksum = "73f88a1307638156682bada9d7604135552957b7818057dcef22705b4d509495" dependencies = [ "num-traits", ] @@ -2277,11 +2088,10 @@ dependencies = [ [[package]] name = "num-rational" -version = "0.4.1" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0638a1c9d0a3c0914158145bc76cff373a75a627e6ecbfb71cbe6f453a5a19b0" +checksum = "f83d14da390562dca69fc84082e73e548e1ad308d24accdedd2720017cb37824" dependencies = [ - "autocfg", "num-bigint", "num-integer", "num-traits", @@ -2372,7 +2182,7 @@ checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.61", + "syn 2.0.66", ] [[package]] @@ -2402,7 +2212,7 @@ checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39" [[package]] name = "p3-air" version = "0.1.0" -source = "git+https://github.com/Plonky3/Plonky3.git?branch=sp1#da0489b75025ec17f1100952694d8b7879c2b43e" +source = "git+https://github.com/Plonky3/Plonky3.git?branch=sp1#f535642f5bea6a2bfded8c4e51b1f2960b1f6da7" dependencies = [ "p3-field", "p3-matrix", @@ -2411,7 +2221,7 @@ dependencies = [ [[package]] name = "p3-baby-bear" version = "0.1.0" -source = "git+https://github.com/Plonky3/Plonky3.git?branch=sp1#da0489b75025ec17f1100952694d8b7879c2b43e" +source = "git+https://github.com/Plonky3/Plonky3.git?branch=sp1#f535642f5bea6a2bfded8c4e51b1f2960b1f6da7" dependencies = [ "num-bigint", "p3-field", @@ -2425,7 +2235,7 @@ dependencies = [ [[package]] name = "p3-blake3" version = "0.1.0" -source = "git+https://github.com/Plonky3/Plonky3.git?branch=sp1#da0489b75025ec17f1100952694d8b7879c2b43e" +source = "git+https://github.com/Plonky3/Plonky3.git?branch=sp1#f535642f5bea6a2bfded8c4e51b1f2960b1f6da7" dependencies = [ "blake3", "p3-symmetric", @@ -2434,7 +2244,7 @@ dependencies = [ [[package]] name = "p3-challenger" version = "0.1.0" -source = "git+https://github.com/Plonky3/Plonky3.git?branch=sp1#da0489b75025ec17f1100952694d8b7879c2b43e" +source = "git+https://github.com/Plonky3/Plonky3.git?branch=sp1#f535642f5bea6a2bfded8c4e51b1f2960b1f6da7" dependencies = [ "p3-field", "p3-maybe-rayon", @@ -2446,7 +2256,7 @@ dependencies = [ [[package]] name = "p3-commit" version = "0.1.0" -source = "git+https://github.com/Plonky3/Plonky3.git?branch=sp1#da0489b75025ec17f1100952694d8b7879c2b43e" +source = "git+https://github.com/Plonky3/Plonky3.git?branch=sp1#f535642f5bea6a2bfded8c4e51b1f2960b1f6da7" dependencies = [ "itertools 0.12.1", "p3-challenger", @@ -2459,7 +2269,7 @@ dependencies = [ [[package]] name = "p3-dft" version = "0.1.0" -source = "git+https://github.com/Plonky3/Plonky3.git?branch=sp1#da0489b75025ec17f1100952694d8b7879c2b43e" +source = "git+https://github.com/Plonky3/Plonky3.git?branch=sp1#f535642f5bea6a2bfded8c4e51b1f2960b1f6da7" dependencies = [ "p3-field", "p3-matrix", @@ -2471,7 +2281,7 @@ dependencies = [ [[package]] name = "p3-field" version = "0.1.0" -source = "git+https://github.com/Plonky3/Plonky3.git?branch=sp1#da0489b75025ec17f1100952694d8b7879c2b43e" +source = "git+https://github.com/Plonky3/Plonky3.git?branch=sp1#f535642f5bea6a2bfded8c4e51b1f2960b1f6da7" dependencies = [ "itertools 0.12.1", "num-bigint", @@ -2484,7 +2294,7 @@ dependencies = [ [[package]] name = "p3-fri" version = "0.1.0" -source = "git+https://github.com/Plonky3/Plonky3.git?branch=sp1#da0489b75025ec17f1100952694d8b7879c2b43e" +source = "git+https://github.com/Plonky3/Plonky3.git?branch=sp1#f535642f5bea6a2bfded8c4e51b1f2960b1f6da7" dependencies = [ "itertools 0.12.1", "p3-challenger", @@ -2502,7 +2312,7 @@ dependencies = [ [[package]] name = "p3-interpolation" version = "0.1.0" -source = "git+https://github.com/Plonky3/Plonky3.git?branch=sp1#da0489b75025ec17f1100952694d8b7879c2b43e" +source = "git+https://github.com/Plonky3/Plonky3.git?branch=sp1#f535642f5bea6a2bfded8c4e51b1f2960b1f6da7" dependencies = [ "p3-field", "p3-matrix", @@ -2512,7 +2322,7 @@ dependencies = [ [[package]] name = "p3-keccak" version = "0.1.0" -source = "git+https://github.com/Plonky3/Plonky3.git?branch=sp1#da0489b75025ec17f1100952694d8b7879c2b43e" +source = "git+https://github.com/Plonky3/Plonky3.git?branch=sp1#f535642f5bea6a2bfded8c4e51b1f2960b1f6da7" dependencies = [ "p3-symmetric", "tiny-keccak", @@ -2521,7 +2331,7 @@ dependencies = [ [[package]] name = "p3-keccak-air" version = "0.1.0" -source = "git+https://github.com/Plonky3/Plonky3.git?branch=sp1#da0489b75025ec17f1100952694d8b7879c2b43e" +source = "git+https://github.com/Plonky3/Plonky3.git?branch=sp1#f535642f5bea6a2bfded8c4e51b1f2960b1f6da7" dependencies = [ "p3-air", "p3-field", @@ -2534,7 +2344,7 @@ dependencies = [ [[package]] name = "p3-matrix" version = "0.1.0" -source = "git+https://github.com/Plonky3/Plonky3.git?branch=sp1#da0489b75025ec17f1100952694d8b7879c2b43e" +source = "git+https://github.com/Plonky3/Plonky3.git?branch=sp1#f535642f5bea6a2bfded8c4e51b1f2960b1f6da7" dependencies = [ "itertools 0.12.1", "p3-field", @@ -2548,7 +2358,7 @@ dependencies = [ [[package]] name = "p3-maybe-rayon" version = "0.1.0" -source = "git+https://github.com/Plonky3/Plonky3.git?branch=sp1#da0489b75025ec17f1100952694d8b7879c2b43e" +source = "git+https://github.com/Plonky3/Plonky3.git?branch=sp1#f535642f5bea6a2bfded8c4e51b1f2960b1f6da7" dependencies = [ "rayon", ] @@ -2556,7 +2366,7 @@ dependencies = [ [[package]] name = "p3-mds" version = "0.1.0" -source = "git+https://github.com/Plonky3/Plonky3.git?branch=sp1#da0489b75025ec17f1100952694d8b7879c2b43e" +source = "git+https://github.com/Plonky3/Plonky3.git?branch=sp1#f535642f5bea6a2bfded8c4e51b1f2960b1f6da7" dependencies = [ "itertools 0.12.1", "p3-dft", @@ -2570,7 +2380,7 @@ dependencies = [ [[package]] name = "p3-merkle-tree" version = "0.1.0" -source = "git+https://github.com/Plonky3/Plonky3.git?branch=sp1#da0489b75025ec17f1100952694d8b7879c2b43e" +source = "git+https://github.com/Plonky3/Plonky3.git?branch=sp1#f535642f5bea6a2bfded8c4e51b1f2960b1f6da7" dependencies = [ "itertools 0.12.1", "p3-commit", @@ -2586,7 +2396,7 @@ dependencies = [ [[package]] name = "p3-poseidon2" version = "0.1.0" -source = "git+https://github.com/Plonky3/Plonky3.git?branch=sp1#da0489b75025ec17f1100952694d8b7879c2b43e" +source = "git+https://github.com/Plonky3/Plonky3.git?branch=sp1#f535642f5bea6a2bfded8c4e51b1f2960b1f6da7" dependencies = [ "gcd", "p3-field", @@ -2598,7 +2408,7 @@ dependencies = [ [[package]] name = "p3-symmetric" version = "0.1.0" -source = "git+https://github.com/Plonky3/Plonky3.git?branch=sp1#da0489b75025ec17f1100952694d8b7879c2b43e" +source = "git+https://github.com/Plonky3/Plonky3.git?branch=sp1#f535642f5bea6a2bfded8c4e51b1f2960b1f6da7" dependencies = [ "itertools 0.12.1", "p3-field", @@ -2608,7 +2418,7 @@ dependencies = [ [[package]] name = "p3-uni-stark" version = "0.1.0" -source = "git+https://github.com/Plonky3/Plonky3.git?branch=sp1#da0489b75025ec17f1100952694d8b7879c2b43e" +source = "git+https://github.com/Plonky3/Plonky3.git?branch=sp1#f535642f5bea6a2bfded8c4e51b1f2960b1f6da7" dependencies = [ "itertools 0.12.1", "p3-air", @@ -2626,16 +2436,16 @@ dependencies = [ [[package]] name = "p3-util" version = "0.1.0" -source = "git+https://github.com/Plonky3/Plonky3.git?branch=sp1#da0489b75025ec17f1100952694d8b7879c2b43e" +source = "git+https://github.com/Plonky3/Plonky3.git?branch=sp1#f535642f5bea6a2bfded8c4e51b1f2960b1f6da7" dependencies = [ "serde", ] [[package]] name = "parity-scale-codec" -version = "3.6.9" +version = "3.6.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "881331e34fa842a2fb61cc2db9643a8fedc615e47cfcc52597d1af0db9a7e8fe" +checksum = "306800abfa29c7f16596b5970a588435e3d5b3149683d00c12b699cc19f895ee" dependencies = [ "arrayvec", "bitvec", @@ -2647,11 +2457,11 @@ dependencies = [ [[package]] name = "parity-scale-codec-derive" -version = "3.6.9" +version = "3.6.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be30eaf4b0a9fba5336683b38de57bb86d179a35862ba6bfcf57625d006bde5b" +checksum = "d830939c76d294956402033aee57a6da7b438f2294eb94864c37b0569053a42c" dependencies = [ - "proc-macro-crate 2.0.2", + "proc-macro-crate 3.1.0", "proc-macro2", "quote", "syn 1.0.109", @@ -2659,9 +2469,9 @@ dependencies = [ [[package]] name = "parking_lot" -version = "0.12.2" +version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e4af0ca4f6caed20e900d564c242b8e5d4903fdacf31d3daf527b66fe6f42fb" +checksum = "f1bf18183cf54e8d6059647fc3063646a1801cf30896933ec2311622cc4b9a27" dependencies = [ "lock_api", "parking_lot_core", @@ -2720,7 +2530,7 @@ checksum = "2f38a4412a78282e09a2cf38d195ea5420d15ba0602cb375210efbc877243965" dependencies = [ "proc-macro2", "quote", - "syn 2.0.61", + "syn 2.0.66", ] [[package]] @@ -2806,12 +2616,11 @@ dependencies = [ [[package]] name = "proc-macro-crate" -version = "2.0.2" +version = "3.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b00f26d3400549137f92511a46ac1cd8ce37cb5598a96d382381458b992a5d24" +checksum = "6d37c51ca738a55da99dc0c4a34860fd675453b8b36209178c2249bb13651284" dependencies = [ - "toml_datetime", - "toml_edit 0.20.2", + "toml_edit 0.21.1", ] [[package]] @@ -2840,9 +2649,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.82" +version = "1.0.84" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ad3d49ab951a01fbaafe34f2ec74122942fe18a3f9814c3268f1bb72042131b" +checksum = "ec96c6a92621310b51366f1e28d05ef11489516e93be030060e5fc12024a49d6" dependencies = [ "unicode-ident", ] @@ -2869,9 +2678,9 @@ dependencies = [ [[package]] name = "prost" -version = "0.12.4" +version = "0.12.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d0f5d036824e4761737860779c906171497f6d55681139d8312388f8fe398922" +checksum = "deb1435c188b76130da55f17a466d252ff7b1418b2ad3e037d127b94e3411f29" dependencies = [ "bytes", "prost-derive", @@ -2879,22 +2688,22 @@ dependencies = [ [[package]] name = "prost-derive" -version = "0.12.4" +version = "0.12.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19de2de2a00075bf566bee3bd4db014b11587e84184d3f7a791bc17f1a8e9e48" +checksum = "81bddcdb20abf9501610992b6759a4c888aef7d1a7247ef75e2404275ac24af1" dependencies = [ "anyhow", - "itertools 0.10.5", + "itertools 0.12.1", "proc-macro2", "quote", - "syn 2.0.61", + "syn 2.0.66", ] [[package]] name = "prost-types" -version = "0.12.4" +version = "0.12.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3235c33eb02c1f1e212abdbe34c78b264b038fb58ca612664343271e36e55ffe" +checksum = "9091c90b0a32608e984ff2fa4091273cbdd755d54935c51d520887f4a1dbd5b0" dependencies = [ "prost", ] @@ -3043,33 +2852,34 @@ checksum = "adad44e29e4c806119491a7f06f03de4d1af22c3a680dd47f1e6e179439d1f56" [[package]] name = "reqwest" -version = "0.11.27" +version = "0.12.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd67538700a17451e7cba03ac727fb961abb7607553461627b97de0b89cf4a62" +checksum = "566cafdd92868e0939d3fb961bd0dc25fcfaaed179291093b3d43e6b3150ea10" dependencies = [ - "base64 0.21.7", + "base64", "bytes", "encoding_rs", "futures-core", "futures-util", - "h2 0.3.26", - "hickory-resolver", - "http 0.2.12", - "http-body 0.4.6", - "hyper 0.14.28", + "h2", + "http", + "http-body", + "http-body-util", + "hyper", "hyper-rustls", - "hyper-tls 0.5.0", + "hyper-tls", + "hyper-util", "ipnet", "js-sys", "log", "mime", - "mime_guess", "native-tls", "once_cell", "percent-encoding", "pin-project-lite", "rustls", - "rustls-pemfile 1.0.4", + "rustls-pemfile", + "rustls-pki-types", "serde", "serde_json", "serde_urlencoded", @@ -3084,71 +2894,22 @@ dependencies = [ "wasm-bindgen-futures", "web-sys", "webpki-roots", - "winreg 0.50.0", -] - -[[package]] -name = "reqwest" -version = "0.12.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "566cafdd92868e0939d3fb961bd0dc25fcfaaed179291093b3d43e6b3150ea10" -dependencies = [ - "base64 0.22.1", - "bytes", - "futures-core", - "futures-util", - "http 1.1.0", - "http-body 1.0.0", - "http-body-util", - "hyper 1.3.1", - "hyper-tls 0.6.0", - "hyper-util", - "ipnet", - "js-sys", - "log", - "mime", - "native-tls", - "once_cell", - "percent-encoding", - "pin-project-lite", - "rustls-pemfile 2.1.2", - "serde", - "serde_json", - "serde_urlencoded", - "sync_wrapper", - "tokio", - "tokio-native-tls", - "tower-service", - "url", - "wasm-bindgen", - "wasm-bindgen-futures", - "web-sys", - "winreg 0.52.0", + "winreg", ] [[package]] name = "reqwest-middleware" -version = "0.2.5" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a735987236a8e238bf0296c7e351b999c188ccc11477f311b82b55c93984216" +checksum = "a45d100244a467870f6cb763c4484d010a6bed6bd610b3676e3825d93fb4cfbd" dependencies = [ "anyhow", "async-trait", - "http 0.2.12", - "reqwest 0.11.27", + "http", + "reqwest", "serde", - "task-local-extensions", "thiserror", -] - -[[package]] -name = "resolv-conf" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "52e44394d2086d010551b14b53b1f24e31647570cd1deb0379e2c21b329aba00" -dependencies = [ - "hostname", - "quick-error", + "tower-service", ] [[package]] @@ -3228,9 +2989,9 @@ checksum = "f86854cf50259291520509879a5c294c3c9a4c334e9ff65071c51e42ef1e2343" [[package]] name = "rustc-demangle" -version = "0.1.23" +version = "0.1.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" +checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" [[package]] name = "rustc-hex" @@ -3271,23 +3032,16 @@ dependencies = [ [[package]] name = "rustls" -version = "0.21.12" +version = "0.22.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f56a14d1f48b391359b22f731fd4bd7e43c97f3c50eee276f3aa09c94784d3e" +checksum = "bf4ef73721ac7bcd79b2b315da7779d8fc09718c6b3d2d1b2d94850eb8c18432" dependencies = [ "log", "ring", + "rustls-pki-types", "rustls-webpki", - "sct", -] - -[[package]] -name = "rustls-pemfile" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1c74cae0a4cf6ccbbf5f359f08efdf8ee7e1dc532573bf0db71968cb56b1448c" -dependencies = [ - "base64 0.21.7", + "subtle", + "zeroize", ] [[package]] @@ -3296,31 +3050,32 @@ version = "2.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "29993a25686778eb88d4189742cd713c9bce943bc54251a33509dc63cbacf73d" dependencies = [ - "base64 0.22.1", + "base64", "rustls-pki-types", ] [[package]] name = "rustls-pki-types" -version = "1.6.0" +version = "1.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "51f344d206c5e1b010eec27349b815a4805f70a778895959d70b74b9b529b30a" +checksum = "976295e77ce332211c0d24d92c0e83e50f5c5f046d11082cea19f3df13a3562d" [[package]] name = "rustls-webpki" -version = "0.101.7" +version = "0.102.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b6275d1ee7a1cd780b64aca7726599a1dbc893b1e64144529e55c3c2f745765" +checksum = "ff448f7e92e913c4b7d4c6d8e4540a1724b319b4152b8aef6d4cf8339712b33e" dependencies = [ "ring", + "rustls-pki-types", "untrusted", ] [[package]] name = "rustversion" -version = "1.0.16" +version = "1.0.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "092474d1a01ea8278f69e6a358998405fae5b8b963ddaeb2b0b04a128bf1dfb0" +checksum = "955d28af4278de8121b7ebeb796b6a45735dc01436d898801014aced2773a3d6" [[package]] name = "rusty-fork" @@ -3342,9 +3097,9 @@ checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" [[package]] name = "scale-info" -version = "2.11.2" +version = "2.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7c453e59a955f81fb62ee5d596b450383d699f152d350e9d23a0db2adb78e4c0" +checksum = "eca070c12893629e2cc820a9761bedf6ce1dcddc9852984d1dc734b8bd9bd024" dependencies = [ "cfg-if", "derive_more", @@ -3354,11 +3109,11 @@ dependencies = [ [[package]] name = "scale-info-derive" -version = "2.11.2" +version = "2.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "18cf6c6447f813ef19eb450e985bcce6705f9ce7660db221b59093d15c79c4b7" +checksum = "2d35494501194174bda522a32605929eefc9ecf7e0a326c26db1fdd85881eb62" dependencies = [ - "proc-macro-crate 1.3.1", + "proc-macro-crate 3.1.0", "proc-macro2", "quote", "syn 1.0.109", @@ -3379,16 +3134,6 @@ version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" -[[package]] -name = "sct" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da046153aa2352493d6cb7da4b6e5c0c057d8a1d0a9aa8560baffdd945acd414" -dependencies = [ - "ring", - "untrusted", -] - [[package]] name = "sec1" version = "0.7.3" @@ -3455,29 +3200,29 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.200" +version = "1.0.203" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ddc6f9cc94d67c0e21aaf7eda3a010fd3af78ebf6e096aa6e2e13c79749cce4f" +checksum = "7253ab4de971e72fb7be983802300c30b5a7f0c2e56fab8abfc6a214307c0094" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.200" +version = "1.0.203" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "856f046b9400cee3c8c94ed572ecdb752444c24528c035cd35882aad6f492bcb" +checksum = "500cbc0ebeb6f46627f50f3f5811ccf6bf00643be300b4c3eabc0ef55dc5b5ba" dependencies = [ "proc-macro2", "quote", - "syn 2.0.61", + "syn 2.0.66", ] [[package]] name = "serde_json" -version = "1.0.116" +version = "1.0.117" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3e17db7126d17feb94eb3fad46bf1a96b034e8aacbc2e775fe81505f8b0b2813" +checksum = "455182ea6142b14f93f4bc5320a2b31c1f266b66a4a5c858b013302a5d8cbfc3" dependencies = [ "itoa", "ryu", @@ -3512,7 +3257,7 @@ version = "3.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0ad483d2ab0149d5a5ebcd9972a3852711e0153d863bf5a5d0391d28883c4a20" dependencies = [ - "base64 0.22.1", + "base64", "chrono", "hex", "indexmap 1.9.3", @@ -3533,7 +3278,7 @@ dependencies = [ "darling", "proc-macro2", "quote", - "syn 2.0.61", + "syn 2.0.66", ] [[package]] @@ -3549,9 +3294,9 @@ dependencies = [ [[package]] name = "sha3-asm" -version = "0.1.0" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bac61da6b35ad76b195eb4771210f947734321a8d81d7738e1580d953bc7a15e" +checksum = "a9b57fd861253bff08bb1919e995f90ba8f4889de2726091c8876f3a4e823b40" dependencies = [ "cc", "cfg-if", @@ -3730,7 +3475,7 @@ dependencies = [ "p3-matrix", "prost", "prost-types", - "reqwest 0.11.27", + "reqwest", "reqwest-middleware", "serde", "serde_json", @@ -3765,9 +3510,9 @@ checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" [[package]] name = "strsim" -version = "0.10.0" +version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" +checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" [[package]] name = "strum" @@ -3785,7 +3530,7 @@ dependencies = [ "proc-macro2", "quote", "rustversion", - "syn 2.0.61", + "syn 2.0.66", ] [[package]] @@ -3807,9 +3552,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.61" +version = "2.0.66" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c993ed8ccba56ae856363b1845da7266a7cb78e1d146c8a32d54b45a8b831fc9" +checksum = "c42f3f41a2de00b01c0aaad383c5a45241efc8b2d1eda5661812fda5f3cdcff5" dependencies = [ "proc-macro2", "quote", @@ -3818,14 +3563,14 @@ dependencies = [ [[package]] name = "syn-solidity" -version = "0.7.2" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5aa0cefd02f532035d83cfec82647c6eb53140b0485220760e669f4bad489e36" +checksum = "b8db114c44cf843a8bacd37a146e37987a0b823a0e8bc4fdc610c9c72ab397a5" dependencies = [ "paste", "proc-macro2", "quote", - "syn 2.0.61", + "syn 2.0.66", ] [[package]] @@ -3861,15 +3606,6 @@ version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" -[[package]] -name = "task-local-extensions" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba323866e5d033818e3240feeb9f7db2c4296674e4d9e16b97b7bf8f490434e8" -dependencies = [ - "pin-utils", -] - [[package]] name = "tempfile" version = "3.10.1" @@ -3884,22 +3620,22 @@ dependencies = [ [[package]] name = "thiserror" -version = "1.0.60" +version = "1.0.61" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "579e9083ca58dd9dcf91a9923bb9054071b9ebbd800b342194c9feb0ee89fc18" +checksum = "c546c80d6be4bc6a00c0f01730c08df82eaa7a7a61f11d656526506112cc1709" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.60" +version = "1.0.61" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2470041c06ec3ac1ab38d0356a6119054dedaea53e12fbefc0de730a1c08524" +checksum = "46c3384250002a6d5af4d114f2845d37b57521033f30d5c3f46c4d70e1197533" dependencies = [ "proc-macro2", "quote", - "syn 2.0.61", + "syn 2.0.66", ] [[package]] @@ -4003,7 +3739,7 @@ checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.61", + "syn 2.0.66", ] [[package]] @@ -4018,11 +3754,12 @@ dependencies = [ [[package]] name = "tokio-rustls" -version = "0.24.1" +version = "0.25.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c28327cf380ac148141087fbfb9de9d7bd4e84ab5d2c28fbc911d753de8a7081" +checksum = "775e0c0f0adb3a2f22a00c4745d728b479985fc15ee7ca6a2608388c5569860f" dependencies = [ "rustls", + "rustls-pki-types", "tokio", ] @@ -4053,9 +3790,9 @@ dependencies = [ [[package]] name = "toml_datetime" -version = "0.6.3" +version = "0.6.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7cda73e2f1397b1262d6dfdcef8aafae14d1de7748d66822d3bfeeb6d03e5e4b" +checksum = "4badfd56924ae69bcc9039335b2e017639ce3f9b001c393c1b2d1ef846ce2cbf" [[package]] name = "toml_edit" @@ -4070,9 +3807,9 @@ dependencies = [ [[package]] name = "toml_edit" -version = "0.20.2" +version = "0.21.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "396e4d48bbb2b7554c944bde63101b5ae446cff6ec4a24227428f15eb72ef338" +checksum = "6a8534fd7f78b5405e860340ad6575217ce99f38d4d5c8f2442cb5ecb50090e1" dependencies = [ "indexmap 2.2.6", "toml_datetime", @@ -4127,7 +3864,7 @@ checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.61", + "syn 2.0.66", ] [[package]] @@ -4191,17 +3928,17 @@ checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" [[package]] name = "twirp" version = "0.3.0" -source = "git+https://github.com/github/twirp-rs.git#aacdd3971e52735b64476ec1dcc56fb3d7f2771e" +source = "git+https://github.com/github/twirp-rs.git#c85f31f9c54957374e7dcb3534fc52cff0aa2dc5" dependencies = [ "async-trait", "axum", "bytes", "futures", - "http 1.1.0", + "http", "http-body-util", - "hyper 1.3.1", + "hyper", "prost", - "reqwest 0.11.27", + "reqwest", "serde", "serde_json", "thiserror", @@ -4240,15 +3977,6 @@ version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "eaea85b334db583fe3274d12b4cd1880032beab409c0d774be044d4480ab9a94" -[[package]] -name = "unicase" -version = "2.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f7d2d4dafb69621809a81864c9c1b864479e1235c0dd4e199924b9742439ed89" -dependencies = [ - "version_check", -] - [[package]] name = "unicode-bidi" version = "0.3.15" @@ -4289,7 +4017,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "31e6302e3bb753d46e83516cae55ae196fc0c309407cf11ab35cc51a4c2a4633" dependencies = [ "form_urlencoded", - "idna 0.5.0", + "idna", "percent-encoding", ] @@ -4356,7 +4084,7 @@ dependencies = [ "once_cell", "proc-macro2", "quote", - "syn 2.0.61", + "syn 2.0.66", "wasm-bindgen-shared", ] @@ -4390,7 +4118,7 @@ checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.61", + "syn 2.0.66", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -4423,15 +4151,12 @@ dependencies = [ [[package]] name = "webpki-roots" -version = "0.25.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f20c57d8d7db6d3b86154206ae5d8fba62dd39573114de97c2cb0578251f8e1" - -[[package]] -name = "widestring" -version = "1.1.0" +version = "0.26.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7219d36b6eac893fa81e84ebe06485e7dcbb616177469b142df14f1f4deb1311" +checksum = "b3de34ae270483955a94f4b21bdaaeb83d508bb84a01435f393818edb0012009" +dependencies = [ + "rustls-pki-types", +] [[package]] name = "winapi" @@ -4621,16 +4346,6 @@ dependencies = [ "memchr", ] -[[package]] -name = "winreg" -version = "0.50.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "524e57b2c537c0f9b1e69f1965311ec12182b4122e45035b1508cd24d2adadb1" -dependencies = [ - "cfg-if", - "windows-sys 0.48.0", -] - [[package]] name = "winreg" version = "0.52.0" @@ -4667,14 +4382,14 @@ checksum = "15e934569e47891f7d9411f1a451d947a60e000ab3bd24fbb970f000387d1b3b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.61", + "syn 2.0.66", ] [[package]] name = "zeroize" -version = "1.7.0" +version = "1.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "525b4ec142c6b68a2d10f01f7bbf6755599ca3f81ea53b8431b7dd348f5fdb2d" +checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde" dependencies = [ "zeroize_derive", ] @@ -4687,5 +4402,5 @@ checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" dependencies = [ "proc-macro2", "quote", - "syn 2.0.61", + "syn 2.0.66", ] From 6ed60da996cd8b877e43bcac578caeab637169c7 Mon Sep 17 00:00:00 2001 From: lightsing Date: Thu, 13 Jun 2024 11:23:21 +0800 Subject: [PATCH 24/34] update Cargo.toml --- examples/poseidon_bn254/program/Cargo.toml | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/examples/poseidon_bn254/program/Cargo.toml b/examples/poseidon_bn254/program/Cargo.toml index 93f0771080..22fc582e46 100644 --- a/examples/poseidon_bn254/program/Cargo.toml +++ b/examples/poseidon_bn254/program/Cargo.toml @@ -7,15 +7,20 @@ edition = "2021" [dependencies] sp1-zkvm = { path = "../../../zkvm/entrypoint" } hex = "0.4" -halo2curves = { git = "https://github.com/kunxian-xia/halo2curves.git", branch = "feat/sp1" } +halo2curves = { git = "https://github.com/scroll-tech/halo2curves.git", branch = "feat/sp1" } poseidon_base = { git = "https://github.com/scroll-tech/poseidon-circuit.git", package = "poseidon-base", branch = "feat/sp1" } #halo2curves = { path = "../../../../halo2curves" } #poseidon_base = { path = "../../../../poseidon-circuit/poseidon-base", package = "poseidon-base" } [patch.crates-io] -ff = { git = "https://github.com/scroll-tech/ff", rev = "7e94aa6" } -#[patch."https://github.com/kunxian-xia/halo2curves.git"] +ff = { git = "https://github.com/scroll-tech/ff", branch = "feat/sp1" } +halo2curves = { git = "https://github.com/scroll-tech/halo2curves.git", branch = "feat/sp1" } + +#[patch.crates-io] +#ff = { path = "../../../../ff" } +#halo2curves = { path = "../../../../halo2curves" } +#[patch."https://github.com/scroll-tech/ff"] +#ff = { path = "../../../../ff" } +#[patch."https://github.com/scroll-tech/halo2curves.git"] #halo2curves = { path = "../../../../halo2curves" } -[patch."https://github.com/kunxian-xia/halo2curves.git"] -halo2curves = { git = "https://github.com/lightsing/halo2curves.git", branch = "feat/sp1" } \ No newline at end of file From 6f5d81b8b704226a70c6002ff5721d623fdb1bbd Mon Sep 17 00:00:00 2001 From: lightsing Date: Thu, 13 Jun 2024 11:56:47 +0800 Subject: [PATCH 25/34] cleanup --- examples/poseidon_bn254/program/Cargo.toml | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/examples/poseidon_bn254/program/Cargo.toml b/examples/poseidon_bn254/program/Cargo.toml index 22fc582e46..c4894356a4 100644 --- a/examples/poseidon_bn254/program/Cargo.toml +++ b/examples/poseidon_bn254/program/Cargo.toml @@ -10,17 +10,6 @@ hex = "0.4" halo2curves = { git = "https://github.com/scroll-tech/halo2curves.git", branch = "feat/sp1" } poseidon_base = { git = "https://github.com/scroll-tech/poseidon-circuit.git", package = "poseidon-base", branch = "feat/sp1" } -#halo2curves = { path = "../../../../halo2curves" } -#poseidon_base = { path = "../../../../poseidon-circuit/poseidon-base", package = "poseidon-base" } - [patch.crates-io] ff = { git = "https://github.com/scroll-tech/ff", branch = "feat/sp1" } halo2curves = { git = "https://github.com/scroll-tech/halo2curves.git", branch = "feat/sp1" } - -#[patch.crates-io] -#ff = { path = "../../../../ff" } -#halo2curves = { path = "../../../../halo2curves" } -#[patch."https://github.com/scroll-tech/ff"] -#ff = { path = "../../../../ff" } -#[patch."https://github.com/scroll-tech/halo2curves.git"] -#halo2curves = { path = "../../../../halo2curves" } From 7eb3efbd603c4c4c0ca586cb87b1578cdee3daaa Mon Sep 17 00:00:00 2001 From: kunxian-xia Date: Thu, 13 Jun 2024 18:53:52 +0800 Subject: [PATCH 26/34] fix errors after merge upstream --- core/src/operations/field/field_op.rs | 1 - core/src/runtime/syscall.rs | 6 +- .../syscall/precompiles/bn254_scalar/mac.rs | 45 +- .../syscall/precompiles/bn254_scalar/mod.rs | 6 +- .../syscall/precompiles/bn254_scalar/mul.rs | 30 +- examples/poseidon_bn254/program/Cargo.lock | 175 ---- .../program/elf/riscv32im-succinct-zkvm-elf | Bin 0 -> 172524 bytes examples/poseidon_bn254/program/src/main.rs | 2 +- examples/poseidon_bn254/script/Cargo.lock | 947 +++++++++++++++++- examples/poseidon_bn254/script/src/main.rs | 5 +- 10 files changed, 984 insertions(+), 233 deletions(-) create mode 100755 examples/poseidon_bn254/program/elf/riscv32im-succinct-zkvm-elf diff --git a/core/src/operations/field/field_op.rs b/core/src/operations/field/field_op.rs index 38ed4cd0ac..9c8943d0ce 100644 --- a/core/src/operations/field/field_op.rs +++ b/core/src/operations/field/field_op.rs @@ -3,7 +3,6 @@ use std::fmt::Debug; use num::{BigUint, Zero}; use p3_air::AirBuilder; use p3_field::PrimeField32; -use serde::{Deserialize, Serialize}; use sp1_derive::AlignedBorrow; use super::params::{FieldParameters, Limbs}; diff --git a/core/src/runtime/syscall.rs b/core/src/runtime/syscall.rs index 9d73882da7..e23e1c6329 100644 --- a/core/src/runtime/syscall.rs +++ b/core/src/runtime/syscall.rs @@ -343,14 +343,14 @@ pub fn default_syscall_map() -> HashMap> { SyscallCode::BLS12381_DECOMPRESS, Arc::new(WeierstrassDecompressChip::::new()), ); - syscall_map.insert(SyscallCode::UINT256_MUL, Rc::new(Uint256MulChip::new())); + syscall_map.insert(SyscallCode::UINT256_MUL, Arc::new(Uint256MulChip::new())); syscall_map.insert( SyscallCode::BN254_SCALAR_MUL, - Rc::new(Bn254ScalarMulChip::new()), + Arc::new(Bn254ScalarMulChip::new()), ); syscall_map.insert( SyscallCode::BN254_SCALAR_MAC, - Rc::new(Bn254ScalarMacChip::new()), + Arc::new(Bn254ScalarMacChip::new()), ); syscall_map diff --git a/core/src/syscall/precompiles/bn254_scalar/mac.rs b/core/src/syscall/precompiles/bn254_scalar/mac.rs index f8fdec334f..c237a948bd 100644 --- a/core/src/syscall/precompiles/bn254_scalar/mac.rs +++ b/core/src/syscall/precompiles/bn254_scalar/mac.rs @@ -11,18 +11,14 @@ use typenum::U8; use crate::{ air::MachineAir, + bytes::event::ByteRecord, memory::{MemoryCols, MemoryReadCols, MemoryWriteCols}, operations::field::field_op::{FieldOpCols, FieldOperation}, + operations::field::params::{FieldParameters, NumLimbs}, runtime::{ExecutionRecord, Program, Syscall, SyscallCode}, stark::SP1AirBuilder, syscall::precompiles::bn254_scalar::Limbs, - utils::{ - ec::{ - field::{FieldParameters, NumLimbs}, - weierstrass::bn254::Bn254ScalarField, - }, - limbs_from_prev_access, pad_rows, - }, + utils::{ec::weierstrass::bn254::Bn254ScalarField, limbs_from_prev_access, pad_rows}, }; use super::{create_bn254_scalar_arith_event, Bn254FieldOperation, NUM_WORDS_PER_FE}; @@ -103,8 +99,20 @@ impl MachineAir for Bn254ScalarMacChip { cols.arg1_ptr = F::from_canonical_u32(event.arg1.ptr); cols.arg2_ptr = F::from_canonical_u32(event.arg2.ptr); - let mul = cols.mul_eval.populate(&a, &b, FieldOperation::Mul); - cols.add_eval.populate(&arg1, &mul, FieldOperation::Add); + let mul = cols.mul_eval.populate( + &mut new_byte_lookup_events, + event.shard, + &a, + &b, + FieldOperation::Mul, + ); + cols.add_eval.populate( + &mut new_byte_lookup_events, + event.shard, + &arg1, + &mul, + FieldOperation::Add, + ); for i in 0..cols.arg1_access.len() { cols.arg1_access[i] @@ -136,8 +144,10 @@ impl MachineAir for Bn254ScalarMacChip { let cols: &mut Bn254ScalarMacCols = row.as_mut_slice().borrow_mut(); let zero = BigUint::zero(); - cols.mul_eval.populate(&zero, &zero, FieldOperation::Mul); - cols.add_eval.populate(&zero, &zero, FieldOperation::Add); + cols.mul_eval + .populate(&mut vec![], 0, &zero, &zero, FieldOperation::Mul); + cols.add_eval + .populate(&mut vec![], 0, &zero, &zero, FieldOperation::Add); row }); @@ -180,9 +190,16 @@ where let b: Limbs<::Var, ::Limbs> = limbs_from_prev_access(&row.b_access); - row.mul_eval.eval(builder, &a, &b, FieldOperation::Mul); - row.add_eval - .eval(builder, &arg1, &row.mul_eval.result, FieldOperation::Add); + row.mul_eval + .eval(builder, &a, &b, FieldOperation::Mul, row.shard, row.is_real); + row.add_eval.eval( + builder, + &arg1, + &row.mul_eval.result, + FieldOperation::Add, + row.shard, + row.is_real, + ); for i in 0..Bn254ScalarField::NB_LIMBS { builder.when(row.is_real).assert_eq( diff --git a/core/src/syscall/precompiles/bn254_scalar/mod.rs b/core/src/syscall/precompiles/bn254_scalar/mod.rs index 602b201bfa..8854aa48e2 100644 --- a/core/src/syscall/precompiles/bn254_scalar/mod.rs +++ b/core/src/syscall/precompiles/bn254_scalar/mod.rs @@ -6,12 +6,10 @@ pub use mac::Bn254ScalarMacChip; pub use mul::Bn254ScalarMulChip; use crate::{ + operations::field::params::{FieldParameters, NumWords}, operations::field::{field_op::FieldOperation, params::Limbs}, runtime::{MemoryReadRecord, MemoryWriteRecord, SyscallContext}, - utils::ec::{ - field::{FieldParameters, NumWords}, - weierstrass::bn254::Bn254ScalarField, - }, + utils::ec::weierstrass::bn254::Bn254ScalarField, }; use num::BigUint; use typenum::Unsigned; diff --git a/core/src/syscall/precompiles/bn254_scalar/mul.rs b/core/src/syscall/precompiles/bn254_scalar/mul.rs index 2cd7d1d373..fb29e81255 100644 --- a/core/src/syscall/precompiles/bn254_scalar/mul.rs +++ b/core/src/syscall/precompiles/bn254_scalar/mul.rs @@ -8,20 +8,16 @@ use p3_field::{Field, PrimeField32}; use p3_matrix::{dense::RowMajorMatrix, Matrix}; use sp1_derive::AlignedBorrow; +use crate::bytes::event::ByteRecord; use crate::{ air::MachineAir, memory::{MemoryCols, MemoryReadCols, MemoryWriteCols}, operations::field::field_op::FieldOpCols, + operations::field::params::{FieldParameters, NumLimbs}, runtime::{ExecutionRecord, Program, Syscall, SyscallCode}, stark::SP1AirBuilder, syscall::precompiles::bn254_scalar::Limbs, - utils::{ - ec::{ - field::{FieldParameters, NumLimbs}, - weierstrass::bn254::Bn254ScalarField, - }, - limbs_from_prev_access, pad_rows, - }, + utils::{ec::weierstrass::bn254::Bn254ScalarField, limbs_from_prev_access, pad_rows}, }; use super::{create_bn254_scalar_arith_event, Bn254FieldOperation, NUM_WORDS_PER_FE}; @@ -98,7 +94,13 @@ impl MachineAir for Bn254ScalarMulChip { cols.p_ptr = F::from_canonical_u32(event.arg1.ptr); cols.q_ptr = F::from_canonical_u32(event.arg2.ptr); - cols.eval.populate(&p, &q, OP.to_field_operation()); + cols.eval.populate( + &mut new_byte_lookup_events, + event.shard, + &p, + &q, + OP.to_field_operation(), + ); for i in 0..cols.p_access.len() { cols.p_access[i] @@ -118,7 +120,8 @@ impl MachineAir for Bn254ScalarMulChip { let cols: &mut Bn254ScalarMulCols = row.as_mut_slice().borrow_mut(); let zero = BigUint::zero(); - cols.eval.populate(&zero, &zero, OP.to_field_operation()); + cols.eval + .populate(&mut vec![], 0, &zero, &zero, OP.to_field_operation()); row }); @@ -159,7 +162,14 @@ where let q: Limbs<::Var, ::Limbs> = limbs_from_prev_access(&row.q_access); - row.eval.eval(builder, &p, &q, OP.to_field_operation()); + row.eval.eval( + builder, + &p, + &q, + OP.to_field_operation(), + row.shard, + row.is_real, + ); for i in 0..Bn254ScalarField::NB_LIMBS { builder diff --git a/examples/poseidon_bn254/program/Cargo.lock b/examples/poseidon_bn254/program/Cargo.lock index 7806435006..3334760917 100644 --- a/examples/poseidon_bn254/program/Cargo.lock +++ b/examples/poseidon_bn254/program/Cargo.lock @@ -181,12 +181,6 @@ dependencies = [ "spki", ] -[[package]] -name = "either" -version = "1.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3dca9240753cf90908d7e4aac30f630662b02aebaa1b58a3cadabdb23385b58b" - [[package]] name = "elliptic-curve" version = "0.13.8" @@ -229,12 +223,6 @@ version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c" -[[package]] -name = "gcd" -version = "2.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d758ba1b47b00caf47f24925c0074ecb20d6dfcffe7f6d53395c0465674841a" - [[package]] name = "generic-array" version = "0.14.7" @@ -328,15 +316,6 @@ dependencies = [ "hashbrown", ] -[[package]] -name = "itertools" -version = "0.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba291022dbbd398a455acf126c1e341954079855bc60dfdda641363bd6922569" -dependencies = [ - "either", -] - [[package]] name = "k256" version = "0.13.3" @@ -457,108 +436,6 @@ version = "1.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" -[[package]] -name = "p3-baby-bear" -version = "0.1.0" -source = "git+https://github.com/Plonky3/Plonky3.git?branch=sp1#f535642f5bea6a2bfded8c4e51b1f2960b1f6da7" -dependencies = [ - "num-bigint", - "p3-field", - "p3-mds", - "p3-poseidon2", - "p3-symmetric", - "rand", - "serde", -] - -[[package]] -name = "p3-dft" -version = "0.1.0" -source = "git+https://github.com/Plonky3/Plonky3.git?branch=sp1#f535642f5bea6a2bfded8c4e51b1f2960b1f6da7" -dependencies = [ - "p3-field", - "p3-matrix", - "p3-maybe-rayon", - "p3-util", - "tracing", -] - -[[package]] -name = "p3-field" -version = "0.1.0" -source = "git+https://github.com/Plonky3/Plonky3.git?branch=sp1#f535642f5bea6a2bfded8c4e51b1f2960b1f6da7" -dependencies = [ - "itertools", - "num-bigint", - "num-traits", - "p3-util", - "rand", - "serde", -] - -[[package]] -name = "p3-matrix" -version = "0.1.0" -source = "git+https://github.com/Plonky3/Plonky3.git?branch=sp1#f535642f5bea6a2bfded8c4e51b1f2960b1f6da7" -dependencies = [ - "itertools", - "p3-field", - "p3-maybe-rayon", - "p3-util", - "rand", - "serde", - "tracing", -] - -[[package]] -name = "p3-maybe-rayon" -version = "0.1.0" -source = "git+https://github.com/Plonky3/Plonky3.git?branch=sp1#f535642f5bea6a2bfded8c4e51b1f2960b1f6da7" - -[[package]] -name = "p3-mds" -version = "0.1.0" -source = "git+https://github.com/Plonky3/Plonky3.git?branch=sp1#f535642f5bea6a2bfded8c4e51b1f2960b1f6da7" -dependencies = [ - "itertools", - "p3-dft", - "p3-field", - "p3-matrix", - "p3-symmetric", - "p3-util", - "rand", -] - -[[package]] -name = "p3-poseidon2" -version = "0.1.0" -source = "git+https://github.com/Plonky3/Plonky3.git?branch=sp1#f535642f5bea6a2bfded8c4e51b1f2960b1f6da7" -dependencies = [ - "gcd", - "p3-field", - "p3-mds", - "p3-symmetric", - "rand", -] - -[[package]] -name = "p3-symmetric" -version = "0.1.0" -source = "git+https://github.com/Plonky3/Plonky3.git?branch=sp1#f535642f5bea6a2bfded8c4e51b1f2960b1f6da7" -dependencies = [ - "itertools", - "p3-field", - "serde", -] - -[[package]] -name = "p3-util" -version = "0.1.0" -source = "git+https://github.com/Plonky3/Plonky3.git?branch=sp1#f535642f5bea6a2bfded8c4e51b1f2960b1f6da7" -dependencies = [ - "serde", -] - [[package]] name = "parity-scale-codec" version = "3.6.12" @@ -604,12 +481,6 @@ version = "1.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" -[[package]] -name = "pin-project-lite" -version = "0.2.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bda66fc9667c18cb2758a2ac84d1167245054bcf85d5d1aaa6923f45801bdd02" - [[package]] name = "pkcs8" version = "0.10.2" @@ -825,18 +696,6 @@ dependencies = [ "snowbridge-amcl", ] -[[package]] -name = "sp1-primitives" -version = "0.1.0" -dependencies = [ - "itertools", - "lazy_static", - "p3-baby-bear", - "p3-field", - "p3-poseidon2", - "p3-symmetric", -] - [[package]] name = "sp1-zkvm" version = "0.1.0" @@ -847,13 +706,10 @@ dependencies = [ "k256", "libm", "once_cell", - "p3-baby-bear", - "p3-field", "rand", "serde", "sha2", "sp1-precompiles", - "sp1-primitives", ] [[package]] @@ -929,37 +785,6 @@ dependencies = [ "winnow", ] -[[package]] -name = "tracing" -version = "0.1.40" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" -dependencies = [ - "pin-project-lite", - "tracing-attributes", - "tracing-core", -] - -[[package]] -name = "tracing-attributes" -version = "0.1.27" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.66", -] - -[[package]] -name = "tracing-core" -version = "0.1.32" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54" -dependencies = [ - "once_cell", -] - [[package]] name = "typenum" version = "1.17.0" diff --git a/examples/poseidon_bn254/program/elf/riscv32im-succinct-zkvm-elf b/examples/poseidon_bn254/program/elf/riscv32im-succinct-zkvm-elf new file mode 100755 index 0000000000000000000000000000000000000000..1f325bc41528f90d8e7bb6b773c715d2880a8b4e GIT binary patch literal 172524 zcmeFacYGC9{>Odh)+B_03@Jc_n42cDu?%p~wIq}T%YqV;0J@-DAb<+40>QGFa7h9d zECU481*t)7t0Tl+T_r+tQFkqr1T3Hi5>OWlC7>=m?=y2L`g4EfdH#D|>+5x$Gc)IW z&i8!Jx6fp_f6#S#nx=_U|GC5=q0V}pn<9F1jD6Z=-|8(=gkNNdSP>(9Tv7LW(^LIE zqpg0P$nOlAYH6Y~2lZ3;MMrgo|Dx0{#s1A4s|oet{!20v-Ulzl*bQ3mRYWxlRrj1ijzx+?pt^RWhaYxh|n+p5pU%xaj_Oi%hdv@H)y5@+B{wne8B4ozT=6~=Ry1G zJQ4JHJ??dtBIt_ogx2{YGd@{_IM<5g?mtZv9p$6;%r=}FoG_xOVJ-l?G1ek7%N;649$#=7R{ZaPXtoa z?0dSmqX?v|5}}kj&7D@Rg;%SEVXuHvC9!pnaJGR|=Y(#pYm%w<-@ zi{M;ulv=kteULCabAD{0%k-9s;13+@51%x59MOWYUY9$=1MlFgkNL9em~%O6%W;`= z)V`L9<}VliWO~ZPsWHt--k$>58v9Vkew1rAuaNTAvW=~wbZAT0v|yRnRqGXHHXU*6 zMKHnZs=mnHvyE!c)Vczx3)I?Ntj)#RT&%^d))Gq3)ttT?>mvL6U)MJK7i-(QP&oAF zh@fhFa)h~Km1eGw7y6>%!d#dxg2L+xu~t34koA5D?K!OX!^nEeXrEbAwX>d&{uk@9 z{txSU<=56@RMv~�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

n0PyH0r?n%Vo^92ePqF8o>dBlvNV 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%0D7zo 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 Date: Thu, 13 Jun 2024 21:37:19 +0800 Subject: [PATCH 27/34] fix merge errors --- core/src/runtime/mod.rs | 2 +- .../syscall/precompiles/bn254_scalar/mac.rs | 41 +- .../syscall/precompiles/bn254_scalar/mod.rs | 2 + .../syscall/precompiles/bn254_scalar/mul.rs | 23 +- .../program/elf/riscv32im-succinct-zkvm-elf | Bin 172524 -> 171748 bytes examples/poseidon_bn254/script/Cargo.lock | 1579 +++++++++++------ 6 files changed, 1059 insertions(+), 588 deletions(-) diff --git a/core/src/runtime/mod.rs b/core/src/runtime/mod.rs index cd7906572c..6953f4a0c1 100644 --- a/core/src/runtime/mod.rs +++ b/core/src/runtime/mod.rs @@ -840,10 +840,10 @@ impl Runtime { .or_insert(1); } + let global_clk = self.state.global_clk; let syscall_impl = self.get_syscall(syscall).cloned(); let mut precompile_rt = SyscallContext::new(self); - let global_clk = self.state.global_clk; log::debug!( "[clk: {}, pc: 0x{:x}] ecall syscall_id=0x{:x}, b: 0x{:x}, c: 0x{:x}", global_clk, diff --git a/core/src/syscall/precompiles/bn254_scalar/mac.rs b/core/src/syscall/precompiles/bn254_scalar/mac.rs index c237a948bd..b3f0b46957 100644 --- a/core/src/syscall/precompiles/bn254_scalar/mac.rs +++ b/core/src/syscall/precompiles/bn254_scalar/mac.rs @@ -31,6 +31,7 @@ const OP: Bn254FieldOperation = Bn254FieldOperation::Mac; pub struct Bn254ScalarMacCols { is_real: T, shard: T, + channel: T, clk: T, arg1_ptr: T, arg2_ptr: T, @@ -95,6 +96,7 @@ impl MachineAir for Bn254ScalarMacChip { cols.is_real = F::one(); cols.shard = F::from_canonical_u32(event.shard); + cols.channel = F::from_canonical_u32(event.channel); cols.clk = F::from_canonical_u32(event.clk); cols.arg1_ptr = F::from_canonical_u32(event.arg1.ptr); cols.arg2_ptr = F::from_canonical_u32(event.arg2.ptr); @@ -102,6 +104,7 @@ impl MachineAir for Bn254ScalarMacChip { let mul = cols.mul_eval.populate( &mut new_byte_lookup_events, event.shard, + event.channel, &a, &b, FieldOperation::Mul, @@ -109,27 +112,36 @@ impl MachineAir for Bn254ScalarMacChip { cols.add_eval.populate( &mut new_byte_lookup_events, event.shard, + event.channel, &arg1, &mul, FieldOperation::Add, ); for i in 0..cols.arg1_access.len() { - cols.arg1_access[i] - .populate(event.arg1.memory_records[i], &mut new_byte_lookup_events); + cols.arg1_access[i].populate( + event.channel, + event.arg1.memory_records[i], + &mut new_byte_lookup_events, + ); } for i in 0..cols.arg2_access.len() { - cols.arg2_access[i] - .populate(event.arg2.memory_records[i], &mut new_byte_lookup_events); + cols.arg2_access[i].populate( + event.channel, + event.arg2.memory_records[i], + &mut new_byte_lookup_events, + ); } for i in 0..cols.a_access.len() { cols.a_access[i].populate( + event.channel, event.a.as_ref().unwrap().memory_records[i], &mut new_byte_lookup_events, ); } for i in 0..cols.b_access.len() { cols.b_access[i].populate( + event.channel, event.b.as_ref().unwrap().memory_records[i], &mut new_byte_lookup_events, ); @@ -145,9 +157,9 @@ impl MachineAir for Bn254ScalarMacChip { let zero = BigUint::zero(); cols.mul_eval - .populate(&mut vec![], 0, &zero, &zero, FieldOperation::Mul); + .populate(&mut vec![], 0, 0, &zero, &zero, FieldOperation::Mul); cols.add_eval - .populate(&mut vec![], 0, &zero, &zero, FieldOperation::Add); + .populate(&mut vec![], 0, 0, &zero, &zero, FieldOperation::Add); row }); @@ -190,14 +202,22 @@ where let b: Limbs<::Var, ::Limbs> = limbs_from_prev_access(&row.b_access); - row.mul_eval - .eval(builder, &a, &b, FieldOperation::Mul, row.shard, row.is_real); + row.mul_eval.eval( + builder, + &a, + &b, + FieldOperation::Mul, + row.shard, + row.channel, + row.is_real, + ); row.add_eval.eval( builder, &arg1, &row.mul_eval.result, FieldOperation::Add, row.shard, + row.channel, row.is_real, ); @@ -210,6 +230,7 @@ where builder.eval_memory_access_slice( row.shard, + row.channel, row.clk.into(), row.arg1_ptr, &row.arg1_access, @@ -218,6 +239,7 @@ where builder.eval_memory_access_slice( row.shard, + row.channel, row.clk.into(), row.arg2_ptr, &row.arg2_access, @@ -244,6 +266,7 @@ where builder.eval_memory_access_slice( row.shard, + row.channel, row.clk.into(), a_ptr, &row.a_access, @@ -252,6 +275,7 @@ where builder.eval_memory_access_slice( row.shard, + row.channel, row.clk.into(), b_ptr, &row.b_access, @@ -261,6 +285,7 @@ where let syscall_id = AB::F::from_canonical_u32(SyscallCode::BN254_SCALAR_MAC.syscall_id()); builder.receive_syscall( row.shard, + row.channel, row.clk, syscall_id, row.arg1_ptr, diff --git a/core/src/syscall/precompiles/bn254_scalar/mod.rs b/core/src/syscall/precompiles/bn254_scalar/mod.rs index 8854aa48e2..e1cfef981e 100644 --- a/core/src/syscall/precompiles/bn254_scalar/mod.rs +++ b/core/src/syscall/precompiles/bn254_scalar/mod.rs @@ -81,6 +81,7 @@ impl Bn254FieldOperation { #[derive(Clone, Debug, Serialize, Deserialize)] pub struct Bn254FieldArithEvent { pub shard: u32, + pub channel: u32, pub clk: u32, pub op: Bn254FieldOperation, pub arg1: FieldArithMemoryAccess, @@ -158,6 +159,7 @@ pub fn create_bn254_scalar_arith_event( let shard = rt.current_shard(); Bn254FieldArithEvent { shard, + channel: rt.current_channel(), clk: start_clk, op, arg1, diff --git a/core/src/syscall/precompiles/bn254_scalar/mul.rs b/core/src/syscall/precompiles/bn254_scalar/mul.rs index fb29e81255..cdfa72a006 100644 --- a/core/src/syscall/precompiles/bn254_scalar/mul.rs +++ b/core/src/syscall/precompiles/bn254_scalar/mul.rs @@ -30,6 +30,7 @@ const OP: Bn254FieldOperation = Bn254FieldOperation::Mul; pub struct Bn254ScalarMulCols { is_real: T, shard: T, + channel: T, clk: T, p_ptr: T, q_ptr: T, @@ -90,6 +91,7 @@ impl MachineAir for Bn254ScalarMulChip { cols.is_real = F::one(); cols.shard = F::from_canonical_u32(event.shard); + cols.channel = F::from_canonical_u32(event.channel); cols.clk = F::from_canonical_u32(event.clk); cols.p_ptr = F::from_canonical_u32(event.arg1.ptr); cols.q_ptr = F::from_canonical_u32(event.arg2.ptr); @@ -97,18 +99,25 @@ impl MachineAir for Bn254ScalarMulChip { cols.eval.populate( &mut new_byte_lookup_events, event.shard, + event.channel, &p, &q, OP.to_field_operation(), ); for i in 0..cols.p_access.len() { - cols.p_access[i] - .populate(event.arg1.memory_records[i], &mut new_byte_lookup_events); + cols.p_access[i].populate( + event.channel, + event.arg1.memory_records[i], + &mut new_byte_lookup_events, + ); } for i in 0..cols.q_access.len() { - cols.q_access[i] - .populate(event.arg2.memory_records[i], &mut new_byte_lookup_events); + cols.q_access[i].populate( + event.channel, + event.arg2.memory_records[i], + &mut new_byte_lookup_events, + ); } rows.push(row); @@ -121,7 +130,7 @@ impl MachineAir for Bn254ScalarMulChip { let zero = BigUint::zero(); cols.eval - .populate(&mut vec![], 0, &zero, &zero, OP.to_field_operation()); + .populate(&mut vec![], 0, 0, &zero, &zero, OP.to_field_operation()); row }); @@ -168,6 +177,7 @@ where &q, OP.to_field_operation(), row.shard, + row.channel, row.is_real, ); @@ -179,6 +189,7 @@ where builder.eval_memory_access_slice( row.shard, + row.channel, row.clk.into(), row.q_ptr, &row.q_access, @@ -187,6 +198,7 @@ where builder.eval_memory_access_slice( row.shard, + row.channel, row.clk.into(), row.p_ptr, &row.p_access, @@ -196,6 +208,7 @@ where let syscall_id = AB::F::from_canonical_u32(SyscallCode::BN254_SCALAR_MUL.syscall_id()); builder.receive_syscall( row.shard, + row.channel, row.clk, syscall_id, row.p_ptr, diff --git a/examples/poseidon_bn254/program/elf/riscv32im-succinct-zkvm-elf b/examples/poseidon_bn254/program/elf/riscv32im-succinct-zkvm-elf index 1f325bc41528f90d8e7bb6b773c715d2880a8b4e..d1a08dc17b02a89a2ba86b4dc864b75650d86a23 100755 GIT binary patch delta 63064 zcmbq+3t$x0)&JZ{HUtbYkOv_I*kl6)2w~q3L|GtG)j^ylw=WxTw7>(k#B^-;#;m&jA!zAt~6JoQhCKYx(zSC)|vNuIVUsW{KH zU3~X3{Zf4A2X-o^6_S$oqEw9R`AjDLE8#cs);w0OY{@^1ZC4KEPwG2a2%AjXch>YR zV{-db%EW$SN;xmeb z8Oj-^?ZpLV^>;zrb34}*>|};a8VWCE>=(+WGjHnuWO1I9%NxloY0J*aqR&~O-?z9( zYWJ+B;^b{t$_Gw`m2(DO*2lu6dD6=Jl|2L3R+7O=-ZRe^=b5GAHj|{Z0E9R1$#{?Qyjx;qm{`s;LF3c+`Hklf7 z&NuaevvVDJBPNHJ?3GCg(UrX=^)kLrl!WMOc4>Wu>0HH>D;2NKl{o4cF7T1CC4a*O z%9hemrN7?YhNP=I_A90xGWU~xiQ&qj(nSLkABPM2%Eg06tJR)s`i;_9R#DNuuDI_j zoyw}d(uc$Po+>smt;Q3NDb~nvWoKCno2-}zJsf;p)!g=`Vp_*k&F!7!c5W74cw1Bf zS6AVcZsE}ZhK#d+|l-d zS`au%t$Lx(BeHAzmr84&vD0e#!=#FiFGM`{$@`K5jzWeXrV48>;0MZCrD6>iRwpVf zwfE}vaYivUI}>BYc~rTg>VBs*hAZUuc4c|EqEPxRNobruD_g@;Dx{)tVXlnO$#eAG zs+K#~)L*$XH}AekS%tK_xNqNY)9O~JZGR1QJFQIWqbBythQtNRsc=Pw^dzFlpWU%LHYMz_oMUWM2Xrf zw(dF;`6PA?2V={wNeo|ypE--ZDtB*WW$mx0GWW|Iodg=?YsRF<_E6HI=S0$(zZOZ? z{tqR+BTLfNBI(YVzZotw>(18SUdZtEeEWatYtQc#B2Mo(lfLHs{qO2UsVXH&4g0oJDPH>rf>&@XN5phq+qcE00z=yN!^BtPJ;2oT0kq5mTB-btQ~b8? zRDNLqL5;phWZwSf&TW6lk*iF^LkE#BWbQEaRom5yT-7`NZdJS zZs&nF{*vn|D@MnylB7z?Psx*{g;D}-OdUUp^8$lNhB|o7+kq1kJVYSP>`EJ%%>hFRjgrnw8weZ4Hu=I8>JBcNVv;5aomTXm) zAF41(;~}HO4-GQ;$3cXC$%(PbfkPFA?W08_7pnY|m6M0g@>Q!H$uvuG9(qjbNE$^; zX*P~K!l7*))g&`0EYV0d7o*y+fm82L;ncg-@0IJ7&F_p=#=n1-EX9#?0C0APOMY*)7Nn2$h*}QiM5t~ zY56d%r@v6Cd2dEpMn0k%5(||z?^#CIXn{0J4Wz($3M9`+2@`>r?{wt7D5o#yqXhG$x7B)l4}iex$U2I<>!NA!eOwP%ZT+MMoW@Cl}|j9LvZTbBptymMyg} z=7tldLR7r;aKSTv3_%hvqV)btl$N9QS9MG+E-jV9m8KG>q}J#a z#bRcVvR5hkyfm&leAb60rcbC69$vMTYW?Hg8_w^|-66Fzk+drZ9lJf}Wbf&L5EnBuqC<}hCFsZgC zb~mYtzxr-BWw^RcrtjiA+DwY65p`kfqjd*=BSosL=|32B;WP}!Ff3_^$#haTj^q?m z024lB)GD00Mrl7;qgel4HP$5xvJy)K)brEw?h#bbz!elPmbw>Z=+viJla%HE{u3gD za$5U{KU|TQr^ZajG)oPnNkg4J6$sdsWyf57L={NGlwHT38jO_a((vJC(ckn74>L(Q zfx#HHk6)C@ZO>7;C6kqpj$a_RJ*Zf}7_HW@^!dsWjO7H--ixR(?O!UbUpO)q_`go7 zfBuV$`>5gGs+4?b$&{2nOJ+6m%k-@Le@V|udWW(?r%`lb(148cNbf3Zj}N;*!j#UB zI>oe36tn#h)pxkWl0o`<%G0?`(Mhi<`uGrYQ*T*#H)J2 z)9KP5l>J{!o+=#SKZp8-bVH?=dp6YnJKa#_)K}?lN^DOz%>OH8&DXEj8M@+SGBO()ge1!a$9s zS|^!iD(n7ZA87iJ`XY3vTKW7Y<*onBs5X6LslAw4#!P0Gf)(ghZ7e(m>%+V<^wu3; zV?Fqd((vtFY?gB1+d<5(9Qk&bstJ{*Ym$yD<^LVU<|_XGjD69a$}{ zqdf$w02)j@mr?oK=3@4*cMex86Hkp(Tbc9&rS;Uu>hJb9mB#Oe446k#_ToHDONGbV zUs2Y6H-t4S+rInL(8=N3P5p}dV)fi1v?4TNq}sAyQ8s;FFLz8;_I*EWV88-T!Zclr zv{O0x{RPBr==Ajy)+QcD@5JYx!-n41oUd%}JU=cvpoB+3U%&9!@Xxe<){XxCgy`RM zpP>HzOSSgVzoSMiBe6`QZkPIZtaC8VNa)y9T3Y{pgP5TSr;2>q_fvEfGxn{een76J zZbhzg;ACzA4K!k)GPT7vtYX!&>EwoO%*84irq@zquZhFna`asY9cwEy5d+c3c#7C#x|m z1<6WU0AWNs2YW*54v7gnB*kJb`4jFR!J7LNQ7zs_dJvY^tETP=_Sb9&|wr zg+_gg%wptwOKlYzMimp$hV`UYC<}%nTO;ErOpFmyVEjwml+wHo}W}(;nykQEX_j z?q)=Snv-cGZym+7DMkC&eDf%FncAcIOK3UDt>f9)aj9Ne6fN=RF1@l^uv2w(V7`|3$tAfN13L+8iqQ7m&E(!G){?Bz6 zRJ;9oo>!{G2%j8@R3mqEW6e`x$yBELqIDb_PrgVPe35vZ?-<91cPZSX*?l2B0(Ax4 zY(?Qp>sfUdA8yHRM&d!@{6um ziX_W_j1spurb41pbpCK=6Hv*GU5c${b8Ti5P{~(z zll$zhO<=n0ezi~ zh}JboX!g6(HA`plqc%2J)!?_EhKBZW=^7FagNF8VPD6u#WV!~a&Y(e>aT*%hhox&s z)L?#ENxO5rp^SZ|%?Qrm-a%~RnDzn5DJb>-qK*R<#Qqo^M`N;a$3*SY^Pa&r6greV z?3!b=vxw2|dX=~O*{-~)%^GiKSKi8bO5%eOp2$b%FO2uUFGk8fIW$tf^zOzXtgO&q zsT)BCDcj3x`Jo}qrFr6IUS7%W9j}HbHu1F?dCDEHrn$o^rpH0CA;_)QFcY6VgxTbT zQ>pw{C0{p$4OX4eUS!;pF!NKDm~ym#%gsaCFxmef?jOp^CiuSz-=3Qr-kX~*mgWKM zgwjx*%KI4wQ!-49F{Bn@bfo2sm;fK;>xPoPYQAeIb1(3VUBcaM?-VL+BQShFBkf+= zze8zzX0D|Mzek+#U}QaMsmAZGurJXTc*kOXMiR|H9c7>E>e`$!D@O#R@Q<)Mq`i>5 zB59Ct>eR=T#*%V=teoZYwRvR3KNagg|Dn3S-NZNdVeWqZ4>ERY>Quh;U51UZR$|WWe2#-v^*Q!E^_Fqs)bn3CSn-%IzegSC+=3SUon_4%D z(|SkpYkkvQY{XOAv`Ol5NjWnQv+v}r+FwBjbXAT#vlMRa$g@a$rIlMv5)M?P@S5B_ zJsyz2uTI}2KUZB4<|P9$Z!PB+3}jW!zgF!GyegJ=ei0pe$W9S4NUcVUv_55f;BA^< z6W@a6L~>GXm}rv^uvhU1n&_z=fS*hb1LFXFj<+2}&G`?$-3 zqcY3ZT>j&J%*?Ou%Vub?v6AoTi;7gGp5_PpV)~{Q={BC*k6kXe?c{U%AqZ6EH}bXp z5Cp2k4g9Ts>_v?e<(to7_f@y;q1vlIESOEYfmIe@x%R}@q_nYRi)mFR-9%l znvA8Mu@NQKi&JjCtb`THrXy5sg9iUouQdg=rEURH1xR1=JtgRSO`rEH_BqclW!Uoh zoHvxRdKsl&Qp((gZT}XPe?Y8|e0)zS8#%1wSc=x}q5z_Ya=>_w}FPvLXOOyLJCY{Ed(7i4U4-eI&9QHa0r${KbSQ~2x}Hmd)< z#ikNzH&R%(JTir^tzlPH{NoF?onYre9Mg(0{*a2PtUFc0_n6t4BYsQk$YR741`0!` zg>q8U66KUu@}p)pq-yHQM*~x7Z>88%Chc5}J@a{gmcnwMT+6nODV8VRp2D%@bg*4~ zP8AzAEbtwctY&?1{y)rAXcaekbrK}dGXY#sg<`$bj4BJTP1=KqG zlrO1f*9Wf!#e2tP22m2zfbrG?s7jc81519**vjhtpG5h0|`Dt3uJ z=w&qEk*lW^i%Ak3yAeA`F0`J!wkJ`$ofzt1T^=GjPa=7(KIZok8Tv0(=RY6P*!a>+ zJ~0nrVJcOGFIPy#eQ-dhX10esFp)=O)}cnJe>=D4Fk2sq>bZRlZ^~hJ_EDD^aegv~ zh2m}1mY+XDJ2l^`fzdHYM6=M>ULlNEdx|05)JR!+jdTnVHKO*9Hz(8QbquEiRIRSX zpe*t`b2Tz-(+kjEZ0KoeR|-9?s1)ge?t9vf5o%AX`U>V7W_xNSmQhbT&M{*41(-^G zE~ZkCT>ccc?xw0!sdAsvcG)#zDz#z$LQJLZ)~8bZ*id%1I;oU)bLTM3Fx6~s;;qA2 znVi_o*9>Fl(2bpa!`L{LnOMM24P%2f$%(vjIL1GbEYZxT4`+7S|4W`2&TfxOk6<6_ zlp2qhjaDn5ZLDIlYWq~}>J<+yLa6Oy{}OWtjEthwYQH>Opv~o6rRmdhQEA=Hj-FN< zpasWNR72E7U^3}X+p+qSm~GGG4NmsU|LqAGH@nyca-u(PaWQj~-hZj(Y#X0FklO0f z1Ic7f1(H-vX3k5fOFSjdWGhA|QrxCpKN6d3QxEawZdQ@!KR~j4yNiXYpRtioaoXb) zzP%&hQBTNGei2q!0B>@$dCa@f!$z?Qyw<}OGcVt)qP-qAMeaD4=X=>s_KV%mds!jN z3%rc@c$pvYVI1+F+&BT{40Q166W9xK$4$En&SHP=E01`Nf7F0kwCg#ZAHaUcWzX@Z z0Gm{*9xLaF4ZWv?Wo=*0+WmZh{UK*q+sle+3##`Fy&L*6*>?H_F6Ud%hrYmNyZ4>X z-ehvy%Y5^NY=#`Tf*-w*RTp;b7JZ!BP_N{b)7i9{9 z#n()SpCC(nq!>%Y#`9$qXMtx@avfK1ypmP#uKxkEGP&a#-Z+C*$Q^U|@)>OPu$Qkb z&YMYB2e1zBkQ`HP8(_Hjo*ptNBACB7801344 z#6=j?+vf5u^c{GXw_k*|W@_XIFTymHN}1QTkUM8$D+P<$%`@5Om+KiYb+=YzV7i|& zKosGO7RsYksUczi+ z{}+7;-*gG{k=2UHbOS$l2^&LoBkBSt$HD?wk2_ufQg>SR}rD8*jY=d$uA;+fv2UiklSZjm3D87?2FXytXBL?-i)XY1=I|FG`+A zDGU4_iHOnGOk%LEdM2bViCO75ugxh`wtJA9)&Q(~?GdnztY#r$7zFsG|_asjBK{$caKtHR1}J z_-dNKE(!zM$40F7Q)wMf^8;71OOkqCWI|6sn7D=X2;FojpzDS{p?f5B(_w&W;h-E=C?xThMr{FekWx98e(5FFFz1w)zuxp zhsUrI!3w3iiiueo0wrfe1CCi%p?8?JkC#N)zagF*#VmEgZhw@`$f*wO+f7bf9e7Qw zch%|1Ns2v<{yN{$gbpC^I^WmCrVSkN9mSuLH&PbgeacF>xtUcD4E#~0zxc`#?E|EIv*gDo7qLwrGe7%!c2U1iaTnMRc=%?%@p|TF4g9t1*;vz(TdJfQ z9=rql5@TD~0M^LQZo!1Ffd^Yypz!9ynh#sR`qlWCS4n3> zTQxrC;4{8y;r!_MEaGQ0FRWj*SXu}9v$$?@afB|ZeZj2<^`;%MyHPey%3-7Od6Xfd2g$dCULfq z4Ii)uKL?O>(yUnvnPc!)kSBtC7Cr;h*n1Z;i|H8HWB6wa*@zsJnLmF6n^TKo`r}nn z6QutKpK@D;1)M!{ni_)x@_Th z-@u0RwKuS${^qbbRYo$QX%3_hC#s|y@Lhrr6+p+8_&qrTHyH3F{GOVDrvWFu$P1)^Nn?j)i<7FMnnc8)MqKqDs1w|6>uG z*Z=u0mQuARZil7(mBs9_`o?iplGzH6|HBN1dVjsVx=LytRwXrlVwTpNGD{!fcg^rB z$y>!AT!K#a@X9KQ)EvP#RrlBUmhpXZCI9CVc6r~*RaMdq;2IuS$}IMlK?r}SF93;J zg%{WhOezSU8kL^CWaIZQ#b#g))Y7wm7602(Hh~rK(i@pap5Df1+{n)9zpAZDa)Esk zVvJvWBX+i)zL5=)_qXxaZ)DZjW;}i)j^wPX(e5EO72jlJE+2gpvy5mhsghdGtdf=$ zS4pvji{=NHEQu~MN6E#~8i<|=(c0bT$Jt}@(5=Aq`0lKd&cJsAz7ZjkpsP7wd^;O% zY69J%;=6BWr1Poh5=R5deDsY^We1Q1FNJt8FZsF7q&(h z1(!50Twq?jG#rjDUK|^|v}FydTvuK&7~TLzSn$s4u{-sbAF@#HU2qLQzL*vBnK!f1 zY%Ra}W;S-fS~vxcK7bFksx@o*qc^k5`+oxZaNv9KDdcD0f|gu)H-d`aa1$FY&$*l5 zcN24$t^sKjB!P19e^l|8bR64#rpbQ1`Sb8eM>_7A!G0FKAwZW(~gRev=*Q z#9Ps0ZUT8MkKW4W7H%1>no7~zG={%m#U(5$VZPQW1wbM(R8E{Rm9)8 zk(KdZEN5r;Zvu@*2L_u*^IKOj$DofuqETp{mPHjh2?Pp1V-@rDU*<~rYdODo6&pTq zwxXK45Gw3QXI;kktzwm^kJaD|0i_uqiY5N_Dz-1a$5SPhczgaFgv>_Mb(`8~lbNqaONeN*2%2<;YR>6iFW$P8M`tM6dd701D+z^%c!B*F)M6}5oQ z4gA_W*mczxVj)2t@8$R&iSGmG*r*jP2gZ7k6NQYA%~wYD^eo0phdgA1C& zm>Arz8oU?Z^q50Smzb9{MbQu=(Pif5#b!zR3w3GWow%Q0zLwdW{aT?cKdlnsF#+G? zgnnjoOEk8G{3Yo!TQu1@nv5=6XRhmatNGU2+J1GT`(1sFvII{wDPthk>Ua34N98u;z& z(Y09v{L%GT`_xS9OqxP6wW!zfY5W7oj9CvJxsV<*sS&)j26^gmmw=X-#_Km=T~%-) zzhDC!Syk|Z&Q3q*QbVDC<_fk(zBA`ODjJ!45cE3!^aeJ>bP_+8@i#WGK~soRj%KiF zW@l$hmXtKYdBOka;?7QrNN6rKNIxIOL#vxV8Y2uIy)08-+UhBjNfD>{g`tp zbgR6g>8e$d8F(vr+b`wUZe-Q<2QKgIT&~LaNk5hPF!;_ZQl21NPk>f;1v!0~y!8tH zI(=`S%|C|@`{t`UJI!ht8uffg&l2oBZMizV^45U1?P}6f#%Dgjax1ohV4ed7NI(x| z_B?2HbNGS>SXrF#A>g8GJ3AX;1i5&Y?qcjr68{wVGaEZQ>$>4rqAuoyP(|JFCxX8` zl2w0P%r)jf;Q3f*=Q3ml1FYmJs-Y#ISI+B7UrP$J(6@qqD1%-DJ8qLmy$+DahK{IS6EpRl4FP|vX49bfGQb^xTAdadThDs%3U27^Y$YSm@{GJ4;5C9*pyp%M zd1S+W@MbPbmeFdgBjO(gzhQA_=O#=Dc5Y+?c%G!C&|7a#$x^Ylg4P7uUZX$r_JUe)3%}0(4;- zSmf-ZpsiWWUw9A|nveO&raLsgHYf_SLEj9z(N|=L7xew0>qREobkLsHbpTWPM$qtLFg3GsD5Ww}KO&}QD-*;%AYn)#0VaXFxM3(LJ=8(7};U_l2x^!+?&PSDImz(dt= z05m^nvxorK>mf`fISSsg_56h`n3NUthdVd$cek*zidy{Mydf0^b&#D1+VdND;X`ap zyam6v{iL&#^wVR;Cjr`a&~~ZeZOt}PY=z9kpQhWq2Q)8ex-KfmeoamfC#s>tpfx}a z5J~AQ(Ds7n$8UI1^jbu30sScGS_>70B>F1QD<6dy`D6@T_Br_3q$W*Pz%Gbv z2R)*e6OLnI39%palaKKSA7*3nPT}{=C;00RBLXX7@PQ}z=MS^8zFz!3?-!k&Yq@PJ z8`RGX)pJ1Fv7Og%g$on-UGyYc5M_x6P+E`w)PZIUnr)ytLCZ9)9rRUM=m$Z6D}zq@ zj)7kD6ei~CTr|Fp8G3KpVMTCmu6b+BM6pk5a7K5EEGsy{D2TXxX zc23nzjtiA#GfNlU3>;hf~ zzFw;SS0RoK_*URez82eFnBQdq~Jl|S{x4vj{qMAR*#edkF%=>dch*w$XVO3Mc#Y)uO4Uh@rj^|GJ^hh zOpmwfDuD4ilC%rBR!c|siVhk0bAXQ;(%%7Gjw2zxQho(oYryXSFEil$e5qd2&#TBV z2O5Ytl+rSM?HaVdy_(^&Nt&?x?kCtqxuVm6hTrw=WXeP&WC~PaA2i}>ubPPVBHhn0PhKF(SbU+a3BT}c!D|vD)>_1!v@d% z47k#e{uN;Th>l5dS^5$L{cw&H3@t|21_fg@g-=GIFl0`K+t~m;(T> z)9?epbn2$#Q^1FSooL)7|HpY~#7$FfVUa&65x`Aw&e_uJqX+YtXI)K;DeCY8^agCxd#5vTF~J4o27yr z^b}6jPTq zp~o>8#DNbGM*gD9`6~$R27#rBi9>%hODDB1%5wwyPy_#m!1^&RdF)N#gKwCne3R;- z{)=G1pHuiCuu*>cVim{rPWEk$pyRV?qgi{%Lm^-%_OXjVqY|wJ-uzCg8E!++mcM6~ zXsjoLR$Y&&6Zo^V0z^>fb?>L}G*tPKznkMyjV5p&ENnpnD>5Jj>wpV@8#NqV0uKP| zF>>`%N%{^hM|U7RxEZ)eHxPCF4sZjo9wWnU#KgnEZv;MZyB^g@@N*EhLLo*Uq3}as zaiXl@f0p5g_K-)0po$tkG)o6TBZEiW1o;olcymF;XAIJ%)fgL}fiEOHU6Ub&%^3n~ zGw?4n@aq})6aK(1h6|JYH}uua-`T~+vuAn#XYe(KpG{vs;`8b22!DXS=JMC*>oEWB z86=4Cq0a)n$A9oF(B*tSzD)O2V(8@eKFfwo+k>CiuT(eYDFQwOz6rQ5ia@ws1Wsw3^oBTS;gf&Y)sip_`PbCdX7h?eGa@C>h`b;@&*q_ zU$Tnd2f1kt`29TO^q^h{EaCiJ$M*v_0Ox~DdOCnl8SpXSh91H~_3)Fd&ux1=cSb5FS~DbpYg5Psq~6!1~1l;$xbEn*&vnP1E-n za1pY#Yxqsz>A>Su9GAWWLBCT#3TmsN00QH+1SghZqHx?S`I#EF!+waF#TRCYw(=>g z&jbGG%M^bRFja}pzZClPhoX2P@cL8Q@F?-Ce$DKYKLxE7w*fG~2`7|U(BA_WXqeK^ z`rb@mc$hR9eELg*s^4>^Rs6MIvq|wkfZT*+m|F=oUjd&7tXG#AeZy=6CS_|F$}b+2 z2age72zmV;1-a%%VEsM?;fH|rOB29x>GI{0G*}N)Oro{}lR~Oo^3^AIpb5N(TP46W za$DC(l36zhU5sTdx&mN2w4-roKM86N`Hp^W%`kYPtQR1TKd*=cL@+~;+7vx00VYiu zfw{|_xQGBcm0%a}`X8k*$d(a55)%1q0{WU#$8_UHeVFt%4BCo1riZGaQ^R7M0vDG+y(OZG( z293^t447`y^rsyjQurnabhV~XQ}7)yU9-UyMDS~C(PIGXjq6fix_)zp#=i}iuHxwO zj|0=S938&}OjmTU385AMn6B#-s^yoZF{34McSpDQGGMyLgMx|#31GU@5`D1!9ifU zFr<4Z2V(?X9_p{9uLq`!M3|Ne1Fi(dg(9_C!k|^abhk)P{}eFp7{$fmJ6ZfU5a_~@ z?lM!IBrYGFp((Ti(?ukjF_8S#z;r1|H()g|T~N~Hp9a=%VUheHVEr~0;Xdfio9@J1 z#i1$8L&rnyvQbt$p4V5P!_->=I+mi_)sAEn=<;#DO~Wm~Yvb5i(Gxre0yQHY=lvM7DFeO~cq>?o1` zP|r6b0~62KstCvF?w0y6@s)|`4wsRiiRpfqk#EG;!GM{#+E5MwaydP8iB5f(w0<1g zUsHwvT_n>5UVs9xfqw*;E}3nDfZkOT*5&D&u446sXQuH{`E(=Am>?6=#UUeqJ-2mW z5>iu^PNu7hy4auAsCE;knu@Mfv#DWfDEt+eYT}@V3+`4OqmOw%0#2aZqA?+T%R0m^ zD$1+L|7;x`M>TO68BlD!2?6rFt{~@L+TKZFConk%-HwpoMtqbD$<)}q4-*g+s6@*k zTn~o!=!2-SfMRQ$E^Dd}#xNvUZ>Xs!faxZmFbI`T4`KCDG2QIb@i&ks+ys_hvqnD2 z(QQCo{)+f`l^{x>WndH_!OeyQ|5^=~>juGN<#(WpfSr&d4?Y8Z`a>mtBLfr9sE@Dh zU|4D4SyhoTE9X|M;(=R1C#_R}DV5%&Kg*)kn7*$So!m?MTp^d#OY4TD^k-m^zqp7f zB;ke!ZoyB9JwBWVBr4- z_!}5(*3x$Z`@we;j-v#VHz2Y=ph%+olt3rI1cKs9wD{2trfbqhekP_X)H?r%Fu3NP)KI<^c$w;Pnmx+WA3@lm zyAb$W;618<;E%8&s0^4C8#5s6tx9E>4bweu^8P5`XH=ssV?=r5J|N0Lui=hOGvUhq*1W>3ZhASChc zkwF3_5X}l%d;xsefJtzBO-eo!55>T^AN*}#PyucPrVGaf8YcPn8qA*5he_W+;0Q7( z0)gt39#Wt_OsaMw2*ED_f%rcFF2HSL9h2OW5h?j);I}}2fF}PiuzoX|($82yvnRNy zk*P88!0l>@NFl{U(|TMq+*>6~VOUrG0Cg3CLVBnU`}{=3ddKrRGSDBrUoaX(yoA9( z!tsWYDT|4aiOr+Z`I(sBXHXv|ZN?@5r9T7$72soFlGkzW3e`iR3c#7Vhr+$I0*Vp zcT#W%N}xY_9U3hr-qz9S9%vfVJ$@Ma-a>}@nu5}AG04YXhd`}vG4|NL0X_l&Ix*MV zJz@1>k^{rmNnDoKTgkP+<@cuWoxpwrrgXFGQt30W+Wwbi2+-|%^r@Ts1(i!WEcLkO$S6!|sU!a-vD8`A;Br& zUBJQvsKZfSc*MZJ1o)HzlVY2c!QHL9-16{q+nAnm+;Whk!ob ze-Es`mO=dg-i8vOL?DYgy&dB{m9Sk~8UGJ38FX0V-+`636D2MOCXeTAL4NRPF7g)& zehmV-c$0=_JfvC(C=&b_c#i5af!_eu-}xYg#Xr{+YU$@?;L$$Pq&|8TlSi&mNlbh> z4K4~G!3JcA%~au`R^UCrdb_6tEsiRYjwF6c8R$_hVjX;b@f&Px{NG?D-$jA*Ix$(= zkEE4IK@DQ{3dAdtk`Xk{ZAGU`w&^YQSxm^uG`cQM@)Z-n*B&a%*}zAjuMP^5T~^98 zaxvC4u9U5rIG&;KkqrE520osF3(pc+i2sm5W7BY4-NCgQ3^)%0C*e#zz86sfCFR`B z!1}8?6mGQ-WBLhsdZ@OWHB25P{Bl}`$2&hX;y5f4uV{+o*q{L(IuSE)7$o{6;dm9R zB1~Ee{&Mg|6={6JI{zT}MKIVntZXvy<+HJs1wO5r(8bEqI1tV=l#mqdF(e>dNJF%USCvM6bgF$2>%a5*xhtCD&Y6V?s5lKAU&j7vzs zdkp;Rfa&!pU4Aj}LE@|N&!k&Gp!cqHftA4Y?v;-30zPTL3NXDgrSs`KcS6tDoWWl< z5lalC0wU;mGcwpVsY==mf?i_6I-kBXaf3gdpNVHpP3Hq^`D;-e$q-nTfe&Wj!wu;Q zGqE?2&Tr|04NHsQd z!eQj6`#%}=%MAu4Ag}}q_1PTKNt+D(C%|71em>}AFg-^N{I|i^U(h4|_+MZyWhlT6 zzd-(*L7;~$-U$K1Ov93&IO-#MMn9UBF0Wv4h50m}?zWxp)$$tf`zq3f#JcZstOr1qv2&})0Nc-Hu z#~%Vge|eDz`+@bB772d?tiQBKxO%E;3jLR=guaaiP69ulr($B=b`_HxRq=J{>G@rM zWdl$NSesswD&-vzDuNPP$x)`i0HB9n#vr_VZLMHTbq&_KmCp{Bkq*0#I@4qaW zUgU2i5MMf(5)ioH@?-*mmtT>>6VS9MgDp<7!Qn;T2AmPo=&Zcs8)8ci;zr&r4$L zbG`>c69}uIni9->5`hK$7ZjQBv%sWK#0BuT86_OlAZ!xf z9ZvOO(gGw{1Dp$j-v1NU`SiWkfIo)3{thZtS#dzcdZd&5euF&WlG&<0_@7B5O&6hVY$H~cX~Jup=kHOmn2eFpppuwuYRfHxTM zLr-9chsVU!9r{nAS#SI)CLy}Qvz}6$p=fpxxEFX06zB%L1^goe9<&2XQv<#V_{W9} z{|vm|fZI`G{h@xs@(4T@zd6-2#XyLlj&igTJ`OxfuQQbRscmQ#20Zv_vDBWVDRFSQQ@yN3-uxS9pJb05+j5B3(yJ-n3N})QU+ziA2p}=4y4y#RVRbz zJdO581}tN$#lL_{-~3sX_*(!JWS;|9Z^4!k_=Ii0!e8-u2-m?hyaf0J44RFciN70o z`UC1F8sTq&iyp+^T+!sOg#r3Q9=S7~LD-dn-^;-LF4U8&a{yNcZp^@UW#DHsaQyuY z0;xB;jBv?yRrG}iW5rIDZv~<{E|@MD;y+X(PX-QU;JedtymL=Fq4UEGT=;|Z415_l zl7WAmfq$KW|B;5V2~jj7J%h6{a4ZAgn}MIt!2im?120O~f3^|RCPb5w0IX!-7c%h2 z8MtI-dIpm+@O2rOr1dHlDf*~RGwOwPb98JMTAx(V^S z6hX{vKg+=7m!xMfH3Kimz&`;lFEC3dP4qW%a4HDgFw`vVff~Y(0+*DTQDBsx2+x90 zAP6dc5%_SaS-fjT{8xc14g9x({Uv5`%18XqfvvzrS_XYCMOO~I9POU?rNHaHHj93R z@Fl>sBCezxBa=Bs~ZffD=?1loi!YYI+Y z1>OT&Cf%SF5vFy@a!YX%_6)_;&)+t_Qv6O8WKy(>kI=;}4mGDs!v5D#X79_>ddp z|7K0#?;y}F#%v7_yas~{=6tI(i>CwAoX)E8?*OJw=JUk2@)`GG+h=oghs98&ZLo^VMys9h6mCgdDdAe@UB4FCb(Sz(UU}K5; zhSaS)y+GFk)A|tQ5*~RFnC6U48h#%*PLoWXFfy!evy^KB3xH|oYPPH@*Z@rXLWm`y z@O5CCMz7a!K}21`>n@)JOdDI)994c9Fs&o>{B}mr{%Dq}6HY+DSi*~==`nHpJd_w! zM$Z5V7xxyRN>-{dLs(i0ga2U`+bmSai*8aEn{}FjZvz`W=30jKPrIGE%Qhg|nm#d0 z+j3QlUjc4Kos!E3piURvjB`*#HQ2x=={aE9?QhgFh~0u&G0sUFn4136+YwV=r&`I< zm57;d%u+&=|27T+{mHKujgVM{wHxqxn#-OCrseq&O<|-B&GHmF7EOL3Fm2&iYWNdi zy1_w%sPMoV1lf0H@pcqp*N@bFB)tmbuiOQTWt2#(`vH{UJ)5wWwBQ6tX8#=_}ibu<>)tNYX%+%rb#W`AR+$IM-VdzYSm-s zqT_iS7GI@qFq44i2}%6rr)*_W%wdms zTy9s`>GcNf_7Fe(Z+3Q(J#4l5!gi-O7;@OG5g&j5Q|2v-Iir!7+ZwewJVC419pR&o zGUu5wk0)xg+MI4{EaZ+wdFMHDDQ~$>9xx#04#r~MkjvqUIf7ApB*3da!`mzSkFuW^ zxt!5Z$Pof77z$gR8tbvokhv%5bcI4OTi70o#)4KCpZqzi<$wH)l@@s-L2u9*4%@x< zh%Iaj5$l2hHoGet_Ihj%yEhh!Ivkp^j?dYj1IT#ZeDAVw^L0PGDdxJ)Ej2}#)khs+ zug_!ixndrx4GG4D=Pj+b;w>}V+?%hzaelo$>aj(FK1VndaX6yxsBlW$Xe8uyhV4Oj#Ora{LJ_Oi>G3#Fz-YbAditXF?nL8V z)jGP9?JDX!eNk_AN7Rrfgr{uT1%#(29cNdLwZ5ICvi^j7R%#&RrUsUGd(>qy*)9z_fdQ)brIcr z5JBDpvnL7#7bW^;*F+qx(kUO2zCxh1-|KH{Ms*6MQEBfh8;gT?z_u|d~n zQbnaZdQB|EP9u-;U$a5+ta-RkFAuAyEiSA&=AN@whxuw;G|n ziJ*e4_TJSvdKYo^F5>JeGA`3#cUPH|2*2SQRvgb>QeRIAg)Xv8kfrpZ$r;8ghbV?C~Nfcvw$mZ~d@yEYiHmgrH)Y=2j)&tMp1J40oyt@p0GRD<| zQg;tLPgh<%Swe4DW|HUYo`-hWt=AB9-Sbq>#Iw2^5!Zdf9z27=AiQwF;w5tzHb?61 zUYFAoa#?L|hs|!&XV2k9KWtsHQ153Q@sQW&#dOXWbNQlPmmbp@QrU#8QgFc!n-<+F&1l3Euojy6XYE|?n%F2k8S*&F+^|kuEPN&c9aJnKsrz`4?)hB0vy-D)m zcPtPOc|u{V!(v{KH5_yVG2=enjFR)`-ZH9BPKmop#xtx>&U3qpW=JOIqrFNdXYbi0 z)1B9)GP2c$jlX}NT*g2Do`vIKhb!ocdcq<2&Kr$HlJ3K37PGpYHWwm26!S#fu8`dt zjmA7SZ^Ragy6cm3csu zkuz*_TfIJ;Ef}-~9rjoVYxrQq>5axQc?dc~!TRJRwcnOfIK;m2_ry3|V4vOnovqV!l|^hGi7?Q*1$>Jr=QBgCQSwD^T%ar`^lHX7Ytr zx837&MqDqMH}gyKND#)#Y`0 zJWhAW>ehSp#Y;m=TB4XX$6^tiFYL71-IzD)T`~TMe`GHHp%?tW-fKr%PuS)4cw;fE zNAK`dk%fz*_0z%fINUaCH0D4lqgJg;oEN2k3?Q;_e!a^Uvspv-P$(R-V|5?W1n`&m z>%-xYHRP~+&=4c;kT=XP%8^|~-iXuY#=j&Ij(CHxKf>4N$kqXv`C^F@w%L4+kQ;N( z03S9`o>&xuSze#R=Lus<8jQwxRjwQ<$54jV4|buP&PWjI1Jc~9X1Kg_`SBdNg740i z>&qjUTUoK7^>`ib2<>B~i3~EybwzHc)ob%Qv7_X0Iiijj|6`tf?O@kUi<+09I-9Ux z6?0lWc1(j&K2KP%d2OCtT;%at-7Xu<@i{zhPt>Zi9?z4@ifmY7+3fD1Gv*0nu=Nt_ z`l6VfMqg~UIAUS=!lq>vYgxLu30Z|>ktnJc+fN=lcAxD0#XfRv-0N~+L(lC*-6OY% zHPyjc;b`O?!M;@xJ9yZ9vAYp)K_{XF7~5jnNCE{tOWKkRy{l-ZR?I_APc45aUk;$c ze2$pg3rB>|9S5DKZ$2h2rZJrTbk(b1OJQi+j}T~hEp+r%W4%m z!Y&nHKV4Ua>g}nXySK`+XZ1@wYY5nroo&~O%_x{X+1vImn(RYUqVaBm(9w;*vbf8U zMQwLlyLfg`H_d=Qd4_yx+#bes4qM{Bpx5K`+ETlesRDG9)9HJ~*1c%FOCw5-SG^iw zJAJR%yYn?BnVA;YPu~K^>31ZK><#JiY~2%HV$0f+vPA|qwzG{SZ}pcK&BIwo)a&)R z!XBs7=JW-VJ&Zey^)t4;>^2O{PFL6!abt{*cwJG1117Wesg~5csD~Fd$)g9m=FYt^ za3zfkQM)S~isGNa3b}&zkcNYA-rn)SAu7*z3zucj^Rz4<9ODc&5XL^BmGO5gDC>0_kxP0aXK|n?@T%_hQS6WT$mt5d^lyYx@}I66DumO2Xh9G%~|hE zMqKZr$;O-}8qccs^eu2Dt1eA#Hm%7cvLfnF_ep1y0HS-P2Sx(=r+-nC2WM%IPnfNqCfTm$Hqm#n=I=E-iX z!#$o*)aAylh=@1T7;^fsHjl&{xMq>sLCYqZCYfx+y-9NOV7X+WUoVW$!#ePh%-sTd!3FVo)3F(^xr@3!% zZRWl~Pd4^c7oMzT<5!o;7sP`;tnYm;pVMQb z+|dd7q7EA!oH~Mb>JFdevo`a+!qdc?RL8(9QC?`Zg*+}s@LpN<5usY$(YO(jdv+< zYLS^K+eI`r(db>&nZ0pU(+xB1`gGg!Y<9k~QXXH7>phWZ4BLb;E6yZhVQfJ0r(5I_ z{?|&m9Q)KRS19cAglIn)ck^g_s(Y2mDh>N^Z7&k_xWd?=40=O2lJell3ES}@T%B`x z>M{4#s?-&1!9U*ZJny25F2wpY7{lGba5!c~v^Zi`=HmaYkn7`E`-Z%+up{I{=k74< zCia?)JY#3d#iz~d;y7IDP9VH{j&3r&piJ!gg$ zq3F2h215%MEvb(|rqMf5MY&y7Uq z2N%r4kxIYoHL0G`&3BEI&n=32F{Ii(5qlU1ks*hJpD_v>)z&D^*l-0IhhVs{ZBK1x zhH)7i`($*$6AB`9D3RNW?QDtjgKHz$z72&Cwho^a^U|b0;=PKdRwTWPp1uKk&x}or z-qjigj$X<|`vB@TK(AUIqAtazMX$1{ee7OEQ?r}iMG+&~rbVx^sm;FLMU$b|tEj`C z+_dOjHZ|<_7G0@XTd!I%W}SA8rS^k*Rf|2I9@>W(1)cUj@ZNXsqJFi={1OA(%V(G zyB=6Ha!*eN^_bF^C8e2qcG8RO|EwP4e;ki>rW>beIHL=DZ8j{GJgJ)kt|+DxQ5(+L zB6Q)yW5Y}=idTi)9or5&rq83dvDpNrWCzNrp`Zl&p*`~yUJ#m zn%W}iRWx6?G-Mj&xDHD9}Z%J2`5l%VrZzjtjkuX05Pz z*3e2e<6gCPQ>-ke>f_RadZW_p`KK0jM%k>UrY>;wD(X&-%_&j%KdV}I4{atR4&A5k zEw?+fD~M}TK+#e3)U~EAAbBtacKEP5!~DbQal2g3h}VXV65Ir`Xcl1sWt>Qs&Cn%z%*@{n#6I(d~(F6o+NvZq@M zojqFU?8!n`cNQ-2c59(aSlCUGUEO*3-%!|H8ns5dmbn6M>L!ib*;75cRgZL&*3)Br zd3yAwm*3#dRz2+qpl)i^+mpY%J?7@?DXFhV7x+9qImoKIAiKplXrMxtWsP_nf5<17 zcCD+2CU#d>HmhoA*EIWkNYj(~HmllybZb7f$!?f7QMPWG)cCT84c>PV9_?C;*U#>@ z==L6qfjiyQ4R+_~R(E$Ds14m5J4gP!$m6uT@VdMUcUHqOm%~f1;MWy7BY3UM;ql>J zBU~}_hWJ^N=EQim;c?L!ayW4@?IGn=r7bnYe zi?CmZOYSl3HpIL!PteV+Q{;P#A~6gjcD!7U_X)A%V&iX2kuNK9VIwaZvAOUHveg^4 z`}phA<>B$zd@?VHJL}Gn9i>BK<+m-7{u*(yaI(SAbS)qkN1!-Ul5Q3W3kQV!TbNNkPX3!Q_Y?dyc3XTj*TER ztX?b&ae+MMjrN$}ifM9n5iTjj>ds z3@5=6{E-WrH)zGS`vvF9GmCK9(M2}b}|q$gD23 zK9BJv_uPAK$F-D)@40u~ea>EcJ-%yw*NrbdxpL;|i$=vIu%oT0@jFc9aNJ0*9u+hF zIAe%K?1!PBWf5?QdG&z)$x-pne&q1h*aZi)fdilyn1$>AJ}UP0IW5K4UgnMkQ; zkBJZ2v_kq>2vGo&Ad@Jf`dIBRkTOSuff_)|M9>fqtZggVxm3UZn6UI;9TU4|*j+cb zWXh6(Pi0u|S<5H&_J_o5Ke1rMQr(DR>MSy_^wEcS)_&p#F6LnM(&tS>(#4lYN& zw6G)|jK|P|LNW2-_D8Cx(qBI*9_c3uZ7XR^oih%i5U$1Sl6a<&AR!TYMEIM!(zZ=Q z#f9cs*j`|41ih&6PZX0?JRqLZ*kqn%IC@!1Q;Ds7x>BgWdr_8HkVAqLc(qy1cnR#} zND=jhv@Jpx4~s*6AXbcNK!RYQ6p3v%{XKo!VkSE-f-P28aw-XAenLebWiCvrj1nucjnQ z4f^GV+B+fc>f1V&1Ly&WPfFzBGlN+Wi{;P%@g9bUSfv7 zcrLby;z|(en-+xZ!@8j|5haN9a7nISSP;kij?3AH?CIEwqvVvmdjw+7)2tVrk zJPv3+`s7KWaN1$QHrQbpP!+bbY8+1pYy}t6rT4;89-O1EofIeVf-#H4J(*`p>9~Bg zmt=NkQTtLE{TH#)GfU#xzNrGmj8k!P2RF|tKX6LS=yxo^O5z|XNKtfaL>O7jP^tI{ z1Tn*Zz(YqkWfZ?u>`o3`qu7>3Fk(qY3Q6f=yNN_5l;D`7@i=~X>mp=*x>_XYsZ89h zUtPxX69&QGVrmV0l5KlZ5j%q-nD1R*?-%%k8M%Ek}D zu%cpbD5G>s`J6M00ZJdm82dDp!BT_6$#DWr&fSeNd=s$T}yu0sN5nW^+`%m={ZgY8QuR5Dv#1EZ~FB(VWBG8A{ z=Fo<3C*-oH#0UFypb%R?*P{)eGn(r&r^I{v^ti|ngONEb0nT5g*$jumowz=fLhPrn z^go>vS7tD~680h!otQxa?p@ztNZd&{=(&zmgy*3pE&a1aafkly$HXl&&;fExY!*Qq zlaxifKJ?Cyi;owf??do~(TDBlEHxY3@=cZccJgGyYD*^+P_*!j)&EICivYWJ4HK-P z7{PV!lF(@f8t>F{1h3ij)lcg?=f$0~Fkf6;3^BbErb*UpLYoE9_kKdm3^=(elB6H> zL*N?1`SRs{ZlV}FPidTDc2OKwDn?KfRLX)2N1w`92caVHqH<>x3TGD0>t9TXW3xka z+cBo(+o#3pSvR#3C!m}{jTN2UIEyVeuH}lzWf=+jTo1nT7$KCO+y$%tz_t>h0)8X88N}xBRcB3t8Fb?cyefnRgdb55^ z+K>lCYv90y?~NN^tPCNkD-{U>RYUBj)IUEW9?-iJaT5doau@S z52j*IFV2boO(f?NsHd6!PKrYz*MXO1IxEr~>bG0J$|#qum2+xw+--DczI~kgh>%@t-N+XAIilo1C?2v!Bj!yQ>1N> z&H3C14)PEpEAh;T6kpLk&5WdaC(Oa6ttzD0Ai)wis7n7d#}~q%2b96#;$8{dQvLli zOj6wWq?n!I=13lKxG>RTFqT@B&omt(aCX+rB!t39hH~!{dW2GMt9F~1SABOPNKIg3s12Fp=-j4Dys4VN?)rsDf&A=TSv^d829*+SfTZTZ?h z@Z?isZa{^a<{2v^tz^As7NdE&&m0(2xn`3spZrDYe|!p~RLv7$umD|57{GW#x@{)@ z!S^n zHgi|Oe>v#y8%Uevk<^NyCzezm=k*WIihV_jVIhVkmmuX<8?k7M6{#I^7k||&b162D zp%f+w#d5g>4RB}6zWyq)Uj6ii&`vL$U)6`siiMe>AsMv_4T~_%>ihJ8bK(x5C(3;) z23C|Rv`Cg0&WS4^2a%yW1E_Ej7}~sgZl}W#5KLx9GiJ=>PzQp&LyMwbIWL~+VX_!E zt5PyYpsheZpK=C%abDcscg?ILPXS+;Am6w2fmQL?Vop-QUm}O85d?B{>Xp``n|D#G z6gVDBw&aJ` zrJI(%?Jx%y@XZvCoAr;^#17U>XCVfXITPeLK4VDM#O?Z*YvP6;ObpKoEDIY)GL-2b z{VF&5pR0@l0jfyM&1cZ5xY|^(x6%WG-ogcQ05wTeieGa#Lf96|Uz^r0 zqI_+eIc`JF#zg0Ob}hh`S1vGV&<{FaJ|!&QI#4Tz(NNkps>esMc6F z#sF6XfqV>N23D8M+x26w5LYl3l+{a8KPahqwll!ES{6}; z4}}X4Yq zk{f1d02qvv79fG zh>IgaNbpg$9m* zL#%FokD%0>&To^o>a~2G-tm%H>QO``&vsJadvFM;zxtwhfF={-S%znOIXs~VEQLz; zy#D>qi$2LcISNED+$U_&IH{_K&prrxQC<%LbKnb7JEE{atZJ^`S6y;q88T?jGvPkk zQdPDVGiBk14XrGte4aI4EXXOw!^;7Sz$4&_h)aFyUk>$ik8zxH&B?Z@5=-hXG-@DO zny}!1J}(Xwyc2&(R}2NzfCXIxK!!e0Jf^%>@n|O`E79$ii1ZT2#Tx35&K~iC3XT5^?|<*JVO3I zKpJ&UJp3>!UFy6Gr?_4TcGJ+XwKWum30`})7Im2LHe{oZEsNN!kTxYy00ySWudJS- z(megJ{`XtO4ZA8v%FErAV*6cdVQlTdF>n}p3BH2J_orlWzDByi0zqX*)pm&M(M#V{7?$1c9f111k^Z`Vn{ZGs5~8JOlN znhvNEmmzw!ah(FHXI9KPqa>uD3JJ9f93UtfnIk+=vT@Rt9C+GI=IX5{h$T%ST4Veb z*bi%Q>yWimf~*Tz*CC=oJGZ!qecVSKH?%E6|J#ccOJ156H|X^*iv2~(6mu82g^sw0 zd}{;Qr?6nTw3^V$0&AAG6;OgQY6+pUlOyw6D<+v|A}txC1^t_bFZ$Oq4=zJ(9YHN= z^a)LMlU_66Q!f}2QMAiwA|KOc+9_j%h~_!AiQo)*%Ai>Kl~=@v`w?miIU|%R;So^g z`TJMIY?0=G5)qk|s-H9<7N8^s8SI@1g;N zA|YKken>lzW1{71Z)oLXo|a9wjZH<6qOucIbqyNJT!`?dS2d35chzrvS$sr)VFA<< zD4gyjAT>s9gM)bH(#LucB~YeS03R`ez)AJt=SUe!P@8I|VYdS6n5I`Z)=z73yr2^; zrx%o}34>55%GN$$JaHY~dIQeVoK8y-xhuAuA`GKm>;AJ&31tKJOcRAcyw9jb{0p926X$lT&K{tcl8aJl7ns7Cop8 zR;PsWaF}kst&3<5M~eh~{wiI^@z=y{v;15jN)6mi5hkXwa-0gAPZhz5BS)6zmzPL( zTmnWKQ)xuw0pQHWe0IXyZZf@=HCGb6U+d!jy3KvJSU3H*U&p;90NgnZ31*lAJpday zSIYH`Ip93w#d+HN3nbl{ejp~WD%VZ zS(btA@FOh|Kd(^6DBVkJcDO}+C8E=0oBV56$vD|$vo}ok53h>ddiyuTjSRH|h4u&` zXp^IXf1^A{HIja?5>_X?BL0FWTrPf?tNAvn=7zJFLp$j;&7c1TEp&jV delta 63559 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 Date: Fri, 14 Jun 2024 10:34:24 +0800 Subject: [PATCH 28/34] fix upgrade --- core/src/runtime/record.rs | 1 - core/src/runtime/syscall.rs | 4 ++-- core/src/stark/air.rs | 1 + core/src/syscall/memcpy.rs | 41 +++++++++++++++++++++++++------------ 4 files changed, 31 insertions(+), 16 deletions(-) diff --git a/core/src/runtime/record.rs b/core/src/runtime/record.rs index e1aee10dbe..e0bf532a82 100644 --- a/core/src/runtime/record.rs +++ b/core/src/runtime/record.rs @@ -26,7 +26,6 @@ use crate::syscall::precompiles::uint256::Uint256MulEvent; use crate::syscall::precompiles::ECDecompressEvent; use crate::syscall::precompiles::{ECAddEvent, ECDoubleEvent}; use crate::syscall::MemCopyEvent; -use crate::utils::env; use crate::utils::SP1CoreOpts; /// A record of the execution of a program. Contains event data for everything that happened during diff --git a/core/src/runtime/syscall.rs b/core/src/runtime/syscall.rs index b6b4fd636b..513ed2a203 100644 --- a/core/src/runtime/syscall.rs +++ b/core/src/runtime/syscall.rs @@ -376,11 +376,11 @@ pub fn default_syscall_map() -> HashMap> { syscall_map.insert( SyscallCode::MEMCPY_32, - Rc::new(MemCopyChip::::new()), + Arc::new(MemCopyChip::::new()), ); syscall_map.insert( SyscallCode::MEMCPY_64, - Rc::new(MemCopyChip::::new()), + Arc::new(MemCopyChip::::new()), ); syscall_map diff --git a/core/src/stark/air.rs b/core/src/stark/air.rs index 802be9b453..49dad25e7f 100644 --- a/core/src/stark/air.rs +++ b/core/src/stark/air.rs @@ -7,6 +7,7 @@ use crate::StarkGenericConfig; use p3_field::PrimeField32; pub use riscv_chips::*; use tracing::instrument; +use typenum::{U16, U32, U64, U8}; /// A module for importing all the different RISC-V chips. pub(crate) mod riscv_chips { diff --git a/core/src/syscall/memcpy.rs b/core/src/syscall/memcpy.rs index 70178a8574..afd02ab996 100644 --- a/core/src/syscall/memcpy.rs +++ b/core/src/syscall/memcpy.rs @@ -9,6 +9,7 @@ use p3_matrix::{dense::RowMajorMatrix, Matrix}; use serde::{Deserialize, Serialize}; use sp1_derive::AlignedBorrow; +use crate::bytes::event::ByteRecord; use crate::operations::field::params::Limbs; use crate::utils::{limbs_from_access, limbs_from_prev_access}; use crate::{ @@ -23,18 +24,20 @@ use crate::{ #[derive(Clone, Debug, Serialize, Deserialize)] pub struct MemCopyEvent { pub shard: u32, + pub channel: u32, pub clk: u32, pub src_ptr: u32, pub dst_ptr: u32, - pub src_access: Vec, - pub dst_access: Vec, + pub read_records: Vec, + pub write_records: Vec, } #[derive(Debug, Clone, AlignedBorrow)] #[repr(C)] -pub struct MemCopyCols { +pub struct MemCopyCols { is_real: T, shard: T, + channel: T, clk: T, src_ptr: T, dst_ptr: T, @@ -42,11 +45,11 @@ pub struct MemCopyCols { dst_access: GenericArray, NumWords>, } -pub struct MemCopyChip { +pub struct MemCopyChip { _marker: PhantomData<(NumWords, NumBytes)>, } -impl MemCopyChip { +impl MemCopyChip { const NUM_COLS: usize = core::mem::size_of::>(); pub fn new() -> Self { @@ -70,7 +73,7 @@ impl MemCopyChip Syscall +impl Syscall for MemCopyChip { fn execute(&self, ctx: &mut crate::runtime::SyscallContext, src: u32, dst: u32) -> Option { @@ -79,11 +82,12 @@ impl Syscall let event = MemCopyEvent { shard: ctx.current_shard(), + channel: ctx.current_channel(), clk: ctx.clk, src_ptr: src, dst_ptr: dst, - src_access: read, - dst_access: write, + read_records: read, + write_records: write, }; ctx.record_mut() .memcpy_events @@ -97,8 +101,6 @@ impl Syscall impl MachineAir for MemCopyChip -where - [(); Self::NUM_COLS]:, { type Record = ExecutionRecord; @@ -113,20 +115,30 @@ where let mut new_byte_lookup_events = vec![]; for event in input.memcpy_events.get(&NumWords::USIZE).unwrap_or(&vec![]) { - let mut row = [F::zero(); Self::NUM_COLS]; + let mut row = Vec::with_capacity(Self::NUM_COLS); + row.resize(Self::NUM_COLS, F::zero()); let cols: &mut MemCopyCols = row.as_mut_slice().borrow_mut(); cols.is_real = F::one(); cols.shard = F::from_canonical_u32(event.shard); + cols.channel = F::from_canonical_u32(event.channel); cols.clk = F::from_canonical_u32(event.clk); cols.src_ptr = F::from_canonical_u32(event.src_ptr); cols.dst_ptr = F::from_canonical_u32(event.dst_ptr); for i in 0..NumWords::USIZE { - cols.src_access[i].populate(event.src_access[i], &mut new_byte_lookup_events); + cols.src_access[i].populate( + event.channel, + event.read_records[i], + &mut new_byte_lookup_events, + ); } for i in 0..NumWords::USIZE { - cols.dst_access[i].populate(event.dst_access[i], &mut new_byte_lookup_events); + cols.dst_access[i].populate( + event.channel, + event.write_records[i], + &mut new_byte_lookup_events, + ); } rows.push(row); @@ -171,6 +183,7 @@ impl Date: Fri, 14 Jun 2024 13:37:10 +0800 Subject: [PATCH 29/34] use self-hosted runner for pr ci --- .github/workflows/pr.yml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/pr.yml b/.github/workflows/pr.yml index 120f0e981d..f6abdf9b7c 100644 --- a/.github/workflows/pr.yml +++ b/.github/workflows/pr.yml @@ -26,7 +26,7 @@ concurrency: jobs: test-x86: name: Test (x86-64) - runs-on: runs-on,runner=64cpu-linux-x64 + runs-on: runs-on,runner=self-hosted-linux-x64 env: CARGO_NET_GIT_FETCH_WITH_CLI: "true" steps: @@ -57,7 +57,7 @@ jobs: test-arm: name: Test (ARM) - runs-on: runs-on,runner=64cpu-linux-arm64 + runs-on: runs-on,runner=self-hosted-linux-arm64 env: CARGO_NET_GIT_FETCH_WITH_CLI: "true" steps: @@ -88,7 +88,7 @@ jobs: lint: name: Formatting & Clippy - runs-on: runs-on,runner=8cpu-linux-x64 + runs-on: runs-on,runner=self-hosted-linux-x64 env: CARGO_NET_GIT_FETCH_WITH_CLI: "true" steps: @@ -116,7 +116,7 @@ jobs: examples: name: Examples - runs-on: runs-on,runner=8cpu-linux-x64 + runs-on: runs-on,runner=self-hosted-linux-x64 env: CARGO_NET_GIT_FETCH_WITH_CLI: "true" steps: @@ -145,7 +145,7 @@ jobs: cli: name: CLI - runs-on: runs-on,runner=8cpu-linux-x64 + runs-on: runs-on,runner=self-hosted-linux-x64 env: CARGO_NET_GIT_FETCH_WITH_CLI: "true" steps: From d455d690646a7c913b57e97ac77ed8ec65b21d46 Mon Sep 17 00:00:00 2001 From: kunxian xia Date: Fri, 14 Jun 2024 13:46:20 +0800 Subject: [PATCH 30/34] self-hosted runner --- .github/workflows/pr.yml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/pr.yml b/.github/workflows/pr.yml index f6abdf9b7c..6b90112212 100644 --- a/.github/workflows/pr.yml +++ b/.github/workflows/pr.yml @@ -26,7 +26,7 @@ concurrency: jobs: test-x86: name: Test (x86-64) - runs-on: runs-on,runner=self-hosted-linux-x64 + runs-on: [self-hosted, Linux, X64] env: CARGO_NET_GIT_FETCH_WITH_CLI: "true" steps: @@ -57,7 +57,7 @@ jobs: test-arm: name: Test (ARM) - runs-on: runs-on,runner=self-hosted-linux-arm64 + runs-on: runs-on,runner=64cpu-linux-arm64 env: CARGO_NET_GIT_FETCH_WITH_CLI: "true" steps: @@ -88,7 +88,7 @@ jobs: lint: name: Formatting & Clippy - runs-on: runs-on,runner=self-hosted-linux-x64 + runs-on: [self-hosted, Linux, X64] env: CARGO_NET_GIT_FETCH_WITH_CLI: "true" steps: @@ -116,7 +116,7 @@ jobs: examples: name: Examples - runs-on: runs-on,runner=self-hosted-linux-x64 + runs-on: [self-hosted, Linux, X64] env: CARGO_NET_GIT_FETCH_WITH_CLI: "true" steps: @@ -145,7 +145,7 @@ jobs: cli: name: CLI - runs-on: runs-on,runner=self-hosted-linux-x64 + runs-on: [self-hosted, Linux, X64] env: CARGO_NET_GIT_FETCH_WITH_CLI: "true" steps: From 30d29bc643a66574a876aff7bdd65c6da672a47b Mon Sep 17 00:00:00 2001 From: kunxian xia Date: Fri, 14 Jun 2024 14:21:56 +0800 Subject: [PATCH 31/34] fix --- core/src/syscall/precompiles/bn254_scalar/mod.rs | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/core/src/syscall/precompiles/bn254_scalar/mod.rs b/core/src/syscall/precompiles/bn254_scalar/mod.rs index e1cfef981e..48e33fcb7e 100644 --- a/core/src/syscall/precompiles/bn254_scalar/mod.rs +++ b/core/src/syscall/precompiles/bn254_scalar/mod.rs @@ -172,16 +172,15 @@ pub fn create_bn254_scalar_arith_event( #[cfg(test)] mod tests { use crate::{ - runtime::Program, - runtime::Runtime, - utils::{run_test, setup_logger, tests::BN254_SCALAR_ARITH_ELF}, + runtime::{Program, Runtime}, + utils::{run_test, setup_logger, tests::BN254_SCALAR_ARITH_ELF, SP1CoreOpts}, }; #[test] fn test_bn254_scalar_arith_simple() { setup_logger(); let program = Program::from(BN254_SCALAR_ARITH_ELF); - let mut rt = Runtime::new(program); + let mut rt = Runtime::new(program, SP1CoreOpts::default()); rt.run(); // run_test(program).unwrap(); } From ec58b04126269796a133aaee8d1bb2e72573cd1f Mon Sep 17 00:00:00 2001 From: kunxian xia Date: Fri, 14 Jun 2024 18:13:50 +0800 Subject: [PATCH 32/34] fix --- core/src/runtime/record.rs | 20 ++++++++++++++++++++ core/src/stark/air.rs | 5 ++--- core/src/syscall/memcpy.rs | 4 +++- 3 files changed, 25 insertions(+), 4 deletions(-) diff --git a/core/src/runtime/record.rs b/core/src/runtime/record.rs index e0bf532a82..ce7a884d5a 100644 --- a/core/src/runtime/record.rs +++ b/core/src/runtime/record.rs @@ -131,6 +131,7 @@ pub struct ShardingConfig { pub bls12381_double_len: usize, pub uint256_mul_len: usize, pub bn254_scalar_arith_len: usize, + pub memcpy_len: usize, } impl ShardingConfig { @@ -162,6 +163,7 @@ impl Default for ShardingConfig { bls12381_double_len: shard_size, uint256_mul_len: shard_size, bn254_scalar_arith_len: shard_size, + memcpy_len: shard_size, } } } @@ -254,6 +256,11 @@ impl MachineRecord for ExecutionRecord { "bn254_scalar_arith_events".to_string(), self.bn254_scalar_arith_events.len(), ); + + for (sz, events) in self.memcpy_events.iter() { + stats.insert(format!("memcpy{}_events", sz), events.len()); + } + stats } @@ -505,6 +512,19 @@ impl MachineRecord for ExecutionRecord { .extend_from_slice(bls12381_double_chunk); } + for (sz, events) in self.memcpy_events.iter_mut() { + for (memcpy_chunk, shard) in take(events) + .chunks_mut(config.memcpy_len) + .zip(shards.iter_mut()) + { + if let Some(events) = shard.memcpy_events.get_mut(sz) { + events.extend_from_slice(memcpy_chunk); + } else { + shard.memcpy_events.insert(*sz, memcpy_chunk.to_vec()); + } + } + } + for (bn254_scalar_arith_chunk, shard) in take(&mut self.bn254_scalar_arith_events) .chunks_mut(config.bn254_scalar_arith_len) .zip(shards.iter_mut()) diff --git a/core/src/stark/air.rs b/core/src/stark/air.rs index 49dad25e7f..dc4e73e772 100644 --- a/core/src/stark/air.rs +++ b/core/src/stark/air.rs @@ -186,11 +186,10 @@ impl RiscvAir { chips.push(RiscvAir::MemoryFinal(memory_finalize)); let program_memory_init = MemoryProgramChip::new(); chips.push(RiscvAir::ProgramMemory(program_memory_init)); - let byte = ByteChip::default(); - chips.push(RiscvAir::ByteLookup(byte)); - chips.push(RiscvAir::MemCpy32(MemCopyChip::new())); chips.push(RiscvAir::MemCpy64(MemCopyChip::new())); + let byte = ByteChip::default(); + chips.push(RiscvAir::ByteLookup(byte)); chips } diff --git a/core/src/syscall/memcpy.rs b/core/src/syscall/memcpy.rs index afd02ab996..9d46135861 100644 --- a/core/src/syscall/memcpy.rs +++ b/core/src/syscall/memcpy.rs @@ -11,7 +11,7 @@ use sp1_derive::AlignedBorrow; use crate::bytes::event::ByteRecord; use crate::operations::field::params::Limbs; -use crate::utils::{limbs_from_access, limbs_from_prev_access}; +use crate::utils::{limbs_from_access, limbs_from_prev_access, pad_rows}; use crate::{ air::MachineAir, memory::{MemoryReadCols, MemoryWriteCols}, @@ -145,6 +145,8 @@ impl>(), Self::NUM_COLS, From ad46cdf91674a2b64de74f70182a2bf3a8bf5464 Mon Sep 17 00:00:00 2001 From: kunxian xia Date: Fri, 14 Jun 2024 18:20:24 +0800 Subject: [PATCH 33/34] update elf --- .../program/elf/riscv32im-succinct-zkvm-elf | Bin 171748 -> 173620 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/examples/poseidon_bn254/program/elf/riscv32im-succinct-zkvm-elf b/examples/poseidon_bn254/program/elf/riscv32im-succinct-zkvm-elf index d1a08dc17b02a89a2ba86b4dc864b75650d86a23..52442a1ba73bb96c2dee05837287bb8be6ad79fe 100755 GIT binary patch delta 32860 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 Th`q#e`3nB8^y2*;HuwJnw}Yl^ delta 31232 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 RxY?CtR01y&{>?7${{z&6XsiGL From 1b558fe9064b648d233dc361d5a80ad41828d35d Mon Sep 17 00:00:00 2001 From: Zhang Zhuo Date: Thu, 27 Jun 2024 14:21:29 +0800 Subject: [PATCH 34/34] use 0 as bn254 scalar nonce. FIX later --- core/src/runtime/syscall.rs | 2 ++ core/src/syscall/memcpy.rs | 1 + core/src/syscall/precompiles/bn254_scalar/mac.rs | 1 + core/src/syscall/precompiles/bn254_scalar/mul.rs | 2 ++ 4 files changed, 6 insertions(+) diff --git a/core/src/runtime/syscall.rs b/core/src/runtime/syscall.rs index db78ad2166..20398863a3 100644 --- a/core/src/runtime/syscall.rs +++ b/core/src/runtime/syscall.rs @@ -467,6 +467,8 @@ mod tests { SyscallCode::BN254_SCALAR_MAC => { assert_eq!(code as u32, sp1_zkvm::syscalls::BN254_SCALAR_MAC) } + SyscallCode::MEMCPY_32 => todo!(), + SyscallCode::MEMCPY_64 => todo!(), } } } diff --git a/core/src/syscall/memcpy.rs b/core/src/syscall/memcpy.rs index 9d46135861..0547b46997 100644 --- a/core/src/syscall/memcpy.rs +++ b/core/src/syscall/memcpy.rs @@ -204,6 +204,7 @@ impl { shard: T, channel: T, clk: T, + nonce: T, p_ptr: T, q_ptr: T, p_access: [MemoryWriteCols; NUM_WORDS_PER_FE], @@ -210,6 +211,7 @@ where row.shard, row.channel, row.clk, + AB::F::from_canonical_u32(0u32), syscall_id, row.p_ptr, row.q_ptr,