diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 00000000..eb5a316c --- /dev/null +++ b/.dockerignore @@ -0,0 +1 @@ +target diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 00000000..5ffab3dc --- /dev/null +++ b/Dockerfile @@ -0,0 +1,20 @@ +FROM alpine:3.18.2 + +ENV PATH="$PATH:/root/.cargo/bin" \ + RUSTFLAGS="-C target-feature=-crt-static" \ + TOOLCHAIN="nightly-2022-11-14" + +RUN apk add --no-cache --update-cache \ + curl clang15 clang15-dev git gcc g++ protoc llvm-dev bash openssl-dev && \ + curl https://sh.rustup.rs -sSf | \ + sh -s -- -y --profile minimal --default-toolchain $TOOLCHAIN &&\ + rustup target add wasm32-unknown-unknown --toolchain $TOOLCHAIN &&\ + rustup component add rustfmt --toolchain $TOOLCHAIN + +WORKDIR /app + +COPY . . + +WORKDIR /app/pallet/nova + +RUN cargo test --release diff --git a/README.md b/README.md index 44013cd3..9e16b98d 100644 --- a/README.md +++ b/README.md @@ -30,6 +30,12 @@ We provide the composable layer 2 technologies by **Recursive Snarks** on top of $ cargo test --all --release ``` +or + +```shell +$ docker-compose up +``` + ## Status **We are in research and development phase and this is alpha quality software. Please use at your own risk**. diff --git a/bn254/README.md b/bn254/README.md index 96571dbe..92a0f8ad 100644 --- a/bn254/README.md +++ b/bn254/README.md @@ -1,14 +1,13 @@ -# Bls12 381 Curve -[![CI](https://github.com/KogarashiNetwork/bls12_381/actions/workflows/ci.yml/badge.svg)](https://github.com/KogarashiNetwork/bls12_381/actions/workflows/ci.yml) [![crates.io badge](https://img.shields.io/crates/v/bls-12-381.svg)](https://crates.io/crates/bls-12-381) [![Documentation](https://docs.rs/bls-12-381/badge.svg)](https://docs.rs/bls-12-381) [![GitHub license](https://img.shields.io/badge/license-GPL3%2FApache2-blue)](#LICENSE) [![codecov](https://codecov.io/gh/KogarashiNetwork/bls12_381/branch/master/graph/badge.svg?token=W83P6U2QKE)](https://codecov.io/gh/KogarashiNetwork/bls12_381) [![dependency status](https://deps.rs/crate/zero-bls12-381/latest/status.svg)](https://deps.rs/crate/zero-bls12-381/latest) +# BN254 Curve -Pairing friendly bls12-381 curve supports fully `no_std` and [`parity-scale-codec`](https://github.com/paritytech/parity-scale-codec). +Pairing friendly bn254 curve supports fully `no_std` and [`parity-scale-codec`](https://github.com/paritytech/parity-scale-codec). ## Overview This crate includes field and extension fields, curve implementation. There are two curve $G1$ and $G2$ described as following. -$G1: y^2 = x^3 + 4$ +$G1: y^2 = x^3 + 3$ -$G2: y^2 = x^3 + 4(u + 1)$ +$G2: y^2 = x^3 + 3(u + 1)$ These two group supports bilinearity by pairing. Let $G$ and $H$ be generator of $G1$, and $G2$, and $e$ be pairing function. The relationship is described as following. diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 00000000..bf7a60bf --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,7 @@ +version: '3' +services: + nova: + build: . + container_name: nova + tty: true + stdin_open: true diff --git a/groth16/Cargo.toml b/groth16/Cargo.toml index d9f979b6..850f6361 100644 --- a/groth16/Cargo.toml +++ b/groth16/Cargo.toml @@ -27,3 +27,6 @@ std = [ "zkstd/std", "rayon" ] + +[[example]] +name = "simple" diff --git a/groth16/README.md b/groth16/README.md index 6125b2a9..36b4812a 100644 --- a/groth16/README.md +++ b/groth16/README.md @@ -1,3 +1,83 @@ # zkSNARKs -Plonk and Groth16 implementation +Implementation of [`On the Size of Pairing-based Non-interactive Arguments`](https://eprint.iacr.org/2016/260.pdf) + +## Usage + +```rs +use bn_254::Fr as BnScalar; +use zkgroth16::{Bn254Driver, Circuit, Error, ZkSnark}; +use zkstd::{ + circuit::prelude::{FieldAssignment, R1cs}, + common::OsRng, +}; + +// Circuit definition +// x: public input +// o: public output +// Constraints are as follows +// x^3 + x + 5 = o +#[derive(Debug)] +pub struct DummyCircuit { + x: BnScalar, + o: BnScalar, +} + +impl DummyCircuit { + pub fn new(x: BnScalar, o: BnScalar) -> Self { + Self { x, o } + } +} + +impl Default for DummyCircuit { + fn default() -> Self { + Self::new(0.into(), 0.into()) + } +} + +impl Circuit for DummyCircuit { + fn synthesize(&self, composer: &mut R1cs) -> Result<(), Error> { + // Declare public input + let x = FieldAssignment::instance(composer, self.x); + // Declare public output + let o = FieldAssignment::instance(composer, self.o); + // Declare public constant + let c = FieldAssignment::constant(&BnScalar::from(5)); + + // Constrain sym1 == x * x + let sym1 = FieldAssignment::mul(composer, &x, &x); + // Constrain y == sym1 * x + let y = FieldAssignment::mul(composer, &sym1, &x); + // Constrain sym2 = y + x + let sym2 = FieldAssignment::add(composer, &y, &x); + + // Constrain sym2 + c == o + FieldAssignment::enforce_eq(composer, &(&sym2 + &c), &o); + + Ok(()) + } +} + +fn main() { + // Public input and output + let x = BnScalar::from(3); + let o = BnScalar::from(35); + + // Initialize circuit with arguments + let circuit = DummyCircuit::new(x, o); + + // Setup prover and verifier + let (mut prover, verifier) = + ZkSnark::setup::(OsRng).expect("Failed to compile circuit"); + + // Generate proof + let proof = prover + .create_proof(&mut OsRng, circuit) + .expect("Failed to prove"); + + // Verify proof + verifier + .verify(&proof, &[x, o]) + .expect("Failed to verify the proof"); +} +``` diff --git a/groth16/examples/simple.rs b/groth16/examples/simple.rs new file mode 100644 index 00000000..1e4ccf75 --- /dev/null +++ b/groth16/examples/simple.rs @@ -0,0 +1,75 @@ +use bn_254::Fr as BnScalar; +use zkgroth16::{Bn254Driver, Circuit, Error, ZkSnark}; +use zkstd::{ + circuit::prelude::{FieldAssignment, R1cs}, + common::OsRng, +}; + +// Circuit definition +// x: public input +// o: public output +// Constraints are as follows +// x^3 + x + 5 = o +#[derive(Debug)] +pub struct DummyCircuit { + x: BnScalar, + o: BnScalar, +} + +impl DummyCircuit { + pub fn new(x: BnScalar, o: BnScalar) -> Self { + Self { x, o } + } +} + +impl Default for DummyCircuit { + fn default() -> Self { + Self::new(0.into(), 0.into()) + } +} + +impl Circuit for DummyCircuit { + fn synthesize(&self, composer: &mut R1cs) -> Result<(), Error> { + // Declare public input + let x = FieldAssignment::instance(composer, self.x); + // Declare public output + let o = FieldAssignment::instance(composer, self.o); + // Declare public constant + let c = FieldAssignment::constant(&BnScalar::from(5)); + + // Constrain sym1 == x * x + let sym1 = FieldAssignment::mul(composer, &x, &x); + // Constrain y == sym1 * x + let y = FieldAssignment::mul(composer, &sym1, &x); + // Constrain sym2 = y + x + let sym2 = FieldAssignment::add(composer, &y, &x); + + // Constrain sym2 + c == o + FieldAssignment::enforce_eq(composer, &(&sym2 + &c), &o); + + Ok(()) + } +} + +fn main() { + // Public input and output + let x = BnScalar::from(3); + let o = BnScalar::from(35); + + // Initialize circuit with arguments + let circuit = DummyCircuit::new(x, o); + + // Setup prover and verifier + let (mut prover, verifier) = + ZkSnark::setup::(OsRng).expect("Failed to compile circuit"); + + // Generate proof + let proof = prover + .create_proof(&mut OsRng, circuit) + .expect("Failed to prove"); + + // Verify proof + verifier + .verify(&proof, &[x, o]) + .expect("Failed to verify the proof"); +} diff --git a/groth16/src/lib.rs b/groth16/src/lib.rs index b99795d3..897fbc47 100644 --- a/groth16/src/lib.rs +++ b/groth16/src/lib.rs @@ -11,7 +11,7 @@ mod prover; mod verifier; mod zksnark; -pub use circuit::Circuit; +pub use circuit::{Bn254Driver, Circuit}; pub use error::Error; pub use proof::Proof; pub use prover::Prover; @@ -20,9 +20,7 @@ pub use zksnark::ZkSnark; #[cfg(test)] mod tests { - use crate::circuit::{Bn254Driver, Circuit}; - use crate::error::Error; - use crate::zksnark::ZkSnark; + use super::*; use bn_254::Fr as BnScalar; use zkstd::circuit::prelude::{FieldAssignment, R1cs}; @@ -56,7 +54,6 @@ mod tests { let sym1 = FieldAssignment::mul(composer, &x, &x); let y = FieldAssignment::mul(composer, &sym1, &x); - // TODO: check why using the `Add` trait crashes this test let sym2 = FieldAssignment::add(composer, &y, &x); FieldAssignment::enforce_eq(composer, &(&sym2 + &c), &o); diff --git a/grumpkin/README.md b/grumpkin/README.md index 05e2b036..4f1b7d34 100644 --- a/grumpkin/README.md +++ b/grumpkin/README.md @@ -1,8 +1,12 @@ # Grumpkin Curve -grumpkin curve implementation. +Grumpkin curve supports fully `no_std` and [`parity-scale-codec`](https://github.com/paritytech/parity-scale-codec). -$E: y^2 = x^3 + 3$ +$E: y^2 = x^3 - 17$ + +## Overview + +This crate includes Grumpkin curve operation. This is cycle pair of bn254 curve. ## Test diff --git a/nova/README.md b/nova/README.md index 1072fabf..af9a8b90 100644 --- a/nova/README.md +++ b/nova/README.md @@ -1 +1,3 @@ # Nova + +Implementation of [`Nova: Recursive Zero-Knowledge Arguments from Folding Schemes`](https://eprint.iacr.org/2021/370.pdf) diff --git a/pallet/nova/README.md b/pallet/nova/README.md new file mode 100644 index 00000000..7362ff54 --- /dev/null +++ b/pallet/nova/README.md @@ -0,0 +1,91 @@ +# Nova Module + +The Nova module provides functionality for Recursive Snarks. + +## Overview + +The Nova module provides functions for: + +- Defining circuit to be folded +- Folding custom circuit r1cs +- Setup public parameters +- Checking satisfiability of folded r1cs + +## Terminology + +- **Recursive Snark**: One types of Snarks which proves a proof inside of another proof. [halo2](https://github.com/zcash/halo2) accumulation scheme is one of the most famous recursive Snark example. Prover proves the validity of verifier in addition to prover arithmetization. + +- **Cycle of Curves**: Curve pair which has inverse scalar and base field for each other. Prover arithmetization is performed on base field and verifier arithmetization is on scalar field. In recursive snark, prover proves both arithmetization thus, cycle of curves can be used for optimization. [pasta](https://github.com/zcash/pasta_curves) curves is one of the most famous cycle of curves example. + +- **Folding Scheme**: One types of recursive snark strategy. Folding scheme compresses the statement instead of generating proof. We can skip heavy computation such as the Fft and large Msm by avoiding proof generation. + +- **IVC Scheme** One types of [Proof-Carrying Data](https://eprint.iacr.org/2020/1618.pdf). IVC (Incrementally Verifiable Computation) means computations over path graphs. + +## Interface + +### Dispatchable Functions + +- `verify` - Verify IVC scheme final proof + +## Usage + +The following examples show how to use the Nova module in your custom module. + +### Examples from the FRAME + +The Nova module uses the `FunctionCircuit` trait to define circuit to be folded: + +```rs +impl FunctionCircuit for ExampleFunction { + fn invoke(z: &DenseVectors) -> DenseVectors { + let next_z = z[0] * z[0] * z[0] + z[0] + F::from(5); + DenseVectors::new(vec![next_z]) + } + + fn invoke_cs>( + cs: &mut R1cs, + z_i: Vec>, + ) -> Vec> { + let five = FieldAssignment::constant(&F::from(5)); + let z_i_square = FieldAssignment::mul(cs, &z_i[0], &z_i[0]); + let z_i_cube = FieldAssignment::mul(cs, &z_i_square, &z_i[0]); + + vec![&(&z_i_cube + &z_i[0]) + &five] + } +} +``` + +- `invoke` - Return function result +- `invoke_cs` - Custom circuit constraints + +In above example, we prove $f(x) = x^3 + x + 5$ for given input $x$. +The Nova module verifies the folding scheme validity by `verify` pallet function. + +```rs +let z0_primary = DenseVectors::new(vec![Fr::from(0)]); +let z0_secondary = DenseVectors::new(vec![Fq::from(0)]); +let mut ivc = + Ivc::, ExampleFunction>::init( + &pp, + z0_primary, + z0_secondary, + ); +(0..2).for_each(|_| { + ivc.prove_step(&pp); +}); +let proof = ivc.prove_step(&pp); + +new_test_ext().execute_with(|| { + assert!(Nova::verify(Origin::signed(1), proof, pp.clone()).is_ok()); +}); +``` + +In above example, we verify the validity of folding $x_3 = f^{(3)}(x)$ + +## Test + +```shell +$ cargo test --all --release +``` + +License: Apache-2.0 diff --git a/pallet/nova/src/mock.rs b/pallet/nova/src/mock.rs index 3d0c0f30..fcc8e3b5 100644 --- a/pallet/nova/src/mock.rs +++ b/pallet/nova/src/mock.rs @@ -1,4 +1,4 @@ -use crate as nova_ivc_pallet; +use crate as pallet_nova; use crate::*; use frame_support::parameter_types; use frame_system as system; @@ -19,7 +19,7 @@ frame_support::construct_runtime!( UncheckedExtrinsic = UncheckedExtrinsic, { System: frame_system::{Module, Call, Config, Storage, Event}, - TemplateModule: nova_ivc_pallet::{Module, Call, Storage}, + TemplateModule: pallet_nova::{Module, Call, Storage}, } ); @@ -76,7 +76,7 @@ impl FunctionCircuit for ExampleFunction { } } -impl nova_ivc_pallet::Config for Test { +impl pallet_nova::Config for Test { type E1 = Bn254Driver; type E2 = GrumpkinDriver; type FC1 = ExampleFunction;