Skip to content

Commit

Permalink
Merge branch 'main' of https://github.com/mdvillagra/lambdaworks into…
Browse files Browse the repository at this point in the history
… main
  • Loading branch information
mdvillagra committed Sep 5, 2023
2 parents 8233c08 + 5413230 commit 6f32048
Show file tree
Hide file tree
Showing 33 changed files with 5,606 additions and 27 deletions.
22 changes: 0 additions & 22 deletions .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -112,25 +112,3 @@ jobs:
run: make clippy-metal
- name: Run tests
run: make test-metal

test_nvidia:
name: Test (Ubuntu, NVIDIA GPU)
runs-on: [self-hosted, cuda]
env:
CARGO_TERM_COLOR: always
steps:
- uses: actions/checkout@v3
- name: Rustup toolchain install
uses: dtolnay/rust-toolchain@stable
with:
toolchain: stable
components: clippy

- name: Add CUDA binaries to PATH
run: |
echo /usr/local/cuda/bin >> $GITHUB_PATH
- name: Run clippy
run: make clippy-cuda
- name: Run tests
run: cargo test -F cuda
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
[workspace]
members = ["math", "crypto", "gpu", "benches"]
members = ["math", "crypto", "gpu", "benches", "provers/plonk"]
exclude = ["ensure-no_std"]

[workspace.package]
Expand Down
78 changes: 74 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,16 +16,22 @@ Zero-Knowledge and Validity Proofs have gained a lot of attention over the last
So, we decided to build our library, focusing on performance, with clear documentation and developer-focused. Our core team is a group of passionate people from different backgrounds and different strengths; we think that the whole is greater than just the addition of the parts. We don't want to be a compilation of every research result in the ZK space. We want this to be a library that can be used in production, not just in academic research. We want to offer developers the main building blocks and proof systems so that they can build their applications on top of this library.

## Provers and Polynomial Commitment Schemes using LambdaWorks

All provers are being migrated to Lambdaworks library

Right now Plonk prover is in this repo, you can find the others here:

