Skip to content

Commit

Permalink
Address PR comments (without CLI yet)
Browse files Browse the repository at this point in the history
  • Loading branch information
ytham committed Dec 15, 2024
1 parent 454b776 commit 0ab0944
Showing 1 changed file with 16 additions and 21 deletions.
37 changes: 16 additions & 21 deletions book/src/using-extensions/pairing.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ A full guest program example is available here: [pairing_check.rs](https://githu

We'll be working with an example using the BLS12-381 elliptic curve. This is in addition to the setup that needs to be done in the [Writing a Program](../writing-apps/write-program.md) section.

In the guest program, we will import the `PairingCheck` and `IntMod` traits, along with a few other values that we will require:
In the guest program, we will import the `PairingCheck` and `IntMod` traits, along with the BLS12-381 curve structs (**IMPORTANT:** this requires the `bls12_381` feature enabled in Cargo.toml for the `openvm-pairing-guest` dependency), and a few other values that we will need:

```rust title="guest program"
use openvm_pairing_guest::{
Expand All @@ -29,6 +29,7 @@ use openvm::io::read;
Additionally, we'll need to initialize our moduli and `Fp2` struct via the following macros. For a more in-depth description of these macros, please see the [Customizable Extensions](./customizable-extensions.md) section.

```rust
// These correspond to the BLS12-381 coordinate and scalar moduli, respectively
openvm_algebra_moduli_setup::moduli_init! {
"0x1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffaaab",
"0x73eda753299d7d483339d80809a1d80553bda402fffe5bfeffffffff00000001"
Expand All @@ -46,11 +47,13 @@ setup_0();
setup_all_complex_extensions();
```

There are two moduli defined internally in the Bls12_381 feature. The `moduli_init!` macro thus requires both of them to be initialized. However, we do not need the scalar field of BLS12-381 (which is at index 1), and thus we only initialize the modulus from index 0, thus we only use `setup_0()` (as opposed to `setup_all_moduli()`, which will save us some columns when generating the trace).

## Input values

The inputs to the pairing check are `AffinePoint`s in $\mathbb{F}_p$ and $\mathbb{F}_{p^2}$. They can be constructed via the `AffinePoint::new` function, with the inner `Fp` and `Fp2` values constructed via various `from_...` functions.

We can create a new struct that will hold this point outside of our guest program and import it into our guest program:
We can create a new struct outside of our guest program that will hold these `AffinePoint`s and import it into our guest program:

```rust
#[derive(Clone, serde::Serialize, serde::Deserialize)]
Expand All @@ -68,11 +71,9 @@ Our guest program imports the struct and can read it in via:
let io: PairingCheckInput = read();
```

> Please note that the coefficients of the input points must equal to 0: $ad + bc = 0$, with $a,b$ as the $p0,q0$ points and $c,d$ as the $p1,q1$ points. A point is given by $a*g$, where $a$ is a scalar and $g$ is the generator in either $\mathbb{F}_p$ or $\mathbb{F}_{p^2}$. To get the above $ad + bc = 0$ equation, we can negate (`.neg()`) a single `AffinePoint` to ensure that the equation holds.
## Pairing check

Most users that use the pairing extension will want to assert that a pairing is valid (the final exponentiation equals one). This with the `PairingCheck` trait imported from the previous section, we have access to the `pairing_check` function on the `Bls12_381` struct. After reading in the input struct, we can use its values in the `pairing_check`:
Most users that use the pairing extension will want to assert that a pairing is valid (the final exponentiation equals one). With the `PairingCheck` trait imported from the previous section, we have access to the `pairing_check` function on the `Bls12_381` struct. After reading in the input struct, we can use its values in the `pairing_check`:

```rust
let res = Bls12_381::pairing_check(
Expand All @@ -86,20 +87,9 @@ assert!(res.is_ok())

We also have access to each of the specific functions that the pairing check utilizes for either the BN254 or BLS12-381 elliptic curves.

### Line function evaluations

Line functions can be separately evaluated:

```rust
// Line functions in 023 form; b0, c0, b1, c1 are Fp2
let l0 = EvaluatedLine::<Fp2> { b: b0, c: c0 }
let l1 = EvaluatedLine::<Fp2> { b: b1, c: c1 };
let r = Bls12_381::mul_023_by_023(l0, l1);
```

### Multi-Miller loop

The multi-Miller loop can also be ran separately via:
The multi-Miller loop requires the MultiMillerLoop trait can also be ran separately via:

```rust
let f = Bls12_381::multi_miller_loop(
Expand All @@ -108,12 +98,17 @@ let f = Bls12_381::multi_miller_loop(
);
```

### Final exponentiation hint
### Final exponentiation

Final exponentiation is computed on the host and hinted to OpenVM via the `final_exp_hint` function:
Final exponentiation can be run separately by importing the `FinalExp` trait.

```rust
let (c, s) = Bls12_381::final_exp_hint(&f);
use openvm_pairing_guest::pairing::FinalExp;
let (c, s) = Bls12_381::assert_final_exp_is_one(
&f,
&[p0, p1],
&[q0, q1],
);
```

Where $c$ is the residue witness and $s$ is the scaling factor (BLS12-381) or cubic non-residue power (BN254), and the input $f$ is the result of the multi-Miller loop.
Where $c$ is the residue witness and $s$ is the scaling factor (BLS12-381) or cubic non-residue power (BN254), and the input $f$ is the result of the multi-Miller loop. The `p0`, `p1`, `q0`, `q1` points are the same as those used in the multi_miller_loop function.

0 comments on commit 0ab0944

Please sign in to comment.