-
Notifications
You must be signed in to change notification settings - Fork 13
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: Make builder generic for both shares and plain, add shared prov…
…ing key and start with MPC prover (#193)
- Loading branch information
Showing
50 changed files
with
1,479 additions
and
784 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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<P: Pairing> SharedBuilderVariable<PlainDriver<P::ScalarField>, P> { | ||
pub fn promote_public_witness_vector( | ||
witness: Vec<P::ScalarField>, | ||
) -> Vec<SharedBuilderVariable<PlainDriver<P::ScalarField>, P>> { | ||
witness | ||
.into_iter() | ||
.map(SharedBuilderVariable::Public) | ||
.collect() | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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<T, P> | ||
where | ||
P: Pairing, | ||
T: PrimeFieldMpcProtocol<P::ScalarField>, | ||
{ | ||
Public(P::ScalarField), | ||
Shared(T::FieldShare), | ||
} | ||
|
||
impl<T, P> SharedBuilderVariable<T, P> | ||
where | ||
P: Pairing, | ||
T: PrimeFieldMpcProtocol<P::ScalarField>, | ||
{ | ||
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<T, P> Clone for SharedBuilderVariable<T, P> | ||
where | ||
P: Pairing, | ||
T: PrimeFieldMpcProtocol<P::ScalarField>, | ||
{ | ||
fn clone(&self) -> Self { | ||
match self { | ||
SharedBuilderVariable::Public(value) => Self::Public(*value), | ||
SharedBuilderVariable::Shared(value) => Self::Shared(value.clone()), | ||
} | ||
} | ||
} | ||
|
||
impl<T, P> PartialEq for SharedBuilderVariable<T, P> | ||
where | ||
P: Pairing, | ||
T: PrimeFieldMpcProtocol<P::ScalarField>, | ||
{ | ||
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<T, P> Debug for SharedBuilderVariable<T, P> | ||
where | ||
P: Pairing, | ||
T: PrimeFieldMpcProtocol<P::ScalarField>, | ||
{ | ||
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<T, P> UltraCircuitVariable<P::ScalarField> for SharedBuilderVariable<T, P> | ||
where | ||
P: Pairing, | ||
T: PrimeFieldMpcProtocol<P::ScalarField>, | ||
{ | ||
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"), | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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<T, P> = GenericUltraCircuitBuilder<P, SharedBuilderVariable<T, P>>; | ||
|
||
pub type PlainCoBuilder<P> = CoUltraCircuitBuilder<PlainDriver<<P as Pairing>::ScalarField>, P>; | ||
pub type Rep3CoBuilder<P, N> = | ||
CoUltraCircuitBuilder<Rep3Protocol<<P as Pairing>::ScalarField, N>, P>; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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<T, P: Pairing> ProvingKey<T, P> | ||
where | ||
T: PrimeFieldMpcProtocol<P::ScalarField>, | ||
{ | ||
const PUBLIC_INPUT_WIRE_INDEX: usize = | ||
ProverWitnessEntities::<T::FieldShare, P::ScalarField>::W_R; | ||
|
||
// We ignore the TraceStructure for now (it is None in barretenberg for UltraHonk) | ||
pub fn create(driver: &T, mut circuit: CoUltraCircuitBuilder<T, P>, crs: ProverCrs<P>) -> 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<T, P>, | ||
path_g1: &str, | ||
) -> Result<ProverCrs<P>> { | ||
PlainProvingKey::get_prover_crs(circuit, path_g1) | ||
} | ||
|
||
fn new(circuit_size: usize, num_public_inputs: usize, crs: ProverCrs<P>) -> 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<T, P>, | ||
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, | ||
); | ||
} | ||
} |
Oops, something went wrong.