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

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?

@finitology
Copy link

finitology 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://[email protected]/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