Skip to content

Commit

Permalink
BN254 groth16 verifier (MystenLabs#9196)
Browse files Browse the repository at this point in the history
## Description 

Add a Move API for verifying Groth16 zero-knowledge proofs with the
BN254 elliptic curve construction.

## Test Plan 

All tests pass.
  • Loading branch information
jonas-lj authored Mar 14, 2023
1 parent f72f3a3 commit 894dfb5
Show file tree
Hide file tree
Showing 7 changed files with 281 additions and 44 deletions.
128 changes: 122 additions & 6 deletions crates/sui-framework/docs/groth16.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,19 @@



- [Struct `Curve`](#0x2_groth16_Curve)
- [Struct `PreparedVerifyingKey`](#0x2_groth16_PreparedVerifyingKey)
- [Struct `PublicProofInputs`](#0x2_groth16_PublicProofInputs)
- [Struct `ProofPoints`](#0x2_groth16_ProofPoints)
- [Constants](#@Constants_0)
- [Function `bls12381`](#0x2_groth16_bls12381)
- [Function `bn254`](#0x2_groth16_bn254)
- [Function `pvk_from_bytes`](#0x2_groth16_pvk_from_bytes)
- [Function `pvk_to_bytes`](#0x2_groth16_pvk_to_bytes)
- [Function `public_proof_inputs_from_bytes`](#0x2_groth16_public_proof_inputs_from_bytes)
- [Function `proof_points_from_bytes`](#0x2_groth16_proof_points_from_bytes)
- [Function `prepare_verifying_key`](#0x2_groth16_prepare_verifying_key)
- [Function `prepare_verifying_key_internal`](#0x2_groth16_prepare_verifying_key_internal)
- [Function `verify_groth16_proof`](#0x2_groth16_verify_groth16_proof)
- [Function `verify_groth16_proof_internal`](#0x2_groth16_verify_groth16_proof_internal)

Expand All @@ -22,6 +26,35 @@



<a name="0x2_groth16_Curve"></a>

## Struct `Curve`

Represents an elliptic curve construction to be used in the verifier. Currently we support BLS12-381 and BN254.
This should be given as the first parameter to <code>prepare_verifying_key</code> or <code>verify_groth16_proof</code>.


<pre><code><b>struct</b> <a href="groth16.md#0x2_groth16_Curve">Curve</a> <b>has</b> <b>copy</b>, drop, store
</code></pre>



<details>
<summary>Fields</summary>


<dl>
<dt>
<code>id: u8</code>
</dt>
<dd>

</dd>
</dl>


</details>

<a name="0x2_groth16_PreparedVerifyingKey"></a>

## Struct `PreparedVerifyingKey`
Expand Down Expand Up @@ -129,6 +162,15 @@ A <code><a href="groth16.md#0x2_groth16_ProofPoints">ProofPoints</a></code> wrap
## Constants


<a name="0x2_groth16_EInvalidCurve"></a>



<pre><code><b>const</b> <a href="groth16.md#0x2_groth16_EInvalidCurve">EInvalidCurve</a>: u64 = 1;
</code></pre>



<a name="0x2_groth16_EInvalidVerifyingKey"></a>


Expand All @@ -138,6 +180,52 @@ A <code><a href="groth16.md#0x2_groth16_ProofPoints">ProofPoints</a></code> wrap



<a name="0x2_groth16_bls12381"></a>

## Function `bls12381`

Return the <code><a href="groth16.md#0x2_groth16_Curve">Curve</a></code> value indicating that the BLS12-381 construction should be used in a given function.


<pre><code><b>public</b> <b>fun</b> <a href="bls12381.md#0x2_bls12381">bls12381</a>(): <a href="groth16.md#0x2_groth16_Curve">groth16::Curve</a>
</code></pre>



<details>
<summary>Implementation</summary>


<pre><code><b>public</b> <b>fun</b> <a href="bls12381.md#0x2_bls12381">bls12381</a>(): <a href="groth16.md#0x2_groth16_Curve">Curve</a> { <a href="groth16.md#0x2_groth16_Curve">Curve</a> { id: 0 } }
</code></pre>



</details>

<a name="0x2_groth16_bn254"></a>

## Function `bn254`

Return the <code><a href="groth16.md#0x2_groth16_Curve">Curve</a></code> value indicating that the BN254 construction should be used in a given function.


<pre><code><b>public</b> <b>fun</b> <a href="groth16.md#0x2_groth16_bn254">bn254</a>(): <a href="groth16.md#0x2_groth16_Curve">groth16::Curve</a>
</code></pre>



<details>
<summary>Implementation</summary>


<pre><code><b>public</b> <b>fun</b> <a href="groth16.md#0x2_groth16_bn254">bn254</a>(): <a href="groth16.md#0x2_groth16_Curve">Curve</a> { <a href="groth16.md#0x2_groth16_Curve">Curve</a> { id: 1 } }
</code></pre>



</details>

<a name="0x2_groth16_pvk_from_bytes"></a>

## Function `pvk_from_bytes`
Expand Down Expand Up @@ -252,14 +340,40 @@ Creates a Groth16 <code><a href="groth16.md#0x2_groth16_ProofPoints">ProofPoints

## Function `prepare_verifying_key`

@param curve: What elliptic curve construction to use. See <code><a href="bls12381.md#0x2_bls12381">bls12381</a></code> and <code>bn254</code>.
@param veriyfing_key: An Arkworks canonical compressed serialization of a verifying key.

Returns four vectors of bytes representing the four components of a prepared verifying key.
This step computes one pairing e(P, Q), and binds the verification to one particular proof statement.
This can be used as inputs for the <code>verify_groth16_proof</code> function.


<pre><code><b>public</b> <b>fun</b> <a href="groth16.md#0x2_groth16_prepare_verifying_key">prepare_verifying_key</a>(verifying_key: &<a href="">vector</a>&lt;u8&gt;): <a href="groth16.md#0x2_groth16_PreparedVerifyingKey">groth16::PreparedVerifyingKey</a>
<pre><code><b>public</b> <b>fun</b> <a href="groth16.md#0x2_groth16_prepare_verifying_key">prepare_verifying_key</a>(curve: &<a href="groth16.md#0x2_groth16_Curve">groth16::Curve</a>, verifying_key: &<a href="">vector</a>&lt;u8&gt;): <a href="groth16.md#0x2_groth16_PreparedVerifyingKey">groth16::PreparedVerifyingKey</a>
</code></pre>



<details>
<summary>Implementation</summary>


<pre><code><b>public</b> <b>fun</b> <a href="groth16.md#0x2_groth16_prepare_verifying_key">prepare_verifying_key</a>(curve: &<a href="groth16.md#0x2_groth16_Curve">Curve</a>, verifying_key: &<a href="">vector</a>&lt;u8&gt;): <a href="groth16.md#0x2_groth16_PreparedVerifyingKey">PreparedVerifyingKey</a> {
<a href="groth16.md#0x2_groth16_prepare_verifying_key_internal">prepare_verifying_key_internal</a>(curve.id, verifying_key)
}
</code></pre>



</details>

<a name="0x2_groth16_prepare_verifying_key_internal"></a>

## Function `prepare_verifying_key_internal`

Native functions that flattens the inputs into an array and passes to the Rust native function.


<pre><code><b>fun</b> <a href="groth16.md#0x2_groth16_prepare_verifying_key_internal">prepare_verifying_key_internal</a>(curve: u8, verifying_key: &<a href="">vector</a>&lt;u8&gt;): <a href="groth16.md#0x2_groth16_PreparedVerifyingKey">groth16::PreparedVerifyingKey</a>
</code></pre>


Expand All @@ -268,7 +382,7 @@ This can be used as inputs for the <code>verify_groth16_proof</code> function.
<summary>Implementation</summary>


<pre><code><b>public</b> <b>native</b> <b>fun</b> <a href="groth16.md#0x2_groth16_prepare_verifying_key">prepare_verifying_key</a>(verifying_key: &<a href="">vector</a>&lt;u8&gt;): <a href="groth16.md#0x2_groth16_PreparedVerifyingKey">PreparedVerifyingKey</a>;
<pre><code><b>native</b> <b>fun</b> <a href="groth16.md#0x2_groth16_prepare_verifying_key_internal">prepare_verifying_key_internal</a>(curve: u8, verifying_key: &<a href="">vector</a>&lt;u8&gt;): <a href="groth16.md#0x2_groth16_PreparedVerifyingKey">PreparedVerifyingKey</a>;
</code></pre>


Expand All @@ -292,14 +406,15 @@ This can be used as inputs for the <code>verify_groth16_proof</code> function.

## Function `verify_groth16_proof`

@param curve: What elliptic curve construction to use. See the <code><a href="bls12381.md#0x2_bls12381">bls12381</a></code> and <code>bn254</code> functions.
@param prepared_verifying_key: Consists of four vectors of bytes representing the four components of a prepared verifying key.
@param public_proof_inputs: Represent inputs that are public.
@param proof_points: Represent three proof points.

Returns a boolean indicating whether the proof is valid.


<pre><code><b>public</b> <b>fun</b> <a href="groth16.md#0x2_groth16_verify_groth16_proof">verify_groth16_proof</a>(prepared_verifying_key: &<a href="groth16.md#0x2_groth16_PreparedVerifyingKey">groth16::PreparedVerifyingKey</a>, public_proof_inputs: &<a href="groth16.md#0x2_groth16_PublicProofInputs">groth16::PublicProofInputs</a>, proof_points: &<a href="groth16.md#0x2_groth16_ProofPoints">groth16::ProofPoints</a>): bool
<pre><code><b>public</b> <b>fun</b> <a href="groth16.md#0x2_groth16_verify_groth16_proof">verify_groth16_proof</a>(curve: &<a href="groth16.md#0x2_groth16_Curve">groth16::Curve</a>, prepared_verifying_key: &<a href="groth16.md#0x2_groth16_PreparedVerifyingKey">groth16::PreparedVerifyingKey</a>, public_proof_inputs: &<a href="groth16.md#0x2_groth16_PublicProofInputs">groth16::PublicProofInputs</a>, proof_points: &<a href="groth16.md#0x2_groth16_ProofPoints">groth16::ProofPoints</a>): bool
</code></pre>


Expand All @@ -308,8 +423,9 @@ Returns a boolean indicating whether the proof is valid.
<summary>Implementation</summary>


<pre><code><b>public</b> <b>fun</b> <a href="groth16.md#0x2_groth16_verify_groth16_proof">verify_groth16_proof</a>(prepared_verifying_key: &<a href="groth16.md#0x2_groth16_PreparedVerifyingKey">PreparedVerifyingKey</a>, public_proof_inputs: &<a href="groth16.md#0x2_groth16_PublicProofInputs">PublicProofInputs</a>, proof_points: &<a href="groth16.md#0x2_groth16_ProofPoints">ProofPoints</a>): bool {
<pre><code><b>public</b> <b>fun</b> <a href="groth16.md#0x2_groth16_verify_groth16_proof">verify_groth16_proof</a>(curve: &<a href="groth16.md#0x2_groth16_Curve">Curve</a>, prepared_verifying_key: &<a href="groth16.md#0x2_groth16_PreparedVerifyingKey">PreparedVerifyingKey</a>, public_proof_inputs: &<a href="groth16.md#0x2_groth16_PublicProofInputs">PublicProofInputs</a>, proof_points: &<a href="groth16.md#0x2_groth16_ProofPoints">ProofPoints</a>): bool {
<a href="groth16.md#0x2_groth16_verify_groth16_proof_internal">verify_groth16_proof_internal</a>(
curve.id,
&prepared_verifying_key.vk_gamma_abc_g1_bytes,
&prepared_verifying_key.alpha_g1_beta_g2_bytes,
&prepared_verifying_key.gamma_g2_neg_pc_bytes,
Expand All @@ -331,7 +447,7 @@ Returns a boolean indicating whether the proof is valid.
Native functions that flattens the inputs into arrays of vectors and passed to the Rust native function.


<pre><code><b>public</b> <b>fun</b> <a href="groth16.md#0x2_groth16_verify_groth16_proof_internal">verify_groth16_proof_internal</a>(vk_gamma_abc_g1_bytes: &<a href="">vector</a>&lt;u8&gt;, alpha_g1_beta_g2_bytes: &<a href="">vector</a>&lt;u8&gt;, gamma_g2_neg_pc_bytes: &<a href="">vector</a>&lt;u8&gt;, delta_g2_neg_pc_bytes: &<a href="">vector</a>&lt;u8&gt;, public_proof_inputs: &<a href="">vector</a>&lt;u8&gt;, proof_points: &<a href="">vector</a>&lt;u8&gt;): bool
<pre><code><b>fun</b> <a href="groth16.md#0x2_groth16_verify_groth16_proof_internal">verify_groth16_proof_internal</a>(curve: u8, vk_gamma_abc_g1_bytes: &<a href="">vector</a>&lt;u8&gt;, alpha_g1_beta_g2_bytes: &<a href="">vector</a>&lt;u8&gt;, gamma_g2_neg_pc_bytes: &<a href="">vector</a>&lt;u8&gt;, delta_g2_neg_pc_bytes: &<a href="">vector</a>&lt;u8&gt;, public_proof_inputs: &<a href="">vector</a>&lt;u8&gt;, proof_points: &<a href="">vector</a>&lt;u8&gt;): bool
</code></pre>


Expand All @@ -340,7 +456,7 @@ Native functions that flattens the inputs into arrays of vectors and passed to t
<summary>Implementation</summary>


<pre><code><b>public</b> <b>native</b> <b>fun</b> <a href="groth16.md#0x2_groth16_verify_groth16_proof_internal">verify_groth16_proof_internal</a>(vk_gamma_abc_g1_bytes: &<a href="">vector</a>&lt;u8&gt;, alpha_g1_beta_g2_bytes: &<a href="">vector</a>&lt;u8&gt;, gamma_g2_neg_pc_bytes: &<a href="">vector</a>&lt;u8&gt;, delta_g2_neg_pc_bytes: &<a href="">vector</a>&lt;u8&gt;, public_proof_inputs: &<a href="">vector</a>&lt;u8&gt;, proof_points: &<a href="">vector</a>&lt;u8&gt;): bool;
<pre><code><b>native</b> <b>fun</b> <a href="groth16.md#0x2_groth16_verify_groth16_proof_internal">verify_groth16_proof_internal</a>(curve: u8, vk_gamma_abc_g1_bytes: &<a href="">vector</a>&lt;u8&gt;, alpha_g1_beta_g2_bytes: &<a href="">vector</a>&lt;u8&gt;, gamma_g2_neg_pc_bytes: &<a href="">vector</a>&lt;u8&gt;, delta_g2_neg_pc_bytes: &<a href="">vector</a>&lt;u8&gt;, public_proof_inputs: &<a href="">vector</a>&lt;u8&gt;, proof_points: &<a href="">vector</a>&lt;u8&gt;): bool;
</code></pre>


Expand Down
29 changes: 26 additions & 3 deletions crates/sui-framework/sources/crypto/groth16.move
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,21 @@ module sui::groth16 {
// Error for input is not a valid Arkwork representation of a verifying key.
const EInvalidVerifyingKey: u64 = 0;

// Error if the given curve is not supported
const EInvalidCurve: u64 = 1;

/// Represents an elliptic curve construction to be used in the verifier. Currently we support BLS12-381 and BN254.
/// This should be given as the first parameter to `prepare_verifying_key` or `verify_groth16_proof`.
struct Curve has store, copy, drop {
id: u8,
}

/// Return the `Curve` value indicating that the BLS12-381 construction should be used in a given function.
public fun bls12381(): Curve { Curve { id: 0 } }

/// Return the `Curve` value indicating that the BN254 construction should be used in a given function.
public fun bn254(): Curve { Curve { id: 1 } }

/// A `PreparedVerifyingKey` consisting of four components in serialized form.
struct PreparedVerifyingKey has store, copy, drop {
vk_gamma_abc_g1_bytes: vector<u8>,
Expand Down Expand Up @@ -55,20 +70,28 @@ module sui::groth16 {
ProofPoints { bytes }
}

/// @param curve: What elliptic curve construction to use. See `bls12381` and `bn254`.
/// @param veriyfing_key: An Arkworks canonical compressed serialization of a verifying key.
///
/// Returns four vectors of bytes representing the four components of a prepared verifying key.
/// This step computes one pairing e(P, Q), and binds the verification to one particular proof statement.
/// This can be used as inputs for the `verify_groth16_proof` function.
public native fun prepare_verifying_key(verifying_key: &vector<u8>): PreparedVerifyingKey;
public fun prepare_verifying_key(curve: &Curve, verifying_key: &vector<u8>): PreparedVerifyingKey {
prepare_verifying_key_internal(curve.id, verifying_key)
}

/// Native functions that flattens the inputs into an array and passes to the Rust native function.
native fun prepare_verifying_key_internal(curve: u8, verifying_key: &vector<u8>): PreparedVerifyingKey;

/// @param curve: What elliptic curve construction to use. See the `bls12381` and `bn254` functions.
/// @param prepared_verifying_key: Consists of four vectors of bytes representing the four components of a prepared verifying key.
/// @param public_proof_inputs: Represent inputs that are public.
/// @param proof_points: Represent three proof points.
///
/// Returns a boolean indicating whether the proof is valid.
public fun verify_groth16_proof(prepared_verifying_key: &PreparedVerifyingKey, public_proof_inputs: &PublicProofInputs, proof_points: &ProofPoints): bool {
public fun verify_groth16_proof(curve: &Curve, prepared_verifying_key: &PreparedVerifyingKey, public_proof_inputs: &PublicProofInputs, proof_points: &ProofPoints): bool {
verify_groth16_proof_internal(
curve.id,
&prepared_verifying_key.vk_gamma_abc_g1_bytes,
&prepared_verifying_key.alpha_g1_beta_g2_bytes,
&prepared_verifying_key.gamma_g2_neg_pc_bytes,
Expand All @@ -79,5 +102,5 @@ module sui::groth16 {
}

/// Native functions that flattens the inputs into arrays of vectors and passed to the Rust native function.
public native fun verify_groth16_proof_internal(vk_gamma_abc_g1_bytes: &vector<u8>, alpha_g1_beta_g2_bytes: &vector<u8>, gamma_g2_neg_pc_bytes: &vector<u8>, delta_g2_neg_pc_bytes: &vector<u8>, public_proof_inputs: &vector<u8>, proof_points: &vector<u8>): bool;
native fun verify_groth16_proof_internal(curve: u8, vk_gamma_abc_g1_bytes: &vector<u8>, alpha_g1_beta_g2_bytes: &vector<u8>, gamma_g2_neg_pc_bytes: &vector<u8>, delta_g2_neg_pc_bytes: &vector<u8>, public_proof_inputs: &vector<u8>, proof_points: &vector<u8>): bool;
}
2 changes: 1 addition & 1 deletion crates/sui-framework/sources/crypto/groth16.spec.move
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
// SPDX-License-Identifier: Apache-2.0

spec sui::groth16 {
spec prepare_verifying_key {
spec prepare_verifying_key_internal {
pragma opaque;
// TODO: stub to be replaced by actual abort conditions if any
aborts_if [abstract] true;
Expand Down
Loading

0 comments on commit 894dfb5

Please sign in to comment.