Skip to content

Commit

Permalink
merge supernova repo
Browse files Browse the repository at this point in the history
  • Loading branch information
govereau committed Jan 9, 2024
2 parents d27d4e0 + ecc80d3 commit 73cecd0
Show file tree
Hide file tree
Showing 45 changed files with 8,906 additions and 0 deletions.
9 changes: 9 additions & 0 deletions supernova/.github/checkout.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
#!/bin/sh

set -e
eval `ssh-agent -s`
echo "$deploy_key" > key
chmod 600 key
ssh-add key
echo
cargo update
61 changes: 61 additions & 0 deletions supernova/.github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
name: CI

on:
pull_request:
push:
branches:
- main

jobs:
check-fmt:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions-rust-lang/setup-rust-toolchain@v1
with:
toolchain: stable
- run: cargo fmt --all -- --check

build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: webfactory/ssh-agent@v0.8.0
with:
ssh-private-key: ${{ secrets.SPARTAN_SSH_DEPLOY }}
- uses: actions-rust-lang/setup-rust-toolchain@v1
with:
toolchain: stable
- uses: webfactory/ssh-agent@v0.8.0
with:
ssh-private-key: ${{ secrets.SPARTAN_SSH_DEPLOY }}
- run: |
cargo build --release
cd supernova-benches && cargo bench --profile=release --no-run
cargo-clippy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions-rust-lang/setup-rust-toolchain@v1
with:
toolchain: stable
- uses: webfactory/ssh-agent@v0.8.0
with:
ssh-private-key: ${{ secrets.SPARTAN_SSH_DEPLOY }}
- run: |
cargo clippy --tests --no-default-features && cargo clippy --tests
test:
needs: build
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions-rust-lang/setup-rust-toolchain@v1
with:
toolchain: stable
- uses: webfactory/ssh-agent@v0.8.0
with:
ssh-private-key: ${{ secrets.SPARTAN_SSH_DEPLOY }}
- run: |
cargo test --release
2 changes: 2 additions & 0 deletions supernova/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
target
Cargo.lock
64 changes: 64 additions & 0 deletions supernova/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
[package]
name = "supernova"
version = "0.1.0"
edition = "2021"

[dependencies]
ark-ff = "0.4.0"
ark-ec = { version = "0.4.0", default-features = false }
ark-std = "0.4.0"
ark-crypto-primitives = { version = "0.4.0", features = ["r1cs", "sponge"] }
ark-relations = { version = "0.4.0" }
ark-r1cs-std = { version = "0.4.0" }
ark-serialize = { version = "0.4.0", features = ["derive"] }
ark-poly = "0.4.0"
ark-poly-commit = { version = "0.4.0", optional = true }
ark_spartan = { git = "ssh://git@github.com/nexus-xyz/committed-relaxed-spartan.git", package = "ark-spartan", optional = true }

merlin = { version = "3.0.0", optional = true }
sha3 = { version = "0.10", default-features = false }

tracing = { version = "0.1", default-features = false }
rayon = { version = "1.8.0", optional = true }

[features]
default = ["parallel"]
parallel = [
"rayon",
"ark-ff/parallel",
"ark-ec/parallel",
"ark-std/parallel",
"ark-crypto-primitives/parallel",
"ark-r1cs-std/parallel",
]
spartan = ["ark-poly-commit", "ark_spartan", "merlin"]

[dev-dependencies]
ark-test-curves = { version = "0.4.2", features = ["bls12_381_curve"] }

ark-pallas = "0.4.0"
ark-vesta = "0.4.0"

ark-bn254 = "0.4.0"
ark-grumpkin = "0.4.0"

tracing-subscriber = { version = "0.2", default-features = false, features = [
"fmt",
"ansi",
] }

[patch.crates-io]
ark-bls12-381 = { git = "https://github.com/arkworks-rs/curves/", rev = "3fded1f" }
ark-crypto-primitives = { git = "https://github.com/arkworks-rs/crypto-primitives", rev = "d27a5c8" }
ark-r1cs-std = { git = "https://github.com/arkworks-rs/r1cs-std/", rev = "2ca3bd7" }
ark-ff = { git = "https://github.com/arkworks-rs/algebra/", rev = "c92be0e" }
ark-ec = { git = "https://github.com/arkworks-rs/algebra/", rev = "c92be0e" }
ark-poly = { git = "https://github.com/arkworks-rs/algebra/", rev = "c92be0e" }
ark-poly-commit = { git = "https://github.com/arkworks-rs/poly-commit/", rev = "c724fa6" }
ark-serialize = { git = "https://github.com/arkworks-rs/algebra/", rev = "c92be0e" }

ark-bn254 = { git = "https://github.com/arkworks-rs/curves", rev = "ccf8392" }
ark-grumpkin = { git = "https://github.com/arkworks-rs/curves", rev = "ccf8392" }
ark-pallas = { git = "https://github.com/arkworks-rs/curves/", rev = "3fded1f" }
ark-vesta = { git = "https://github.com/arkworks-rs/curves/", rev = "3fded1f" }
ark-test-curves = { git = "https://github.com/arkworks-rs/algebra/", rev = "c92be0e" }
1 change: 1 addition & 0 deletions supernova/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
# SuperNova
128 changes: 128 additions & 0 deletions supernova/src/absorb.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
//! An extension for arkworks interface for cryptographic sponge.
//!
//! Poseidon cryptographic sponge from arkworks is defined over some specified field, and current implementation may
//! either silently discard non-native field element absorbed into the sponge, or panic. Thus, care must be taken
//! when choosing between [`Absorb`] and [`AbsorbNonNative`], because both would compile.
//!
//! Let G1, G2 denote a cycle of elliptic curves: G1 = E(F2) with scalar field F1, G2 = E(F1) with scalar field F2.
//! If r1cs input consists of elements from F1, then its commitment is a point on the curve G1 -- elements from F2.
//! Usually, F1 is chosen as a field the sponge operates with, hence commitments from G1 should be absorbed with
//! non-native implementation, whereas commitments from G2 should be absorbed natively.
//!
//! The algorithm for conversion between F1 and F2 should be a unique mapping, e.g. BigNat representation.
#![deny(unsafe_code)]

use ark_crypto_primitives::sponge::{self as ark_sponge, Absorb};
use ark_ec::{
short_weierstrass::{Projective, SWCurveConfig},
CurveGroup,
};
use ark_ff::PrimeField;

use super::{commitment::CommitmentScheme, utils::cast_field_element_unique};
use crate::r1cs::{R1CSInstance, RelaxedR1CSInstance};

/// An interface to objects that can be absorbed by [`ark_sponge::CryptographicSponge`] defined
/// over F1, but cannot be natively represented as an array of elements of F1.
pub trait AbsorbNonNative<F1: PrimeField + Absorb> {
/// Converts self into an array of elements from non-native field F1 and appends
/// it to `dest`.
fn to_non_native_field_elements(&self, dest: &mut Vec<F1>);

/// Converts self into an array of elements from non-native field F1 and appends
/// it into an array of elements from F2 using [`Absorb`].
fn to_sponge_field_elements<F2: PrimeField>(&self, dest: &mut Vec<F2>) {
let mut _dest = Vec::new();
self.to_non_native_field_elements(&mut _dest);

Absorb::to_sponge_field_elements(&_dest, dest);
}
}

/// Extension of [`ark_sponge::CryptographicSponge`] for non-native objects.
pub trait CryptographicSpongeExt: ark_sponge::CryptographicSponge {
/// Absorb an input using non-native implementation.
fn absorb_non_native<F>(&mut self, input: &impl AbsorbNonNative<F>)
where
F: PrimeField + Absorb;
}

impl<S> CryptographicSpongeExt for S
where
S: ark_sponge::CryptographicSponge,
{
fn absorb_non_native<F>(&mut self, input: &impl AbsorbNonNative<F>)
where
F: PrimeField + Absorb,
{
let mut dest = Vec::new();
input.to_non_native_field_elements(&mut dest);

self.absorb(&dest);
}
}

