Skip to content

Instantly share code, notes, and snippets.

@critesjosh
Created August 11, 2023 19:46
Show Gist options
  • Save critesjosh/4aa36e87a0cc3f09feaf1febb4d11348 to your computer and use it in GitHub Desktop.
Save critesjosh/4aa36e87a0cc3f09feaf1febb4d11348 to your computer and use it in GitHub Desktop.
the full script for the instructive page here: https://noir-lang.org/typescript
import circuit from '../target/test.json' assert { type: 'json' };
import { decompressSync } from 'fflate';
import { Crs, newBarretenbergApiAsync, RawBuffer } from '@aztec/bb.js/dest/node/index.js';
import { ethers } from 'ethers'; // I'm lazy so I'm using ethers to pad my input
import { executeCircuit, compressWitness } from '@noir-lang/acvm_js';
async function main() {
const acirBuffer = Buffer.from(circuit.bytecode, 'base64');
const acirBufferUncompressed = decompressSync(acirBuffer);
const api = await newBarretenbergApiAsync(4);
const [exact, circuitSize, subgroup] = await api.acirGetCircuitSizes(acirBufferUncompressed);
const subgroupSize = Math.pow(2, Math.ceil(Math.log2(circuitSize)));
const crs = await Crs.new(subgroupSize + 1);
await api.commonInitSlabAllocator(subgroupSize);
await api.srsInitSrs(new RawBuffer(crs.getG1Data()), crs.numPoints, new RawBuffer(crs.getG2Data()));
const acirComposer = await api.acirNewAcirComposer(subgroupSize);
async function generateWitness(input: any, acirBuffer: Buffer): Promise<Uint8Array> {
const initialWitness = new Map<number, string>();
initialWitness.set(1, ethers.utils.hexZeroPad(`0x${input.x.toString(16)}`, 32));
initialWitness.set(2, ethers.utils.hexZeroPad(`0x${input.y.toString(16)}`, 32));
// initialWitness.set(3, ethers.utils.hexZeroPad(`0x${input.z.toString(16)}`, 32));
const witnessMap = await executeCircuit(acirBuffer, initialWitness, () => {
throw Error('unexpected oracle');
});
const witnessBuff = compressWitness(witnessMap);
return witnessBuff;
}
async function generateProof(witness: Uint8Array) {
const proof = await api.acirCreateProof(
acirComposer,
acirBufferUncompressed,
decompressSync(witness),
false,
);
return proof;
}
async function verifyProof(proof: Uint8Array) {
await api.acirInitProvingKey(acirComposer, acirBufferUncompressed);
const verified = await api.acirVerifyProof(acirComposer, proof, false);
return verified;
}
const input = { x: 3, y: 4 };
const witness = await generateWitness(input, acirBuffer);
console.log('Witness generated!');
const proof = await generateProof(witness);
console.log('Proof generated!');
await verifyProof(proof);
console.log('Proof verified!');
api.destroy();
}
main();
@chung080702
Copy link

chung080702 commented Aug 15, 2023

How to fix this error when I am trying to run the above code?