- [Cairo STARK LambdaWorks prover](https://github.com/lambdaclass/lambdaworks_cairo_prover/tree/main)
- [Plonk LambdaWorks prover](https://github.com/lambdaclass/lambdaworks_plonk_prover)
- [CairoVM Trace Generation using LambdaWorks](https://github.com/lambdaclass/cairo-rs/pull/1184)
- [ABI compatible KZG commitment scheme - EIP-4844](https://github.com/lambdaclass/lambdaworks_kzg)

## Main crates

- [Finite Field Algebra](https://github.com/lambdaclass/lambdaworks/tree/main/math/src/field)
- [Polynomial operations](https://github.com/lambdaclass/lambdaworks/blob/main/math/src/polynomial.rs)
- [Fast Fourier Transform](https://github.com/lambdaclass/lambdaworks/tree/main/fft)
- [Math](https://github.com/lambdaclass/lambdaworks/tree/main/math)
- [Crypto primitives](https://github.com/lambdaclass/lambdaworks/crypto)
- [Plonk Prover](https://github.com/lambdaclass/lambdaworks/provers/plonk)

### Crypto
- [Elliptic curves](https://github.com/lambdaclass/lambdaworks/tree/main/math/src/elliptic_curve)
- [Multiscalar multiplication](https://github.com/lambdaclass/lambdaworks/tree/main/math/src/msm)

Expand Down Expand Up @@ -114,6 +120,70 @@ make benchmark BENCH=field

You can check the generated HTML report in `target/criterion/reports/index.html`

# Lambdaworks Plonk Prover
A fast implementation of the [Plonk](https://eprint.iacr.org/2019/953) zk-protocol written in Rust. This is part of the [Lambdaworks](https://github.com/lambdaclass/lambdaworks) zero-knowledge framework. It includes a high-level API to seamlessly build your own circuits.

<div>

[![Telegram Chat][tg-badge]][tg-url]

[tg-badge]: https://img.shields.io/static/v1?color=green&logo=telegram&label=chat&style=flat&message=join
[tg-url]: https://t.me/+98Whlzql7Hs0MDZh

</div>

This prover is still in development and may contain bugs. It is not intended to be used in production yet.

## Building a circuit
The following code creates a circuit with two public inputs `x`, `y` and asserts `x * e = y`:

```rust
let system = &mut ConstraintSystem::<FrField>::new();
let x = system.new_public_input();
let y = system.new_public_input();
let e = system.new_variable();

let z = system.mul(&x, &e);
system.assert_eq(&y, &z);;
```

## Generating a proof
### Setup
A setup is needed in order to generate a proof for a new circuit. The following code generates a verifying key that will be used by both the prover and the verifier:

```rust
let common = CommonPreprocessedInput::from_constraint_system(&system, &ORDER_R_MINUS_1_ROOT_UNITY);
let srs = test_srs(common.n);
let kzg = KZG::new(srs); // The commitment scheme for plonk.
let verifying_key = setup(&common, &kzg);
```

### Prover
First, we fix values for `x` and `e` and solve the constraint system:
```rust
let inputs = HashMap::from([(x, FieldElement::from(4)), (e, FieldElement::from(3))]);
let assignments = system.solve(inputs).unwrap();
```

Finally, we call the prover:
```rust
let witness = Witness::new(assignments, &system);
let public_inputs = system.public_input_values(&assignments);
let prover = Prover::new(kzg.clone(), TestRandomFieldGenerator {});
let proof = prover.prove(&witness, &public_inputs, &common, &verifying_key);
```

## Verifying a proof
Just call the verifier:

```rust
let verifier = Verifier::new(kzg);
assert!(verifier.verify(&proof, &public_inputs, &common, &verifying_key));
```

# More info
You can find more info in the [documentation](https://lambdaclass.github.io/lambdaworks_plonk_prover/).

## 📚 References

The following links, repos and projects have been important in the development of this library and we want to thank and acknowledge them.
Expand Down
6 changes: 6 additions & 0 deletions docs/src/SUMMARY.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,9 @@

- [FFT Library]()
- [Benchmarks](./fft/benchmarks.md)

- [Plonk]()
- [Recap](./plonk/recap.md)
- [Protocol](./plonk/protocol.md)
- [Implementation](./plonk/implementation.md)
- [Circuit API](./plonk/constraint_system.md)
7 changes: 7 additions & 0 deletions docs/src/plonk/SUMMARY.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# Lambdaworks Plonk Prover

- [Recap](./recap.md)
- [Protocol](./protocol.md)
- [Implementation](./implementation.md)
- [Circuit API](./constraint_system.md)

103 changes: 103 additions & 0 deletions docs/src/plonk/constraint_system.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
# Circuit API
In this section, we'll discuss how to build your own constraint system to prove the execution of a particular program.

## Simple Example

Let's take the following simple program as an example. We have two public inputs: `x` and `y`. We want to prove to a verifier that we know a private input `e` such that `x * e = y`. You can achieve this by building the following constraint system:

```rust
use lambdaworks_plonk::constraint_system::ConstraintSystem;
use lambdaworks_math::elliptic_curve::short_weierstrass::curves::bls12_381::default_types::FrField;

fn main() {
let system = &mut ConstraintSystem::<FrField>::new();
let x = system.new_public_input();
let y = system.new_public_input();
let e = system.new_variable();

let z = system.mul(&x, &e);

// This constraint system asserts that x * e == y
system.assert_eq(&y, &z);
}
```

This code creates a constraint system over the field of the BLS12381 curve. Then, it creates three variables: two public inputs `x` and `y`, and a private variable `e`. Note that every variable is private except for the public inputs. Finally, it adds the constraints that represent a multiplication and an assertion.

Before generating proofs for this system, we need to run a setup and obtain a verifying key:

```rust
let common = CommonPreprocessedInput::from_constraint_system(&system, &ORDER_R_MINUS_1_ROOT_UNITY);
let srs = test_srs(common.n);
let kzg = KZG::new(srs); // The commitment scheme for plonk.
let vk = setup(&common, &kzg);
```

Now we can generate proofs for our system. We just need to specify the public inputs and obtain a witness that is a solution for our constraint system:

```rust
let inputs = HashMap::from([(x, FieldElement::from(4)), (e, FieldElement::from(3))]);
let assignments = system.solve(inputs).unwrap();
let witness = Witness::new(assignments, &system);
```

Once you have all these ingredients, you can call the prover:

```rust
let public_inputs = system.public_input_values(&assignments);
let prover = Prover::new(kzg.clone(), TestRandomFieldGenerator {});
let proof = prover.prove(&witness, &public_inputs, &common, &vk);
```

and verify:

```rust
let verifier = Verifier::new(kzg);
assert!(verifier.verify(&proof, &public_inputs, &common, &vk));
```

## Building Complex Systems

Some operations are common, and it makes sense to wrap the set of constraints that do these operations in a function and use it several times. Lambdaworks comes with a collection of functions to help you build your own constraint systems, such as conditionals, inverses, and hash functions.

However, if you have an operation that does not come with Lambdaworks, you can easily extend Lambdaworks functionality. Suppose that the exponentiation operation is something common in your program. You can write the [square and multiply](https://en.wikipedia.org/wiki/Exponentiation_by_squaring) algorithm and put it inside a function:

```rust
pub fn pow(
system: &mut ConstraintSystem<FrField>,
base: Variable,
exponent: Variable,
) -> Variable {
let exponent_bits = system.new_u32(&exponent);
let mut result = system.new_constant(FieldElement::one());

for i in 0..32 {
if i != 0 {
result = system.mul(&result, &result);
}
let result_times_base = system.mul(&result, &base);
result = system.if_else(&exponent_bits[i], &result_times_base, &result);
}
result
}
```

This function can then be used to modify our simple program from the previous section. The following circuit checks that the prover knows `e` such that `pow(x, e) = y`:

```rust
use lambdaworks_plonk::constraint_system::ConstraintSystem;
use lambdaworks_math::elliptic_curve::short_weierstrass::curves::bls12_381::default_types::FrField;

fn main() {
let system = &mut ConstraintSystem::<FrField>::new();
let x = system.new_public_input();
let y = system.new_public_input();
let e = system.new_variable();

let z = pow(system, &x, &e);
system.assert_eq(&y, &z);
}
```

You can keep composing these functions in order to create more complex systems.

Loading

0 comments on commit 6f32048

Please sign in to comment.