/// Unique affine coordinates are non-native elements, boolean `infinity` is converted to `ZERO` or `ONE`.
///
/// The conversion to affine point must be consistent with in-circuit implementation.
impl<P: SWCurveConfig> AbsorbNonNative<P::ScalarField> for Projective<P>
where
P::BaseField: PrimeField,
P::ScalarField: Absorb,
{
fn to_non_native_field_elements(&self, dest: &mut Vec<P::ScalarField>) {
let affine = self.into_affine();

let x = cast_field_element_unique::<P::BaseField, P::ScalarField>(&affine.x);
let y = cast_field_element_unique::<P::BaseField, P::ScalarField>(&affine.y);
let infinity = P::ScalarField::from(affine.infinity);
Absorb::to_sponge_field_elements(&[&x[..], &y[..], &[infinity]].concat(), dest);
}
}

/// Since r1cs instance contains both elements from F1 and F2, it's a matter of notion what to call
/// native absorb implementation: either it has to cast commitments coordinates or the input `X`.
///
/// Assume that native implementation is the one that doesn't have to cast public input.
impl<G, C> AbsorbNonNative<G::BaseField> for R1CSInstance<G, C>
where
G: CurveGroup,
G::BaseField: PrimeField + Absorb,
G::Affine: Absorb,
C: CommitmentScheme<G, Commitment = G>,
{
fn to_non_native_field_elements(&self, dest: &mut Vec<G::BaseField>) {
Absorb::to_sponge_field_elements(&self.commitment_W.into_affine(), dest);

for x in &self.X[1..] {
let x_base = cast_field_element_unique::<G::ScalarField, G::BaseField>(x);
Absorb::to_sponge_field_elements(&x_base, dest);
}
}
}

/// See the above comment for [`R1CSInstance`] non-native absorb implementation.
impl<G, C> AbsorbNonNative<G::BaseField> for RelaxedR1CSInstance<G, C>
where
G: CurveGroup,
G::BaseField: PrimeField + Absorb,
G::Affine: Absorb,
C: CommitmentScheme<G, Commitment = G>,
{
fn to_non_native_field_elements(&self, dest: &mut Vec<G::BaseField>) {
Absorb::to_sponge_field_elements(&self.commitment_W.into_affine(), dest);
Absorb::to_sponge_field_elements(&self.commitment_E.into_affine(), dest);

for x in &self.X {
let x_base = cast_field_element_unique::<G::ScalarField, G::BaseField>(x);
Absorb::to_sponge_field_elements(&x_base, dest);
}
}
}

impl<F: PrimeField + Absorb, A: AbsorbNonNative<F>> AbsorbNonNative<F> for &A {
fn to_non_native_field_elements(&self, dest: &mut Vec<F>) {
(*self).to_non_native_field_elements(dest)
}
}
23 changes: 23 additions & 0 deletions supernova/src/circuits/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
use ark_ff::PrimeField;
use ark_r1cs_std::fields::fp::FpVar;
use ark_relations::r1cs::{ConstraintSystemRef, SynthesisError};

pub mod nova;

pub trait NovaConstraintSynthesizer<F: PrimeField> {
fn generate_constraints(
self,
cs: ConstraintSystemRef<F>,
) -> Result<Vec<FpVar<F>>, SynthesisError>;
}

pub trait StepCircuit<F: PrimeField>: Send + Sync {
const ARITY: usize;

fn generate_constraints(
&self,
cs: ConstraintSystemRef<F>,
i: &FpVar<F>,
z: &[FpVar<F>],
) -> Result<Vec<FpVar<F>>, SynthesisError>;
}
7 changes: 7 additions & 0 deletions supernova/src/circuits/nova/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
pub mod pcd;
pub mod sequential;

pub mod public_params;

pub use super::{NovaConstraintSynthesizer, StepCircuit};
pub use crate::multifold::Error;
Loading

0 comments on commit 73cecd0

Please sign in to comment.