Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 9 additions & 8 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -8,30 +8,31 @@ license = "MIT OR Apache-2.0"
[dependencies]
ark-std = { version = "0.5.0-alpha", default-features = false }
ark-ff = { version = "0.5.0-alpha", default-features = false }
ark-circom = { git = "https://github.com/HungryCatsStudio/circom-compat", branch = "update-0.5" }
ark-circom = { version = "0.5.0-alpha" }
ark-poly = { version = "0.5.0-alpha", default-features = false }
ark-relations = { version = "0.5.0-alpha", default-features = false }
ark-crypto-primitives = { version = "0.5.0-alpha", default-features = false, features = ["sponge"] }
ark-ec = { version = "0.5.0-alpha", default-features = false }
ark-serialize = { version = "0.5.0-alpha", default-features = false, features = ["derive"] }
ark-poly-commit = { git = "https://github.com/HungryCatsStudio/poly-commit", branch = "release-0.5", default-features = false, features = [ "test-types" ] }
itertools = "0.10.0"
derivative = { version = "2", features = [ "use_core" ] }
criterion = { version = "0.5", default-features = false }
num-bigint = "0.4.0"
rand_chacha = { version = "0.3.0", default-features = false }
blake2 = { version = "0.10", default-features = false }

[dev-dependencies]
criterion = { version = "0.5", default-features = false }
ark-bn254 = { version = "0.5.0-alpha", default-features = false, features = [ "curve" ] }
ark-bls12-377 = { version = "0.5.0-alpha", default-features = false, features = [ "curve" ] }
ark-poly-commit = { git = "https://github.com/HungryCatsStudio/poly-commit", branch = "release-0.5", default-features = false, features = [ "test-types" ] }
ark-serialize = { version = "0.5.0-alpha", default-features = false, features = ["derive"] }
ark-ec = { version = "0.5.0-alpha", default-features = false }
serde = { version = "1.0.104", features = ["derive"] }
serde_json = "1.0.48"
criterion = "0.3"
tokio = { version = "1.0", features = ["macros"] }

[features]
default = [ "std" ]
std = [ "ark-ff/std", "ark-ec/std", "ark-poly/std", "ark-std/std", "ark-relations/std", "ark-serialize/std", "ark-crypto-primitives/std", "ark-poly-commit/std" ]
test-types = [ "ark-poly-commit/test-types" ]
bench = [ "std", "test-types" ]

[[bench]]
name = "prove_verify"
harness = false
11 changes: 11 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -107,3 +107,14 @@ A few caveats are in order:
- A `LigeroCircuit` is constructed from an `ArithmeticCircuit` by designating some of its nodes as outputs. The proof system convinces the verifier that the value of each of those outputs with the witness provided by the prover is equal to one.
- The proof system described in the reference paper is slightly expanded to naturally handle constants, which were not part of the original description.
- Each `LigeroCircuit` starts with a constant node of value `1`, as necessitated by the proof system. This is handled transparently whenever an `ArithmeticCircuit` is compiled into a `LigeroCircuit`.

## Benchmarks

Currently, we construct a very simple `ArithmeticCircuit` over the scalar field of BN254 for computing n Fibonacci steps with only addition gates. Note that the parameters (e.g. matrix dimensions) have not been optimized.

To run the benchmarks, use:
```
cargo bench
```

Sample results on a c5a.4xlarge AWS instance are shown in [benches/results.txt](benches/results.txt).
65 changes: 65 additions & 0 deletions benches/prove_verify.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
use ark_bn254::Fr;
use ark_crypto_primitives::sponge::poseidon::PoseidonSponge;
use ark_ff::Field;
use ark_poly_commit::test_sponge;
use criterion::{criterion_group, criterion_main, BenchmarkId, Criterion};
use ligero::arithmetic_circuit::ArithmeticCircuit;
use ligero::ligero::{types::LigeroMTTestParams, LigeroCircuit};
use ligero::DEFAULT_SECURITY_LEVEL;

fn generate_fibonacci_circuit(steps: usize) -> ArithmeticCircuit<Fr> {
let mut circuit = ArithmeticCircuit::new();

let one = circuit.constant(Fr::ONE);

let f_0 = circuit.new_variable_with_label("f_0");
let f_1 = circuit.new_variable_with_label("f_1");

let mut first_operand = f_0;
let mut second_operand = f_1;

for _ in 2..steps {
let next = circuit.add(first_operand, second_operand);
first_operand = second_operand;
second_operand = next;
}

circuit.add_nodes([second_operand, one]);
circuit
}

fn bench_prove_verify(c: &mut Criterion) {
let mut group = c.benchmark_group("ligero");
for size in [12, 16].iter() {
let steps = 1 << size;
let circuit = generate_fibonacci_circuit(steps);
let output_node = circuit.last();
let ligero_circuit = LigeroCircuit::new(circuit, vec![output_node], DEFAULT_SECURITY_LEVEL);
let sponge: PoseidonSponge<Fr> = test_sponge();
let mt_params = LigeroMTTestParams::new();

group.bench_function(BenchmarkId::new("prove_fibonacci", size), |b| {
b.iter(|| {
ligero_circuit.prove_with_labels(
vec![("f_0", Fr::from(1)), ("f_1", Fr::from(1))],
&mt_params,
&mut sponge.clone(),
)
})
});

let proof = ligero_circuit.prove_with_labels(
vec![("f_0", Fr::from(1)), ("f_1", Fr::from(1))],
&mt_params,
&mut sponge.clone(),
);

group.bench_function(BenchmarkId::new("verify_fibonacci", size), |b| {
b.iter(|| ligero_circuit.verify(&proof, &mt_params, &mut sponge.clone()))
});
}
group.finish();
}

