Skip to content

Commit

Permalink
Add PCS types and basic setup flow using SRS (#28)
Browse files Browse the repository at this point in the history
* add basic setup flow using SRS

* merge with main

* some small fixes to bugs in the compression module from recent PRs

* spartan integration fixes

* tests for srs generation

* sets default srs size to 19

* use `deserialize_compressed_unchecked`

* remove unnecessary blinding factor from SRS generation

* fix

* adds SRS to git lfs

* add git lfs to CI workflow

* sample test srs in CI

* install nexus-tools in CI

* ignore tests related to large SRS

* remove SRS generation from CI

* merge fixes

* fmt

* fixes from review

* small fix

* remove file-manipulating tests

* Adds a cli option to the prover crate for compression (#55)

* testing proof deserialization

* proofs save and verify

* removed cargo.lock

* todo: merge dorebell onto this

* fixed merge mistakes

* reads proof and compresses. key not yet saved to file

* added back cargo.lock

* moved the compression cli into prover crate

* formatting

* remove whitespace

* added com option to prove

* updated local prove

* todo:save key and proof to file

* derive CanonicalSerialize+CanonicalDeserialize for Spartan types

* add options to save and load spartan key from file

* save compressed proof to file, implement arkworks serialization

* clippy

* remove SRS generation from CI

* ignore spartan_encode_test

* integrate compression cli with recent version of nexus-tools

* add cli function to sample test SRS

* forgot to add new files

* small compression UI fixes

* add spartan setup command to main 'cargo nexus'

* bump number of SRS vars to 27

* minor fix

* review fixes

* another round of review fixes

* read pp and srs from default cache locations if unspecified during compression

* add helper function to get minimum srs size for a given k

---------

Co-authored-by: Dan Dore <dorebell@gmail.com>

* fix broken edit links in docs (#99)

* CCS implementation (#52)

* Initial CCS implementation.

* Remove direct construction interfaces so that everything goes through R1CS.

* Trim more, Fold multipliers together, and inline satisfaction checking.

* Fix formatting.

* Precompute products.

* Remove direct CCS construction.

* Add mle helpers.

* Start to integrate polynomial commitments.

* Shading closer to polynomial commitments.

* Initial stab at relating various polynomial types and traits.

* Finish utility functions.

* Fix endianness and ranges and get tests passing.

* Fix formatting.

* Realized there's a better way to invoke the partially fixed polynomial.

* Update interfaces and some additional reworking.

* Resolve clippy.

* Unify shapes.

* Product renaming

Co-authored-by: Dan Dore <dorebell@gmail.com>

* Revert "Unify shapes."

This reverts commit 3463e43.

* Move to polynomial/poly commitment implementations from Spartan repo.

* Move to unified matrix-based model.

* Fix tests.

* Fix fmt.

* Remove files accidently restored during rebase.

* Move to using polynomial commitment exlcusively.

* Fix formatting.

---------

Co-authored-by: Dan Dore <dorebell@gmail.com>

* All Contributors Setup (#120)

* Update README.md

* Update README.md

* Create .all-contributorsrc

* docs: add nexus-xyz as a contributor for code (#121)

* docs: update README.md

* docs: update .all-contributorsrc

---------

Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com>

* Switch Contributors (#122)

* Delete .all-contributorsrc

* Update README.md

* fix merge conflicts

---------

Co-authored-by: Guru Vamsi Policharla <guruvamsi.policharla@gmail.com>
Co-authored-by: Daniel Marin <60114322+danielmarinq@users.noreply.github.com>
Co-authored-by: Samuel Judson <sam@sjudson.com>
Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com>
  • Loading branch information
5 people authored Mar 14, 2024
1 parent 35f5d2f commit 6045c59
Show file tree
Hide file tree
Showing 49 changed files with 1,475 additions and 191 deletions.
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,6 @@ Cargo.lock
.*.swp

.config.env

# public parameter files
*.zst
5 changes: 5 additions & 0 deletions config/src/vm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,18 @@ pub enum NovaImpl {
#[serde(rename = "par")]
#[cfg_attr(feature = "clap_derive", clap(name = "par"))]
Parallel,

#[serde(rename = "par-com")]
#[cfg_attr(feature = "clap_derive", clap(name = "par-com"))]
ParallelCompressible,
}

impl fmt::Display for NovaImpl {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
NovaImpl::Sequential => write!(f, "seq"),
NovaImpl::Parallel => write!(f, "par"),
NovaImpl::ParallelCompressible => write!(f, "par-com"),
}
}
}
Expand Down
17 changes: 8 additions & 9 deletions network/src/api.rs
Original file line number Diff line number Diff line change
@@ -1,14 +1,5 @@
use serde::{Deserialize, Serialize};

#[derive(Serialize, Deserialize)]
pub enum NexusAPI {
Program { account: String, elf: Vec<u8> },
Query { hash: String },
Proof(Proof),
Error(String),
}
pub use NexusAPI::*;

#[derive(Default, Clone, Serialize, Deserialize)]
pub struct Proof {
pub hash: String,
Expand Down Expand Up @@ -36,3 +27,11 @@ impl std::fmt::Display for Proof {
Ok(())
}
}

#[derive(Serialize, Deserialize)]
pub enum NexusAPI {
Program { account: String, elf: Vec<u8> },
Query { hash: String },
NexusProof(Proof),
Error(String),
}
2 changes: 1 addition & 1 deletion network/src/bin/pcdnode/db.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use std::collections::HashMap;
use std::sync::{Arc, Mutex};

use nexus_network::api::Proof;
use crate::api::Proof;

#[derive(Clone, Default)]
pub struct DB(Arc<Mutex<DBase>>);
Expand Down
2 changes: 1 addition & 1 deletion network/src/bin/pcdnode/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ async fn main() -> Result<()> {

let opts = Opts::parse();

let pp = gen_or_load(false, 0, &opts.pp_file)?;
let pp = gen_or_load(false, 0, &opts.pp_file, None)?;
let state = WorkerState::new(pp);

start_local_workers(state.clone())?;
Expand Down
21 changes: 14 additions & 7 deletions network/src/bin/pcdnode/post.rs
Original file line number Diff line number Diff line change
@@ -1,18 +1,25 @@
use std::collections::VecDeque;
use std::sync::Arc;

use nexus_network::{
api::{NexusAPI, Proof},
pcd::{
encode,
NexusMsg::{self, LeafReq, NodeReq, PCDRes},
},
Result,
};
use sha2::{Digest, Sha256};

use hyper::{header, Body, Request, Response, StatusCode};
use tokio::task::JoinHandle;

use nexus_network::api::*;
use nexus_network::pcd::*;
use nexus_network::*;
use crate::{
api::NexusAPI::{Error, NexusProof, Program, Query},
request_work, WorkerState, LOG_TARGET,
};
use nexus_vm::{eval::NexusVM, riscv::translate_elf_bytes, trace::trace};

use crate::workers::*;

pub fn manage_proof(mut state: WorkerState, hash: String, mut vm: NexusVM) -> Result<()> {
let trace = Arc::new(trace(&mut vm, 1, true)?);

Expand Down Expand Up @@ -96,7 +103,7 @@ fn api(mut state: WorkerState, msg: NexusAPI) -> Result<NexusAPI> {
let vm = translate_elf_bytes(&elf)?;
let hash = hex::encode(Sha256::digest(&elf));
manage_proof(state, hash.clone(), vm)?;
Ok(Proof(Proof { hash, ..Proof::default() }))
Ok(NexusProof(Proof { hash, ..Proof::default() }))
}
Query { hash } => {
tracing::info!(
Expand All @@ -106,7 +113,7 @@ fn api(mut state: WorkerState, msg: NexusAPI) -> Result<NexusAPI> {
let proof = state.db.query_proof(&hash);
match proof {
None => Err("proof not found".into()),
Some(p) => Ok(Proof(p)),
Some(p) => Ok(NexusProof(p)),
}
}
_ => Err("Invalid Message".into()),
Expand Down
9 changes: 6 additions & 3 deletions network/src/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,11 @@ use hyper::body::{Buf, HttpBody};
use hyper::client::HttpConnector;
use tokio::runtime;

use crate::api::*;
use crate::Result;
use crate::client::NexusAPI::{Error, NexusProof, Program, Query};
use crate::{
api::{NexusAPI, Proof},
Result,
};

pub const LOG_TARGET: &str = "nexus-network::client";

Expand Down Expand Up @@ -56,7 +59,7 @@ impl Client {
.map_err(|_err| "request failed".to_owned())??;

match response {
Proof(p) => Ok(p),
NexusProof(p) => Ok(p),
Error(m) => Err(m.into()),
_ => Err("unexpected response".into()),
}
Expand Down
2 changes: 1 addition & 1 deletion network/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,6 @@ pub mod pcd;
pub mod ws;

pub type DynError = Box<dyn std::error::Error + Send + Sync>;
pub type Result<T> = std::result::Result<T, DynError>;
pub type Result<T, E = DynError> = std::result::Result<T, E>;

pub const LOG_TARGET: &str = "nexus-network";
2 changes: 1 addition & 1 deletion network/src/pcd.rs
Original file line number Diff line number Diff line change
Expand Up @@ -215,7 +215,7 @@ mod test {
#[ignore]
fn round_trip_node() {
let circuit = nop_circuit(3).unwrap();
let pp: ParPP = gen_pp(&circuit).unwrap();
let pp: ParPP = gen_pp(&circuit, &()).unwrap();
let n0 = PCDNode::prove_leaf(&pp, &circuit, 0, &circuit.input(0).unwrap()).unwrap();
let n2 = PCDNode::prove_leaf(&pp, &circuit, 2, &circuit.input(2).unwrap()).unwrap();
let n = PCDNode::prove_parent(&pp, &circuit, &n0, &n2).unwrap();
Expand Down
17 changes: 17 additions & 0 deletions nova/src/circuits/nova/pcd/compression/conversion.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ use ark_spartan::{
polycommitments::PolyCommitmentScheme,
Assignment, Instance,
};
use ark_std::{error::Error, fmt::Display};

use super::PolyVectorCommitment;
use crate::{
Expand All @@ -23,6 +24,22 @@ impl From<R1CSError> for ConversionError {
}
}

impl Error for ConversionError {
fn source(&self) -> Option<&(dyn Error + 'static)> {
match self {
ConversionError::ConversionError(e) => Some(e),
}
}
}

impl Display for ConversionError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::ConversionError(e) => write!(f, "Conversion error: {e}"),
}
}
}

impl<G> TryFrom<R1CSShape<G>> for CRR1CSShape<G::ScalarField>
where
G: SWCurveConfig,
Expand Down
43 changes: 43 additions & 0 deletions nova/src/circuits/nova/pcd/compression/error.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use ark_relations::r1cs::SynthesisError;
use ark_spartan::errors::ProofVerifyError;
use ark_std::{error::Error, fmt::Display};

use super::conversion::ConversionError;
pub use crate::folding::nova::cyclefold::Error as NovaError;
Expand Down Expand Up @@ -53,3 +54,45 @@ impl From<ProofVerifyError> for SpartanError {
Self::InvalidProof(ProofError::InvalidSpartanProof(error))
}
}

impl Error for SpartanError {
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
match self {
SpartanError::ConversionError(e) => Some(e),
SpartanError::FoldingError(e) => Some(e),
SpartanError::InvalidProof(e) => Some(e),
}
}
}

impl Display for SpartanError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
SpartanError::ConversionError(e) => write!(f, "{}", e),
SpartanError::FoldingError(e) => write!(f, "{}", e),
SpartanError::InvalidProof(e) => write!(f, "{}", e),
}
}
}

impl Error for ProofError {
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
match self {
Self::InvalidProof => None,
Self::InvalidPublicInput => None,
Self::InvalidSpartanProof(e) => Some(e),
Self::SecondaryCircuitNotSatisfied => None,
}
}
}

impl Display for ProofError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::InvalidProof => write!(f, "Invalid proof"),
Self::InvalidPublicInput => write!(f, "Invalid public input"),
Self::InvalidSpartanProof(e) => write!(f, "{}", e),
Self::SecondaryCircuitNotSatisfied => write!(f, "Secondary circuit not satisfied"),
}
}
}
36 changes: 30 additions & 6 deletions nova/src/circuits/nova/pcd/compression/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ use ark_ec::{
use ark_ff::PrimeField;
use ark_serialize::{CanonicalDeserialize, CanonicalSerialize};
use ark_spartan::{
committed_relaxed_snark as ark_spartan_snark, committed_relaxed_snark::CRSNARKKey as SNARKGens,
committed_relaxed_snark as spartan_snark, committed_relaxed_snark::CRSNARKKey as SNARKGens,
crr1csproof::CRR1CSShape, polycommitments::PolyCommitmentScheme, ComputationCommitment,
ComputationDecommitment,
};
Expand All @@ -24,6 +24,7 @@ use crate::{
NIMFSProof, R1CSInstance, RelaxedR1CSInstance, RelaxedR1CSWitness,
},
nova::pcd::{augmented::SQUEEZE_NATIVE_ELEMENTS_NUM, PCDNode},
r1cs::R1CSShape,
StepCircuit, LOG_TARGET,
};

Expand All @@ -38,6 +39,7 @@ pub use error::{ProofError, SpartanError};

pub type PVC<G, PC> = PolyVectorCommitment<Projective<G>, PC>;

#[derive(CanonicalSerialize, CanonicalDeserialize)]
pub struct CompressedPCDProof<G1, G2, PC, C2, RO, SC>
where
G1: SWCurveConfig,
Expand All @@ -60,7 +62,7 @@ where

pub W_secondary_prime: RelaxedR1CSWitness<G2>,

pub spartan_proof: ark_spartan_snark::SNARK<Projective<G1>, PC>,
pub spartan_proof: spartan_snark::SNARK<Projective<G1>, PC>,
pub folding_proof: NIMFSProof<G1, G2, PVC<G1, PC>, C2, RO>,

_random_oracle: PhantomData<RO>,
Expand All @@ -75,6 +77,29 @@ pub struct SNARKKey<G: CurveGroup, PC: PolyCommitmentScheme<G>> {
snark_gens: SNARKGens<G, PC>,
}

impl<G: CurveGroup, PC: PolyCommitmentScheme<G>> SNARKKey<G, PC> {
/// convenience function to derive the minimum log size of the SRS
/// needed to support compession for a given `shape`.
pub fn get_min_srs_size(shape: &R1CSShape<G>) -> usize {
let R1CSShape {
num_constraints,
num_vars,
num_io,
A,
B,
C,
} = shape;
// spartan uses the convention that num_inputs does not include the leading `u`.
let num_inputs = num_io - 1;
let num_nz_entries = max(A.len(), max(B.len(), C.len()));
SNARKGens::<G, PC>::get_min_num_vars(
*num_constraints,
*num_vars,
num_inputs,
num_nz_entries,
)
}
}
pub struct SNARK<G1, G2, PC, C2, RO, SC>
where
G1: SWCurveConfig,
Expand Down Expand Up @@ -115,7 +140,6 @@ where
let PublicParams { shape: _shape, .. } = pp;
// converts the R1CSShape from this crate into a CRR1CSShape from the Spartan crate
let shape: CRR1CSShape<G1::ScalarField> = _shape.clone().try_into()?;
// the `try_into()` call above pads the number of constraints, variables, and inputs
let (num_cons, num_vars, num_inputs) = (
shape.get_num_cons(),
shape.get_num_vars(),
Expand All @@ -125,7 +149,7 @@ where
let num_nz_entries = max(_shape.A.len(), max(_shape.B.len(), _shape.C.len()));
let snark_gens = SNARKGens::new(srs, num_cons, num_vars, num_inputs, num_nz_entries);
let (computation_comm, computation_decomm) =
ark_spartan_snark::SNARK::<Projective<G1>, PC>::encode(&shape.inst, &snark_gens);
spartan_snark::SNARK::<Projective<G1>, PC>::encode(&shape.inst, &snark_gens);
Ok(SNARKKey {
shape,
computation_comm,
Expand Down Expand Up @@ -174,7 +198,7 @@ where
let mut transcript = Transcript::new(b"spartan_snark");
// Now, we use Spartan to prove knowledge of the witness `W_prime`
// for the committed relaxed r1cs instance `U_prime`
let spartan_proof = ark_spartan_snark::SNARK::<Projective<G1>, PC>::prove(
let spartan_proof = spartan_snark::SNARK::<Projective<G1>, PC>::prove(
shape,
&U_prime.try_into()?,
W_prime.try_into()?,
Expand Down Expand Up @@ -259,7 +283,7 @@ where
// Finally, we verify the Spartan proof for the committed relaxed r1cs instance `U_prime`.

let mut transcript = Transcript::new(b"spartan_snark");
ark_spartan_snark::SNARK::<Projective<G1>, PC>::verify(
spartan_snark::SNARK::<Projective<G1>, PC>::verify(
spartan_proof,
&key.computation_comm,
&U_prime.try_into()?,
Expand Down
Loading

0 comments on commit 6045c59

Please sign in to comment.