From 54867af84f95c3cffb36a77d3d2a00b71ac101d7 Mon Sep 17 00:00:00 2001 From: Roman Walch <9820846+rw0x0@users.noreply.github.com> Date: Thu, 26 Sep 2024 16:00:24 +0200 Subject: [PATCH] feat: Make builder generic for both shares and plain, add shared proving key and start with MPC prover (#193) --- Cargo.toml | 2 + co-noir/co-acvm/Cargo.toml | 2 - co-noir/co-ultrahonk/Cargo.toml | 19 + co-noir/co-ultrahonk/src/lib.rs | 19 + .../src/parse/builder_variable.rs | 92 ++++ co-noir/co-ultrahonk/src/parse/mod.rs | 14 + co-noir/co-ultrahonk/src/parse/proving_key.rs | 134 ++++++ co-noir/co-ultrahonk/src/parse/types.rs | 128 ++++++ co-noir/co-ultrahonk/src/prelude.rs | 8 + co-noir/co-ultrahonk/src/prover.rs | 38 ++ co-noir/co-ultrahonk/src/types.rs | 101 +++++ co-noir/co-ultrahonk/tests/poseidon.rs | 36 ++ co-noir/ultrahonk/Cargo.toml | 4 +- co-noir/ultrahonk/src/decider/polynomial.rs | 88 ++-- co-noir/ultrahonk/src/decider/prover.rs | 6 +- .../decider/relations/auxiliary_relation.rs | 4 +- .../delta_range_constraint_relation.rs | 4 +- .../decider/relations/elliptic_relation.rs | 4 +- .../relations/logderiv_lookup_relation.rs | 4 +- .../ultrahonk/src/decider/relations/mod.rs | 4 +- .../decider/relations/permutation_relation.rs | 4 +- .../relations/poseidon2_external_relation.rs | 4 +- .../relations/poseidon2_internal_relation.rs | 4 +- .../relations/ultra_arithmetic_relation.rs | 4 +- co-noir/ultrahonk/src/decider/sumcheck/mod.rs | 6 +- .../ultrahonk/src/decider/sumcheck/prover.rs | 4 +- co-noir/ultrahonk/src/decider/types.rs | 42 +- co-noir/ultrahonk/src/decider/univariate.rs | 10 +- .../ultrahonk/src/decider/zeromorph/mod.rs | 8 +- .../ultrahonk/src/decider/zeromorph/prover.rs | 9 +- .../ultrahonk/src/decider/zeromorph/types.rs | 24 +- co-noir/ultrahonk/src/lib.rs | 125 ++++-- co-noir/ultrahonk/src/oink/prover.rs | 6 +- co-noir/ultrahonk/src/oink/types.rs | 26 +- co-noir/ultrahonk/src/parse/acir_format.rs | 4 +- co-noir/ultrahonk/src/parse/builder.rs | 148 ++++--- co-noir/ultrahonk/src/parse/mod.rs | 44 +- co-noir/ultrahonk/src/parse/plookup.rs | 6 +- co-noir/ultrahonk/src/parse/proving_key.rs | 205 +++------ co-noir/ultrahonk/src/parse/types.rs | 408 +++++++++++------- co-noir/ultrahonk/src/poseidon2/mod.rs | 20 +- .../src/poseidon2/poseidon2_bn254.rs | 192 ++++----- .../src/poseidon2/poseidon2_params.rs | 2 +- .../src/poseidon2/poseidon2_permutation.rs | 30 +- co-noir/ultrahonk/src/prelude.rs | 16 + co-noir/ultrahonk/src/sponge_hasher.rs | 15 +- co-noir/ultrahonk/src/transcript.rs | 16 +- co-noir/ultrahonk/src/types.rs | 158 ++++--- co-noir/ultrahonk/tests/poseidon.rs | 9 +- mpc-core/src/traits.rs | 3 +- 50 files changed, 1479 insertions(+), 784 deletions(-) create mode 100644 co-noir/co-ultrahonk/Cargo.toml create mode 100644 co-noir/co-ultrahonk/src/lib.rs create mode 100644 co-noir/co-ultrahonk/src/parse/builder_variable.rs create mode 100644 co-noir/co-ultrahonk/src/parse/mod.rs create mode 100644 co-noir/co-ultrahonk/src/parse/proving_key.rs create mode 100644 co-noir/co-ultrahonk/src/parse/types.rs create mode 100644 co-noir/co-ultrahonk/src/prelude.rs create mode 100644 co-noir/co-ultrahonk/src/prover.rs create mode 100644 co-noir/co-ultrahonk/src/types.rs create mode 100644 co-noir/co-ultrahonk/tests/poseidon.rs create mode 100644 co-noir/ultrahonk/src/prelude.rs diff --git a/Cargo.toml b/Cargo.toml index 454584f0..8600fc60 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -9,6 +9,7 @@ members = [ "co-circom/co-plonk", "co-noir/co-acvm", "co-noir/ultrahonk", + "co-noir/co-ultrahonk", "mpc-core", "mpc-net", "tests", @@ -85,6 +86,7 @@ tokio = { version = "1.34.0", features = [ toml = "0.8.13" tracing = { version = "0.1.40" } tracing-subscriber = "0.3" +ultrahonk = { version = "0.1.0", path = "co-noir/ultrahonk" } # This profile can be used for CI in pull requests. [profile.ci-dev] diff --git a/co-noir/co-acvm/Cargo.toml b/co-noir/co-acvm/Cargo.toml index f0117b8d..bf597acf 100644 --- a/co-noir/co-acvm/Cargo.toml +++ b/co-noir/co-acvm/Cargo.toml @@ -19,8 +19,6 @@ intmap.workspace = true mpc-core.workspace = true noirc-abi.workspace = true noirc-artifacts.workspace = true -num-bigint.workspace = true -num-traits.workspace = true thiserror.workspace = true tracing.workspace = true diff --git a/co-noir/co-ultrahonk/Cargo.toml b/co-noir/co-ultrahonk/Cargo.toml new file mode 100644 index 00000000..2482486d --- /dev/null +++ b/co-noir/co-ultrahonk/Cargo.toml @@ -0,0 +1,19 @@ +[package] +name = "co-ultrahonk" +version = "0.1.0" +publish.workspace = true +authors.workspace = true +edition.workspace = true +repository.workspace = true +homepage.workspace = true +license.workspace = true +rust-version.workspace = true + +[dependencies] +ark-ec.workspace = true +ark-ff.workspace = true +ark-bn254.workspace = true +eyre.workspace = true +mpc-core.workspace = true +tracing.workspace = true +ultrahonk.workspace = true diff --git a/co-noir/co-ultrahonk/src/lib.rs b/co-noir/co-ultrahonk/src/lib.rs new file mode 100644 index 00000000..ac756818 --- /dev/null +++ b/co-noir/co-ultrahonk/src/lib.rs @@ -0,0 +1,19 @@ +pub(crate) mod parse; +pub mod prelude; +pub(crate) mod prover; +pub(crate) mod types; + +use ark_ec::pairing::Pairing; +use mpc_core::protocols::plain::PlainDriver; +use parse::builder_variable::SharedBuilderVariable; + +impl SharedBuilderVariable, P> { + pub fn promote_public_witness_vector( + witness: Vec, + ) -> Vec, P>> { + witness + .into_iter() + .map(SharedBuilderVariable::Public) + .collect() + } +} diff --git a/co-noir/co-ultrahonk/src/parse/builder_variable.rs b/co-noir/co-ultrahonk/src/parse/builder_variable.rs new file mode 100644 index 00000000..8256d42c --- /dev/null +++ b/co-noir/co-ultrahonk/src/parse/builder_variable.rs @@ -0,0 +1,92 @@ +use ark_ec::pairing::Pairing; +use mpc_core::traits::PrimeFieldMpcProtocol; +use std::fmt::Debug; +use ultrahonk::prelude::UltraCircuitVariable; + +pub enum SharedBuilderVariable +where + P: Pairing, + T: PrimeFieldMpcProtocol, +{ + Public(P::ScalarField), + Shared(T::FieldShare), +} + +impl SharedBuilderVariable +where + P: Pairing, + T: PrimeFieldMpcProtocol, +{ + pub fn get_as_shared(&self, driver: &T) -> T::FieldShare { + match self { + SharedBuilderVariable::Public(value) => driver.promote_to_trivial_share(*value), + SharedBuilderVariable::Shared(value) => value.to_owned(), + } + } +} + +impl Clone for SharedBuilderVariable +where + P: Pairing, + T: PrimeFieldMpcProtocol, +{ + fn clone(&self) -> Self { + match self { + SharedBuilderVariable::Public(value) => Self::Public(*value), + SharedBuilderVariable::Shared(value) => Self::Shared(value.clone()), + } + } +} + +impl PartialEq for SharedBuilderVariable +where + P: Pairing, + T: PrimeFieldMpcProtocol, +{ + fn eq(&self, other: &Self) -> bool { + match (self, other) { + (SharedBuilderVariable::Public(a), SharedBuilderVariable::Public(b)) => a == b, + (SharedBuilderVariable::Shared(a), SharedBuilderVariable::Shared(b)) => a == b, + _ => false, + } + } +} + +impl Debug for SharedBuilderVariable +where + P: Pairing, + T: PrimeFieldMpcProtocol, +{ + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + SharedBuilderVariable::Public(value) => write!(f, "Public({:?})", value), + SharedBuilderVariable::Shared(value) => write!(f, "Shared({:?})", value), + } + } +} + +impl UltraCircuitVariable for SharedBuilderVariable +where + P: Pairing, + T: PrimeFieldMpcProtocol, +{ + type Shared = T::FieldShare; + + fn from_public(value: P::ScalarField) -> Self { + Self::Public(value) + } + + fn is_public(&self) -> bool { + match self { + SharedBuilderVariable::Public(_) => true, + SharedBuilderVariable::Shared(_) => false, + } + } + + fn public_into_field(self) -> P::ScalarField { + match self { + SharedBuilderVariable::Public(val) => val, + SharedBuilderVariable::Shared(_) => panic!("Expected public value"), + } + } +} diff --git a/co-noir/co-ultrahonk/src/parse/mod.rs b/co-noir/co-ultrahonk/src/parse/mod.rs new file mode 100644 index 00000000..deff3e4e --- /dev/null +++ b/co-noir/co-ultrahonk/src/parse/mod.rs @@ -0,0 +1,14 @@ +pub(crate) mod builder_variable; +pub(crate) mod proving_key; +pub(crate) mod types; + +use ark_ec::pairing::Pairing; +use builder_variable::SharedBuilderVariable; +use mpc_core::protocols::{plain::PlainDriver, rep3::Rep3Protocol}; +use ultrahonk::prelude::GenericUltraCircuitBuilder; + +pub type CoUltraCircuitBuilder = GenericUltraCircuitBuilder>; + +pub type PlainCoBuilder

= CoUltraCircuitBuilder::ScalarField>, P>; +pub type Rep3CoBuilder = + CoUltraCircuitBuilder::ScalarField, N>, P>; diff --git a/co-noir/co-ultrahonk/src/parse/proving_key.rs b/co-noir/co-ultrahonk/src/parse/proving_key.rs new file mode 100644 index 00000000..7a34693b --- /dev/null +++ b/co-noir/co-ultrahonk/src/parse/proving_key.rs @@ -0,0 +1,134 @@ +use super::CoUltraCircuitBuilder; +use crate::parse::types::TraceData; +use crate::types::Polynomials; +use crate::types::ProverWitnessEntities; +use crate::types::ProvingKey; +use ark_ec::pairing::Pairing; +use ark_ff::One; +use eyre::Result; +use mpc_core::traits::PrimeFieldMpcProtocol; +use std::marker::PhantomData; +use ultrahonk::prelude::ProverCrs; +use ultrahonk::prelude::ProvingKey as PlainProvingKey; +use ultrahonk::prelude::UltraCircuitVariable; + +impl ProvingKey +where + T: PrimeFieldMpcProtocol, +{ + const PUBLIC_INPUT_WIRE_INDEX: usize = + ProverWitnessEntities::::W_R; + + // We ignore the TraceStructure for now (it is None in barretenberg for UltraHonk) + pub fn create(driver: &T, mut circuit: CoUltraCircuitBuilder, crs: ProverCrs

) -> Self { + tracing::info!("ProvingKey create"); + circuit.add_gates_to_ensure_all_polys_are_non_zero(); + circuit.finalize_circuit(); + + let dyadic_circuit_size = circuit.compute_dyadic_size(); + let mut proving_key = Self::new(dyadic_circuit_size, circuit.public_inputs.len(), crs); + // Construct and add to proving key the wire, selector and copy constraint polynomials + proving_key.populate_trace(driver, &mut circuit, false); + + // First and last lagrange polynomials (in the full circuit size) + proving_key.polynomials.precomputed.lagrange_first_mut()[0] = P::ScalarField::one(); + proving_key.polynomials.precomputed.lagrange_last_mut()[dyadic_circuit_size - 1] = + P::ScalarField::one(); + + PlainProvingKey::construct_lookup_table_polynomials( + proving_key + .polynomials + .precomputed + .get_table_polynomials_mut(), + &circuit, + dyadic_circuit_size, + 0, + ); + PlainProvingKey::construct_lookup_read_counts( + proving_key + .polynomials + .witness + .lookup_read_counts_and_tags_mut() + .try_into() + .unwrap(), + &mut circuit, + dyadic_circuit_size, + ); + + // Construct the public inputs array + let block = circuit.blocks.get_pub_inputs(); + assert!(block.is_pub_inputs); + for var_idx in block.wires[Self::PUBLIC_INPUT_WIRE_INDEX] + .iter() + .take(proving_key.num_public_inputs as usize) + .cloned() + { + let var = circuit.get_variable(var_idx as usize); + proving_key.public_inputs.push(var.public_into_field()); + } + + // TODO the following elements are not part of the proving key so far + // Set the recursive proof indices + // proving_key.recursive_proof_public_input_indices = + // circuit.recursive_proof_public_input_indices; + // proving_key.contains_recursive_proof = circuit.contains_recursive_proof; + + proving_key + } + + pub fn get_prover_crs( + circuit: &CoUltraCircuitBuilder, + path_g1: &str, + ) -> Result> { + PlainProvingKey::get_prover_crs(circuit, path_g1) + } + + fn new(circuit_size: usize, num_public_inputs: usize, crs: ProverCrs

) -> Self { + tracing::info!("ProvingKey new"); + let polynomials = Polynomials::new(circuit_size); + + Self { + crs, + circuit_size: circuit_size as u32, + public_inputs: Vec::with_capacity(num_public_inputs), + num_public_inputs: num_public_inputs as u32, + pub_inputs_offset: 0, + polynomials, + memory_read_records: Vec::new(), + memory_write_records: Vec::new(), + phantom: PhantomData, + } + } + + fn populate_trace( + &mut self, + driver: &T, + builder: &mut CoUltraCircuitBuilder, + is_strucutred: bool, + ) { + tracing::info!("Populating trace"); + + let mut trace_data = TraceData::new(builder, self); + trace_data.construct_trace_data(driver, builder, is_strucutred); + + let ram_rom_offset = trace_data.ram_rom_offset; + let copy_cycles = trace_data.copy_cycles; + self.pub_inputs_offset = trace_data.pub_inputs_offset; + + PlainProvingKey::add_memory_records_to_proving_key( + ram_rom_offset, + builder, + &mut self.memory_read_records, + &mut self.memory_write_records, + ); + + // Compute the permutation argument polynomials (sigma/id) and add them to proving key + PlainProvingKey::compute_permutation_argument_polynomials( + &mut self.polynomials.precomputed, + builder, + copy_cycles, + self.circuit_size as usize, + self.pub_inputs_offset as usize, + ); + } +} diff --git a/co-noir/co-ultrahonk/src/parse/types.rs b/co-noir/co-ultrahonk/src/parse/types.rs new file mode 100644 index 00000000..c06f52ef --- /dev/null +++ b/co-noir/co-ultrahonk/src/parse/types.rs @@ -0,0 +1,128 @@ +use super::CoUltraCircuitBuilder; +use crate::types::ProvingKey; +use ark_ec::pairing::Pairing; +use mpc_core::traits::PrimeFieldMpcProtocol; +use ultrahonk::prelude::{CycleNode, CyclicPermutation, Polynomial, NUM_SELECTORS, NUM_WIRES}; + +pub(crate) struct TraceData<'a, T, P: Pairing> +where + T: PrimeFieldMpcProtocol, +{ + pub(crate) wires: [&'a mut Polynomial; NUM_WIRES], + pub(crate) selectors: [&'a mut Polynomial; NUM_SELECTORS], + pub(crate) copy_cycles: Vec, + pub(crate) ram_rom_offset: u32, + pub(crate) pub_inputs_offset: u32, +} + +impl<'a, T, P: Pairing> TraceData<'a, T, P> +where + T: PrimeFieldMpcProtocol, +{ + pub(crate) fn new( + builder: &CoUltraCircuitBuilder, + proving_key: &'a mut ProvingKey, + ) -> Self { + let mut iter = proving_key.polynomials.witness.get_wires_mut().iter_mut(); + let wires = [ + iter.next().unwrap(), + iter.next().unwrap(), + iter.next().unwrap(), + iter.next().unwrap(), + ]; + + let mut iter = proving_key + .polynomials + .precomputed + .get_selectors_mut() + .iter_mut(); + let selectors = [ + iter.next().unwrap(), + iter.next().unwrap(), + iter.next().unwrap(), + iter.next().unwrap(), + iter.next().unwrap(), + iter.next().unwrap(), + iter.next().unwrap(), + iter.next().unwrap(), + iter.next().unwrap(), + iter.next().unwrap(), + iter.next().unwrap(), + iter.next().unwrap(), + iter.next().unwrap(), + ]; + let copy_cycles = vec![vec![]; builder.variables.len()]; + + Self { + wires, + selectors, + copy_cycles, + ram_rom_offset: 0, + pub_inputs_offset: 0, + } + } + + pub(crate) fn construct_trace_data( + &mut self, + driver: &T, + builder: &mut CoUltraCircuitBuilder, + is_structured: bool, + ) { + tracing::info!("Construct trace data"); + // Complete the public inputs execution trace block from builder.public_inputs + builder.populate_public_inputs_block(); + + let mut offset = 1; // Offset at which to place each block in the trace polynomials + // For each block in the trace, populate wire polys, copy cycles and selector polys + + for block in builder.blocks.get() { + let block_size = block.len(); + + // Update wire polynomials and copy cycles + // NB: The order of row/column loops is arbitrary but needs to be row/column to match old copy_cycle code + + for block_row_idx in 0..block_size { + for wire_idx in 0..NUM_WIRES { + let var_idx = block.wires[wire_idx][block_row_idx] as usize; // an index into the variables array + let real_var_idx = builder.real_variable_index[var_idx] as usize; + let trace_row_idx = block_row_idx + offset; + // Insert the real witness values from this block into the wire polys at the correct offset + self.wires[wire_idx][trace_row_idx] = + builder.get_variable(var_idx).get_as_shared(driver); + // Add the address of the witness value to its corresponding copy cycle + self.copy_cycles[real_var_idx].push(CycleNode { + wire_index: wire_idx as u32, + gate_index: trace_row_idx as u32, + }); + } + } + + // Insert the selector values for this block into the selector polynomials at the correct offset + // TODO(https://github.com/AztecProtocol/barretenberg/issues/398): implicit arithmetization/flavor consistency + for (selector_poly, selector) in self.selectors.iter_mut().zip(block.selectors.iter()) { + debug_assert_eq!(selector.len(), block_size); + + for (src, des) in selector.iter().zip(selector_poly.iter_mut().skip(offset)) { + *des = *src; + } + } + + // Store the offset of the block containing RAM/ROM read/write gates for use in updating memory records + if block.has_ram_rom { + self.ram_rom_offset = offset as u32; + } + // Store offset of public inputs block for use in the pub(crate)input mechanism of the permutation argument + if block.is_pub_inputs { + self.pub_inputs_offset = offset as u32; + } + + // If the trace is structured, we populate the data from the next block at a fixed block size offset + if is_structured { + offset += block.get_fixed_size() as usize; + } else { + // otherwise, the next block starts immediately following the previous one + offset += block_size; + } + } + } +} diff --git a/co-noir/co-ultrahonk/src/prelude.rs b/co-noir/co-ultrahonk/src/prelude.rs new file mode 100644 index 00000000..eb989702 --- /dev/null +++ b/co-noir/co-ultrahonk/src/prelude.rs @@ -0,0 +1,8 @@ +pub use crate::parse::{ + builder_variable::SharedBuilderVariable, CoUltraCircuitBuilder, PlainCoBuilder, Rep3CoBuilder, +}; +pub use crate::prover::CoUltraHonk; +pub use crate::types::ProvingKey; +// Re-exporting the following traits from `ultrahonk`: +pub use ultrahonk::prelude::HonkProof; +pub use ultrahonk::Utils; diff --git a/co-noir/co-ultrahonk/src/prover.rs b/co-noir/co-ultrahonk/src/prover.rs new file mode 100644 index 00000000..7a33762e --- /dev/null +++ b/co-noir/co-ultrahonk/src/prover.rs @@ -0,0 +1,38 @@ +use crate::types::ProvingKey; +use mpc_core::traits::PrimeFieldMpcProtocol; +use std::marker::PhantomData; +use ultrahonk::prelude::{ + HonkCurve, HonkProof, HonkProofResult, TranscriptFieldType, TranscriptType, + POSEIDON2_BN254_T4_PARAMS, +}; + +pub struct CoUltraHonk> +where + T: PrimeFieldMpcProtocol, +{ + pub(crate) driver: T, + phantom_data: PhantomData

, +} + +impl> CoUltraHonk +where + T: PrimeFieldMpcProtocol, +{ + pub fn new(driver: T) -> Self { + Self { + driver, + phantom_data: PhantomData, + } + } + + pub fn prove( + &mut self, + proving_key: ProvingKey, + ) -> HonkProofResult> { + tracing::trace!("UltraHonk prove"); + + let mut transcript = TranscriptType::new(&POSEIDON2_BN254_T4_PARAMS); + + todo!("prove"); + } +} diff --git a/co-noir/co-ultrahonk/src/types.rs b/co-noir/co-ultrahonk/src/types.rs new file mode 100644 index 00000000..90254dad --- /dev/null +++ b/co-noir/co-ultrahonk/src/types.rs @@ -0,0 +1,101 @@ +use ark_ec::pairing::Pairing; +use mpc_core::traits::PrimeFieldMpcProtocol; +use std::marker::PhantomData; +use ultrahonk::prelude::{Polynomial, PrecomputedEntities, ProverCrs}; + +pub struct ProvingKey +where + T: PrimeFieldMpcProtocol, +{ + pub(crate) crs: ProverCrs

, + pub(crate) circuit_size: u32, + pub(crate) public_inputs: Vec, + pub(crate) num_public_inputs: u32, + pub(crate) pub_inputs_offset: u32, + pub(crate) polynomials: Polynomials, + pub(crate) memory_read_records: Vec, + pub(crate) memory_write_records: Vec, + pub(crate) phantom: PhantomData, +} + +// This is what we get from the proving key, we shift at a later point +#[derive(Default)] +pub(crate) struct Polynomials { + pub(crate) witness: ProverWitnessEntities, Polynomial>, + pub(crate) precomputed: PrecomputedEntities>, +} + +impl Polynomials { + pub(crate) fn new(circuit_size: usize) -> Self { + let mut polynomials = Self::default(); + // Shifting is done at a later point + polynomials + .witness + .get_wires_mut() + .iter_mut() + .for_each(|el| el.resize(circuit_size, Default::default())); + polynomials + .witness + .lookup_read_counts_and_tags_mut() + .iter_mut() + .for_each(|el| el.resize(circuit_size, Default::default())); + polynomials.precomputed.iter_mut().for_each(|el| { + el.resize(circuit_size, Default::default()); + }); + + polynomials + } +} + +const PROVER_PRIVATE_WITNESS_ENTITIES_SIZE: usize = 4; +const PROVER_PUBLIC_WITNESS_ENTITIES_SIZE: usize = 2; +#[derive(Default)] +pub(crate) struct ProverWitnessEntities { + pub(crate) private_elements: [Shared; PROVER_PRIVATE_WITNESS_ENTITIES_SIZE], + pub(crate) public_elements: [Public; PROVER_PUBLIC_WITNESS_ENTITIES_SIZE], +} + +impl ProverWitnessEntities { + const W_L: usize = 0; // column 0 + pub(crate) const W_R: usize = 1; // column 1 + const W_O: usize = 2; // column 2 + const W_4: usize = 3; // column 3 (modified by prover) + + const LOOKUP_READ_COUNTS: usize = 0; // column 6 + const LOOKUP_READ_TAGS: usize = 1; // column 7 + + // const Z_PERM: usize = 4; // column 4 (computed by prover) + // const LOOKUP_INVERSES: usize = 5; // column 5 (computed by prover); + + pub(crate) fn get_wires_mut(&mut self) -> &mut [Shared] { + &mut self.private_elements[Self::W_L..=Self::W_4] + } + + pub(crate) fn w_l(&self) -> &Shared { + &self.private_elements[Self::W_L] + } + + pub(crate) fn w_r(&self) -> &Shared { + &self.private_elements[Self::W_R] + } + + pub(crate) fn w_o(&self) -> &Shared { + &self.private_elements[Self::W_O] + } + + pub(crate) fn w_4(&self) -> &Shared { + &self.private_elements[Self::W_4] + } + + pub(crate) fn lookup_read_counts(&self) -> &Public { + &self.public_elements[Self::LOOKUP_READ_COUNTS] + } + + pub(crate) fn lookup_read_tags(&self) -> &Public { + &self.public_elements[Self::LOOKUP_READ_TAGS] + } + + pub(crate) fn lookup_read_counts_and_tags_mut(&mut self) -> &mut [Public] { + &mut self.public_elements[Self::LOOKUP_READ_COUNTS..Self::LOOKUP_READ_TAGS + 1] + } +} diff --git a/co-noir/co-ultrahonk/tests/poseidon.rs b/co-noir/co-ultrahonk/tests/poseidon.rs new file mode 100644 index 00000000..33b2878c --- /dev/null +++ b/co-noir/co-ultrahonk/tests/poseidon.rs @@ -0,0 +1,36 @@ +use ark_bn254::Bn254; +use co_ultrahonk::prelude::{CoUltraHonk, PlainCoBuilder, ProvingKey, SharedBuilderVariable}; +use mpc_core::protocols::plain::PlainDriver; +use ultrahonk::{prelude::HonkProof, Utils}; + +#[test] +fn poseidon_plaindriver_test() { + const CRS_PATH_G1: &str = "../ultrahonk/crs/bn254_g1.dat"; + // const CRS_PATH_G2: &str = "crs/bn254_g2.dat"; + const CIRCUIT_FILE: &str = "../../test_vectors/noir/poseidon/kat/poseidon.json"; + const WITNESS_FILE: &str = "../../test_vectors/noir/poseidon/kat/poseidon.gz"; + const PROOF_FILE: &str = "../../test_vectors/noir/poseidon/kat/poseidon.proof"; + + let constraint_system = Utils::get_constraint_system_from_file(CIRCUIT_FILE, true).unwrap(); + let witness = Utils::get_witness_from_file(WITNESS_FILE).unwrap(); + + let witness = SharedBuilderVariable::promote_public_witness_vector(witness); + + let builder = + PlainCoBuilder::::create_circuit(constraint_system, 0, witness, true, false); + + let driver = PlainDriver::default(); + + let prover_crs = ProvingKey::get_prover_crs(&builder, CRS_PATH_G1).unwrap(); + let proving_key = ProvingKey::create(&driver, builder, prover_crs); + + let mut prover = CoUltraHonk::new(driver); + let proof = prover.prove(proving_key).unwrap(); + let proof_u8 = proof.to_buffer(); + + let read_proof_u8 = std::fs::read(PROOF_FILE).unwrap(); + assert_eq!(proof_u8, read_proof_u8); + + let read_proof = HonkProof::from_buffer(&read_proof_u8).unwrap(); + assert_eq!(proof, read_proof); +} diff --git a/co-noir/ultrahonk/Cargo.toml b/co-noir/ultrahonk/Cargo.toml index 47b165c7..caac7761 100644 --- a/co-noir/ultrahonk/Cargo.toml +++ b/co-noir/ultrahonk/Cargo.toml @@ -11,10 +11,10 @@ rust-version.workspace = true [dependencies] acir.workspace = true +ark-bn254.workspace = true ark-ec.workspace = true ark-ff.workspace = true ark-serialize.workspace = true -ark-bn254.workspace = true byteorder.workspace = true eyre.workspace = true itertools.workspace = true @@ -25,4 +25,6 @@ num-traits.workspace = true serde_json.workspace = true tracing.workspace = true thiserror.workspace = true + +[dev-dependencies] rand.workspace = true diff --git a/co-noir/ultrahonk/src/decider/polynomial.rs b/co-noir/ultrahonk/src/decider/polynomial.rs index 961bd889..5807e7af 100644 --- a/co-noir/ultrahonk/src/decider/polynomial.rs +++ b/co-noir/ultrahonk/src/decider/polynomial.rs @@ -1,12 +1,12 @@ -use ark_ff::PrimeField; +use ark_ff::{PrimeField, Zero}; use std::ops::{AddAssign, Index, IndexMut}; #[derive(Clone, Debug, Default)] -pub struct Polynomial { +pub struct Polynomial { pub(crate) coefficients: Vec, } -pub struct ShiftedPoly<'a, F: PrimeField> { +pub struct ShiftedPoly<'a, F> { pub(crate) coefficients: &'a [F], zero: F, // TODO is there are better solution } @@ -21,7 +21,7 @@ impl<'a, F: PrimeField> ShiftedPoly<'a, F> { res } - pub fn as_ref(&self) -> &[F] { + pub(crate) fn as_ref(&self) -> &[F] { self.coefficients } } @@ -38,15 +38,21 @@ impl<'a, F: PrimeField> Index for ShiftedPoly<'a, F> { } } -impl Polynomial { - pub fn new(coefficients: Vec) -> Self { - Self { coefficients } +impl AsRef<[F]> for Polynomial { + fn as_ref(&self) -> &[F] { + &self.coefficients } +} - pub fn new_zero(size: usize) -> Self { - Self { - coefficients: vec![F::zero(); size], - } +impl AsMut<[F]> for Polynomial { + fn as_mut(&mut self) -> &mut [F] { + &mut self.coefficients + } +} + +impl Polynomial { + pub fn new(coefficients: Vec) -> Self { + Self { coefficients } } pub fn iter(&self) -> impl Iterator { @@ -57,10 +63,30 @@ impl Polynomial { self.coefficients.iter_mut() } + pub fn is_empty(&self) -> bool { + self.coefficients.is_empty() + } + pub fn len(&self) -> usize { self.coefficients.len() } + pub fn resize(&mut self, size: usize, value: F) { + self.coefficients.resize(size, value); + } + + pub fn into_vec(self) -> Vec { + self.coefficients + } +} + +impl Polynomial { + pub fn new_zero(size: usize) -> Self { + Self { + coefficients: vec![F::zero(); size], + } + } + pub fn degree(&self) -> usize { let mut len = self.coefficients.len() - 1; for c in self.coefficients.iter().rev() { @@ -73,26 +99,22 @@ impl Polynomial { len } - pub fn as_ref(&self) -> &[F] { - &self.coefficients - } - - pub fn as_mut(&mut self) -> &mut [F] { - &mut self.coefficients - } - - pub fn resize(&mut self, size: usize, value: F) { - self.coefficients.resize(size, value); - } - - pub fn into_vec(self) -> Vec { - self.coefficients + // Can only shift by 1 + pub fn shifted(&self) -> ShiftedPoly { + assert!(!self.coefficients.is_empty()); + assert!(self.coefficients[0].is_zero()); + ShiftedPoly { + coefficients: &self.coefficients[1..], + zero: F::zero(), + } } +} +impl Polynomial { /** * @brief Divides p(X) by (X-r) in-place. */ - pub fn factor_roots(&mut self, root: &F) { + pub(crate) fn factor_roots(&mut self, root: &F) { if root.is_zero() { // if one of the roots is 0 after having divided by all other roots, // then p(X) = a₁⋅X + ⋯ + aₙ₋₁⋅Xⁿ⁻¹ @@ -151,19 +173,9 @@ impl Polynomial { pub(crate) fn add_scaled(&mut self, src: &Polynomial, scalar: &F) { self.add_scaled_slice(&src.coefficients, scalar); } - - // Can only shift by 1 - pub(crate) fn shifted(&self) -> ShiftedPoly { - assert!(!self.coefficients.is_empty()); - assert!(self.coefficients[0].is_zero()); - ShiftedPoly { - coefficients: &self.coefficients[1..], - zero: F::zero(), - } - } } -impl Index for Polynomial { +impl Index for Polynomial { type Output = F; fn index(&self, index: usize) -> &Self::Output { @@ -171,7 +183,7 @@ impl Index for Polynomial { } } -impl IndexMut for Polynomial { +impl IndexMut for Polynomial { fn index_mut(&mut self, index: usize) -> &mut Self::Output { &mut self.coefficients[index] } diff --git a/co-noir/ultrahonk/src/decider/prover.rs b/co-noir/ultrahonk/src/decider/prover.rs index 4f164a1a..d6c336f0 100644 --- a/co-noir/ultrahonk/src/decider/prover.rs +++ b/co-noir/ultrahonk/src/decider/prover.rs @@ -7,13 +7,13 @@ use crate::{ }; use std::marker::PhantomData; -pub struct Decider> { +pub(crate) struct Decider> { pub(super) memory: ProverMemory

, phantom_data: PhantomData

, } impl> Decider

{ - pub fn new(memory: ProverMemory

) -> Self { + pub(crate) fn new(memory: ProverMemory

) -> Self { Self { memory, phantom_data: PhantomData, @@ -70,7 +70,7 @@ impl> Decider

{ Self::compute_opening_proof(prover_opening_claim, transcript, crs) } - pub fn prove( + pub(crate) fn prove( mut self, circuit_size: u32, crs: &ProverCrs

, diff --git a/co-noir/ultrahonk/src/decider/relations/auxiliary_relation.rs b/co-noir/ultrahonk/src/decider/relations/auxiliary_relation.rs index 4f7cb29e..100df2df 100644 --- a/co-noir/ultrahonk/src/decider/relations/auxiliary_relation.rs +++ b/co-noir/ultrahonk/src/decider/relations/auxiliary_relation.rs @@ -31,7 +31,7 @@ pub(crate) struct AuxiliaryRelationAcc { } impl AuxiliaryRelationAcc { - pub fn scale(&mut self, elements: &[F]) { + pub(crate) fn scale(&mut self, elements: &[F]) { assert!(elements.len() == AuxiliaryRelation::NUM_RELATIONS); self.r0 *= elements[0]; self.r1 *= elements[1]; @@ -41,7 +41,7 @@ impl AuxiliaryRelationAcc { self.r5 *= elements[5]; } - pub fn extend_and_batch_univariates( + pub(crate) fn extend_and_batch_univariates( &self, result: &mut SumcheckRoundOutput, extended_random_poly: &SumcheckRoundOutput, diff --git a/co-noir/ultrahonk/src/decider/relations/delta_range_constraint_relation.rs b/co-noir/ultrahonk/src/decider/relations/delta_range_constraint_relation.rs index def95b1a..397dbc6d 100644 --- a/co-noir/ultrahonk/src/decider/relations/delta_range_constraint_relation.rs +++ b/co-noir/ultrahonk/src/decider/relations/delta_range_constraint_relation.rs @@ -15,7 +15,7 @@ pub(crate) struct DeltaRangeConstraintRelationAcc { } impl DeltaRangeConstraintRelationAcc { - pub fn scale(&mut self, elements: &[F]) { + pub(crate) fn scale(&mut self, elements: &[F]) { assert!(elements.len() == DeltaRangeConstraintRelation::NUM_RELATIONS); self.r0 *= elements[0]; self.r1 *= elements[1]; @@ -23,7 +23,7 @@ impl DeltaRangeConstraintRelationAcc { self.r3 *= elements[3]; } - pub fn extend_and_batch_univariates( + pub(crate) fn extend_and_batch_univariates( &self, result: &mut SumcheckRoundOutput, extended_random_poly: &SumcheckRoundOutput, diff --git a/co-noir/ultrahonk/src/decider/relations/elliptic_relation.rs b/co-noir/ultrahonk/src/decider/relations/elliptic_relation.rs index 0552c587..58fd3731 100644 --- a/co-noir/ultrahonk/src/decider/relations/elliptic_relation.rs +++ b/co-noir/ultrahonk/src/decider/relations/elliptic_relation.rs @@ -12,13 +12,13 @@ pub(crate) struct EllipticRelationAcc { } impl EllipticRelationAcc { - pub fn scale(&mut self, elements: &[F]) { + pub(crate) fn scale(&mut self, elements: &[F]) { assert!(elements.len() == EllipticRelation::NUM_RELATIONS); self.r0 *= elements[0]; self.r1 *= elements[1]; } - pub fn extend_and_batch_univariates( + pub(crate) fn extend_and_batch_univariates( &self, result: &mut SumcheckRoundOutput, extended_random_poly: &SumcheckRoundOutput, diff --git a/co-noir/ultrahonk/src/decider/relations/logderiv_lookup_relation.rs b/co-noir/ultrahonk/src/decider/relations/logderiv_lookup_relation.rs index 870f7efb..fa198a4b 100644 --- a/co-noir/ultrahonk/src/decider/relations/logderiv_lookup_relation.rs +++ b/co-noir/ultrahonk/src/decider/relations/logderiv_lookup_relation.rs @@ -13,13 +13,13 @@ pub(crate) struct LogDerivLookupRelationAcc { } impl LogDerivLookupRelationAcc { - pub fn scale(&mut self, elements: &[F]) { + pub(crate) fn scale(&mut self, elements: &[F]) { assert!(elements.len() == LogDerivLookupRelation::NUM_RELATIONS); self.r0 *= elements[0]; self.r1 *= elements[1]; } - pub fn extend_and_batch_univariates( + pub(crate) fn extend_and_batch_univariates( &self, result: &mut SumcheckRoundOutput, extended_random_poly: &SumcheckRoundOutput, diff --git a/co-noir/ultrahonk/src/decider/relations/mod.rs b/co-noir/ultrahonk/src/decider/relations/mod.rs index 64d0fe1e..be646759 100644 --- a/co-noir/ultrahonk/src/decider/relations/mod.rs +++ b/co-noir/ultrahonk/src/decider/relations/mod.rs @@ -64,7 +64,7 @@ pub(crate) struct AllRelationAcc { } impl AllRelationAcc { - pub fn scale(&mut self, first_scalar: F, elements: &[F]) { + pub(crate) fn scale(&mut self, first_scalar: F, elements: &[F]) { assert!(elements.len() == NUM_SUBRELATIONS - 1); self.r_arith.scale(&[first_scalar, elements[0]]); self.r_perm.scale(&elements[1..3]); @@ -76,7 +76,7 @@ impl AllRelationAcc { self.r_pos_int.scale(&elements[21..]); } - pub fn extend_and_batch_univariates( + pub(crate) fn extend_and_batch_univariates( &self, result: &mut SumcheckRoundOutput, extended_random_poly: &SumcheckRoundOutput, diff --git a/co-noir/ultrahonk/src/decider/relations/permutation_relation.rs b/co-noir/ultrahonk/src/decider/relations/permutation_relation.rs index ccdb225a..11aa4433 100644 --- a/co-noir/ultrahonk/src/decider/relations/permutation_relation.rs +++ b/co-noir/ultrahonk/src/decider/relations/permutation_relation.rs @@ -13,13 +13,13 @@ pub(crate) struct UltraPermutationRelationAcc { } impl UltraPermutationRelationAcc { - pub fn scale(&mut self, elements: &[F]) { + pub(crate) fn scale(&mut self, elements: &[F]) { assert!(elements.len() == UltraPermutationRelation::NUM_RELATIONS); self.r0 *= elements[0]; self.r1 *= elements[1]; } - pub fn extend_and_batch_univariates( + pub(crate) fn extend_and_batch_univariates( &self, result: &mut SumcheckRoundOutput, extended_random_poly: &SumcheckRoundOutput, diff --git a/co-noir/ultrahonk/src/decider/relations/poseidon2_external_relation.rs b/co-noir/ultrahonk/src/decider/relations/poseidon2_external_relation.rs index 4f8d8f11..74d0343c 100644 --- a/co-noir/ultrahonk/src/decider/relations/poseidon2_external_relation.rs +++ b/co-noir/ultrahonk/src/decider/relations/poseidon2_external_relation.rs @@ -15,7 +15,7 @@ pub(crate) struct Poseidon2ExternalRelationAcc { } impl Poseidon2ExternalRelationAcc { - pub fn scale(&mut self, elements: &[F]) { + pub(crate) fn scale(&mut self, elements: &[F]) { assert!(elements.len() == Poseidon2ExternalRelation::NUM_RELATIONS); self.r0 *= elements[0]; self.r1 *= elements[1]; @@ -23,7 +23,7 @@ impl Poseidon2ExternalRelationAcc { self.r3 *= elements[3]; } - pub fn extend_and_batch_univariates( + pub(crate) fn extend_and_batch_univariates( &self, result: &mut SumcheckRoundOutput, extended_random_poly: &SumcheckRoundOutput, diff --git a/co-noir/ultrahonk/src/decider/relations/poseidon2_internal_relation.rs b/co-noir/ultrahonk/src/decider/relations/poseidon2_internal_relation.rs index 74739d9a..073e0701 100644 --- a/co-noir/ultrahonk/src/decider/relations/poseidon2_internal_relation.rs +++ b/co-noir/ultrahonk/src/decider/relations/poseidon2_internal_relation.rs @@ -19,7 +19,7 @@ pub(crate) struct Poseidon2InternalRelationAcc { } impl Poseidon2InternalRelationAcc { - pub fn scale(&mut self, elements: &[F]) { + pub(crate) fn scale(&mut self, elements: &[F]) { assert!(elements.len() == Poseidon2InternalRelation::NUM_RELATIONS); self.r0 *= elements[0]; self.r1 *= elements[1]; @@ -27,7 +27,7 @@ impl Poseidon2InternalRelationAcc { self.r3 *= elements[3]; } - pub fn extend_and_batch_univariates( + pub(crate) fn extend_and_batch_univariates( &self, result: &mut SumcheckRoundOutput, extended_random_poly: &SumcheckRoundOutput, diff --git a/co-noir/ultrahonk/src/decider/relations/ultra_arithmetic_relation.rs b/co-noir/ultrahonk/src/decider/relations/ultra_arithmetic_relation.rs index ff1bc828..a463afc6 100644 --- a/co-noir/ultrahonk/src/decider/relations/ultra_arithmetic_relation.rs +++ b/co-noir/ultrahonk/src/decider/relations/ultra_arithmetic_relation.rs @@ -13,13 +13,13 @@ pub(crate) struct UltraArithmeticRelationAcc { } impl UltraArithmeticRelationAcc { - pub fn scale(&mut self, elements: &[F]) { + pub(crate) fn scale(&mut self, elements: &[F]) { assert!(elements.len() == UltraArithmeticRelation::NUM_RELATIONS); self.r0 *= elements[0]; self.r1 *= elements[1]; } - pub fn extend_and_batch_univariates( + pub(crate) fn extend_and_batch_univariates( &self, result: &mut SumcheckRoundOutput, extended_random_poly: &SumcheckRoundOutput, diff --git a/co-noir/ultrahonk/src/decider/sumcheck/mod.rs b/co-noir/ultrahonk/src/decider/sumcheck/mod.rs index e0a3b688..c0093ec1 100644 --- a/co-noir/ultrahonk/src/decider/sumcheck/mod.rs +++ b/co-noir/ultrahonk/src/decider/sumcheck/mod.rs @@ -1,10 +1,10 @@ -pub mod prover; -pub mod sumcheck_round; +pub(crate) mod prover; +pub(crate) mod sumcheck_round; use super::types::ClaimedEvaluations; use ark_ff::PrimeField; -pub struct SumcheckOutput { +pub(crate) struct SumcheckOutput { pub(crate) claimed_evaluations: ClaimedEvaluations, pub(crate) challenges: Vec, } diff --git a/co-noir/ultrahonk/src/decider/sumcheck/prover.rs b/co-noir/ultrahonk/src/decider/sumcheck/prover.rs index 9b047160..f78cf2d6 100644 --- a/co-noir/ultrahonk/src/decider/sumcheck/prover.rs +++ b/co-noir/ultrahonk/src/decider/sumcheck/prover.rs @@ -5,7 +5,7 @@ use crate::decider::types::{ClaimedEvaluations, GateSeparatorPolynomial, Partial use crate::honk_curve::HonkCurve; use crate::transcript::{TranscriptFieldType, TranscriptType}; use crate::types::AllEntities; -use crate::{get_msb64, CONST_PROOF_SIZE_LOG_N}; +use crate::{Utils, CONST_PROOF_SIZE_LOG_N}; // Keep in mind, the UltraHonk protocol (UltraFlavor) does not per default have ZK impl> Decider

{ @@ -75,7 +75,7 @@ impl> Decider

{ tracing::trace!("Sumcheck prove"); let multivariate_n = circuit_size; - let multivariate_d = get_msb64(multivariate_n as u64); + let multivariate_d = Utils::get_msb64(multivariate_n as u64); let mut sum_check_round = SumcheckRound::new(multivariate_n as usize); diff --git a/co-noir/ultrahonk/src/decider/types.rs b/co-noir/ultrahonk/src/decider/types.rs index df41e855..426155b5 100644 --- a/co-noir/ultrahonk/src/decider/types.rs +++ b/co-noir/ultrahonk/src/decider/types.rs @@ -8,28 +8,28 @@ use ark_ff::PrimeField; use itertools::izip; use std::{iter, vec}; -pub struct ProverMemory { - pub polys: AllEntities>, - pub relation_parameters: RelationParameters, +pub(crate) struct ProverMemory { + pub(crate) polys: AllEntities>, + pub(crate) relation_parameters: RelationParameters, } -pub const MAX_PARTIAL_RELATION_LENGTH: usize = 7; -pub type ProverUnivariates = AllEntities>; -pub type PartiallyEvaluatePolys = AllEntities>; -pub type ClaimedEvaluations = AllEntities; - -pub struct RelationParameters { - pub eta_1: F, - pub eta_2: F, - pub eta_3: F, - pub beta: F, - pub gamma: F, - pub public_input_delta: F, - pub alphas: [F; NUM_ALPHAS], - pub gate_challenges: Vec, +pub(crate) const MAX_PARTIAL_RELATION_LENGTH: usize = 7; +pub(crate) type ProverUnivariates = AllEntities>; +pub(crate) type PartiallyEvaluatePolys = AllEntities>; +pub(crate) type ClaimedEvaluations = AllEntities; + +pub(crate) struct RelationParameters { + pub(crate) eta_1: F, + pub(crate) eta_2: F, + pub(crate) eta_3: F, + pub(crate) beta: F, + pub(crate) gamma: F, + pub(crate) public_input_delta: F, + pub(crate) alphas: [F; NUM_ALPHAS], + pub(crate) gate_challenges: Vec, } -pub struct GateSeparatorPolynomial { +pub(crate) struct GateSeparatorPolynomial { betas: Vec, pub(crate) beta_products: Vec, pub(crate) partial_evaluation_result: F, @@ -38,7 +38,7 @@ pub struct GateSeparatorPolynomial { } impl GateSeparatorPolynomial { - pub fn new(betas: Vec) -> Self { + pub(crate) fn new(betas: Vec) -> Self { let pow_size = 1 << betas.len(); let current_element_idx = 0; let periodicity = 2; @@ -63,11 +63,11 @@ impl GateSeparatorPolynomial { } } - pub fn current_element(&self) -> F { + pub(crate) fn current_element(&self) -> F { self.betas[self.current_element_idx] } - pub fn partially_evaluate(&mut self, round_challenge: F) { + pub(crate) fn partially_evaluate(&mut self, round_challenge: F) { let current_univariate_eval = F::ONE + (round_challenge * (self.betas[self.current_element_idx] - F::ONE)); self.partial_evaluation_result *= current_univariate_eval; diff --git a/co-noir/ultrahonk/src/decider/univariate.rs b/co-noir/ultrahonk/src/decider/univariate.rs index 735d6613..156e1a92 100644 --- a/co-noir/ultrahonk/src/decider/univariate.rs +++ b/co-noir/ultrahonk/src/decider/univariate.rs @@ -4,30 +4,30 @@ use std::ops::{Add, AddAssign, Mul, MulAssign, Neg, Sub, SubAssign}; use crate::decider::barycentric::Barycentric; #[derive(Clone, Debug)] -pub struct Univariate { +pub(crate) struct Univariate { pub(crate) evaluations: [F; SIZE], } impl Univariate { - pub fn double(self) -> Self { + pub(crate) fn double(self) -> Self { let mut result = self; result.double_in_place(); result } - pub fn double_in_place(&mut self) { + pub(crate) fn double_in_place(&mut self) { for i in 0..SIZE { self.evaluations[i].double_in_place(); } } - pub fn sqr(self) -> Self { + pub(crate) fn sqr(self) -> Self { let mut result = self; result.square_in_place(); result } - pub fn square_in_place(&mut self) { + pub(crate) fn square_in_place(&mut self) { for i in 0..SIZE { self.evaluations[i].square_in_place(); } diff --git a/co-noir/ultrahonk/src/decider/zeromorph/mod.rs b/co-noir/ultrahonk/src/decider/zeromorph/mod.rs index 41543197..adf1df4b 100644 --- a/co-noir/ultrahonk/src/decider/zeromorph/mod.rs +++ b/co-noir/ultrahonk/src/decider/zeromorph/mod.rs @@ -1,15 +1,15 @@ -pub mod prover; -pub mod types; +pub(crate) mod prover; +pub(crate) mod types; use super::polynomial::Polynomial; use ark_ff::PrimeField; -pub struct ZeroMorphOpeningClaim { +pub(crate) struct ZeroMorphOpeningClaim { pub(crate) polynomial: Polynomial, pub(crate) opening_pair: OpeningPair, } -pub struct OpeningPair { +pub(crate) struct OpeningPair { pub(crate) challenge: F, pub(crate) evaluation: F, } diff --git a/co-noir/ultrahonk/src/decider/zeromorph/prover.rs b/co-noir/ultrahonk/src/decider/zeromorph/prover.rs index 5837b553..13270063 100644 --- a/co-noir/ultrahonk/src/decider/zeromorph/prover.rs +++ b/co-noir/ultrahonk/src/decider/zeromorph/prover.rs @@ -5,12 +5,11 @@ use super::{ }; use crate::{ decider::{polynomial::Polynomial, types::ClaimedEvaluations, zeromorph::OpeningPair}, - get_msb64, honk_curve::HonkCurve, prover::HonkProofResult, transcript::{TranscriptFieldType, TranscriptType}, types::{AllEntities, ProverCrs}, - CONST_PROOF_SIZE_LOG_N, N_MAX, + Utils, CONST_PROOF_SIZE_LOG_N, N_MAX, }; use ark_ec::Group; use ark_ff::{Field, One, Zero}; @@ -41,7 +40,7 @@ impl> Decider

{ polynomial: &Polynomial, u_challenge: &[P::ScalarField], ) -> Vec> { - let log_n = get_msb64(polynomial.len() as u64); + let log_n = Utils::get_msb64(polynomial.len() as u64); // Define the vector of quotients q_k, k = 0, ..., log_N-1 // let mut quotients = Vec::with_capacity(log_n as usize); let mut quotients = vec![Polynomial::default(); log_n as usize]; @@ -354,7 +353,7 @@ impl> Decider

{ // Extract multilinear challenge u and claimed multilinear evaluations from Sumcheck output let u_challenge = multilinear_challenge; - let log_n = crate::get_msb32(circuit_size); + let log_n = Utils::get_msb32(circuit_size); let n = 1 << log_n; // Compute batching of unshifted polynomials f_i and to-be-shifted polynomials g_i: @@ -410,7 +409,7 @@ impl> Decider

{ // Compute the batched, lifted-degree quotient \hat{q} let batched_quotient = - Self::compute_batched_lifted_degree_quotient("ients, &y_challenge, n as usize); + Self::compute_batched_lifted_degree_quotient("ients, &y_challenge, n); // Compute and send the commitment C_q = [\hat{q}] let q_commitment = crate::commit(&batched_quotient.coefficients, commitment_key)?; diff --git a/co-noir/ultrahonk/src/decider/zeromorph/types.rs b/co-noir/ultrahonk/src/decider/zeromorph/types.rs index 79610310..05ef2a3e 100644 --- a/co-noir/ultrahonk/src/decider/zeromorph/types.rs +++ b/co-noir/ultrahonk/src/decider/zeromorph/types.rs @@ -20,7 +20,7 @@ pub(crate) struct PolyGShift<'a, T: Default> { #[allow(unused)] impl<'a, T: Default> PolyF<'a, T> { - pub fn iter(&self) -> impl Iterator { + pub(crate) fn iter(&self) -> impl Iterator { self.precomputed.iter().chain(self.witness.iter()) } } @@ -39,53 +39,53 @@ impl<'a, T: Default> PolyG<'a, T> { const W_O: usize = 2; const W_4: usize = 3; - pub fn iter(&self) -> impl Iterator { + pub(crate) fn iter(&self) -> impl Iterator { self.tables .into_iter() .chain(self.wires) .chain(std::iter::once(self.z_perm)) } - pub fn table_1(&self) -> &T { + pub(crate) fn table_1(&self) -> &T { self.tables[Self::TABLE_1] } - pub fn table_2(&self) -> &T { + pub(crate) fn table_2(&self) -> &T { self.tables[Self::TABLE_2] } - pub fn table_3(&self) -> &T { + pub(crate) fn table_3(&self) -> &T { self.tables[Self::TABLE_3] } - pub fn table_4(&self) -> &T { + pub(crate) fn table_4(&self) -> &T { self.tables[Self::TABLE_4] } - pub fn w_l(&self) -> &T { + pub(crate) fn w_l(&self) -> &T { self.wires[Self::W_L] } - pub fn w_r(&self) -> &T { + pub(crate) fn w_r(&self) -> &T { self.wires[Self::W_R] } - pub fn w_o(&self) -> &T { + pub(crate) fn w_o(&self) -> &T { self.wires[Self::W_O] } - pub fn w_4(&self) -> &T { + pub(crate) fn w_4(&self) -> &T { self.wires[Self::W_4] } - pub fn z_perm(&self) -> &T { + pub(crate) fn z_perm(&self) -> &T { self.z_perm } } #[allow(unused)] impl<'a, T: Default> PolyGShift<'a, T> { - pub fn iter(&self) -> impl Iterator { + pub(crate) fn iter(&self) -> impl Iterator { self.tables.iter().chain(self.wires.iter()) } } diff --git a/co-noir/ultrahonk/src/lib.rs b/co-noir/ultrahonk/src/lib.rs index 866b07ce..0e7eaac7 100644 --- a/co-noir/ultrahonk/src/lib.rs +++ b/co-noir/ultrahonk/src/lib.rs @@ -1,50 +1,111 @@ pub(crate) mod decider; -pub mod honk_curve; +pub(crate) mod honk_curve; pub(crate) mod oink; -pub mod parse; +pub(crate) mod parse; pub(crate) mod poseidon2; -pub mod prover; +pub mod prelude; +pub(crate) mod prover; pub(crate) mod sponge_hasher; mod transcript; -pub mod types; +pub(crate) mod types; +use acir::{circuit::Circuit, native_types::WitnessStack, FieldElement}; use ark_ec::{pairing::Pairing, VariableBaseMSM}; use ark_ff::PrimeField; +use eyre::Error; use itertools::izip; +use noirc_artifacts::program::ProgramArtifact; +use num_bigint::BigUint; +use num_traits::Num; +use prelude::AcirFormat; use prover::{HonkProofError, HonkProofResult}; +use std::io; use types::ProverCrs; -// from http://supertech.csail.mit.edu/papers/debruijn.pdf -pub(crate) fn get_msb32(inp: u32) -> u8 { - const MULTIPLY_DE_BRUIJNI_BIT_POSIITION: [u8; 32] = [ - 0, 9, 1, 10, 13, 21, 2, 29, 11, 14, 16, 18, 22, 25, 3, 30, 8, 12, 20, 28, 15, 17, 24, 7, - 19, 27, 23, 6, 26, 5, 4, 31, - ]; +pub struct Utils {} - let mut v = inp | (inp >> 1); - v |= v >> 2; - v |= v >> 4; - v |= v >> 8; - v |= v >> 16; +impl Utils { + pub(crate) fn field_from_hex_string(str: &str) -> Result { + let tmp = match str.strip_prefix("0x") { + Some(t) => BigUint::from_str_radix(t, 16), + None => BigUint::from_str_radix(str, 16), + }; - MULTIPLY_DE_BRUIJNI_BIT_POSIITION[((v.wrapping_mul(0x07C4ACDD)) >> 27) as usize] -} + Ok(tmp?.into()) + } + + fn read_circuit_from_file(path: &str) -> io::Result> { + let program = std::fs::read_to_string(path)?; + let program_artifact = serde_json::from_str::(&program)?; + Ok(program_artifact.bytecode.functions[0].to_owned()) + } + + fn read_witness_stack_from_file(path: &str) -> io::Result> { + let witness_stack = std::fs::read(path)?; + WitnessStack::try_from(witness_stack.as_slice()) + .map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e)) + } + + pub fn get_constraint_system_from_file( + path: &str, + honk_recusion: bool, + ) -> io::Result> { + let circuit = Self::read_circuit_from_file(path)?; + let constraint_system = AcirFormat::circuit_serde_to_acir_format(circuit, honk_recusion); + Ok(constraint_system) + } + + pub fn get_witness_from_file(path: &str) -> io::Result> { + let mut witness_stack = Self::read_witness_stack_from_file(path)?; + let witness_map = witness_stack + .pop() + .expect("Witness should be present") + .witness; + let witness = AcirFormat::witness_map_to_witness_vector(witness_map); + Ok(witness) + } -pub(crate) fn get_msb64(inp: u64) -> u8 { - const DE_BRUIJNI_SEQUENCE: [u8; 64] = [ - 0, 47, 1, 56, 48, 27, 2, 60, 57, 49, 41, 37, 28, 16, 3, 61, 54, 58, 35, 52, 50, 42, 21, 44, - 38, 32, 29, 23, 17, 11, 4, 62, 46, 55, 26, 59, 40, 36, 15, 53, 34, 51, 20, 43, 31, 22, 10, - 45, 25, 39, 14, 33, 19, 30, 9, 24, 13, 18, 8, 12, 7, 6, 5, 63, - ]; - - let mut t = inp | (inp >> 1); - t |= t >> 2; - t |= t >> 4; - t |= t >> 8; - t |= t >> 16; - t |= t >> 32; - - DE_BRUIJNI_SEQUENCE[((t.wrapping_mul(0x03F79D71B4CB0A89)) >> 58) as usize] + // from http://supertech.csail.mit.edu/papers/debruijn.pdf + pub fn get_msb32(inp: u32) -> u8 { + const MULTIPLY_DE_BRUIJNI_BIT_POSIITION: [u8; 32] = [ + 0, 9, 1, 10, 13, 21, 2, 29, 11, 14, 16, 18, 22, 25, 3, 30, 8, 12, 20, 28, 15, 17, 24, + 7, 19, 27, 23, 6, 26, 5, 4, 31, + ]; + + let mut v = inp | (inp >> 1); + v |= v >> 2; + v |= v >> 4; + v |= v >> 8; + v |= v >> 16; + + MULTIPLY_DE_BRUIJNI_BIT_POSIITION[((v.wrapping_mul(0x07C4ACDD)) >> 27) as usize] + } + + pub fn round_up_power_2(inp: usize) -> usize { + let lower_bound = 1usize << Self::get_msb64(inp as u64); + if lower_bound == inp || lower_bound == 1 { + inp + } else { + lower_bound * 2 + } + } + + pub fn get_msb64(inp: u64) -> u8 { + const DE_BRUIJNI_SEQUENCE: [u8; 64] = [ + 0, 47, 1, 56, 48, 27, 2, 60, 57, 49, 41, 37, 28, 16, 3, 61, 54, 58, 35, 52, 50, 42, 21, + 44, 38, 32, 29, 23, 17, 11, 4, 62, 46, 55, 26, 59, 40, 36, 15, 53, 34, 51, 20, 43, 31, + 22, 10, 45, 25, 39, 14, 33, 19, 30, 9, 24, 13, 18, 8, 12, 7, 6, 5, 63, + ]; + + let mut t = inp | (inp >> 1); + t |= t >> 2; + t |= t >> 4; + t |= t >> 8; + t |= t >> 16; + t |= t >> 32; + + DE_BRUIJNI_SEQUENCE[((t.wrapping_mul(0x03F79D71B4CB0A89)) >> 58) as usize] + } } pub(crate) const NUM_ALPHAS: usize = decider::relations::NUM_SUBRELATIONS - 1; diff --git a/co-noir/ultrahonk/src/oink/prover.rs b/co-noir/ultrahonk/src/oink/prover.rs index b0fb4fc4..47dca82e 100644 --- a/co-noir/ultrahonk/src/oink/prover.rs +++ b/co-noir/ultrahonk/src/oink/prover.rs @@ -29,7 +29,7 @@ use ark_ff::{One, Zero}; use itertools::izip; use std::marker::PhantomData; -pub struct Oink> { +pub(crate) struct Oink> { memory: ProverMemory

, phantom_data: PhantomData

, } @@ -41,7 +41,7 @@ impl> Default for Oink

{ } impl> Oink

{ - pub fn new() -> Self { + pub(crate) fn new() -> Self { Self { memory: ProverMemory::default(), phantom_data: PhantomData, @@ -469,7 +469,7 @@ impl> Oink

{ Ok(()) } - pub fn prove( + pub(crate) fn prove( mut self, proving_key: &ProvingKey

, transcript: &mut TranscriptType, diff --git a/co-noir/ultrahonk/src/oink/types.rs b/co-noir/ultrahonk/src/oink/types.rs index 7bd99d9b..71deb288 100644 --- a/co-noir/ultrahonk/src/oink/types.rs +++ b/co-noir/ultrahonk/src/oink/types.rs @@ -2,21 +2,21 @@ use crate::{decider::polynomial::Polynomial, NUM_ALPHAS}; use ark_ec::pairing::Pairing; use ark_ff::PrimeField; -pub struct ProverMemory { - pub w_4: Polynomial, // column 3 - pub z_perm: Polynomial, // column 4 - pub lookup_inverses: Polynomial, // column 5 - pub public_input_delta: P::ScalarField, - pub challenges: Challenges, +pub(crate) struct ProverMemory { + pub(crate) w_4: Polynomial, // column 3 + pub(crate) z_perm: Polynomial, // column 4 + pub(crate) lookup_inverses: Polynomial, // column 5 + pub(crate) public_input_delta: P::ScalarField, + pub(crate) challenges: Challenges, } -pub struct Challenges { - pub eta_1: F, - pub eta_2: F, - pub eta_3: F, - pub beta: F, - pub gamma: F, - pub alphas: [F; NUM_ALPHAS], +pub(crate) struct Challenges { + pub(crate) eta_1: F, + pub(crate) eta_2: F, + pub(crate) eta_3: F, + pub(crate) beta: F, + pub(crate) gamma: F, + pub(crate) alphas: [F; NUM_ALPHAS], } impl Default for Challenges { diff --git a/co-noir/ultrahonk/src/parse/acir_format.rs b/co-noir/ultrahonk/src/parse/acir_format.rs index 786bbbe4..49c0b917 100644 --- a/co-noir/ultrahonk/src/parse/acir_format.rs +++ b/co-noir/ultrahonk/src/parse/acir_format.rs @@ -71,7 +71,7 @@ pub struct AcirFormat { } impl AcirFormat { - pub fn witness_map_to_witness_vector( + pub(crate) fn witness_map_to_witness_vector( witness_map: WitnessMap>, ) -> Vec { let mut wv = Vec::new(); @@ -91,7 +91,7 @@ impl AcirFormat { } #[allow(clippy::field_reassign_with_default)] - pub fn circuit_serde_to_acir_format( + pub(crate) fn circuit_serde_to_acir_format( circuit: Circuit>, honk_recursion: bool, ) -> Self { diff --git a/co-noir/ultrahonk/src/parse/builder.rs b/co-noir/ultrahonk/src/parse/builder.rs index 8a26d7dd..e140e1cf 100644 --- a/co-noir/ultrahonk/src/parse/builder.rs +++ b/co-noir/ultrahonk/src/parse/builder.rs @@ -9,34 +9,59 @@ use super::{ }, }; use crate::{ - get_msb64, parse::{ plookup::{MultiTableId, Plookup}, types::{FieldCT, GateCounter, RomRecord, RomTable, NUM_WIRES}, }, - poseidon2::field_from_hex_string, + Utils, }; use ark_ec::pairing::Pairing; -use ark_ff::{One, Zero}; +use ark_ff::{One, PrimeField, Zero}; use num_bigint::BigUint; -use std::collections::HashMap; +use std::{collections::HashMap, fmt::Debug}; type GateBlocks = UltraTraceBlocks>; -pub struct UltraCircuitBuilder { - pub(crate) variables: Vec, +pub trait UltraCircuitVariable: Clone + PartialEq + Debug { + type Shared; + + fn from_public(value: F) -> Self; + fn is_public(&self) -> bool; + fn public_into_field(self) -> F; +} + +impl UltraCircuitVariable for F { + type Shared = F; + + fn from_public(value: F) -> Self { + value + } + + fn is_public(&self) -> bool { + true + } + + fn public_into_field(self) -> F { + self + } +} + +pub type UltraCircuitBuilder

= GenericUltraCircuitBuilder::ScalarField>; + +pub struct GenericUltraCircuitBuilder> { + pub variables: Vec, variable_names: HashMap, next_var_index: Vec, prev_var_index: Vec, - pub(crate) real_variable_index: Vec, + pub real_variable_index: Vec, pub(crate) real_variable_tags: Vec, - pub(crate) public_inputs: Vec, + pub public_inputs: Vec, is_recursive_circuit: bool, pub(crate) tau: HashMap, constant_variable_indices: HashMap, pub(crate) zero_idx: u32, one_idx: u32, - pub(crate) blocks: GateBlocks, // Storage for wires and selectors for all gate types + pub blocks: GateBlocks, // Storage for wires and selectors for all gate types num_gates: usize, circuit_finalized: bool, contains_recursive_proof: bool, @@ -54,21 +79,21 @@ pub struct UltraCircuitBuilder { pub(crate) memory_write_records: Vec, } -impl UltraCircuitBuilder

{ - const DUMMY_TAG: u32 = 0; - const REAL_VARIABLE: u32 = u32::MAX - 1; - const FIRST_VARIABLE_IN_CLASS: u32 = u32::MAX - 2; - const UNINITIALIZED_MEMORY_RECORD: u32 = u32::MAX; - const NUMBER_OF_GATES_PER_RAM_ACCESS: usize = 2; - const NUMBER_OF_ARITHMETIC_GATES_PER_RAM_ARRAY: usize = 1; - const NUM_RESERVED_GATES: usize = 4; +impl> GenericUltraCircuitBuilder { + pub(crate) const DUMMY_TAG: u32 = 0; + pub(crate) const REAL_VARIABLE: u32 = u32::MAX - 1; + pub(crate) const FIRST_VARIABLE_IN_CLASS: u32 = u32::MAX - 2; + pub(crate) const UNINITIALIZED_MEMORY_RECORD: u32 = u32::MAX; + pub(crate) const NUMBER_OF_GATES_PER_RAM_ACCESS: usize = 2; + pub(crate) const NUMBER_OF_ARITHMETIC_GATES_PER_RAM_ARRAY: usize = 1; + pub(crate) const NUM_RESERVED_GATES: usize = 4; // number of gates created per non-native field operation in process_non_native_field_multiplications - const GATES_PER_NON_NATIVE_FIELD_MULTIPLICATION_ARITHMETIC: usize = 7; + pub(crate) const GATES_PER_NON_NATIVE_FIELD_MULTIPLICATION_ARITHMETIC: usize = 7; pub fn create_circuit( constraint_system: AcirFormat, size_hint: usize, - witness: Vec, + witness: Vec, honk_recursion: bool, // true for ultrahonk collect_gates_per_opcode: bool, // false for ultrahonk ) -> Self { @@ -148,7 +173,7 @@ impl UltraCircuitBuilder

{ */ fn init( size_hint: usize, - witness_values: Vec, + witness_values: Vec, public_inputs: Vec, varnum: usize, recursive: bool, @@ -158,15 +183,14 @@ impl UltraCircuitBuilder

{ // TODO(https://github.com/AztecProtocol/barretenberg/issues/870): reserve space in blocks here somehow? - for idx in 0..varnum { - // Zeros are added for variables whose existence is known but whose values are not yet known. The values may - // be "set" later on via the assert_equal mechanism. - let value = if idx < witness_values.len() { - witness_values[idx] - } else { - P::ScalarField::zero() - }; - builder.add_variable(value); + let len = witness_values.len(); + for witness in witness_values.into_iter().take(varnum) { + builder.add_variable(witness); + } + // Zeros are added for variables whose existence is known but whose values are not yet known. The values may + // be "set" later on via the assert_equal mechanism. + for _ in len..varnum { + builder.add_variable(S::from_public(P::ScalarField::zero())); } // Add the public_inputs from acir @@ -181,7 +205,7 @@ impl UltraCircuitBuilder

{ builder } - pub(crate) fn add_variable(&mut self, value: P::ScalarField) -> u32 { + pub(crate) fn add_variable(&mut self, value: S) -> u32 { let idx = self.variables.len() as u32; self.variables.push(value); self.real_variable_index.push(idx); @@ -195,7 +219,7 @@ impl UltraCircuitBuilder

{ if let Some(val) = self.constant_variable_indices.get(&variable) { *val } else { - let variable_index = self.add_variable(variable); + let variable_index = self.add_variable(S::from_public(variable)); self.fix_witness(variable_index, variable); self.constant_variable_indices .insert(variable, variable_index); @@ -817,19 +841,19 @@ impl UltraCircuitBuilder

{ // TODO(https://github.com/AztecProtocol/barretenberg/issues/911): These are pairing points extracted from a valid // proof. This is a workaround because we can't represent the point at infinity in biggroup yet. let mut agg_obj_indices = AggregationObjectIndices::default(); - let x0 = field_from_hex_string::( + let x0 = Utils::field_from_hex_string::( "0x031e97a575e9d05a107acb64952ecab75c020998797da7842ab5d6d1986846cf", ) .expect("x0 works"); - let y0 = field_from_hex_string::( + let y0 = Utils::field_from_hex_string::( "0x178cbf4206471d722669117f9758a4c410db10a01750aebb5666547acf8bd5a4", ) .expect("y0 works"); - let x1 = field_from_hex_string::( + let x1 = Utils::field_from_hex_string::( "0x0f94656a2ca489889939f81e9c74027fd51009034b3357f0e91b8a11e7842c38", ) .expect("x1 works"); - let y1 = field_from_hex_string::( + let y1 = Utils::field_from_hex_string::( "0x1b52c2020d7464a0c80c0da527a08193fe27776f50224bd6fb128b46c1ddb67f", ) .expect("y1 works"); @@ -855,7 +879,7 @@ impl UltraCircuitBuilder

{ ]; for val in val_limbs { - let idx = self.add_variable(val); + let idx = self.add_variable(S::from_public(val)); agg_obj_indices[agg_obj_indices_idx] = idx; agg_obj_indices_idx += 1; } @@ -885,6 +909,7 @@ impl UltraCircuitBuilder

{ ) { let mut table = RomTable::new(init); + // TODO this is just implemented for the Plain backend for op in constraint.trace.iter() { assert_eq!(op.access_type, 0); let value = self.poly_to_field_ct(&op.value); @@ -906,13 +931,13 @@ impl UltraCircuitBuilder

{ } } - pub(crate) fn get_variable(&self, index: usize) -> P::ScalarField { + pub fn get_variable(&self, index: usize) -> S { assert!(self.variables.len() > index); - self.variables[self.real_variable_index[index] as usize] + self.variables[self.real_variable_index[index] as usize].to_owned() } pub(crate) fn assert_equal_constant(&mut self, a_idx: usize, b: P::ScalarField) { - assert_eq!(self.variables[a_idx], b); + assert_eq!(self.variables[a_idx], S::from_public(b)); let b_idx = self.put_constant_variable(b); self.assert_equal(a_idx, b_idx as usize); } @@ -1021,7 +1046,7 @@ impl UltraCircuitBuilder

{ fn create_rom_gate(&mut self, record: &mut RomRecord) { // Record wire value can't yet be computed - record.record_witness = self.add_variable(P::ScalarField::zero()); + record.record_witness = self.add_variable(S::from_public(P::ScalarField::zero())); self.apply_aux_selectors(AuxSelectors::RomRead); self.blocks.aux.populate_wires( record.index_witness, @@ -1037,7 +1062,10 @@ impl UltraCircuitBuilder

{ pub(crate) fn read_rom_array(&mut self, rom_id: usize, index_witness: u32) -> u32 { assert!(self.rom_arrays.len() > rom_id); - let val: BigUint = self.get_variable(index_witness as usize).into(); + let val: BigUint = self + .get_variable(index_witness as usize) + .public_into_field() + .into(); let index: usize = val.try_into().unwrap(); assert!(self.rom_arrays[rom_id].state.len() > index); @@ -1120,7 +1148,7 @@ impl UltraCircuitBuilder

{ // self.num_gates += 1; } - pub(crate) fn add_gates_to_ensure_all_polys_are_non_zero(&mut self) { + pub fn add_gates_to_ensure_all_polys_are_non_zero(&mut self) { // q_m, q_1, q_2, q_3, q_4 self.blocks.arithmetic.populate_wires( self.zero_idx, @@ -1328,8 +1356,8 @@ impl UltraCircuitBuilder

{ let left_witness_value = P::ScalarField::from(left_value as u64); let right_witness_value = P::ScalarField::from(right_value as u64); - let left_witness_index = self.add_variable(left_witness_value); - let right_witness_index = self.add_variable(right_witness_value); + let left_witness_index = self.add_variable(S::from_public(left_witness_value)); + let right_witness_index = self.add_variable(S::from_public(right_witness_value)); let dummy_accumulators = self.plookup.get_lookup_accumulators( MultiTableId::HonkDummyMulti, left_witness_value, @@ -1502,7 +1530,7 @@ impl UltraCircuitBuilder

{ } pub fn get_circuit_subgroup_size(num_gates: usize) -> usize { - let mut log2_n = get_msb64(num_gates as u64); + let mut log2_n = Utils::get_msb64(num_gates as u64); if (1 << log2_n) != num_gates { log2_n += 1; } @@ -1561,16 +1589,16 @@ impl UltraCircuitBuilder

{ let first_idx = if i == 0 { key_a_index } else { - self.add_variable(read_values[ColumnIdx::C1][i]) + self.add_variable(S::from_public(read_values[ColumnIdx::C1][i])) }; #[allow(clippy::unnecessary_unwrap)] let second_idx = if i == 0 && (key_b_index.is_some()) { key_b_index.unwrap() } else { - self.add_variable(read_values[ColumnIdx::C2][i]) + self.add_variable(S::from_public(read_values[ColumnIdx::C2][i])) }; - let third_idx = self.add_variable(read_values[ColumnIdx::C3][i]); + let third_idx = self.add_variable(S::from_public(read_values[ColumnIdx::C3][i])); read_data[ColumnIdx::C1].push(first_idx); read_data[ColumnIdx::C2].push(second_idx); @@ -1627,7 +1655,7 @@ impl UltraCircuitBuilder

{ read_data } - pub(crate) fn finalize_circuit(&mut self) { + pub fn finalize_circuit(&mut self) { // /** // * First of all, add the gates related to ROM arrays and range lists. // * Note that the total number of rows in an UltraPlonk program can be divided as following: @@ -1738,7 +1766,7 @@ impl UltraCircuitBuilder

{ ); } - pub(crate) fn compute_dyadic_size(&self) -> usize { + pub fn compute_dyadic_size(&self) -> usize { // for the lookup argument the circuit size must be at least as large as the sum of all tables used let min_size_due_to_lookups = self.get_tables_size(); @@ -1754,4 +1782,24 @@ impl UltraCircuitBuilder

{ // Next power of 2 (dyadic circuit size) Self::get_circuit_subgroup_size(total_num_gates) } + + pub fn populate_public_inputs_block(&mut self) { + tracing::info!("Populating public inputs block"); + + // Update the public inputs block + for idx in self.public_inputs.iter() { + for (wire_idx, wire) in self.blocks.pub_inputs.wires.iter_mut().enumerate() { + if wire_idx < 2 { + // first two wires get a copy of the public inputs + wire.push(*idx); + } else { + // the remaining wires get zeros + wire.push(self.zero_idx); + } + } + for selector in self.blocks.pub_inputs.selectors.iter_mut() { + selector.push(P::ScalarField::zero()); + } + } + } } diff --git a/co-noir/ultrahonk/src/parse/mod.rs b/co-noir/ultrahonk/src/parse/mod.rs index c7087767..6070756d 100644 --- a/co-noir/ultrahonk/src/parse/mod.rs +++ b/co-noir/ultrahonk/src/parse/mod.rs @@ -1,42 +1,6 @@ -pub mod acir_format; -pub mod builder; -pub mod crs; +pub(crate) mod acir_format; +pub(crate) mod builder; +pub(crate) mod crs; pub(crate) mod plookup; -pub mod proving_key; +pub(crate) mod proving_key; pub(crate) mod types; - -use acir::{circuit::Circuit, native_types::WitnessStack, FieldElement}; -use acir_format::AcirFormat; -use noirc_artifacts::program::ProgramArtifact; -use std::io; - -pub fn read_circuit_from_file(path: &str) -> io::Result> { - let program = std::fs::read_to_string(path)?; - let program_artifact = serde_json::from_str::(&program)?; - Ok(program_artifact.bytecode.functions[0].to_owned()) -} - -pub fn read_witness_stack_from_file(path: &str) -> io::Result> { - let witness_stack = std::fs::read(path)?; - WitnessStack::try_from(witness_stack.as_slice()) - .map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e)) -} - -pub fn get_constraint_system_from_file( - path: &str, - honk_recusion: bool, -) -> io::Result> { - let circuit = read_circuit_from_file(path)?; - let constraint_system = AcirFormat::circuit_serde_to_acir_format(circuit, honk_recusion); - Ok(constraint_system) -} - -pub fn get_witness_from_file(path: &str) -> io::Result> { - let mut witness_stack = read_witness_stack_from_file(path)?; - let witness_map = witness_stack - .pop() - .expect("Witness should be present") - .witness; - let witness = AcirFormat::witness_map_to_witness_vector(witness_map); - Ok(witness) -} diff --git a/co-noir/ultrahonk/src/parse/plookup.rs b/co-noir/ultrahonk/src/parse/plookup.rs index 8ab952d1..1c02560f 100644 --- a/co-noir/ultrahonk/src/parse/plookup.rs +++ b/co-noir/ultrahonk/src/parse/plookup.rs @@ -6,7 +6,7 @@ use num_bigint::BigUint; use std::array::from_fn; #[derive(Clone, Debug, PartialEq, Eq)] -pub enum BasicTableId { +pub(crate) enum BasicTableId { Xor, And, Pedersen, @@ -143,7 +143,7 @@ impl FixedBaseParams { } #[derive(Clone, Debug, PartialEq, Eq)] -pub enum MultiTableId { +pub(crate) enum MultiTableId { Sha256ChInput, Sha256ChOutput, Sha256MajInput, @@ -195,7 +195,7 @@ impl From for usize { } } -pub struct Plookup { +pub(crate) struct Plookup { pub(crate) multi_tables: [PlookupMultiTable; MultiTableId::NumMultiTables as usize], } diff --git a/co-noir/ultrahonk/src/parse/proving_key.rs b/co-noir/ultrahonk/src/parse/proving_key.rs index 8f537994..11ac4b45 100644 --- a/co-noir/ultrahonk/src/parse/proving_key.rs +++ b/co-noir/ultrahonk/src/parse/proving_key.rs @@ -1,16 +1,16 @@ use super::{ - builder::UltraCircuitBuilder, + builder::{GenericUltraCircuitBuilder, UltraCircuitBuilder, UltraCircuitVariable}, crs::CrsParser, types::{CyclicPermutation, Mapping, PermutationMapping}, }; use crate::{ decider::polynomial::Polynomial, - get_msb64, - parse::types::{CycleNode, TraceData, NUM_WIRES}, - types::{Polynomials, ProverCrs, ProvingKey}, + parse::types::{TraceData, NUM_WIRES}, + types::{Polynomials, PrecomputedEntities, ProverCrs, ProvingKey}, + Utils, }; use ark_ec::pairing::Pairing; -use ark_ff::{One, Zero}; +use ark_ff::One; use eyre::Result; impl ProvingKey

{ @@ -30,8 +30,25 @@ impl ProvingKey

{ proving_key.polynomials.precomputed.lagrange_last_mut()[dyadic_circuit_size - 1] = P::ScalarField::one(); - proving_key.construct_lookup_table_polynomials(&circuit, dyadic_circuit_size, 0); - proving_key.construct_lookup_read_counts(&mut circuit, dyadic_circuit_size); + Self::construct_lookup_table_polynomials( + proving_key + .polynomials + .precomputed + .get_table_polynomials_mut(), + &circuit, + dyadic_circuit_size, + 0, + ); + Self::construct_lookup_read_counts( + proving_key + .polynomials + .witness + .lookup_read_counts_and_tags_mut() + .try_into() + .unwrap(), + &mut circuit, + dyadic_circuit_size, + ); // Construct the public inputs array let public_wires_src = proving_key.polynomials.witness.w_r(); @@ -53,16 +70,10 @@ impl ProvingKey

{ proving_key } - fn round_up_power_2(inp: usize) -> usize { - let lower_bound = 1usize << get_msb64(inp as u64); - if lower_bound == inp || lower_bound == 1 { - inp - } else { - lower_bound * 2 - } - } - - pub fn get_prover_crs(circuit: &UltraCircuitBuilder

, path_g1: &str) -> Result> { + pub fn get_prover_crs>( + circuit: &GenericUltraCircuitBuilder, + path_g1: &str, + ) -> Result> { tracing::info!("Getting prover crs"); const EXTRA_SRS_POINTS_FOR_ECCVM_IPA: usize = 1; @@ -73,7 +84,7 @@ impl ProvingKey

{ total_circuit_size + num_extra_gates, ); - let srs_size = Self::round_up_power_2(srs_size) + EXTRA_SRS_POINTS_FOR_ECCVM_IPA; + let srs_size = Utils::round_up_power_2(srs_size) + EXTRA_SRS_POINTS_FOR_ECCVM_IPA; CrsParser::

::get_crs_g1(path_g1, srs_size) } @@ -96,7 +107,8 @@ impl ProvingKey

{ fn populate_trace(&mut self, builder: &mut UltraCircuitBuilder

, is_strucutred: bool) { tracing::info!("Populating trace"); - let trace_data = self.construct_trace_data(builder, is_strucutred); + let mut trace_data = TraceData::new(builder, self); + trace_data.construct_trace_data(builder, is_strucutred); let ram_rom_offset = trace_data.ram_rom_offset; let copy_cycles = trace_data.copy_cycles; @@ -110,100 +122,18 @@ impl ProvingKey

{ ); // Compute the permutation argument polynomials (sigma/id) and add them to proving key - self.compute_permutation_argument_polynomials(builder, copy_cycles); - } - - fn construct_trace_data( - &mut self, - builder: &mut UltraCircuitBuilder

, - is_structured: bool, - ) -> TraceData

{ - tracing::info!("Construct trace data"); - let mut trace_data = TraceData::new(builder, self); - - // Complete the public inputs execution trace block from builder.public_inputs - Self::populate_public_inputs_block(builder); - - let mut offset = 1; // Offset at which to place each block in the trace polynomials - // For each block in the trace, populate wire polys, copy cycles and selector polys - - for block in builder.blocks.get() { - let block_size = block.len(); - - // Update wire polynomials and copy cycles - // NB: The order of row/column loops is arbitrary but needs to be row/column to match old copy_cycle code - - for block_row_idx in 0..block_size { - for wire_idx in 0..NUM_WIRES { - let var_idx = block.wires[wire_idx][block_row_idx] as usize; // an index into the variables array - let real_var_idx = builder.real_variable_index[var_idx] as usize; - let trace_row_idx = block_row_idx + offset; - // Insert the real witness values from this block into the wire polys at the correct offset - trace_data.wires[wire_idx][trace_row_idx] = builder.get_variable(var_idx); - // Add the address of the witness value to its corresponding copy cycle - trace_data.copy_cycles[real_var_idx].push(CycleNode { - wire_index: wire_idx as u32, - gate_index: trace_row_idx as u32, - }); - } - } - - // Insert the selector values for this block into the selector polynomials at the correct offset - // TODO(https://github.com/AztecProtocol/barretenberg/issues/398): implicit arithmetization/flavor consistency - for (selector_poly, selector) in - trace_data.selectors.iter_mut().zip(block.selectors.iter()) - { - debug_assert_eq!(selector.len(), block_size); - - for (src, des) in selector.iter().zip(selector_poly.iter_mut().skip(offset)) { - *des = *src; - } - } - - // Store the offset of the block containing RAM/ROM read/write gates for use in updating memory records - if block.has_ram_rom { - trace_data.ram_rom_offset = offset as u32; - } - // Store offset of public inputs block for use in the pub input mechanism of the permutation argument - if block.is_pub_inputs { - trace_data.pub_inputs_offset = offset as u32; - } - - // If the trace is structured, we populate the data from the next block at a fixed block size offset - if is_structured { - offset += block.get_fixed_size() as usize; - } else { - // otherwise, the next block starts immediately following the previous one - offset += block_size; - } - } - - trace_data - } - - fn populate_public_inputs_block(builder: &mut UltraCircuitBuilder

) { - tracing::info!("Populating public inputs block"); - - // Update the public inputs block - for idx in builder.public_inputs.iter() { - for (wire_idx, wire) in builder.blocks.pub_inputs.wires.iter_mut().enumerate() { - if wire_idx < 2 { - // first two wires get a copy of the public inputs - wire.push(*idx); - } else { - // the remaining wires get zeros - wire.push(builder.zero_idx); - } - } - for selector in builder.blocks.pub_inputs.selectors.iter_mut() { - selector.push(P::ScalarField::zero()); - } - } + Self::compute_permutation_argument_polynomials( + &mut self.polynomials.precomputed, + builder, + copy_cycles, + self.circuit_size as usize, + self.pub_inputs_offset as usize, + ); } - fn add_memory_records_to_proving_key( + pub fn add_memory_records_to_proving_key>( ram_rom_offset: u32, - builder: &UltraCircuitBuilder

, + builder: &GenericUltraCircuitBuilder, memory_read_records: &mut Vec, memory_write_records: &mut Vec, ) { @@ -221,36 +151,42 @@ impl ProvingKey

{ } } - fn compute_permutation_argument_polynomials( - &mut self, - circuit: &UltraCircuitBuilder

, + pub fn compute_permutation_argument_polynomials>( + polys: &mut PrecomputedEntities>, + circuit: &GenericUltraCircuitBuilder, copy_cycles: Vec, + circuit_size: usize, + pub_inputs_offset: usize, ) { tracing::info!("Computing permutation argument polynomials"); - let mapping = self.compute_permutation_mapping(circuit, copy_cycles); + let mapping = Self::compute_permutation_mapping( + circuit_size, + pub_inputs_offset, + circuit, + copy_cycles, + ); // Compute Honk-style sigma and ID polynomials from the corresponding mappings - let circuit_size = self.circuit_size as usize; - Self::compute_honk_style_permutation_lagrange_polynomials_from_mapping( - self.polynomials.precomputed.get_sigmas_mut(), + polys.get_sigmas_mut(), mapping.sigmas, circuit_size, ); Self::compute_honk_style_permutation_lagrange_polynomials_from_mapping( - self.polynomials.precomputed.get_ids_mut(), + polys.get_ids_mut(), mapping.ids, circuit_size, ); } - fn compute_permutation_mapping( - &self, - circuit_constructor: &UltraCircuitBuilder

, + fn compute_permutation_mapping>( + circuit_size: usize, + pub_inputs_offset: usize, + circuit_constructor: &GenericUltraCircuitBuilder, wire_copy_cycles: Vec, ) -> PermutationMapping { // Initialize the table of permutations so that every element points to itself - let mut mapping = PermutationMapping::new(self.circuit_size as usize); + let mut mapping = PermutationMapping::new(circuit_size); // Represents the index of a variable in circuit_constructor.variables (needed only for generalized) let real_variable_tags = &circuit_constructor.real_variable_tags; @@ -298,10 +234,9 @@ impl ProvingKey

{ // Add information about public inputs so that the cycles can be altered later; See the construction of the // permutation polynomials for details. let num_public_inputs = circuit_constructor.public_inputs.len(); - let public_inputs_offset = self.pub_inputs_offset as usize; for i in 0..num_public_inputs { - let idx = i + public_inputs_offset; + let idx = i + pub_inputs_offset; mapping.sigmas[0][idx].row_index = idx as u32; mapping.sigmas[0][idx].column_index = 0; mapping.sigmas[0][idx].is_public_input = true; @@ -362,14 +297,12 @@ impl ProvingKey

{ } } - fn construct_lookup_table_polynomials( - &mut self, - circuit: &UltraCircuitBuilder

, + pub fn construct_lookup_table_polynomials>( + table_polynomials: &mut [Polynomial], + circuit: &GenericUltraCircuitBuilder, dyadic_circuit_size: usize, additional_offset: usize, ) { - let table_polynomials = self.polynomials.precomputed.get_table_polynomials_mut(); - // Create lookup selector polynomials which interpolate each table column. // Our selector polys always need to interpolate the full subgroup size, so here we offset so as to // put the table column's values at the end. (The first gates are for non-lookup constraints). @@ -394,9 +327,9 @@ impl ProvingKey

{ } } - fn construct_lookup_read_counts( - &mut self, - circuit: &mut UltraCircuitBuilder

, + pub fn construct_lookup_read_counts>( + witness: &mut [Polynomial; 2], + circuit: &mut GenericUltraCircuitBuilder, dyadic_circuit_size: usize, ) { // TODO(https://github.com/AztecProtocol/barretenberg/issues/1033): construct tables and counts at top of trace @@ -416,11 +349,9 @@ impl ProvingKey

{ // increment the read count at the corresponding index in the full polynomial let index_in_poly = table_offset + index_in_table; - self.polynomials.witness.lookup_read_counts_mut()[index_in_poly] += - P::ScalarField::one(); - self.polynomials.witness.lookup_read_tags_mut()[index_in_poly] = - P::ScalarField::one(); - // tag is 1 if entry has been read 1 or more times + witness[0][index_in_poly] += P::ScalarField::one(); // Read count + witness[1][index_in_poly] = P::ScalarField::one(); // Read Tag + // tag is 1 if entry has been read 1 or more times } table_offset += table.len(); // set the offset of the next table within the polynomials } diff --git a/co-noir/ultrahonk/src/parse/types.rs b/co-noir/ultrahonk/src/parse/types.rs index 79edd915..0406b319 100644 --- a/co-noir/ultrahonk/src/parse/types.rs +++ b/co-noir/ultrahonk/src/parse/types.rs @@ -1,4 +1,4 @@ -use super::builder::UltraCircuitBuilder; +use super::builder::{GenericUltraCircuitBuilder, UltraCircuitBuilder, UltraCircuitVariable}; use super::plookup::{BasicTableId, MultiTableId}; use crate::batch_invert; use crate::decider::polynomial::Polynomial; @@ -14,64 +14,64 @@ use std::hash::{Hash, Hasher}; use std::ops::{Index, IndexMut}; #[derive(Default, PartialEq, Eq)] -pub struct PolyTriple { - pub a: u32, - pub b: u32, - pub c: u32, - pub q_m: F, - pub q_l: F, - pub q_r: F, - pub q_o: F, - pub q_c: F, +pub(crate) struct PolyTriple { + pub(crate) a: u32, + pub(crate) b: u32, + pub(crate) c: u32, + pub(crate) q_m: F, + pub(crate) q_l: F, + pub(crate) q_r: F, + pub(crate) q_o: F, + pub(crate) q_c: F, } #[derive(Default, PartialEq, Eq)] -pub struct AddTriple { - pub a: u32, - pub b: u32, - pub c: u32, - pub a_scaling: F, - pub b_scaling: F, - pub c_scaling: F, - pub const_scaling: F, +pub(crate) struct AddTriple { + pub(crate) a: u32, + pub(crate) b: u32, + pub(crate) c: u32, + pub(crate) a_scaling: F, + pub(crate) b_scaling: F, + pub(crate) c_scaling: F, + pub(crate) const_scaling: F, } #[derive(Default, PartialEq, Eq)] -pub struct AddQuad { - pub a: u32, - pub b: u32, - pub c: u32, - pub d: u32, - pub a_scaling: F, - pub b_scaling: F, - pub c_scaling: F, - pub d_scaling: F, - pub const_scaling: F, +pub(crate) struct AddQuad { + pub(crate) a: u32, + pub(crate) b: u32, + pub(crate) c: u32, + pub(crate) d: u32, + pub(crate) a_scaling: F, + pub(crate) b_scaling: F, + pub(crate) c_scaling: F, + pub(crate) d_scaling: F, + pub(crate) const_scaling: F, } #[derive(Default, PartialEq, Eq)] -pub struct MulQuad { - pub a: u32, - pub b: u32, - pub c: u32, - pub d: u32, - pub mul_scaling: F, - pub a_scaling: F, - pub b_scaling: F, - pub c_scaling: F, - pub d_scaling: F, - pub const_scaling: F, +pub(crate) struct MulQuad { + pub(crate) a: u32, + pub(crate) b: u32, + pub(crate) c: u32, + pub(crate) d: u32, + pub(crate) mul_scaling: F, + pub(crate) a_scaling: F, + pub(crate) b_scaling: F, + pub(crate) c_scaling: F, + pub(crate) d_scaling: F, + pub(crate) const_scaling: F, } -pub struct MemOp { - pub access_type: u8, - pub index: PolyTriple, - pub value: PolyTriple, +pub(crate) struct MemOp { + pub(crate) access_type: u8, + pub(crate) index: PolyTriple, + pub(crate) value: PolyTriple, } #[derive(PartialEq, Eq)] #[allow(clippy::upper_case_acronyms)] -pub enum BlockType { +pub(crate) enum BlockType { ROM = 0, RAM = 1, CallData = 2, @@ -85,43 +85,43 @@ impl Default for BlockType { } #[derive(Default)] -pub struct BlockConstraint { - pub init: Vec>, - pub trace: Vec>, - pub type_: BlockType, - pub calldata: u32, +pub(crate) struct BlockConstraint { + pub(crate) init: Vec>, + pub(crate) trace: Vec>, + pub(crate) type_: BlockType, + pub(crate) calldata: u32, } #[derive(Default)] -pub struct AcirFormatOriginalOpcodeIndices { - // pub logic_constraints: Vec, - // pub range_constraints: Vec, - // pub aes128_constraints: Vec, - // pub sha256_constraints: Vec, - // pub sha256_compression: Vec, - // pub schnorr_constraints: Vec, - // pub ecdsa_k1_constraints: Vec, - // pub ecdsa_r1_constraints: Vec, - // pub blake2s_constraints: Vec, - // pub blake3_constraints: Vec, - // pub keccak_constraints: Vec, - // pub keccak_permutations: Vec, - // pub pedersen_constraints: Vec, - // pub pedersen_hash_constraints: Vec, - // pub poseidon2_constraints: Vec, - // pub multi_scalar_mul_constraints: Vec, - // pub ec_add_constraints: Vec, - // pub recursion_constraints: Vec, - // pub honk_recursion_constraints: Vec, - // pub ivc_recursion_constraints: Vec, - // pub bigint_from_le_bytes_constraints: Vec, - // pub bigint_to_le_bytes_constraints: Vec, - // pub bigint_operations: Vec, - pub assert_equalities: Vec, - pub poly_triple_constraints: Vec, - pub quad_constraints: Vec, +pub(crate) struct AcirFormatOriginalOpcodeIndices { + // pub(crate)logic_constraints: Vec, + // pub(crate)range_constraints: Vec, + // pub(crate)aes128_constraints: Vec, + // pub(crate)sha256_constraints: Vec, + // pub(crate)sha256_compression: Vec, + // pub(crate)schnorr_constraints: Vec, + // pub(crate)ecdsa_k1_constraints: Vec, + // pub(crate)ecdsa_r1_constraints: Vec, + // pub(crate)blake2s_constraints: Vec, + // pub(crate)blake3_constraints: Vec, + // pub(crate)keccak_constraints: Vec, + // pub(crate)keccak_permutations: Vec, + // pub(crate)pedersen_constraints: Vec, + // pub(crate)pedersen_hash_constraints: Vec, + // pub(crate)poseidon2_constraints: Vec, + // pub(crate)multi_scalar_mul_constraints: Vec, + // pub(crate)ec_add_constraints: Vec, + // pub(crate)recursion_constraints: Vec, + // pub(crate)honk_recursion_constraints: Vec, + // pub(crate)ivc_recursion_constraints: Vec, + // pub(crate)bigint_from_le_bytes_constraints: Vec, + // pub(crate)bigint_to_le_bytes_constraints: Vec, + // pub(crate)bigint_operations: Vec, + pub(crate) assert_equalities: Vec, + pub(crate) poly_triple_constraints: Vec, + pub(crate) quad_constraints: Vec, // Multiple opcode indices per block: - pub block_constraints: Vec>, + pub(crate) block_constraints: Vec>, } pub struct UltraTraceBlocks { @@ -136,7 +136,7 @@ pub struct UltraTraceBlocks { } impl UltraTraceBlocks { - pub(crate) fn get(&self) -> [&T; 8] { + pub fn get(&self) -> [&T; 8] { [ &self.pub_inputs, &self.arithmetic, @@ -148,17 +148,22 @@ impl UltraTraceBlocks { &self.poseidon_internal, ] } + + pub fn get_pub_inputs(&self) -> &T { + &self.pub_inputs + } } pub const NUM_WIRES: usize = 4; pub const NUM_SELECTORS: usize = 13; pub type UltraTraceBlock = ExecutionTraceBlock; + pub struct ExecutionTraceBlock { - pub(crate) wires: [Vec; NUM_WIRES], // vectors of indices into a witness variables array - pub(crate) selectors: [Vec; NUM_SELECTORS], - pub(crate) has_ram_rom: bool, // does the block contain RAM/ROM gates - pub(crate) is_pub_inputs: bool, // is this the public inputs block - pub(crate) fixed_size: u32, // Fixed size for use in structured trace + pub wires: [Vec; NUM_WIRES], // vectors of indices into a witness variables array + pub selectors: [Vec; NUM_SELECTORS], + pub has_ram_rom: bool, // does the block contain RAM/ROM gates + pub is_pub_inputs: bool, // is this the public inputs block + pub(crate) fixed_size: u32, // Fixed size for use in structured trace } impl Default @@ -214,75 +219,75 @@ impl UltraTraceBlock { const Q_POSEIDON2_EXTERNAL: usize = 11; // column 11 const Q_POSEIDON2_INTERNAL: usize = 12; // column 12 - pub fn w_l(&mut self) -> &mut Vec { + pub(crate) fn w_l(&mut self) -> &mut Vec { &mut self.wires[Self::W_L] } - pub fn w_r(&mut self) -> &mut Vec { + pub(crate) fn w_r(&mut self) -> &mut Vec { &mut self.wires[Self::W_R] } - pub fn w_o(&mut self) -> &mut Vec { + pub(crate) fn w_o(&mut self) -> &mut Vec { &mut self.wires[Self::W_O] } - pub fn w_4(&mut self) -> &mut Vec { + pub(crate) fn w_4(&mut self) -> &mut Vec { &mut self.wires[Self::W_4] } - pub fn q_m(&mut self) -> &mut Vec { + pub(crate) fn q_m(&mut self) -> &mut Vec { &mut self.selectors[Self::Q_M] } - pub fn q_c(&mut self) -> &mut Vec { + pub(crate) fn q_c(&mut self) -> &mut Vec { &mut self.selectors[Self::Q_C] } - pub fn q_1(&mut self) -> &mut Vec { + pub(crate) fn q_1(&mut self) -> &mut Vec { &mut self.selectors[Self::Q_1] } - pub fn q_2(&mut self) -> &mut Vec { + pub(crate) fn q_2(&mut self) -> &mut Vec { &mut self.selectors[Self::Q_2] } - pub fn q_3(&mut self) -> &mut Vec { + pub(crate) fn q_3(&mut self) -> &mut Vec { &mut self.selectors[Self::Q_3] } - pub fn q_4(&mut self) -> &mut Vec { + pub(crate) fn q_4(&mut self) -> &mut Vec { &mut self.selectors[Self::Q_4] } - pub fn q_arith(&mut self) -> &mut Vec { + pub(crate) fn q_arith(&mut self) -> &mut Vec { &mut self.selectors[Self::Q_ARITH] } - pub fn q_delta_range(&mut self) -> &mut Vec { + pub(crate) fn q_delta_range(&mut self) -> &mut Vec { &mut self.selectors[Self::Q_DELTA_RANGE] } - pub fn q_elliptic(&mut self) -> &mut Vec { + pub(crate) fn q_elliptic(&mut self) -> &mut Vec { &mut self.selectors[Self::Q_ELLIPTIC] } - pub fn q_aux(&mut self) -> &mut Vec { + pub(crate) fn q_aux(&mut self) -> &mut Vec { &mut self.selectors[Self::Q_AUX] } - pub fn q_lookup_type(&mut self) -> &mut Vec { + pub(crate) fn q_lookup_type(&mut self) -> &mut Vec { &mut self.selectors[Self::Q_LOOKUP_TYPE] } - pub fn q_poseidon2_external(&mut self) -> &mut Vec { + pub(crate) fn q_poseidon2_external(&mut self) -> &mut Vec { &mut self.selectors[Self::Q_POSEIDON2_EXTERNAL] } - pub fn q_poseidon2_internal(&mut self) -> &mut Vec { + pub(crate) fn q_poseidon2_internal(&mut self) -> &mut Vec { &mut self.selectors[Self::Q_POSEIDON2_INTERNAL] } - pub fn populate_wires(&mut self, idx1: u32, idx2: u32, idx3: u32, idx4: u32) { + pub(crate) fn populate_wires(&mut self, idx1: u32, idx2: u32, idx3: u32, idx4: u32) { self.w_l().push(idx1); self.w_r().push(idx2); self.w_o().push(idx3); @@ -298,20 +303,23 @@ impl UltraTraceBlock { } } -pub struct GateCounter { +pub(crate) struct GateCounter { collect_gates_per_opcode: bool, prev_gate_count: usize, } impl GateCounter { - pub fn new(collect_gates_per_opcode: bool) -> Self { + pub(crate) fn new(collect_gates_per_opcode: bool) -> Self { Self { collect_gates_per_opcode, prev_gate_count: 0, } } - pub(crate) fn compute_diff(&mut self, builder: &UltraCircuitBuilder

) -> usize { + pub(crate) fn compute_diff>( + &mut self, + builder: &GenericUltraCircuitBuilder, + ) -> usize { if !self.collect_gates_per_opcode { return 0; } @@ -321,9 +329,9 @@ impl GateCounter { diff } - pub(crate) fn track_diff( + pub(crate) fn track_diff>( &mut self, - builder: &UltraCircuitBuilder

, + builder: &GenericUltraCircuitBuilder, gates_per_opcode: &mut [usize], opcode_index: usize, ) { @@ -333,7 +341,7 @@ impl GateCounter { } } -pub struct RecursionConstraint { +pub(crate) struct RecursionConstraint { // An aggregation state is represented by two G1 affine elements. Each G1 point has // two field element coordinates (x, y). Thus, four field elements key: Vec, @@ -347,11 +355,11 @@ impl RecursionConstraint { const NUM_AGGREGATION_ELEMENTS: usize = 4; } -pub const AGGREGATION_OBJECT_SIZE: usize = 16; -pub type AggregationObjectIndices = [u32; AGGREGATION_OBJECT_SIZE]; -pub type AggregationObjectPubInputIndices = [u32; AGGREGATION_OBJECT_SIZE]; +pub(crate) const AGGREGATION_OBJECT_SIZE: usize = 16; +pub(crate) type AggregationObjectIndices = [u32; AGGREGATION_OBJECT_SIZE]; +pub(crate) type AggregationObjectPubInputIndices = [u32; AGGREGATION_OBJECT_SIZE]; -pub struct RomTable { +pub(crate) struct RomTable { raw_entries: Vec>, entries: Vec>, length: usize, @@ -360,7 +368,7 @@ pub struct RomTable { } impl RomTable { - pub fn new(table_entries: Vec>) -> Self { + pub(crate) fn new(table_entries: Vec>) -> Self { let raw_entries = table_entries; let length = raw_entries.len(); @@ -378,10 +386,10 @@ impl RomTable { } } - pub fn index_field_ct( + pub(crate) fn index_field_ct>( &mut self, index: &FieldCT, - builder: &mut UltraCircuitBuilder

, + builder: &mut GenericUltraCircuitBuilder, ) -> FieldCT where F: From, @@ -402,8 +410,10 @@ impl RomTable { FieldCT::from_witness_index(output_idx) } - fn initialize_table(&mut self, builder: &mut UltraCircuitBuilder

) - where + fn initialize_table>( + &mut self, + builder: &mut GenericUltraCircuitBuilder, + ) where F: From, P::ScalarField: From, { @@ -442,7 +452,7 @@ impl Index for RomTable { } } -pub struct RamTable { +pub(crate) struct RamTable { raw_entries: Vec>, index_initialized: Vec, length: usize, @@ -452,7 +462,7 @@ pub struct RamTable { } impl RamTable { - pub fn new(table_entries: Vec>) -> Self { + pub(crate) fn new(table_entries: Vec>) -> Self { let raw_entries = table_entries; let length = raw_entries.len(); let index_initialized = vec![false; length]; @@ -474,7 +484,7 @@ impl RamTable { } #[derive(Clone, Debug)] -pub struct FieldCT { +pub(crate) struct FieldCT { pub(crate) additive_constant: F, pub(crate) multiplicative_constant: F, pub(crate) witness_index: u32, @@ -483,7 +493,7 @@ pub struct FieldCT { impl FieldCT { const IS_CONSTANT: u32 = u32::MAX; - pub fn from_field(value: F) -> Self { + pub(crate) fn from_field(value: F) -> Self { Self { additive_constant: value, multiplicative_constant: F::one(), @@ -491,7 +501,7 @@ impl FieldCT { } } - pub fn from_witness_index(witness_index: u32) -> Self { + pub(crate) fn from_witness_index(witness_index: u32) -> Self { Self { additive_constant: F::zero(), multiplicative_constant: F::one(), @@ -499,9 +509,10 @@ impl FieldCT { } } - pub fn from_witness( + // TODO this is just implemented for the plain backend + pub(crate) fn from_witness>( input: P::ScalarField, - builder: &mut UltraCircuitBuilder

, + builder: &mut GenericUltraCircuitBuilder, ) -> Self where F: From, @@ -510,7 +521,7 @@ impl FieldCT { Self::from_witness_ct(witness) } - pub fn from_witness_ct(value: WitnessCT) -> Self { + pub(crate) fn from_witness_ct(value: WitnessCT) -> Self { Self { additive_constant: F::zero(), multiplicative_constant: F::one(), @@ -518,20 +529,24 @@ impl FieldCT { } } - pub fn get_value(&self, builder: &UltraCircuitBuilder

) -> F + pub(crate) fn get_value>( + &self, + builder: &GenericUltraCircuitBuilder, + ) -> F where F: From, { if self.witness_index != Self::IS_CONSTANT { - self.multiplicative_constant - * F::from(builder.get_variable(self.witness_index as usize)) - + self.additive_constant + let variable = builder + .get_variable(self.witness_index as usize) + .public_into_field(); // TODO this is just implemented for the Plain backend + self.multiplicative_constant * F::from(variable) + self.additive_constant } else { self.additive_constant.to_owned() } } - pub fn get_witness_index(&self) -> u32 { + pub(crate) fn get_witness_index(&self) -> u32 { self.witness_index } @@ -542,8 +557,11 @@ impl FieldCT { * succeeds or fails. This can lead to confusion when debugging. If you want to log the inputs, do so before * calling this method. */ - pub fn assert_equal(&self, other: &Self, builder: &mut UltraCircuitBuilder

) - where + pub(crate) fn assert_equal>( + &self, + other: &Self, + builder: &mut GenericUltraCircuitBuilder, + ) where F: From, P::ScalarField: From, { @@ -569,7 +587,10 @@ impl FieldCT { self.witness_index == Self::IS_CONSTANT } - fn normalize(&self, builder: &mut UltraCircuitBuilder

) -> Self + fn normalize>( + &self, + builder: &mut GenericUltraCircuitBuilder, + ) -> Self where F: From, P::ScalarField: From, @@ -585,10 +606,14 @@ impl FieldCT { // We need a new gate to enforce that the `result` was correctly calculated from `this`. let mut result = FieldCT::default(); - let value = F::from(builder.get_variable(self.witness_index as usize)); + let value = F::from( + builder + .get_variable(self.witness_index as usize) + .public_into_field(), + ); // TODO this is just implemented for the Plain backend let out = self.multiplicative_constant * value + self.additive_constant; - result.witness_index = builder.add_variable(P::ScalarField::from(out)); + result.witness_index = builder.add_variable(S::from_public(P::ScalarField::from(out))); result.additive_constant = F::zero(); result.multiplicative_constant = F::one(); @@ -626,7 +651,8 @@ impl Default for FieldCT { } } -pub struct WitnessCT { +// TODO this is just implemented for the Plain backend +pub(crate) struct WitnessCT { pub(crate) witness: F, pub(crate) witness_index: u32, } @@ -634,14 +660,14 @@ pub struct WitnessCT { impl WitnessCT { const IS_CONSTANT: u32 = FieldCT::::IS_CONSTANT; - pub fn from_field( + pub(crate) fn from_field>( value: P::ScalarField, - builder: &mut UltraCircuitBuilder

, + builder: &mut GenericUltraCircuitBuilder, ) -> Self where F: From, { - builder.add_variable(value); + builder.add_variable(S::from_public(value)); Self { witness: F::from(value), witness_index: Self::IS_CONSTANT, @@ -650,7 +676,7 @@ impl WitnessCT { } #[derive(Default)] -pub struct RomRecord { +pub(crate) struct RomRecord { pub(crate) index_witness: u32, pub(crate) value_column1_witness: u32, pub(crate) value_column2_witness: u32, @@ -660,7 +686,7 @@ pub struct RomRecord { } #[derive(Default)] -pub struct RomTranscript { +pub(crate) struct RomTranscript { // Contains the value of each index of the array pub(crate) state: Vec<[u32; 2]>, @@ -676,7 +702,7 @@ enum AccessType { Write, } -pub struct RamRecord { +pub(crate) struct RamRecord { pub(crate) index_witness: u32, pub(crate) timestamp_witness: u32, pub(crate) value_witness: u32, @@ -701,7 +727,7 @@ impl Default for RamRecord { } #[derive(Default)] -pub struct RamTranscript { +pub(crate) struct RamTranscript { // Contains the value of each index of the array pub(crate) state: Vec, @@ -716,7 +742,7 @@ pub struct RamTranscript { } #[derive(PartialEq, Eq)] -pub enum AuxSelectors { +pub(crate) enum AuxSelectors { None, LimbAccumulate1, LimbAccumulate2, @@ -732,13 +758,13 @@ pub enum AuxSelectors { } #[derive(Clone)] -pub struct LookupEntry { +pub(crate) struct LookupEntry { pub(crate) key: [BigUint; 2], pub(crate) value: [F; 2], } impl LookupEntry { - pub fn to_table_components(&self, use_two_key: bool) -> [F; 3] { + pub(crate) fn to_table_components(&self, use_two_key: bool) -> [F; 3] { [ F::from(self.key[0].to_owned()), if use_two_key { @@ -755,7 +781,7 @@ impl LookupEntry { } } -pub struct PlookupBasicTable { +pub(crate) struct PlookupBasicTable { pub(crate) id: BasicTableId, pub(crate) table_index: usize, pub(crate) use_twin_keys: bool, @@ -799,7 +825,7 @@ impl PlookupBasicTable { } impl PlookupBasicTable { - pub fn len(&self) -> usize { + pub(crate) fn len(&self) -> usize { assert_eq!(self.column_1.len(), self.column_2.len()); assert_eq!(self.column_1.len(), self.column_3.len()); self.column_1.len() @@ -834,7 +860,7 @@ impl PlookupBasicTable { table } - pub fn create_basic_table(id: BasicTableId, index: usize) -> Self { + pub(crate) fn create_basic_table(id: BasicTableId, index: usize) -> Self { // TODO this is a dummy implementation assert!(id == BasicTableId::HonkDummyBasic1 || id == BasicTableId::HonkDummyBasic2); @@ -865,7 +891,7 @@ impl PlookupBasicTable { } #[derive(Default)] -pub struct LookupHashMap { +pub(crate) struct LookupHashMap { pub(crate) index_map: HashMap<[F; 3], usize>, // TODO they have a different hash function } @@ -877,7 +903,7 @@ impl Index<[F; 3]> for LookupHashMap { } } -pub struct PlookupMultiTable { +pub(crate) struct PlookupMultiTable { pub(crate) column_1_coefficients: Vec, pub(crate) column_2_coefficients: Vec, pub(crate) column_3_coefficients: Vec, @@ -963,7 +989,7 @@ impl PlookupMultiTable { } #[derive(Default)] -pub struct ReadData { +pub(crate) struct ReadData { pub(crate) lookup_entries: Vec>, pub(crate) columns: [Vec; 3], } @@ -982,13 +1008,13 @@ impl IndexMut for ReadData { } } -pub enum ColumnIdx { +pub(crate) enum ColumnIdx { C1, C2, C3, } -pub struct RangeList { +pub(crate) struct RangeList { pub(crate) target_range: u64, pub(crate) range_tag: u32, pub(crate) tau_tag: u32, @@ -996,7 +1022,7 @@ pub struct RangeList { } #[derive(Clone)] -pub struct CachedPartialNonNativeFieldMultiplication { +pub(crate) struct CachedPartialNonNativeFieldMultiplication { pub(crate) a: [u32; 5], pub(crate) b: [u32; 5], pub(crate) lo_0: F, @@ -1069,13 +1095,13 @@ impl Hash for CachedPartialNonNativeFieldMultiplication { } #[derive(Clone)] -pub(crate) struct CycleNode { - pub(crate) wire_index: u32, - pub(crate) gate_index: u32, +pub struct CycleNode { + pub wire_index: u32, + pub gate_index: u32, } -pub(crate) type CyclicPermutation = Vec; +pub type CyclicPermutation = Vec; -pub struct TraceData<'a, P: Pairing> { +pub(crate) struct TraceData<'a, P: Pairing> { pub(crate) wires: [&'a mut Polynomial; NUM_WIRES], pub(crate) selectors: [&'a mut Polynomial; NUM_SELECTORS], pub(crate) copy_cycles: Vec, @@ -1126,6 +1152,68 @@ impl<'a, P: Pairing> TraceData<'a, P> { pub_inputs_offset: 0, } } + + pub(crate) fn construct_trace_data( + &mut self, + builder: &mut UltraCircuitBuilder

, + is_structured: bool, + ) { + tracing::info!("Construct trace data"); + // Complete the public inputs execution trace block from builder.public_inputs + builder.populate_public_inputs_block(); + + let mut offset = 1; // Offset at which to place each block in the trace polynomials + // For each block in the trace, populate wire polys, copy cycles and selector polys + + for block in builder.blocks.get() { + let block_size = block.len(); + + // Update wire polynomials and copy cycles + // NB: The order of row/column loops is arbitrary but needs to be row/column to match old copy_cycle code + + for block_row_idx in 0..block_size { + for wire_idx in 0..NUM_WIRES { + let var_idx = block.wires[wire_idx][block_row_idx] as usize; // an index into the variables array + let real_var_idx = builder.real_variable_index[var_idx] as usize; + let trace_row_idx = block_row_idx + offset; + // Insert the real witness values from this block into the wire polys at the correct offset + self.wires[wire_idx][trace_row_idx] = builder.get_variable(var_idx); + // Add the address of the witness value to its corresponding copy cycle + self.copy_cycles[real_var_idx].push(CycleNode { + wire_index: wire_idx as u32, + gate_index: trace_row_idx as u32, + }); + } + } + + // Insert the selector values for this block into the selector polynomials at the correct offset + // TODO(https://github.com/AztecProtocol/barretenberg/issues/398): implicit arithmetization/flavor consistency + for (selector_poly, selector) in self.selectors.iter_mut().zip(block.selectors.iter()) { + debug_assert_eq!(selector.len(), block_size); + + for (src, des) in selector.iter().zip(selector_poly.iter_mut().skip(offset)) { + *des = *src; + } + } + + // Store the offset of the block containing RAM/ROM read/write gates for use in updating memory records + if block.has_ram_rom { + self.ram_rom_offset = offset as u32; + } + // Store offset of public inputs block for use in the pub(crate)input mechanism of the permutation argument + if block.is_pub_inputs { + self.pub_inputs_offset = offset as u32; + } + + // If the trace is structured, we populate the data from the next block at a fixed block size offset + if is_structured { + offset += block.get_fixed_size() as usize; + } else { + // otherwise, the next block starts immediately following the previous one + offset += block_size; + } + } + } } #[derive(Clone, Debug, Default)] @@ -1148,7 +1236,7 @@ impl PermutationSubgroupElement { } pub(crate) type Mapping = [Vec; NUM_WIRES]; -pub struct PermutationMapping { +pub(crate) struct PermutationMapping { pub(crate) sigmas: Mapping, pub(crate) ids: Mapping, } diff --git a/co-noir/ultrahonk/src/poseidon2/mod.rs b/co-noir/ultrahonk/src/poseidon2/mod.rs index 758de303..66f7cbbe 100644 --- a/co-noir/ultrahonk/src/poseidon2/mod.rs +++ b/co-noir/ultrahonk/src/poseidon2/mod.rs @@ -1,17 +1,3 @@ -pub mod poseidon2_bn254; -pub mod poseidon2_params; -pub mod poseidon2_permutation; - -use ark_ff::PrimeField; -use eyre::Error; -use num_bigint::BigUint; -use num_traits::Num; - -pub(super) fn field_from_hex_string(str: &str) -> Result { - let tmp = match str.strip_prefix("0x") { - Some(t) => BigUint::from_str_radix(t, 16), - None => BigUint::from_str_radix(str, 16), - }; - - Ok(tmp?.into()) -} +pub(crate) mod poseidon2_bn254; +pub(crate) mod poseidon2_params; +pub(crate) mod poseidon2_permutation; diff --git a/co-noir/ultrahonk/src/poseidon2/poseidon2_bn254.rs b/co-noir/ultrahonk/src/poseidon2/poseidon2_bn254.rs index 2d0216b7..5c953233 100644 --- a/co-noir/ultrahonk/src/poseidon2/poseidon2_bn254.rs +++ b/co-noir/ultrahonk/src/poseidon2/poseidon2_bn254.rs @@ -1,5 +1,5 @@ use super::poseidon2_params::Poseidon2Params; -use crate::poseidon2::field_from_hex_string; +use crate::Utils; use lazy_static::lazy_static; use std::sync::Arc; @@ -11,124 +11,124 @@ const ROUNDS_F: usize = 8; const ROUNDS_P: usize = 56; lazy_static! { - pub static ref MAT_DIAG_M_1: [Scalar; T] = { + pub(crate) static ref MAT_DIAG_M_1: [Scalar; T] = { [ - field_from_hex_string("0x10dc6e9c006ea38b04b1e03b4bd9490c0d03f98929ca1d7fb56821fd19d3b6e7").unwrap(), - field_from_hex_string("0x0c28145b6a44df3e0149b3d0a30b3bb599df9756d4dd9b84a86b38cfb45a740b").unwrap(), - field_from_hex_string("0x00544b8338791518b2c7645a50392798b21f75bb60e3596170067d00141cac15").unwrap(), - field_from_hex_string("0x222c01175718386f2e2e82eb122789e352e105a3b8fa852613bc534433ee428b").unwrap(), + Utils::field_from_hex_string("0x10dc6e9c006ea38b04b1e03b4bd9490c0d03f98929ca1d7fb56821fd19d3b6e7").unwrap(), + Utils::field_from_hex_string("0x0c28145b6a44df3e0149b3d0a30b3bb599df9756d4dd9b84a86b38cfb45a740b").unwrap(), + Utils::field_from_hex_string("0x00544b8338791518b2c7645a50392798b21f75bb60e3596170067d00141cac15").unwrap(), + Utils::field_from_hex_string("0x222c01175718386f2e2e82eb122789e352e105a3b8fa852613bc534433ee428b").unwrap(), ] }; - pub static ref EXTERNAL_RC: Vec<[Scalar; T]> = + pub(crate) static ref EXTERNAL_RC: Vec<[Scalar; T]> = vec![ // First external [ - field_from_hex_string("0x19b849f69450b06848da1d39bd5e4a4302bb86744edc26238b0878e269ed23e5").unwrap(), - field_from_hex_string("0x265ddfe127dd51bd7239347b758f0a1320eb2cc7450acc1dad47f80c8dcf34d6").unwrap(), - field_from_hex_string("0x199750ec472f1809e0f66a545e1e51624108ac845015c2aa3dfc36bab497d8aa").unwrap(), - field_from_hex_string("0x157ff3fe65ac7208110f06a5f74302b14d743ea25067f0ffd032f787c7f1cdf8").unwrap(), + Utils::field_from_hex_string("0x19b849f69450b06848da1d39bd5e4a4302bb86744edc26238b0878e269ed23e5").unwrap(), + Utils::field_from_hex_string("0x265ddfe127dd51bd7239347b758f0a1320eb2cc7450acc1dad47f80c8dcf34d6").unwrap(), + Utils::field_from_hex_string("0x199750ec472f1809e0f66a545e1e51624108ac845015c2aa3dfc36bab497d8aa").unwrap(), + Utils::field_from_hex_string("0x157ff3fe65ac7208110f06a5f74302b14d743ea25067f0ffd032f787c7f1cdf8").unwrap(), ], [ - field_from_hex_string("0x2e49c43c4569dd9c5fd35ac45fca33f10b15c590692f8beefe18f4896ac94902").unwrap(), - field_from_hex_string("0x0e35fb89981890520d4aef2b6d6506c3cb2f0b6973c24fa82731345ffa2d1f1e").unwrap(), - field_from_hex_string("0x251ad47cb15c4f1105f109ae5e944f1ba9d9e7806d667ffec6fe723002e0b996").unwrap(), - field_from_hex_string("0x13da07dc64d428369873e97160234641f8beb56fdd05e5f3563fa39d9c22df4e").unwrap(), + Utils::field_from_hex_string("0x2e49c43c4569dd9c5fd35ac45fca33f10b15c590692f8beefe18f4896ac94902").unwrap(), + Utils::field_from_hex_string("0x0e35fb89981890520d4aef2b6d6506c3cb2f0b6973c24fa82731345ffa2d1f1e").unwrap(), + Utils::field_from_hex_string("0x251ad47cb15c4f1105f109ae5e944f1ba9d9e7806d667ffec6fe723002e0b996").unwrap(), + Utils::field_from_hex_string("0x13da07dc64d428369873e97160234641f8beb56fdd05e5f3563fa39d9c22df4e").unwrap(), ], [ - field_from_hex_string("0x0c009b84e650e6d23dc00c7dccef7483a553939689d350cd46e7b89055fd4738").unwrap(), - field_from_hex_string("0x011f16b1c63a854f01992e3956f42d8b04eb650c6d535eb0203dec74befdca06").unwrap(), - field_from_hex_string("0x0ed69e5e383a688f209d9a561daa79612f3f78d0467ad45485df07093f367549").unwrap(), - field_from_hex_string("0x04dba94a7b0ce9e221acad41472b6bbe3aec507f5eb3d33f463672264c9f789b").unwrap(), + Utils::field_from_hex_string("0x0c009b84e650e6d23dc00c7dccef7483a553939689d350cd46e7b89055fd4738").unwrap(), + Utils::field_from_hex_string("0x011f16b1c63a854f01992e3956f42d8b04eb650c6d535eb0203dec74befdca06").unwrap(), + Utils::field_from_hex_string("0x0ed69e5e383a688f209d9a561daa79612f3f78d0467ad45485df07093f367549").unwrap(), + Utils::field_from_hex_string("0x04dba94a7b0ce9e221acad41472b6bbe3aec507f5eb3d33f463672264c9f789b").unwrap(), ], [ - field_from_hex_string("0x0a3f2637d840f3a16eb094271c9d237b6036757d4bb50bf7ce732ff1d4fa28e8").unwrap(), - field_from_hex_string("0x259a666f129eea198f8a1c502fdb38fa39b1f075569564b6e54a485d1182323f").unwrap(), - field_from_hex_string("0x28bf7459c9b2f4c6d8e7d06a4ee3a47f7745d4271038e5157a32fdf7ede0d6a1").unwrap(), - field_from_hex_string("0x0a1ca941f057037526ea200f489be8d4c37c85bbcce6a2aeec91bd6941432447").unwrap(), + Utils::field_from_hex_string("0x0a3f2637d840f3a16eb094271c9d237b6036757d4bb50bf7ce732ff1d4fa28e8").unwrap(), + Utils::field_from_hex_string("0x259a666f129eea198f8a1c502fdb38fa39b1f075569564b6e54a485d1182323f").unwrap(), + Utils::field_from_hex_string("0x28bf7459c9b2f4c6d8e7d06a4ee3a47f7745d4271038e5157a32fdf7ede0d6a1").unwrap(), + Utils::field_from_hex_string("0x0a1ca941f057037526ea200f489be8d4c37c85bbcce6a2aeec91bd6941432447").unwrap(), ], // Second external [ - field_from_hex_string("0x1797130f4b7a3e1777eb757bc6f287f6ab0fb85f6be63b09f3b16ef2b1405d38").unwrap(), - field_from_hex_string("0x0a76225dc04170ae3306c85abab59e608c7f497c20156d4d36c668555decc6e5").unwrap(), - field_from_hex_string("0x1fffb9ec1992d66ba1e77a7b93209af6f8fa76d48acb664796174b5326a31a5c").unwrap(), - field_from_hex_string("0x25721c4fc15a3f2853b57c338fa538d85f8fbba6c6b9c6090611889b797b9c5f").unwrap(), + Utils::field_from_hex_string("0x1797130f4b7a3e1777eb757bc6f287f6ab0fb85f6be63b09f3b16ef2b1405d38").unwrap(), + Utils::field_from_hex_string("0x0a76225dc04170ae3306c85abab59e608c7f497c20156d4d36c668555decc6e5").unwrap(), + Utils::field_from_hex_string("0x1fffb9ec1992d66ba1e77a7b93209af6f8fa76d48acb664796174b5326a31a5c").unwrap(), + Utils::field_from_hex_string("0x25721c4fc15a3f2853b57c338fa538d85f8fbba6c6b9c6090611889b797b9c5f").unwrap(), ], [ - field_from_hex_string("0x0c817fd42d5f7a41215e3d07ba197216adb4c3790705da95eb63b982bfcaf75a").unwrap(), - field_from_hex_string("0x13abe3f5239915d39f7e13c2c24970b6df8cf86ce00a22002bc15866e52b5a96").unwrap(), - field_from_hex_string("0x2106feea546224ea12ef7f39987a46c85c1bc3dc29bdbd7a92cd60acb4d391ce").unwrap(), - field_from_hex_string("0x21ca859468a746b6aaa79474a37dab49f1ca5a28c748bc7157e1b3345bb0f959").unwrap(), + Utils::field_from_hex_string("0x0c817fd42d5f7a41215e3d07ba197216adb4c3790705da95eb63b982bfcaf75a").unwrap(), + Utils::field_from_hex_string("0x13abe3f5239915d39f7e13c2c24970b6df8cf86ce00a22002bc15866e52b5a96").unwrap(), + Utils::field_from_hex_string("0x2106feea546224ea12ef7f39987a46c85c1bc3dc29bdbd7a92cd60acb4d391ce").unwrap(), + Utils::field_from_hex_string("0x21ca859468a746b6aaa79474a37dab49f1ca5a28c748bc7157e1b3345bb0f959").unwrap(), ], [ - field_from_hex_string("0x05ccd6255c1e6f0c5cf1f0df934194c62911d14d0321662a8f1a48999e34185b").unwrap(), - field_from_hex_string("0x0f0e34a64b70a626e464d846674c4c8816c4fb267fe44fe6ea28678cb09490a4").unwrap(), - field_from_hex_string("0x0558531a4e25470c6157794ca36d0e9647dbfcfe350d64838f5b1a8a2de0d4bf").unwrap(), - field_from_hex_string("0x09d3dca9173ed2faceea125157683d18924cadad3f655a60b72f5864961f1455").unwrap(), + Utils::field_from_hex_string("0x05ccd6255c1e6f0c5cf1f0df934194c62911d14d0321662a8f1a48999e34185b").unwrap(), + Utils::field_from_hex_string("0x0f0e34a64b70a626e464d846674c4c8816c4fb267fe44fe6ea28678cb09490a4").unwrap(), + Utils::field_from_hex_string("0x0558531a4e25470c6157794ca36d0e9647dbfcfe350d64838f5b1a8a2de0d4bf").unwrap(), + Utils::field_from_hex_string("0x09d3dca9173ed2faceea125157683d18924cadad3f655a60b72f5864961f1455").unwrap(), ], [ - field_from_hex_string("0x0328cbd54e8c0913493f866ed03d218bf23f92d68aaec48617d4c722e5bd4335").unwrap(), - field_from_hex_string("0x2bf07216e2aff0a223a487b1a7094e07e79e7bcc9798c648ee3347dd5329d34b").unwrap(), - field_from_hex_string("0x1daf345a58006b736499c583cb76c316d6f78ed6a6dffc82111e11a63fe412df").unwrap(), - field_from_hex_string("0x176563472456aaa746b694c60e1823611ef39039b2edc7ff391e6f2293d2c404").unwrap(), + Utils::field_from_hex_string("0x0328cbd54e8c0913493f866ed03d218bf23f92d68aaec48617d4c722e5bd4335").unwrap(), + Utils::field_from_hex_string("0x2bf07216e2aff0a223a487b1a7094e07e79e7bcc9798c648ee3347dd5329d34b").unwrap(), + Utils::field_from_hex_string("0x1daf345a58006b736499c583cb76c316d6f78ed6a6dffc82111e11a63fe412df").unwrap(), + Utils::field_from_hex_string("0x176563472456aaa746b694c60e1823611ef39039b2edc7ff391e6f2293d2c404").unwrap(), ] ]; - pub static ref INTERNAL_RC: Vec = vec![ - field_from_hex_string("0x0c6f8f958be0e93053d7fd4fc54512855535ed1539f051dcb43a26fd926361cf").unwrap(), - field_from_hex_string("0x123106a93cd17578d426e8128ac9d90aa9e8a00708e296e084dd57e69caaf811").unwrap(), - field_from_hex_string("0x26e1ba52ad9285d97dd3ab52f8e840085e8fa83ff1e8f1877b074867cd2dee75").unwrap(), - field_from_hex_string("0x1cb55cad7bd133de18a64c5c47b9c97cbe4d8b7bf9e095864471537e6a4ae2c5").unwrap(), - field_from_hex_string("0x1dcd73e46acd8f8e0e2c7ce04bde7f6d2a53043d5060a41c7143f08e6e9055d0").unwrap(), - field_from_hex_string("0x011003e32f6d9c66f5852f05474a4def0cda294a0eb4e9b9b12b9bb4512e5574").unwrap(), - field_from_hex_string("0x2b1e809ac1d10ab29ad5f20d03a57dfebadfe5903f58bafed7c508dd2287ae8c").unwrap(), - field_from_hex_string("0x2539de1785b735999fb4dac35ee17ed0ef995d05ab2fc5faeaa69ae87bcec0a5").unwrap(), - field_from_hex_string("0x0c246c5a2ef8ee0126497f222b3e0a0ef4e1c3d41c86d46e43982cb11d77951d").unwrap(), - field_from_hex_string("0x192089c4974f68e95408148f7c0632edbb09e6a6ad1a1c2f3f0305f5d03b527b").unwrap(), - field_from_hex_string("0x1eae0ad8ab68b2f06a0ee36eeb0d0c058529097d91096b756d8fdc2fb5a60d85").unwrap(), - field_from_hex_string("0x179190e5d0e22179e46f8282872abc88db6e2fdc0dee99e69768bd98c5d06bfb").unwrap(), - field_from_hex_string("0x29bb9e2c9076732576e9a81c7ac4b83214528f7db00f31bf6cafe794a9b3cd1c").unwrap(), - field_from_hex_string("0x225d394e42207599403efd0c2464a90d52652645882aac35b10e590e6e691e08").unwrap(), - field_from_hex_string("0x064760623c25c8cf753d238055b444532be13557451c087de09efd454b23fd59").unwrap(), - field_from_hex_string("0x10ba3a0e01df92e87f301c4b716d8a394d67f4bf42a75c10922910a78f6b5b87").unwrap(), - field_from_hex_string("0x0e070bf53f8451b24f9c6e96b0c2a801cb511bc0c242eb9d361b77693f21471c").unwrap(), - field_from_hex_string("0x1b94cd61b051b04dd39755ff93821a73ccd6cb11d2491d8aa7f921014de252fb").unwrap(), - field_from_hex_string("0x1d7cb39bafb8c744e148787a2e70230f9d4e917d5713bb050487b5aa7d74070b").unwrap(), - field_from_hex_string("0x2ec93189bd1ab4f69117d0fe980c80ff8785c2961829f701bb74ac1f303b17db").unwrap(), - field_from_hex_string("0x2db366bfdd36d277a692bb825b86275beac404a19ae07a9082ea46bd83517926").unwrap(), - field_from_hex_string("0x062100eb485db06269655cf186a68532985275428450359adc99cec6960711b8").unwrap(), - field_from_hex_string("0x0761d33c66614aaa570e7f1e8244ca1120243f92fa59e4f900c567bf41f5a59b").unwrap(), - field_from_hex_string("0x20fc411a114d13992c2705aa034e3f315d78608a0f7de4ccf7a72e494855ad0d").unwrap(), - field_from_hex_string("0x25b5c004a4bdfcb5add9ec4e9ab219ba102c67e8b3effb5fc3a30f317250bc5a").unwrap(), - field_from_hex_string("0x23b1822d278ed632a494e58f6df6f5ed038b186d8474155ad87e7dff62b37f4b").unwrap(), - field_from_hex_string("0x22734b4c5c3f9493606c4ba9012499bf0f14d13bfcfcccaa16102a29cc2f69e0").unwrap(), - field_from_hex_string("0x26c0c8fe09eb30b7e27a74dc33492347e5bdff409aa3610254413d3fad795ce5").unwrap(), - field_from_hex_string("0x070dd0ccb6bd7bbae88eac03fa1fbb26196be3083a809829bbd626df348ccad9").unwrap(), - field_from_hex_string("0x12b6595bdb329b6fb043ba78bb28c3bec2c0a6de46d8c5ad6067c4ebfd4250da").unwrap(), - field_from_hex_string("0x248d97d7f76283d63bec30e7a5876c11c06fca9b275c671c5e33d95bb7e8d729").unwrap(), - field_from_hex_string("0x1a306d439d463b0816fc6fd64cc939318b45eb759ddde4aa106d15d9bd9baaaa").unwrap(), - field_from_hex_string("0x28a8f8372e3c38daced7c00421cb4621f4f1b54ddc27821b0d62d3d6ec7c56cf").unwrap(), - field_from_hex_string("0x0094975717f9a8a8bb35152f24d43294071ce320c829f388bc852183e1e2ce7e").unwrap(), - field_from_hex_string("0x04d5ee4c3aa78f7d80fde60d716480d3593f74d4f653ae83f4103246db2e8d65").unwrap(), - field_from_hex_string("0x2a6cf5e9aa03d4336349ad6fb8ed2269c7bef54b8822cc76d08495c12efde187").unwrap(), - field_from_hex_string("0x2304d31eaab960ba9274da43e19ddeb7f792180808fd6e43baae48d7efcba3f3").unwrap(), - field_from_hex_string("0x03fd9ac865a4b2a6d5e7009785817249bff08a7e0726fcb4e1c11d39d199f0b0").unwrap(), - field_from_hex_string("0x00b7258ded52bbda2248404d55ee5044798afc3a209193073f7954d4d63b0b64").unwrap(), - field_from_hex_string("0x159f81ada0771799ec38fca2d4bf65ebb13d3a74f3298db36272c5ca65e92d9a").unwrap(), - field_from_hex_string("0x1ef90e67437fbc8550237a75bc28e3bb9000130ea25f0c5471e144cf4264431f").unwrap(), - field_from_hex_string("0x1e65f838515e5ff0196b49aa41a2d2568df739bc176b08ec95a79ed82932e30d").unwrap(), - field_from_hex_string("0x2b1b045def3a166cec6ce768d079ba74b18c844e570e1f826575c1068c94c33f").unwrap(), - field_from_hex_string("0x0832e5753ceb0ff6402543b1109229c165dc2d73bef715e3f1c6e07c168bb173").unwrap(), - field_from_hex_string("0x02f614e9cedfb3dc6b762ae0a37d41bab1b841c2e8b6451bc5a8e3c390b6ad16").unwrap(), - field_from_hex_string("0x0e2427d38bd46a60dd640b8e362cad967370ebb777bedff40f6a0be27e7ed705").unwrap(), - field_from_hex_string("0x0493630b7c670b6deb7c84d414e7ce79049f0ec098c3c7c50768bbe29214a53a").unwrap(), - field_from_hex_string("0x22ead100e8e482674decdab17066c5a26bb1515355d5461a3dc06cc85327cea9").unwrap(), - field_from_hex_string("0x25b3e56e655b42cdaae2626ed2554d48583f1ae35626d04de5084e0b6d2a6f16").unwrap(), - field_from_hex_string("0x1e32752ada8836ef5837a6cde8ff13dbb599c336349e4c584b4fdc0a0cf6f9d0").unwrap(), - field_from_hex_string("0x2fa2a871c15a387cc50f68f6f3c3455b23c00995f05078f672a9864074d412e5").unwrap(), - field_from_hex_string("0x2f569b8a9a4424c9278e1db7311e889f54ccbf10661bab7fcd18e7c7a7d83505").unwrap(), - field_from_hex_string("0x044cb455110a8fdd531ade530234c518a7df93f7332ffd2144165374b246b43d").unwrap(), - field_from_hex_string("0x227808de93906d5d420246157f2e42b191fe8c90adfe118178ddc723a5319025").unwrap(), - field_from_hex_string("0x02fcca2934e046bc623adead873579865d03781ae090ad4a8579d2e7a6800355").unwrap(), - field_from_hex_string("0x0ef915f0ac120b876abccceb344a1d36bad3f3c5ab91a8ddcbec2e060d8befac").unwrap(), + pub(crate) static ref INTERNAL_RC: Vec = vec![ + Utils::field_from_hex_string("0x0c6f8f958be0e93053d7fd4fc54512855535ed1539f051dcb43a26fd926361cf").unwrap(), + Utils::field_from_hex_string("0x123106a93cd17578d426e8128ac9d90aa9e8a00708e296e084dd57e69caaf811").unwrap(), + Utils::field_from_hex_string("0x26e1ba52ad9285d97dd3ab52f8e840085e8fa83ff1e8f1877b074867cd2dee75").unwrap(), + Utils::field_from_hex_string("0x1cb55cad7bd133de18a64c5c47b9c97cbe4d8b7bf9e095864471537e6a4ae2c5").unwrap(), + Utils::field_from_hex_string("0x1dcd73e46acd8f8e0e2c7ce04bde7f6d2a53043d5060a41c7143f08e6e9055d0").unwrap(), + Utils::field_from_hex_string("0x011003e32f6d9c66f5852f05474a4def0cda294a0eb4e9b9b12b9bb4512e5574").unwrap(), + Utils::field_from_hex_string("0x2b1e809ac1d10ab29ad5f20d03a57dfebadfe5903f58bafed7c508dd2287ae8c").unwrap(), + Utils::field_from_hex_string("0x2539de1785b735999fb4dac35ee17ed0ef995d05ab2fc5faeaa69ae87bcec0a5").unwrap(), + Utils::field_from_hex_string("0x0c246c5a2ef8ee0126497f222b3e0a0ef4e1c3d41c86d46e43982cb11d77951d").unwrap(), + Utils::field_from_hex_string("0x192089c4974f68e95408148f7c0632edbb09e6a6ad1a1c2f3f0305f5d03b527b").unwrap(), + Utils::field_from_hex_string("0x1eae0ad8ab68b2f06a0ee36eeb0d0c058529097d91096b756d8fdc2fb5a60d85").unwrap(), + Utils::field_from_hex_string("0x179190e5d0e22179e46f8282872abc88db6e2fdc0dee99e69768bd98c5d06bfb").unwrap(), + Utils::field_from_hex_string("0x29bb9e2c9076732576e9a81c7ac4b83214528f7db00f31bf6cafe794a9b3cd1c").unwrap(), + Utils::field_from_hex_string("0x225d394e42207599403efd0c2464a90d52652645882aac35b10e590e6e691e08").unwrap(), + Utils::field_from_hex_string("0x064760623c25c8cf753d238055b444532be13557451c087de09efd454b23fd59").unwrap(), + Utils::field_from_hex_string("0x10ba3a0e01df92e87f301c4b716d8a394d67f4bf42a75c10922910a78f6b5b87").unwrap(), + Utils::field_from_hex_string("0x0e070bf53f8451b24f9c6e96b0c2a801cb511bc0c242eb9d361b77693f21471c").unwrap(), + Utils::field_from_hex_string("0x1b94cd61b051b04dd39755ff93821a73ccd6cb11d2491d8aa7f921014de252fb").unwrap(), + Utils::field_from_hex_string("0x1d7cb39bafb8c744e148787a2e70230f9d4e917d5713bb050487b5aa7d74070b").unwrap(), + Utils::field_from_hex_string("0x2ec93189bd1ab4f69117d0fe980c80ff8785c2961829f701bb74ac1f303b17db").unwrap(), + Utils::field_from_hex_string("0x2db366bfdd36d277a692bb825b86275beac404a19ae07a9082ea46bd83517926").unwrap(), + Utils::field_from_hex_string("0x062100eb485db06269655cf186a68532985275428450359adc99cec6960711b8").unwrap(), + Utils::field_from_hex_string("0x0761d33c66614aaa570e7f1e8244ca1120243f92fa59e4f900c567bf41f5a59b").unwrap(), + Utils::field_from_hex_string("0x20fc411a114d13992c2705aa034e3f315d78608a0f7de4ccf7a72e494855ad0d").unwrap(), + Utils::field_from_hex_string("0x25b5c004a4bdfcb5add9ec4e9ab219ba102c67e8b3effb5fc3a30f317250bc5a").unwrap(), + Utils::field_from_hex_string("0x23b1822d278ed632a494e58f6df6f5ed038b186d8474155ad87e7dff62b37f4b").unwrap(), + Utils::field_from_hex_string("0x22734b4c5c3f9493606c4ba9012499bf0f14d13bfcfcccaa16102a29cc2f69e0").unwrap(), + Utils::field_from_hex_string("0x26c0c8fe09eb30b7e27a74dc33492347e5bdff409aa3610254413d3fad795ce5").unwrap(), + Utils::field_from_hex_string("0x070dd0ccb6bd7bbae88eac03fa1fbb26196be3083a809829bbd626df348ccad9").unwrap(), + Utils::field_from_hex_string("0x12b6595bdb329b6fb043ba78bb28c3bec2c0a6de46d8c5ad6067c4ebfd4250da").unwrap(), + Utils::field_from_hex_string("0x248d97d7f76283d63bec30e7a5876c11c06fca9b275c671c5e33d95bb7e8d729").unwrap(), + Utils::field_from_hex_string("0x1a306d439d463b0816fc6fd64cc939318b45eb759ddde4aa106d15d9bd9baaaa").unwrap(), + Utils::field_from_hex_string("0x28a8f8372e3c38daced7c00421cb4621f4f1b54ddc27821b0d62d3d6ec7c56cf").unwrap(), + Utils::field_from_hex_string("0x0094975717f9a8a8bb35152f24d43294071ce320c829f388bc852183e1e2ce7e").unwrap(), + Utils::field_from_hex_string("0x04d5ee4c3aa78f7d80fde60d716480d3593f74d4f653ae83f4103246db2e8d65").unwrap(), + Utils::field_from_hex_string("0x2a6cf5e9aa03d4336349ad6fb8ed2269c7bef54b8822cc76d08495c12efde187").unwrap(), + Utils::field_from_hex_string("0x2304d31eaab960ba9274da43e19ddeb7f792180808fd6e43baae48d7efcba3f3").unwrap(), + Utils::field_from_hex_string("0x03fd9ac865a4b2a6d5e7009785817249bff08a7e0726fcb4e1c11d39d199f0b0").unwrap(), + Utils::field_from_hex_string("0x00b7258ded52bbda2248404d55ee5044798afc3a209193073f7954d4d63b0b64").unwrap(), + Utils::field_from_hex_string("0x159f81ada0771799ec38fca2d4bf65ebb13d3a74f3298db36272c5ca65e92d9a").unwrap(), + Utils::field_from_hex_string("0x1ef90e67437fbc8550237a75bc28e3bb9000130ea25f0c5471e144cf4264431f").unwrap(), + Utils::field_from_hex_string("0x1e65f838515e5ff0196b49aa41a2d2568df739bc176b08ec95a79ed82932e30d").unwrap(), + Utils::field_from_hex_string("0x2b1b045def3a166cec6ce768d079ba74b18c844e570e1f826575c1068c94c33f").unwrap(), + Utils::field_from_hex_string("0x0832e5753ceb0ff6402543b1109229c165dc2d73bef715e3f1c6e07c168bb173").unwrap(), + Utils::field_from_hex_string("0x02f614e9cedfb3dc6b762ae0a37d41bab1b841c2e8b6451bc5a8e3c390b6ad16").unwrap(), + Utils::field_from_hex_string("0x0e2427d38bd46a60dd640b8e362cad967370ebb777bedff40f6a0be27e7ed705").unwrap(), + Utils::field_from_hex_string("0x0493630b7c670b6deb7c84d414e7ce79049f0ec098c3c7c50768bbe29214a53a").unwrap(), + Utils::field_from_hex_string("0x22ead100e8e482674decdab17066c5a26bb1515355d5461a3dc06cc85327cea9").unwrap(), + Utils::field_from_hex_string("0x25b3e56e655b42cdaae2626ed2554d48583f1ae35626d04de5084e0b6d2a6f16").unwrap(), + Utils::field_from_hex_string("0x1e32752ada8836ef5837a6cde8ff13dbb599c336349e4c584b4fdc0a0cf6f9d0").unwrap(), + Utils::field_from_hex_string("0x2fa2a871c15a387cc50f68f6f3c3455b23c00995f05078f672a9864074d412e5").unwrap(), + Utils::field_from_hex_string("0x2f569b8a9a4424c9278e1db7311e889f54ccbf10661bab7fcd18e7c7a7d83505").unwrap(), + Utils::field_from_hex_string("0x044cb455110a8fdd531ade530234c518a7df93f7332ffd2144165374b246b43d").unwrap(), + Utils::field_from_hex_string("0x227808de93906d5d420246157f2e42b191fe8c90adfe118178ddc723a5319025").unwrap(), + Utils::field_from_hex_string("0x02fcca2934e046bc623adead873579865d03781ae090ad4a8579d2e7a6800355").unwrap(), + Utils::field_from_hex_string("0x0ef915f0ac120b876abccceb344a1d36bad3f3c5ab91a8ddcbec2e060d8befac").unwrap(), ]; pub static ref POSEIDON2_BN254_T4_PARAMS: Arc> = Arc::new(Poseidon2Params::new(ROUNDS_F, ROUNDS_P, *MAT_DIAG_M_1, EXTERNAL_RC.to_vec(), INTERNAL_RC.to_vec())); } diff --git a/co-noir/ultrahonk/src/poseidon2/poseidon2_params.rs b/co-noir/ultrahonk/src/poseidon2/poseidon2_params.rs index 81e9f356..36ee292a 100644 --- a/co-noir/ultrahonk/src/poseidon2/poseidon2_params.rs +++ b/co-noir/ultrahonk/src/poseidon2/poseidon2_params.rs @@ -11,7 +11,7 @@ pub struct Poseidon2Params { } impl Poseidon2Params { - pub fn new( + pub(crate) fn new( rounds_f: usize, rounds_p: usize, mat_internal_diag_m_1: [F; T], diff --git a/co-noir/ultrahonk/src/poseidon2/poseidon2_permutation.rs b/co-noir/ultrahonk/src/poseidon2/poseidon2_permutation.rs index e1fba7a5..bf692205 100644 --- a/co-noir/ultrahonk/src/poseidon2/poseidon2_permutation.rs +++ b/co-noir/ultrahonk/src/poseidon2/poseidon2_permutation.rs @@ -4,12 +4,12 @@ use ark_ff::PrimeField; use std::sync::Arc; #[derive(Clone, Debug)] -pub struct Poseidon2 { +pub(crate) struct Poseidon2 { pub(crate) params: Arc>, } impl Poseidon2 { - pub fn new(params: &Arc>) -> Self { + pub(crate) fn new(params: &Arc>) -> Self { Self { params: Arc::clone(params), } @@ -171,7 +171,7 @@ impl FieldHash for Poseidon2< #[cfg(test)] mod test { use super::*; - use crate::poseidon2::{field_from_hex_string, poseidon2_bn254::POSEIDON2_BN254_T4_PARAMS}; + use crate::{poseidon2::poseidon2_bn254::POSEIDON2_BN254_T4_PARAMS, Utils}; use rand::thread_rng; const TESTRUNS: usize = 10; @@ -219,19 +219,19 @@ mod test { ark_bn254::Fr::from(3u64), ]; let expected = [ - field_from_hex_string( + Utils::field_from_hex_string( "0x01bd538c2ee014ed5141b29e9ae240bf8db3fe5b9a38629a9647cf8d76c01737", ) .unwrap(), - field_from_hex_string( + Utils::field_from_hex_string( "0x239b62e7db98aa3a2a8f6a0d2fa1709e7a35959aa6c7034814d9daa90cbac662", ) .unwrap(), - field_from_hex_string( + Utils::field_from_hex_string( "0x04cbb44c61d928ed06808456bf758cbf0c18d1e15a7b6dbc8245fa7515d5e3cb", ) .unwrap(), - field_from_hex_string( + Utils::field_from_hex_string( "0x2e11c5cff2a22c64d01304b778d78f6998eff1ab73163a35603f54794c30847a", ) .unwrap(), @@ -243,37 +243,37 @@ mod test { #[test] fn posedon2_bn254_t4_kat2() { let input = [ - field_from_hex_string( + Utils::field_from_hex_string( "9a807b615c4d3e2fa0b1c2d3e4f56789fedcba9876543210abcdef0123456789", ) .unwrap(), - field_from_hex_string( + Utils::field_from_hex_string( "9a807b615c4d3e2fa0b1c2d3e4f56789fedcba9876543210abcdef0123456789", ) .unwrap(), - field_from_hex_string( + Utils::field_from_hex_string( "0x9a807b615c4d3e2fa0b1c2d3e4f56789fedcba9876543210abcdef0123456789", ) .unwrap(), - field_from_hex_string( + Utils::field_from_hex_string( "0x9a807b615c4d3e2fa0b1c2d3e4f56789fedcba9876543210abcdef0123456789", ) .unwrap(), ]; let expected = [ - field_from_hex_string( + Utils::field_from_hex_string( "0x2bf1eaf87f7d27e8dc4056e9af975985bccc89077a21891d6c7b6ccce0631f95", ) .unwrap(), - field_from_hex_string( + Utils::field_from_hex_string( "0x0c01fa1b8d0748becafbe452c0cb0231c38224ea824554c9362518eebdd5701f", ) .unwrap(), - field_from_hex_string( + Utils::field_from_hex_string( "0x018555a8eb50cf07f64b019ebaf3af3c925c93e631f3ecd455db07bbb52bbdd3", ) .unwrap(), - field_from_hex_string( + Utils::field_from_hex_string( "0x0cbea457c91c22c6c31fd89afd2541efc2edf31736b9f721e823b2165c90fd41", ) .unwrap(), diff --git a/co-noir/ultrahonk/src/prelude.rs b/co-noir/ultrahonk/src/prelude.rs new file mode 100644 index 00000000..405bab15 --- /dev/null +++ b/co-noir/ultrahonk/src/prelude.rs @@ -0,0 +1,16 @@ +pub use crate::decider::polynomial::Polynomial; +pub use crate::honk_curve::HonkCurve; +pub use crate::parse::crs::CrsParser; +pub use crate::parse::{ + acir_format::AcirFormat, + builder::{GenericUltraCircuitBuilder, UltraCircuitBuilder, UltraCircuitVariable}, + types::{CycleNode, CyclicPermutation, NUM_SELECTORS, NUM_WIRES}, +}; +pub use crate::poseidon2::poseidon2_bn254::POSEIDON2_BN254_T4_PARAMS; +pub use crate::prover::HonkProofResult; +pub use crate::prover::UltraHonk; +pub use crate::transcript::TranscriptFieldType; +pub use crate::transcript::TranscriptType; +pub use crate::types::PrecomputedEntities; +pub use crate::types::ProverCrs; +pub use crate::types::{HonkProof, ProvingKey}; diff --git a/co-noir/ultrahonk/src/sponge_hasher.rs b/co-noir/ultrahonk/src/sponge_hasher.rs index f487bb8a..49d45955 100644 --- a/co-noir/ultrahonk/src/sponge_hasher.rs +++ b/co-noir/ultrahonk/src/sponge_hasher.rs @@ -1,7 +1,7 @@ use ark_ff::{One, PrimeField}; use num_bigint::BigUint; -pub trait FieldHash { +pub(crate) trait FieldHash { fn permutation(&self, input: &[F; T]) -> [F; T] { let mut state = *input; self.permutation_in_place(&mut state); @@ -16,7 +16,7 @@ enum SpongeMode { Squeeze, } -pub struct FieldSponge> { +pub(crate) struct FieldSponge> { state: [F; T], cache: [F; R], cache_size: usize, @@ -25,7 +25,7 @@ pub struct FieldSponge> FieldSponge { - pub fn new(iv: F, hasher: H) -> Self { + pub(crate) fn new(iv: F, hasher: H) -> Self { assert!(R < T); let mut state = [F::zero(); T]; state[R] = iv; @@ -107,7 +107,7 @@ impl> FieldSpo * @param input * @return std::array */ - pub fn hash_internal( + pub(crate) fn hash_internal( input: &[F], hasher: H, ) -> [F; OUT_LEN] { @@ -133,11 +133,14 @@ impl> FieldSpo res } - pub fn hash_fixed_lenth(input: &[F], hasher: H) -> [F; OUT_LEN] { + pub(crate) fn hash_fixed_lenth(input: &[F], hasher: H) -> [F; OUT_LEN] { Self::hash_internal::(input, hasher) } - pub fn hash_variable_length(input: &[F], hasher: H) -> [F; OUT_LEN] { + pub(crate) fn hash_variable_length( + input: &[F], + hasher: H, + ) -> [F; OUT_LEN] { Self::hash_internal::(input, hasher) } } diff --git a/co-noir/ultrahonk/src/transcript.rs b/co-noir/ultrahonk/src/transcript.rs index cdd5da44..fe2d9974 100644 --- a/co-noir/ultrahonk/src/transcript.rs +++ b/co-noir/ultrahonk/src/transcript.rs @@ -9,10 +9,10 @@ use ark_ec::AffineRepr; use ark_ff::{PrimeField, Zero}; use std::{collections::BTreeMap, ops::Index, sync::Arc}; -pub(crate) type TranscriptFieldType = ark_bn254::Fr; -pub(crate) type TranscriptType = Poseidon2Transcript; +pub type TranscriptFieldType = ark_bn254::Fr; +pub type TranscriptType = Poseidon2Transcript; -pub(super) struct Poseidon2Transcript +pub struct Poseidon2Transcript where F: PrimeField, { @@ -45,15 +45,15 @@ where } } - pub fn get_proof(self) -> HonkProof { + pub(crate) fn get_proof(self) -> HonkProof { HonkProof::new(self.proof_data) } - pub fn print(&self) { + pub(crate) fn print(&self) { self.manifest.print(); } - pub fn get_manifest(&self) -> &TranscriptManifest { + pub(crate) fn get_manifest(&self) -> &TranscriptManifest { &self.manifest } @@ -265,7 +265,7 @@ where } #[derive(Clone, Debug, Eq, PartialEq, Default)] -struct RoundData { +pub(crate) struct RoundData { challenge_label: Vec, entries: Vec<(String, usize)>, } @@ -282,7 +282,7 @@ impl RoundData { } #[derive(Clone, Debug, Default, PartialEq, Eq)] -struct TranscriptManifest { +pub(crate) struct TranscriptManifest { manifest: BTreeMap, } diff --git a/co-noir/ultrahonk/src/types.rs b/co-noir/ultrahonk/src/types.rs index b8d535fb..9e917d06 100644 --- a/co-noir/ultrahonk/src/types.rs +++ b/co-noir/ultrahonk/src/types.rs @@ -6,15 +6,26 @@ use ark_ec::pairing::Pairing; use ark_ff::PrimeField; use num_bigint::BigUint; +pub struct ProvingKey { + pub(crate) crs: ProverCrs

, + pub(crate) circuit_size: u32, + pub(crate) public_inputs: Vec, + pub(crate) num_public_inputs: u32, + pub(crate) pub_inputs_offset: u32, + pub(crate) polynomials: Polynomials, + pub(crate) memory_read_records: Vec, + pub(crate) memory_write_records: Vec, +} + // This is what we get from the proving key, we shift at a later point #[derive(Default)] -pub struct Polynomials { - pub witness: ProverWitnessEntities>, - pub precomputed: PrecomputedEntities>, +pub(crate) struct Polynomials { + pub(crate) witness: ProverWitnessEntities>, + pub(crate) precomputed: PrecomputedEntities>, } impl Polynomials { - pub fn new(circuit_size: usize) -> Self { + pub(crate) fn new(circuit_size: usize) -> Self { let mut polynomials = Self::default(); // Shifting is done at a later point polynomials @@ -24,33 +35,22 @@ impl Polynomials { polynomials } - pub fn iter(&self) -> impl Iterator> { + pub(crate) fn iter(&self) -> impl Iterator> { self.witness.iter().chain(self.precomputed.iter()) } - pub fn iter_mut(&mut self) -> impl Iterator> { + pub(crate) fn iter_mut(&mut self) -> impl Iterator> { self.witness.iter_mut().chain(self.precomputed.iter_mut()) } } -pub struct ProvingKey { - pub crs: ProverCrs

, - pub circuit_size: u32, - pub public_inputs: Vec, - pub num_public_inputs: u32, - pub pub_inputs_offset: u32, - pub polynomials: Polynomials, - pub memory_read_records: Vec, - pub memory_write_records: Vec, -} - pub struct Crs { - pub monomials: Vec, - pub g2_x: P::G2Affine, + pub(crate) monomials: Vec, + pub(crate) g2_x: P::G2Affine, } pub struct ProverCrs { - pub monomials: Vec, + pub(crate) monomials: Vec, } #[derive(Clone, Debug, PartialEq, Eq)] @@ -63,7 +63,7 @@ impl HonkProof { const FIELDSIZE_BYTES: u32 = Self::NUM_64_LIMBS * 8; const VEC_LEN_BYTES: u32 = 4; - pub fn new(proof: Vec) -> Self { + pub(crate) fn new(proof: Vec) -> Self { Self { proof } } @@ -172,15 +172,15 @@ impl HonkProof { } #[derive(Default)] -pub struct AllEntities { - pub witness: WitnessEntities, - pub precomputed: PrecomputedEntities, - pub shifted_witness: ShiftedWitnessEntities, - pub shifted_tables: ShiftedTableEntities, +pub(crate) struct AllEntities { + pub(crate) witness: WitnessEntities, + pub(crate) precomputed: PrecomputedEntities, + pub(crate) shifted_witness: ShiftedWitnessEntities, + pub(crate) shifted_tables: ShiftedTableEntities, } impl AllEntities { - pub fn iter(&self) -> impl Iterator { + pub(crate) fn iter(&self) -> impl Iterator { self.precomputed .iter() .chain(self.witness.iter()) @@ -196,7 +196,7 @@ impl AllEntities { .chain(self.shifted_witness) } - pub fn iter_mut(&mut self) -> impl Iterator { + pub(crate) fn iter_mut(&mut self) -> impl Iterator { self.precomputed .iter_mut() .chain(self.witness.iter_mut()) @@ -206,7 +206,7 @@ impl AllEntities { } impl AllEntities> { - pub fn new(circuit_size: usize) -> Self { + pub(crate) fn new(circuit_size: usize) -> Self { let mut polynomials = Self::default(); // Shifting is done at a later point polynomials @@ -219,32 +219,32 @@ impl AllEntities> { const WITNESS_ENTITIES_SIZE: usize = 8; #[derive(Default)] -pub struct WitnessEntities { - pub elements: [T; WITNESS_ENTITIES_SIZE], +pub(crate) struct WitnessEntities { + pub(crate) elements: [T; WITNESS_ENTITIES_SIZE], } const PROVER_WITNESS_ENTITIES_SIZE: usize = 6; #[derive(Default)] -pub struct ProverWitnessEntities { - pub elements: [T; PROVER_WITNESS_ENTITIES_SIZE], +pub(crate) struct ProverWitnessEntities { + pub(crate) elements: [T; PROVER_WITNESS_ENTITIES_SIZE], } const SHIFTED_WITNESS_ENTITIES_SIZE: usize = 5; #[derive(Default)] -pub struct ShiftedWitnessEntities { - pub elements: [T; SHIFTED_WITNESS_ENTITIES_SIZE], +pub(crate) struct ShiftedWitnessEntities { + pub(crate) elements: [T; SHIFTED_WITNESS_ENTITIES_SIZE], } const SHIFTED_TABLE_ENTITIES_SIZE: usize = 4; #[derive(Default)] -pub struct ShiftedTableEntities { - pub elements: [T; SHIFTED_TABLE_ENTITIES_SIZE], +pub(crate) struct ShiftedTableEntities { + pub(crate) elements: [T; SHIFTED_TABLE_ENTITIES_SIZE], } const PRECOMPUTED_ENTITIES_SIZE: usize = 27; #[derive(Default)] pub struct PrecomputedEntities { - pub elements: [T; PRECOMPUTED_ENTITIES_SIZE], + pub(crate) elements: [T; PRECOMPUTED_ENTITIES_SIZE], } impl IntoIterator for PrecomputedEntities { @@ -303,55 +303,51 @@ impl ProverWitnessEntities { // const Z_PERM: usize = 4; // column 4 (computed by prover) // const LOOKUP_INVERSES: usize = 5; // column 5 (computed by prover); - pub fn iter(&self) -> impl Iterator { + pub(crate) fn iter(&self) -> impl Iterator { self.elements.iter() } - pub fn iter_mut(&mut self) -> impl Iterator { + pub(crate) fn iter_mut(&mut self) -> impl Iterator { self.elements.iter_mut() } - pub fn into_wires(self) -> impl Iterator { + pub(crate) fn into_wires(self) -> impl Iterator { self.elements .into_iter() // .skip(Self::W_L) .take(Self::W_4 + 1 - Self::W_L) } - pub fn get_wires_mut(&mut self) -> &mut [T] { + pub(crate) fn get_wires_mut(&mut self) -> &mut [T] { &mut self.elements[Self::W_L..=Self::W_4] } - pub fn w_l(&self) -> &T { + pub(crate) fn w_l(&self) -> &T { &self.elements[Self::W_L] } - pub fn w_r(&self) -> &T { + pub(crate) fn w_r(&self) -> &T { &self.elements[Self::W_R] } - pub fn w_o(&self) -> &T { + pub(crate) fn w_o(&self) -> &T { &self.elements[Self::W_O] } - pub fn w_4(&self) -> &T { + pub(crate) fn w_4(&self) -> &T { &self.elements[Self::W_4] } - pub fn lookup_read_counts(&self) -> &T { + pub(crate) fn lookup_read_counts(&self) -> &T { &self.elements[Self::LOOKUP_READ_COUNTS] } - pub fn lookup_read_tags(&self) -> &T { + pub(crate) fn lookup_read_tags(&self) -> &T { &self.elements[Self::LOOKUP_READ_TAGS] } - pub fn lookup_read_counts_mut(&mut self) -> &mut T { - &mut self.elements[Self::LOOKUP_READ_COUNTS] - } - - pub fn lookup_read_tags_mut(&mut self) -> &mut T { - &mut self.elements[Self::LOOKUP_READ_TAGS] + pub(crate) fn lookup_read_counts_and_tags_mut(&mut self) -> &mut [T] { + &mut self.elements[Self::LOOKUP_READ_COUNTS..Self::LOOKUP_READ_TAGS + 1] } } @@ -365,59 +361,59 @@ impl WitnessEntities { pub(crate) const LOOKUP_READ_COUNTS: usize = 6; // column 6 pub(crate) const LOOKUP_READ_TAGS: usize = 7; // column 7 - pub fn iter(&self) -> impl Iterator { + pub(crate) fn iter(&self) -> impl Iterator { self.elements.iter() } - pub fn iter_mut(&mut self) -> impl Iterator { + pub(crate) fn iter_mut(&mut self) -> impl Iterator { self.elements.iter_mut() } - pub fn to_be_shifted_mut(&mut self) -> &mut [T] { + pub(crate) fn to_be_shifted_mut(&mut self) -> &mut [T] { &mut self.elements[Self::W_L..=Self::Z_PERM] } - pub fn w_l(&self) -> &T { + pub(crate) fn w_l(&self) -> &T { &self.elements[Self::W_L] } - pub fn w_r(&self) -> &T { + pub(crate) fn w_r(&self) -> &T { &self.elements[Self::W_R] } - pub fn w_o(&self) -> &T { + pub(crate) fn w_o(&self) -> &T { &self.elements[Self::W_O] } - pub fn w_4(&self) -> &T { + pub(crate) fn w_4(&self) -> &T { &self.elements[Self::W_4] } - pub fn z_perm(&self) -> &T { + pub(crate) fn z_perm(&self) -> &T { &self.elements[Self::Z_PERM] } - pub fn lookup_inverses(&self) -> &T { + pub(crate) fn lookup_inverses(&self) -> &T { &self.elements[Self::LOOKUP_INVERSES] } - pub fn lookup_read_counts(&self) -> &T { + pub(crate) fn lookup_read_counts(&self) -> &T { &self.elements[Self::LOOKUP_READ_COUNTS] } - pub fn lookup_read_tags(&self) -> &T { + pub(crate) fn lookup_read_tags(&self) -> &T { &self.elements[Self::LOOKUP_READ_TAGS] } - pub fn lookup_inverses_mut(&mut self) -> &mut T { + pub(crate) fn lookup_inverses_mut(&mut self) -> &mut T { &mut self.elements[Self::LOOKUP_INVERSES] } - pub fn lookup_read_counts_mut(&mut self) -> &mut T { + pub(crate) fn lookup_read_counts_mut(&mut self) -> &mut T { &mut self.elements[Self::LOOKUP_READ_COUNTS] } - pub fn lookup_read_tags_mut(&mut self) -> &mut T { + pub(crate) fn lookup_read_tags_mut(&mut self) -> &mut T { &mut self.elements[Self::LOOKUP_READ_TAGS] } } @@ -429,31 +425,31 @@ impl ShiftedWitnessEntities { const W_4: usize = 3; // column 3 const Z_PERM: usize = 4; // column 4 - pub fn iter(&self) -> impl Iterator { + pub(crate) fn iter(&self) -> impl Iterator { self.elements.iter() } - pub fn iter_mut(&mut self) -> impl Iterator { + pub(crate) fn iter_mut(&mut self) -> impl Iterator { self.elements.iter_mut() } - pub fn w_l(&self) -> &T { + pub(crate) fn w_l(&self) -> &T { &self.elements[Self::W_L] } - pub fn w_r(&self) -> &T { + pub(crate) fn w_r(&self) -> &T { &self.elements[Self::W_R] } - pub fn w_o(&self) -> &T { + pub(crate) fn w_o(&self) -> &T { &self.elements[Self::W_O] } - pub fn w_4(&self) -> &T { + pub(crate) fn w_4(&self) -> &T { &self.elements[Self::W_4] } - pub fn z_perm(&self) -> &T { + pub(crate) fn z_perm(&self) -> &T { &self.elements[Self::Z_PERM] } } @@ -464,27 +460,27 @@ impl ShiftedTableEntities { const TABLE_3: usize = 2; // column 2 const TABLE_4: usize = 3; // column 3 - pub fn iter(&self) -> impl Iterator { + pub(crate) fn iter(&self) -> impl Iterator { self.elements.iter() } - pub fn iter_mut(&mut self) -> impl Iterator { + pub(crate) fn iter_mut(&mut self) -> impl Iterator { self.elements.iter_mut() } - pub fn table_1(&self) -> &T { + pub(crate) fn table_1(&self) -> &T { &self.elements[Self::TABLE_1] } - pub fn table_2(&self) -> &T { + pub(crate) fn table_2(&self) -> &T { &self.elements[Self::TABLE_2] } - pub fn table_3(&self) -> &T { + pub(crate) fn table_3(&self) -> &T { &self.elements[Self::TABLE_3] } - pub fn table_4(&self) -> &T { + pub(crate) fn table_4(&self) -> &T { &self.elements[Self::TABLE_4] } } diff --git a/co-noir/ultrahonk/tests/poseidon.rs b/co-noir/ultrahonk/tests/poseidon.rs index 8b59fb67..8b13d253 100644 --- a/co-noir/ultrahonk/tests/poseidon.rs +++ b/co-noir/ultrahonk/tests/poseidon.rs @@ -1,8 +1,7 @@ use ark_bn254::Bn254; use ultrahonk::{ - parse::{builder::UltraCircuitBuilder, get_constraint_system_from_file, get_witness_from_file}, - prover::UltraHonk, - types::{HonkProof, ProvingKey}, + prelude::{HonkProof, ProvingKey, UltraCircuitBuilder, UltraHonk}, + Utils, }; #[test] @@ -13,8 +12,8 @@ fn poseidon_test() { const WITNESS_FILE: &str = "../../test_vectors/noir/poseidon/kat/poseidon.gz"; const PROOF_FILE: &str = "../../test_vectors/noir/poseidon/kat/poseidon.proof"; - let constraint_system = get_constraint_system_from_file(CIRCUIT_FILE, true).unwrap(); - let witness = get_witness_from_file(WITNESS_FILE).unwrap(); + let constraint_system = Utils::get_constraint_system_from_file(CIRCUIT_FILE, true).unwrap(); + let witness = Utils::get_witness_from_file(WITNESS_FILE).unwrap(); let builder = UltraCircuitBuilder::::create_circuit(constraint_system, 0, witness, true, false); diff --git a/mpc-core/src/traits.rs b/mpc-core/src/traits.rs index 1c9b4b4f..228f9e27 100644 --- a/mpc-core/src/traits.rs +++ b/mpc-core/src/traits.rs @@ -48,7 +48,8 @@ pub trait PrimeFieldMpcProtocol { + CanonicalSerialize + CanonicalDeserialize + Sync - + Default; + + Default + + PartialEq; /// The type of a vector of shared field elements. type FieldShareVec: FieldShareVecTrait;