criterion_group!(benches, bench_prove_verify);
criterion_main!(benches);
8 changes: 8 additions & 0 deletions benches/results.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
ligero/prove_fibonacci/12
time: [1.9395 s 1.9431 s 1.9467 s]
ligero/verify_fibonacci/12
time: [480.78 ms 482.80 ms 484.80 ms]
ligero/prove_fibonacci/16
time: [11.330 s 11.341 s 11.352 s]
ligero/verify_fibonacci/16
time: [2.5958 s 2.6023 s 2.6087 s]
2 changes: 1 addition & 1 deletion src/arithmetic_circuit/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use ark_ff::{BigInteger, PrimeField};
use ark_relations::r1cs::{ConstraintMatrices, ConstraintSystem};

#[cfg(test)]
pub(crate) mod tests;
pub mod tests;

#[derive(Debug, Clone, PartialEq)]
pub(crate) enum Node<F> {
Expand Down
10 changes: 5 additions & 5 deletions src/arithmetic_circuit/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ use ark_bn254::Fr as FrBN;
use super::Node;

// Defining equation of BLS12-377: y^2 = x^3 + 1 (over Fq)
pub(crate) fn generate_bls12_377_circuit() -> ArithmeticCircuit<FqBLS> {
pub fn generate_bls12_377_circuit() -> ArithmeticCircuit<FqBLS> {
let mut circuit = ArithmeticCircuit::new();

// Ligero circuits must start with a constant 1
Expand Down Expand Up @@ -171,8 +171,8 @@ fn test_indicator() {
);
}

#[test]
fn test_multiplication() {
#[tokio::test]
async fn test_multiplication() {
let cs = read_constraint_system::<FrBN>(
&format!(TEST_DATA_PATH!(), "multiplication.r1cs"),
&format!(TEST_DATA_PATH!(), "multiplication.wasm"),
Expand All @@ -186,8 +186,8 @@ fn test_multiplication() {
assert_eq!(circuit.evaluate(valid_assignment), FrBN::ONE);
}

#[test]
fn test_cube_multioutput() {
#[tokio::test]
async fn test_cube_multioutput() {
let r1cs = read_constraint_system::<FrBN>(
&format!(TEST_DATA_PATH!(), "cube.r1cs"),
&format!(TEST_DATA_PATH!(), "cube.wasm"),
Expand Down
8 changes: 6 additions & 2 deletions src/ligero/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ use crate::{

#[cfg(test)]
mod tests;
mod types;
pub mod types;

// TODO: optimise: when can one evaluate the interpolating polynomial at the
// queried points instead of computing the whole RS encoding in the three
Expand Down Expand Up @@ -93,6 +93,7 @@ pub struct LigeroCircuit<F: PrimeField> {
intermediate_domain: GeneralEvaluationDomain<F>,
}

#[derive(Clone)]
pub struct LigeroProof<F: PrimeField, C: Config> {
// Merkle commitment to the matrix
// U = [U_x
Expand All @@ -113,6 +114,7 @@ pub struct LigeroProof<F: PrimeField, C: Config> {
}

/// Proof for the Test-Interleaved protocol
#[derive(Clone)]
pub struct InterleavedProof<F, C>
where
F: PrimeField,
Expand All @@ -123,6 +125,7 @@ where
paths: Vec<Path<C>>,
}

#[derive(Clone)]
pub struct LinearConstraintsProof<F, C>
where
F: PrimeField,
Expand All @@ -133,6 +136,7 @@ where
paths: Vec<Path<C>>,
}

#[derive(Clone)]
pub struct QuadraticConstraintsProof<F, C>
where
F: PrimeField,
Expand Down Expand Up @@ -612,7 +616,7 @@ impl<F: PrimeField + Absorb> LigeroCircuit<F> {

pub fn verify<C, H, P>(
&self,
proof: LigeroProof<F, C>,
proof: &LigeroProof<F, C>,
mt_params: &P,
sponge: &mut impl CryptographicSponge,
) -> bool
Expand Down
10 changes: 5 additions & 5 deletions src/ligero/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,7 @@ fn proof_and_verify<F: PrimeField + Absorb>(

let proof = ligero_circuit.prove(vars.clone(), &mt_params, &mut sponge.clone());

ligero_circuit.verify(proof, &mt_params, &mut sponge.clone())
ligero_circuit.verify(&proof, &mt_params, &mut sponge.clone())
}

fn test_proof_and_verify<F: PrimeField + Absorb>(
Expand Down Expand Up @@ -358,11 +358,11 @@ pub fn test_multioutput_1() {
&mut prover_sponge,
);

assert!(ligero.verify(proof, &mt_params, &mut verifier_sponge));
assert!(ligero.verify(&proof, &mt_params, &mut verifier_sponge));
}

#[test]
pub fn test_poseidon() {
#[tokio::test]
pub async fn test_poseidon() {
println!("Reading R1CS from file...");
let cs: ConstraintSystem<Fr> = read_constraint_system(
"circom/poseidon/poseidon.r1cs",
Expand Down Expand Up @@ -409,7 +409,7 @@ pub fn test_poseidon() {
let start = std::time::Instant::now();

println!("Verifying LigeroCircuit...");
assert!(ligero.verify(proof, &mt_params, &mut sponge));
assert!(ligero.verify(&proof, &mt_params, &mut sponge));

println!("Time to verify: {:?}", start.elapsed());
}