Skip to content

Commit 9f11632

Browse files
authored
Merge pull request #14 from TomAFrench/tf/update-stuff
feat: update to noir 1.0.0-beta.1
2 parents b356a42 + 12e55d0 commit 9f11632

22 files changed

+5947
-7390
lines changed

.devcontainer/Dockerfile

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
FROM mcr.microsoft.com/devcontainers/typescript-node:18
2+
SHELL ["/bin/bash", "-c"]
3+
RUN apt update && apt install -y curl tar gzip libc++-dev unzip
4+
5+
# For simplicity's sake we install a compatible version of bb.
6+
ENV BB_HOME="/bb"
7+
RUN curl -L https://raw.githubusercontent.com/AztecProtocol/aztec-packages/master/barretenberg/cpp/installation/install | bash
8+
RUN $BB_HOME/bbup -v 0.66.0
9+
ENV PATH="$BB_HOME:$PATH"
10+

.devcontainer/devcontainer.json

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
// For format details, see https://aka.ms/devcontainer.json. For config options, see the
2+
// README at: https://github.com/devcontainers/templates/tree/main/src/docker-existing-dockerfile
3+
{
4+
"name": "Existing Dockerfile",
5+
"build": {
6+
"context": ".",
7+
"dockerfile": "Dockerfile"
8+
},
9+
"features": {
10+
"ghcr.io/noir-lang/features/noir:latest": {
11+
"version": "1.0.0-beta.1"
12+
}
13+
}
14+
}

.github/workflows/ci.yaml

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
name: CI
2+
3+
on:
4+
pull_request:
5+
merge_group:
6+
push:
7+
branches:
8+
- master
9+
10+
# This will cancel previous runs when a branch or PR is updated
11+
concurrency:
12+
group: ${{ github.workflow }}-${{ github.head_ref || github.ref || github.run_id }}
13+
cancel-in-progress: true
14+
15+
jobs:
16+
yarn-lock:
17+
runs-on: ubuntu-22.04
18+
timeout-minutes: 30
19+
20+
steps:
21+
- name: Checkout
22+
uses: actions/checkout@v4
23+
24+
- uses: actions/setup-node@v4
25+
id: node
26+
with:
27+
node-version: 18.19.0
28+
cache: 'yarn'
29+
cache-dependency-path: 'yarn.lock'
30+
31+
- name: Install
32+
run: yarn --immutable
33+
34+
- uses: noir-lang/noirup@v0.1.3
35+
with:
36+
toolchain: 1.0.0-beta.1
37+
38+
- name: Compile circuits
39+
working-directory: ./circuits/
40+
run: nargo compile
41+
42+
- name: Run tests
43+
run: yarn --immutable

README.md

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -73,11 +73,6 @@ const verified = await verify_proof(verifier, proof);
7373

7474
Once we have compiled our program and generated an ACIR, we can generate a Solidity verifier rather than having to use the verifier provided by `nargo` or Noir's typescript wrapper.
7575

76-
In the `scripts` folder you will find a script for compiling a program and generating the Solidity verifier. You can call it using the command below (assuming you are in the root directory of the project).
77-
```
78-
npx ts-node ./scripts/generate_sol_verifier.ts
79-
```
80-
8176
This Solidity verifier can also be generated by calling `nargo contract`. This will produce a Solidity verifier inside of the Noir project which you can then move into the correct `contracts` folder.
8277

8378
It is important to note that if you change your circuit and want to verify proofs in Solidity you must also regenerate your Solidity verifier. The verifier is based upon the circuit and if the circuit changes any previous verifier will be out of date.

circuits/Nargo.toml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
[workspace]
2+
members = [
3+
"mimc_tree",
4+
"pedersen_tree"
5+
]

circuits/mimc_tree/Nargo.toml

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
[package]
2+
name="mimc_tree"
3+
type="bin"
24
authors = [""]
3-
compiler_version = "0.1"
5+
compiler_version = ">=1.0.0"
46

5-
[dependencies]
7+
[dependencies]
8+
mimc = { tag = "v0.1.0", git = "https://github.com/noir-lang/mimc" }

circuits/mimc_tree/src/main.nr

Lines changed: 14 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use dep::std;
1+
use std::embedded_curve_ops::{fixed_base_scalar_mul, EmbeddedCurveScalar};
22

33
fn main(
44
recipient: pub Field,
@@ -15,39 +15,38 @@ fn main(
1515
nullifierHash: pub Field,
1616
) -> pub Field {
1717
// Compute public key from private key to show ownership
18-
let pubkey = std::scalar_mul::fixed_base(priv_key);
19-
let pubkey_x = pubkey[0];
20-
let pubkey_y = pubkey[1];
18+
let pubkey = fixed_base_scalar_mul(EmbeddedCurveScalar::from_field(priv_key));
19+
let pubkey_x = pubkey.x;
20+
let pubkey_y = pubkey.y;
2121

2222
// Compute input note commitment
23-
let note_commitment = std::hash::pedersen([pubkey_x, pubkey_y, secret]);
23+
let note_commitment = std::hash::pedersen_hash([pubkey_x, pubkey_y, secret]);
2424

2525
// Compute input note nullifier
26-
let nullifier = std::hash::pedersen([note_commitment[0], index, priv_key]);
27-
constrain nullifierHash == nullifier[0];
26+
let nullifier = std::hash::pedersen_hash([note_commitment, index, priv_key]);
27+
assert_eq(nullifierHash, nullifier);
2828

2929
// Check that the input note commitment is in the root
30-
let new_root = compute_root_from_leaf(note_commitment[0], index, note_hash_path);
31-
constrain new_root == note_root;
30+
let new_root = compute_root_from_leaf(note_commitment, index, note_hash_path);
31+
assert_eq(new_root, note_root);
3232

3333
// Cannot have unused variables, return the recipient as public output of the circuit
3434
recipient
3535
}
3636

3737
// Returns the root of the tree from the provided leaf and its hashpath, using mimc hash
38-
fn compute_root_from_leaf(leaf : Field, index : Field, hash_path: [Field]) -> Field {
39-
let n = hash_path.len();
40-
let index_bits = index.to_le_bits(n as u32);
38+
fn compute_root_from_leaf<let N: u32>(leaf: Field, index: Field, hash_path: [Field; N]) -> Field {
39+
let index_bits: [u1; N] = index.to_le_bits();
4140
let mut current = leaf;
42-
for i in 0..n {
41+
for i in 0..N {
4342
let path_bit = index_bits[i] as bool;
4443
let (hash_left, hash_right) = if path_bit {
4544
(hash_path[i], current)
4645
} else {
4746
(current, hash_path[i])
4847
};
4948

50-
current = std::hash::mimc_bn254([hash_left, hash_right]);
49+
current = mimc::mimc_bn254([hash_left, hash_right]);
5150
};
5251
current
53-
}
52+
}

circuits/pedersen_tree/Nargo.toml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
[package]
2+
name="pedersen_tree"
3+
type="bin"
24
authors = [""]
3-
compiler_version = "0.1"
5+
compiler_version = ">=1.0.0"
46

57
[dependencies]

circuits/pedersen_tree/src/main.nr

Lines changed: 27 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
1-
use dep::std;
2-
1+
use std::embedded_curve_ops::{fixed_base_scalar_mul, EmbeddedCurveScalar};
32
fn main(
43
recipient : pub Field,
54
// Private key of note
@@ -15,28 +14,40 @@ fn main(
1514
nullifierHash: pub Field,
1615
) -> pub Field {
1716
// Compute public key from private key to show ownership
18-
let pubkey = std::scalar_mul::fixed_base(priv_key);
19-
let pubkey_x = pubkey[0];
20-
let pubkey_y = pubkey[1];
17+
let pubkey = fixed_base_scalar_mul(EmbeddedCurveScalar::from_field(priv_key));
18+
let pubkey_x = pubkey.x;
19+
let pubkey_y = pubkey.y;
2120

2221
// Compute input note commitment
23-
let note_commitment = std::hash::pedersen([pubkey_x, pubkey_y, secret]);
22+
let note_commitment = std::hash::pedersen_hash([pubkey_x, pubkey_y, secret]);
2423

2524
// Compute input note nullifier
26-
let nullifier = std::hash::pedersen([note_commitment[0], index, priv_key]);
27-
constrain nullifierHash == nullifier[0];
28-
29-
// TODO: check_membership is broken with the TS prover
30-
// Check that the input note commitment is in the root
31-
// let is_member = std::merkle::check_membership(note_root, note_commitment[0], index, note_hash_path);
32-
// constrain is_member == 1;
25+
let nullifier = std::hash::pedersen_hash([note_commitment, index, priv_key]);
26+
assert_eq(nullifierHash, nullifier);
3327

34-
let new_root = std::merkle::compute_root_from_leaf(note_commitment[0], index, note_hash_path);
35-
constrain new_root == note_root;
28+
let new_root = compute_root_from_leaf(note_commitment, index, note_hash_path);
29+
assert_eq(new_root, note_root);
3630

3731
// TODO: Can't use println with the TS packages yet
3832
// std::println(new_root);
3933

4034
// Cannot have unused variables, return the recipient as public output of the circuit
4135
recipient
42-
}
36+
}
37+
38+
// Returns the root of the tree from the provided leaf and its hashpath, using mimc hash
39+
fn compute_root_from_leaf<let N: u32>(leaf: Field, index: Field, hash_path: [Field; N]) -> Field {
40+
let index_bits: [u1; N] = index.to_le_bits();
41+
let mut current = leaf;
42+
for i in 0..N {
43+
let path_bit = index_bits[i] as bool;
44+
let (hash_left, hash_right) = if path_bit {
45+
(hash_path[i], current)
46+
} else {
47+
(current, hash_path[i])
48+
};
49+
50+
current = std::hash::pedersen_hash([hash_left, hash_right]);
51+
};
52+
current
53+
}

contracts/PrivateTransfer.sol

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import "@openzeppelin/contracts/security/ReentrancyGuard.sol";
77
import "hardhat/console.sol";
88

99
interface IVerifier {
10-
function verify(bytes calldata) external view returns (bool);
10+
function verify(bytes calldata, bytes32[] calldata) external view returns (bool);
1111
}
1212

1313
contract PrivateTransfer is MerkleTreeWithHistory, ReentrancyGuard {
@@ -69,20 +69,20 @@ contract PrivateTransfer is MerkleTreeWithHistory, ReentrancyGuard {
6969
*/
7070
function withdraw(
7171
bytes calldata proof,
72+
address _recipient,
73+
bytes32 _nullifierHash,
7274
bytes32 _root
7375
) external payable nonReentrant {
74-
uint256 recipient;
75-
bytes32 _nullifierHash;
76-
assembly {
77-
recipient := calldataload(add(calldataload(0x04), 0x24))
78-
_nullifierHash := calldataload(add(calldataload(0x04), 0x64))
79-
}
80-
address payable _recipient = payable(address(uint160(recipient)));
81-
8276
require(!nullifierHashes[_nullifierHash], "The note has been already spent");
8377
require(isKnownRoot(_root), "Cannot find your merkle root");
8478

85-
bool proofResult = verifier.verify(proof);
79+
80+
bytes32[] memory public_inputs = new bytes32[](4);
81+
public_inputs[0] = bytes32(uint256(uint160(_recipient)));
82+
public_inputs[1] = _root;
83+
public_inputs[2] = _nullifierHash;
84+
public_inputs[3] = bytes32(uint256(uint160(_recipient)));
85+
bool proofResult = verifier.verify(proof, public_inputs);
8686
require(proofResult, "Invalid withdraw proof");
8787

8888
// Set nullifier hash to true

0 commit comments

Comments
 (0)