Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore!: remove nargo prove and nargo verify #6321

Merged
merged 6 commits into from
May 16, 2024
Merged
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
3 changes: 3 additions & 0 deletions noir/Earthfile
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,9 @@ examples:
WORKDIR noir-repo/examples/codegen-verifier
RUN ./test.sh

WORKDIR ../prove_and_verify
RUN ./test.sh

format:
FROM +nargo
ENV PATH=$PATH:/usr/src/noir-repo/target/release
Expand Down
2 changes: 0 additions & 2 deletions noir/noir-repo/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

41 changes: 27 additions & 14 deletions noir/noir-repo/docs/docs/getting_started/hello_noir/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -94,9 +94,9 @@ Two additional files would be generated in your project directory:

_Prover.toml_ houses input values, and _Verifier.toml_ houses public values.

## Prove Our Noir Program
## Execute Our Noir Program

Now that the project is set up, we can create a proof of correct execution of our Noir program.
Now that the project is set up, we can execute our Noir program.

Fill in input values for execution in the _Prover.toml_ file. For example:

Expand All @@ -105,37 +105,50 @@ x = "1"
y = "2"
```

Prove the valid execution of your Noir program:
Execute your Noir program:

```sh
nargo prove
nargo execute witness-name
```

A new folder _proofs_ would then be generated in your project directory, containing the proof file
`<project-name>.proof`, where the project name is defined in Nargo.toml.
The witness corresponding to this execution will then be written to the file `./target/witness-name.gz`.

The _Verifier.toml_ file would also be updated with the public values computed from program
execution (in this case the value of `y`):
The _Verifier.toml_ file would also be updated with the public values computed from program execution (in this case the value of `y`):

```toml
y = "0x0000000000000000000000000000000000000000000000000000000000000002"
```

> **Note:** Values in _Verifier.toml_ are computed as 32-byte hex values.
> **Note:** Fields in _Verifier.toml_ are outputted as 32-byte hex values.

## Prove Our Noir Program

:::info

Nargo no longer handles communicating with backends in order to generate proofs. In order to prove/verify your Noir programs, you'll need an installation of [bb](../barretenberg/index.md).

:::

Prove the valid execution of your Noir program using `bb`:

```sh
bb prove -b ./target/hello_world.json -w ./target/witness-name.gz -o ./proof
```

A new file called `proof` will be generated in your project directory, containing the generated proof for your program.

## Verify Our Noir Program

Once a proof is generated, we can verify correct execution of our Noir program by verifying the
proof file.
Once a proof is generated, we can verify correct execution of our Noir program by verifying the proof file.

Verify your proof by running:

```sh
nargo verify
bb write_vk -b ./target/hello_world.json -o ./target/vk
bb verify -k ./target/vk -p ./proof
```

The verification will complete in silence if it is successful. If it fails, it will log the
corresponding error instead.
The verification will complete in silence if it is successful. If it fails, it will log the corresponding error instead.

Congratulations, you have now created and verified a proof for your very first Noir program!

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -92,20 +92,15 @@ fn main(x : Field, y : Field) {
}
```

The parameters `x` and `y` can be seen as the API for the program and must be supplied by the
prover. Since neither `x` nor `y` is marked as public, the verifier does not supply any inputs, when
verifying the proof.
The parameters `x` and `y` can be seen as the API for the program and must be supplied by the prover. Since neither `x` nor `y` is marked as public, the verifier does not supply any inputs, when verifying the proof.

The prover supplies the values for `x` and `y` in the _Prover.toml_ file.

As for the program body, `assert` ensures that the condition to be satisfied (e.g. `x != y`) is
constrained by the proof of the execution of said program (i.e. if the condition was not met, the
verifier would reject the proof as an invalid proof).
As for the program body, `assert` ensures that the condition to be satisfied (e.g. `x != y`) is constrained by the proof of the execution of said program (i.e. if the condition was not met, the verifier would reject the proof as an invalid proof).

### Prover.toml

The _Prover.toml_ file is a file which the prover uses to supply his witness values(both private and
public).
The _Prover.toml_ file is a file which the prover uses to supply the inputs to the Noir program (both private and public).

In our hello world program the _Prover.toml_ file looks like this:

Expand All @@ -114,12 +109,9 @@ x = "1"
y = "2"
```

When the command `nargo prove` is executed, two processes happen:
When the command `nargo execute` is executed, nargo will execute the Noir program using the inputs specified in `Prover.toml`, aborting if it finds that these do not satisfy the constraints defined by `main`. In this example, `x` and `y` must satisfy the inequality constraint `assert(x != y)`.

1. Noir creates a proof that `x`, which holds the value of `1`, and `y`, which holds the value of `2`,
is not equal. This inequality constraint is due to the line `assert(x != y)`.

2. Noir creates and stores the proof of this statement in the _proofs_ directory in a file called your-project.proof. So if your project is named "private_voting" (defined in the project Nargo.toml), the proof will be saved at `./proofs/private_voting.proof`. Opening this file will display the proof in hex format.
If an output name is specified such as `nargo execute foo`, the witness generated by this execution will be written to `./target/foo.gz`. This can then be used to generate a proof of the execution.

#### Arrays of Structs

Expand Down Expand Up @@ -155,45 +147,18 @@ baz = 2

#### Custom toml files

You can specify a `toml` file with a different name to use for proving by using the `--prover-name` or `-p` flags.
You can specify a `toml` file with a different name to use for execution by using the `--prover-name` or `-p` flags.

This command looks for proof inputs in the default **Prover.toml** and generates the proof and saves it at `./proofs/<project-name>.proof`:
This command looks for proof inputs in the default **Prover.toml** and generates the witness and saves it at `./target/foo.gz`:

```bash
nargo prove
nargo execute foo
```

This command looks for proof inputs in the custom **OtherProver.toml** and generates proof and saves it at `./proofs/<project-name>.proof`:
This command looks for proof inputs in the custom **OtherProver.toml** and generates the witness and saves it at `./target/bar.gz`:

```bash
nargo prove -p OtherProver
nargo execute -p OtherProver bar
```

## Verifying a Proof

When the command `nargo verify` is executed, two processes happen:

1. Noir checks in the _proofs_ directory for a proof file with the project name (eg. test_project.proof)

2. If that file is found, the proof's validity is checked

> **Note:** The validity of the proof is linked to the current Noir program; if the program is
> changed and the verifier verifies the proof, it will fail because the proof is not valid for the
> _modified_ Noir program.

In production, the prover and the verifier are usually two separate entities. A prover would
retrieve the necessary inputs, execute the Noir program, generate a proof and pass it to the
verifier. The verifier would then retrieve the public inputs, usually from external sources, and
verify the validity of the proof against it.

Take a private asset transfer as an example:

A person using a browser as the prover would retrieve private inputs locally (e.g. the user's private key) and
public inputs (e.g. the user's encrypted balance on-chain), compute the transfer, generate a proof
and submit it to the verifier smart contract.

The verifier contract would then draw the user's encrypted balance directly from the blockchain and
verify the proof submitted against it. If the verification passes, additional functions in the
verifier contract could trigger (e.g. approve the asset transfer).

Now that you understand the concepts, you'll probably want some editor feedback while you are writing more complex code.
4 changes: 2 additions & 2 deletions noir/noir-repo/docs/docs/how_to/how-to-oracles.md
Original file line number Diff line number Diff line change
Expand Up @@ -177,7 +177,7 @@ interface ForeignCallResult {

## Step 3 - Usage with Nargo

Using the [`nargo` CLI tool](../getting_started/installation/index.md), you can use oracles in the `nargo test`, `nargo execute` and `nargo prove` commands by passing a value to `--oracle-resolver`. For example:
Using the [`nargo` CLI tool](../getting_started/installation/index.md), you can use oracles in the `nargo test` and `nargo execute` commands by passing a value to `--oracle-resolver`. For example:

```bash
nargo test --oracle-resolver http://localhost:5555
Expand All @@ -203,7 +203,7 @@ As one can see, in NoirJS, the [`foreignCallHandler`](../reference/NoirJS/noir_j

Does this mean you don't have to write an RPC server like in [Step #2](#step-2---write-an-rpc-server)?

You don't technically have to, but then how would you run `nargo test` or `nargo prove`? To use both `Nargo` and `NoirJS` in your development flow, you will have to write a JSON RPC server.
You don't technically have to, but then how would you run `nargo test`? To use both `Nargo` and `NoirJS` in your development flow, you will have to write a JSON RPC server.

:::

Expand Down
30 changes: 21 additions & 9 deletions noir/noir-repo/docs/docs/how_to/how-to-solidity-verifier.md
Original file line number Diff line number Diff line change
Expand Up @@ -131,11 +131,25 @@ To verify a proof using the Solidity verifier contract, we call the `verify` fun
function verify(bytes calldata _proof, bytes32[] calldata _publicInputs) external view returns (bool)
```

When using the default example in the [Hello Noir](../getting_started/hello_noir/index.md) guide, the easiest way to confirm that the verifier contract is doing its job is by calling the `verify` function via remix with the required parameters. For `_proof`, run `nargo prove` and use the string in `proof/<file>.proof` (adding the hex `0x` prefix). We can also copy the public input from `Verifier.toml`, as it will be properly formatted as 32-byte strings:
When using the default example in the [Hello Noir](../getting_started/hello_noir/index.md) guide, the easiest way to confirm that the verifier contract is doing its job is by calling the `verify` function via remix with the required parameters. Note that the public inputs must be passed in separately to the rest of the proof so we must split the proof as returned from `bb`.

First generate a proof with `bb` at the location `./proof` using the steps in [get started](../getting_started/hello_noir/index.md), this proof is in a binary format but we want to convert it into a hex string to pass into Remix, this can be done with the

```bash
# This value must be changed to match the number of public inputs (including return values!) in your program.
NUM_PUBLIC_INPUTS=1
PUBLIC_INPUT_BYTES=32*NUM_PUBLIC_INPUTS
HEX_PUBLIC_INPUTS=$(head -c $PUBLIC_INPUT_BYTES ./proof | od -An -v -t x1 | tr -d $' \n')
HEX_PROOF=$(tail -c +$PUBLIC_INPUT_BYTES ./proof | od -An -v -t x1 | tr -d $' \n')

echo "Public inputs:"
echo $HEX_PUBLIC_INPUTS

echo "Proof:"
echo "0x$HEX_PROOF"
```
0x...<proof bytes>... , [0x0000.....02]
```

Remix expects that the public inputs will be split into an array of `bytes32` values so `HEX_PUBLIC_INPUTS` needs to be split up and prefixed with `0x` accordingly. You may notice that the public inputs match up with the values which are written in the `Verifier.toml` file so we can also copy the public input values from `Verifier.toml` which are already split up. Take care to ensure that the order of the public inputs aren't changed.

A programmatic example of how the `verify` function is called can be seen in the example zk voting application [here](https://github.com/noir-lang/noir-examples/blob/33e598c257e2402ea3a6b68dd4c5ad492bce1b0a/foundry-voting/src/zkVote.sol#L35):

Expand All @@ -152,11 +166,9 @@ function castVote(bytes calldata proof, uint proposalId, uint vote, bytes32 null

:::info[Return Values]

A circuit doesn't have the concept of a return value. Return values are just syntactic sugar in
Noir.
A circuit doesn't have the concept of a return value. Return values are just syntactic sugar in Noir.

Under the hood, the return value is passed as an input to the circuit and is checked at the end of
the circuit program.
Under the hood, the return value is passed as an input to the circuit and is checked at the end of the circuit program.

For example, if you have Noir program like this:

Expand All @@ -170,11 +182,11 @@ fn main(
) -> pub Field
```

the `verify` function will expect the public inputs array (second function parameter) to be of length 3, the two inputs and the return value. Like before, these values are populated in Verifier.toml after running `nargo prove`.
the `verify` function will expect the public inputs array (second function parameter) to be of length 3, the two inputs and the return value. Like before, these values are populated in Verifier.toml after running `nargo execute`.

Passing only two inputs will result in an error such as `PUBLIC_INPUT_COUNT_INVALID(3, 2)`.

In this case, the inputs parameter to `verify` would be an array ordered as `[pubkey_x, pubkey_y, return]`.
In this case, the inputs parameter to `verify` would be an array ordered as `[pubkey_x, pubkey_y, return`.

:::

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ y = "1"
Would result in:

```
$ nargo prove
$ nargo execute
error: Assertion failed: 'attempt to add with overflow'
┌─ ~/src/main.nr:9:13
Expand Down
7 changes: 7 additions & 0 deletions noir/noir-repo/examples/prove_and_verify/Nargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
[package]
name = "hello_world"
type = "bin"
authors = [""]
compiler_version = ">=0.29.0"

[dependencies]
2 changes: 2 additions & 0 deletions noir/noir-repo/examples/prove_and_verify/Prover.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
x = "1"
y = "2"
Binary file not shown.
14 changes: 14 additions & 0 deletions noir/noir-repo/examples/prove_and_verify/prove_and_verify.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
#!/bin/bash
set -eu

BACKEND=${BACKEND:-bb}

nargo execute witness

# TODO: `bb` should create `proofs` directory if it doesn't exist.
mkdir -p proofs
$BACKEND prove -b ./target/hello_world.json -w ./target/witness.gz

# TODO: backend should automatically generate vk if necessary.
$BACKEND write_vk -b ./target/hello_world.json
$BACKEND verify -v ./target/vk -p ./proofs/proof
3 changes: 3 additions & 0 deletions noir/noir-repo/examples/prove_and_verify/src/main.nr
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
fn main(x: Field, y: pub Field) {
assert(x != y);
}
10 changes: 10 additions & 0 deletions noir/noir-repo/examples/prove_and_verify/test.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
#!/bin/bash
set -eu

# This file is used for Noir CI and is not required.

BACKEND=${BACKEND:-bb}

rm -rf ./target ./proofs

./prove_and_verify.sh
1 change: 0 additions & 1 deletion noir/noir-repo/tooling/backend_interface/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ license.workspace = true
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
acvm.workspace = true
dirs.workspace = true
thiserror.workspace = true
serde.workspace = true
Expand Down
10 changes: 0 additions & 10 deletions noir/noir-repo/tooling/backend_interface/src/cli/mod.rs
Original file line number Diff line number Diff line change
@@ -1,20 +1,10 @@
// Reference: https://github.com/AztecProtocol/aztec-packages/blob/master/barretenberg/cpp/src/barretenberg/bb/main.cpp

mod gates;
mod proof_as_fields;
mod prove;
mod verify;
mod version;
mod vk_as_fields;
mod write_vk;

pub(crate) use gates::GatesCommand;
pub(crate) use proof_as_fields::ProofAsFieldsCommand;
pub(crate) use prove::ProveCommand;
pub(crate) use verify::VerifyCommand;
pub(crate) use version::VersionCommand;
pub(crate) use vk_as_fields::VkAsFieldsCommand;
pub(crate) use write_vk::WriteVkCommand;

pub(crate) use gates::CircuitReport;

Expand Down

This file was deleted.

Loading
Loading