RuntimeError: unreachable
    at abort (wasm://wasm/025b415a:wasm-function[11127]:0x413b31)
    at throw_or_abort(std::__2::basic_string<char, std::__2::char_traits<char>, std::__2::allocator<char>> const&) (wasm://wasm/025b415a:wasm-function[89]:0x36e1e)
    at serde::BinaryDeserializer<serde::BincodeDeserializer>::read_byte() (wasm://wasm/025b415a:wasm-function[2520]:0x12c52a)
    at serde::BinaryDeserializer<serde::BincodeDeserializer>::deserialize_u64() (wasm://wasm/025b415a:wasm-function[2522]:0x12c586)
    at serde::BincodeDeserializer::deserialize_len() (wasm://wasm/025b415a:wasm-function[2513]:0x12c36b)
    at std::__2::vector<Circuit::Witness, std::__2::allocator<Circuit::Witness>> serde::Deserializable<std::__2::vector<Circuit::Witness, std::__2::allocator<Circuit::Witness>>>::deserialize<serde::BincodeDeserializer>(serde::BincodeDeserializer&) (wasm://wasm/025b415a:wasm-function[2509]:0x12c24d)
    at Circuit::PublicInputs serde::Deserializable<Circuit::PublicInputs>::deserialize<serde::BincodeDeserializer>(serde::BincodeDeserializer&) (wasm://wasm/025b415a:wasm-function[2511]:0x12c2eb)
    at Circuit::Circuit serde::Deserializable<Circuit::Circuit>::deserialize<serde::BincodeDeserializer>(serde::BincodeDeserializer&) (wasm://wasm/025b415a:wasm-function[2218]:0x126cce)
    at Circuit::Circuit::bincodeDeserialize(std::__2::vector<unsigned char, std::__2::allocator<unsigned char>>) (wasm://wasm/025b415a:wasm-function[2208]:0x1269f6)
    at acir_format::circuit_buf_to_acir_format(std::__2::vector<unsigned char, std::__2::allocator<unsigned char>> const&) (wasm://wasm/025b415a:wasm-function[2207]:0x12673e)

I got this error at line:
const [exact, circuitSize, subgroup] = await api.acirGetCircuitSizes(acirBufferUncompressed);

Config in package.json:

  "dependencies": {
    "@aztec/bb.js": "^0.3.6",
    "@noir-lang/acvm_js": "github:noir-lang/acvm-simulator-wasm",
    "ethers": "^5.7.2",
    "fflate": "^0.8.0"
  },
  "devDependencies": {
    "@types/node": "^20.5.0"
  }

@critesjosh
Copy link
Author

critesjosh commented Aug 15, 2023

what version of noir are you running?

Also sharing this info from our discord:

Known Issues with bb.js

I am aware that a recent update has caused a regression with bb.js, so it's not working on the latest nightly build currently. The engineering team is working on setting up e2e integration tests to avoid future regressions.

The current recommendation is to not use bb.js until we have a stable release combo with bb.js and Noir, but if you are feeling ambitious, you can install Noir at a specific commit using nix (https://noir-lang.org/getting_started/nargo_installation#option-3-install-via-nix) nix build "github:noir-lang/noir?ref/ref=??" I don't have a specific commit for you, but it was working around August 9th so you can try one of those 🙂

Thanks for bearing with us.

@critesjosh
Copy link
Author

critesjosh commented Aug 16, 2023

this should work with noir version >0.10.1 now. install with noirup -v 0.10.1

@chung080702
Copy link

Thanks, it worked.

@chung080702
Copy link

I have changed the circuit as follows:

fn main(x: Field, y: pub Field) -> pub Field{
    let z = std::hash::pedersen([x,y])[0];
    assert(z == std::hash::pedersen([x,y])[0]);
    z
}

Then I run the code and print witnessMap. I received:
image

I think witness size of pedersen hash should be bigger. Where am I wrong? I read the noir book, but I still don't understand how you create constraints? I want my code to prove that the pedersen hash of x and y is calculated correctly in noir.

@critesjosh
Copy link
Author

critesjosh commented Aug 17, 2023

i think that's right actually. you can see that value 3 and 5 match and 4 and 6 match. This is what i get when i calculate the pedersen hash in noir.

["0x25ed48b406cb7ac716062c45023b0523f5ed4e9a0baa12876fdc70307a8ad2f5", "0x0c290c796ea74cf713eaa3e74f2afdbffff95bd128dc77c02fce10cc479dfd0a"]

@chung080702
Copy link

I used to work with SnarkJS and Circom. I noticed that the witness size of the Pedersen hash is much larger compared to here. I wonder how all the constraints can be covered with a witness like this.
Looking at the above, I can see that my code doesn't generate constraints during the Pedersen hash calculation process; it only calculates the Pedersen hash first and then creates constraints afterward.
During the proof generation process, does Noir cover all the constraints?

@critesjosh
Copy link
Author

Yes, noir will cover all of the constraints defined in the circuit during the proof generation process. I don't think the pedersen hash calculation requires generating constrains, you only really care about constraining the result, no?

@infinitywarg
Copy link

infinitywarg commented Oct 17, 2023

I keep getting this error, from inside the node_modules after setting up tsconfig and package.json as provided in the tutorial here: https://noir-lang.org/typescript

`npx tsc index.ts
index.ts:1:21 - error TS2732: Cannot find module './target/MyCircuit.json'. Consider using '--resolveJsonModule' to import module with '.json' extension.

1 import circuit from "./target/MyCircuit.json" assert { type: "json" };
~~~~~~~~~~~~~~~~~~~~~~~~~

index.ts:1:47 - error TS2821: Import assertions are only supported when the '--module' option is set to 'esnext' or 'nodenext'.

1 import circuit from "./target/MyCircuit.json" assert { type: "json" };
~~~~~~~~~~~~~~~~~~~~~~~

node_modules/@aztec/bb.js/dest/node/barretenberg_wasm/barretenberg_wasm.d.ts:1:23 - error TS1452: 'resolution-mode' assertions are only supported when moduleResolution is node16 or nodenext.

1 ///
~~~~

node_modules/@aztec/bb.js/dest/node/types/node/point.d.ts:1:23 - error TS1452: 'resolution-mode' assertions are only supported when moduleResolution is node16 or nodenext.

1 ///
~~~~

Found 4 errors in 3 files.

Errors Files
2 index.ts:1
1 node_modules/@aztec/bb.js/dest/node/barretenberg_wasm/barretenberg_wasm.d.ts:1
1 node_modules/@aztec/bb.js/dest/node/types/node/point.d.ts:1
`


tsconfig: https://gist.github.com/critesjosh/6f3ba19fdc9298b24e90ba4f736247dc

package.json:

{ "name": "mycircuit", "version": "1.0.0", "type": "module", "description": "", "main": "index.js", "scripts": { "test": "echo \"Error: no test specified\" && exit 1" }, "keywords": [], "author": "", "license": "ISC", "devDependencies": { "@types/node": "^20.8.6", "typescript": "^5.2.2" }, "dependencies": { "@aztec/bb.js": "^0.3.6", "@noir-lang/acvm_js": "git+https://git@github.com/noir-lang/acvm-simulator-wasm.git#b9d9ca9dfc5140839f23998d9466307215607c42", "ethers": "^5.7.2", "fflate": "^0.8.1" } }

@critesjosh
Copy link
Author

@infinitywarp I recommend trying this new guide: https://noir-lang.org/dev/noir_js/getting_started/tiny_noir_app

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment