diff --git a/package.json b/package.json index 162f2ca..fc73787 100644 --- a/package.json +++ b/package.json @@ -56,6 +56,8 @@ "typescript": "^5.4.2" }, "dependencies": { + "@noir-lang/backend_barretenberg": "0.25.0-00d6494.nightly", + "@noir-lang/noir_js": "0.25.0-00d6494.nightly", "ethers": "^6.11.1" } } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 8b88861..dca1913 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -5,6 +5,12 @@ settings: excludeLinksFromLockfile: false dependencies: + '@noir-lang/backend_barretenberg': + specifier: 0.25.0-00d6494.nightly + version: 0.25.0-00d6494.nightly + '@noir-lang/noir_js': + specifier: 0.25.0-00d6494.nightly + version: 0.25.0-00d6494.nightly ethers: specifier: ^6.11.1 version: 6.11.1 @@ -51,6 +57,18 @@ packages: '@jridgewell/trace-mapping': 0.3.25 dev: true + /@aztec/bb.js@0.26.3: + resolution: {integrity: sha512-iZXQyjVVgDYQt77IggxC1MUZDBd68Q9aXepclq1kv4Ube1wllmlZ3+NGKZx/ma8yd24ytYGtIx/7kY8L4SbdkQ==} + hasBin: true + dependencies: + comlink: 4.4.1 + commander: 10.0.1 + debug: 4.3.4 + tslib: 2.6.2 + transitivePeerDependencies: + - supports-color + dev: false + /@babel/code-frame@7.23.5: resolution: {integrity: sha512-CgH3s1a96LipHCmSUmYFPwY7MNx8C3avkq7i4Wl3cfa662ldtUe4VM1TPXX70pfmrlWTb6jLqTYrZyT2ZTJBgA==} engines: {node: '>=6.9.0'} @@ -1893,6 +1911,38 @@ packages: fastq: 1.17.1 dev: true + /@noir-lang/acvm_js@0.41.0-00d6494.nightly: + resolution: {integrity: sha512-ba5Z75lb4aIXLgzMXuhSPg9taolPi8UVY7YaoOVqNaiP7YZaxXWnghyB/OEzn8iPzWLECFPNKpFWVrU4cKVwjw==} + dev: false + + /@noir-lang/backend_barretenberg@0.25.0-00d6494.nightly: + resolution: {integrity: sha512-GbfNKayPTc+KCKl4pqz33viNEhGLEhXOhgNO/SEzCxxPzE9IkpEdL0h3yo1H16vqHRELvjv5k4oWJBESUPoLiA==} + dependencies: + '@aztec/bb.js': 0.26.3 + '@noir-lang/types': 0.25.0-00d6494.nightly + fflate: 0.8.2 + transitivePeerDependencies: + - supports-color + dev: false + + /@noir-lang/noir_js@0.25.0-00d6494.nightly: + resolution: {integrity: sha512-j6jO/hgEP/y6WHre85PoXlTao+WSID2GAIhHjaiWQ05SYHnXsU2m+GgH77fiiyb5BIJ0lO1wB83c0r+P650g9w==} + dependencies: + '@noir-lang/acvm_js': 0.41.0-00d6494.nightly + '@noir-lang/noirc_abi': 0.25.0-00d6494.nightly + '@noir-lang/types': 0.25.0-00d6494.nightly + dev: false + + /@noir-lang/noirc_abi@0.25.0-00d6494.nightly: + resolution: {integrity: sha512-R4OcOr27NyT55QAVLyJSBZyv8mXL4YJEXPvKLgJbCxzSpG8uQuYr/tc2QwqHyMI9lMbePrpq5tyhcVpK3jmqeg==} + dependencies: + '@noir-lang/types': 0.25.0-00d6494.nightly + dev: false + + /@noir-lang/types@0.25.0-00d6494.nightly: + resolution: {integrity: sha512-oqo+uxWrmhKJNYiyvTrG7wc+kSZQCeRoVWQrMzYFc6TQIfU2/1QEO37SNXZjR7zneC2RAfeLUxmLAXamtYecTg==} + dev: false + /@rollup/plugin-babel@6.0.4(@babel/core@7.24.0)(rollup@3.29.4): resolution: {integrity: sha512-YF7Y52kFdFT/xVSuVdjkV5ZdX/3YtmX0QulG+x0taQOtJdHYzVU61aSSkAgVJ7NOv6qPkIYiJSgSWWN/DM5sGw==} engines: {node: '>=14.0.0'} @@ -3039,6 +3089,15 @@ packages: delayed-stream: 1.0.0 dev: true + /comlink@4.4.1: + resolution: {integrity: sha512-+1dlx0aY5Jo1vHy/tSsIGpSkN4tS9rZSW8FIhG0JH/crs9wwweswIo/POr451r7bZww3hFbPAKnTpimzL/mm4Q==} + dev: false + + /commander@10.0.1: + resolution: {integrity: sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug==} + engines: {node: '>=14'} + dev: false + /commander@2.20.3: resolution: {integrity: sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==} dev: true @@ -3184,7 +3243,6 @@ packages: optional: true dependencies: ms: 2.1.2 - dev: true /decimal.js@10.4.3: resolution: {integrity: sha512-VBBaLc1MgL5XpzgIP7ny5Z6Nx3UrRkIViUkPUdtl9aya5amy3De1gsUUSB1g3+3sExYNjCAsAznmukyxCb1GRA==} @@ -4086,6 +4144,10 @@ packages: bser: 2.1.1 dev: true + /fflate@0.8.2: + resolution: {integrity: sha512-cPJU47OaAoCbg0pBvzsgpTPhmhqI5eJjh/JIu8tPj5q+T7iLvW/JAYUqmE7KOB4R1ZyEhzBaIQpQpardBF5z8A==} + dev: false + /figlet@1.7.0: resolution: {integrity: sha512-gO8l3wvqo0V7wEFLXPbkX83b7MVjRrk1oRLfYlZXol8nEpb/ON9pcKLI4qpBv5YtOTfrINtqb7b40iYY2FTWFg==} engines: {node: '>= 0.4.0'} @@ -5652,7 +5714,6 @@ packages: /ms@2.1.2: resolution: {integrity: sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==} - dev: true /ms@2.1.3: resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} @@ -6778,7 +6839,6 @@ packages: /tslib@2.6.2: resolution: {integrity: sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==} - dev: true /tsutils@3.21.0(typescript@5.4.2): resolution: {integrity: sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==} diff --git a/src/field.ts b/src/field.ts index 2ac8b9b..f4c6256 100644 --- a/src/field.ts +++ b/src/field.ts @@ -31,6 +31,10 @@ export class Field { return new Field(0n); } + hex(): string { + return zeroPadValue(toBeHex(this.value), 32); + } + add(other: Field): Field { return new Field((this.value + other.value) % PRIME); } diff --git a/src/hash.ts b/src/hash.ts new file mode 100644 index 0000000..75a0763 --- /dev/null +++ b/src/hash.ts @@ -0,0 +1,46 @@ +import { ProofData } from '@noir-lang/noir_js'; + +import hash_1 from '@ultralane/circuits/bin/hash_1/target/hash_1.json'; +import hash_2 from '@ultralane/circuits/bin/hash_2/target/hash_2.json'; +import hash_3 from '@ultralane/circuits/bin/hash_3/target/hash_3.json'; + +import { toBigInt } from 'ethers'; + +import { circuit } from './utils'; +import { Field } from './field'; + +export async function hash(preimage: Field[]): Promise { + const json = hash_json(preimage.length); + const noir = await circuit(json); + const result = await noir.execute({ + input: preimage.map((x) => x.hex()), + }); + return new Field(toBigInt(result.returnValue as string)); +} + +export async function hash_prove(preimage: Field[]): Promise { + const json = hash_json(preimage.length); + const noir = await circuit(json); + const proof = await noir.generateProof({ + input: preimage.map((x) => x.hex()), + }); + return proof; +} + +export function hash_json(length: number) { + let json; + switch (length) { + case 1: + json = hash_1; + break; + case 2: + json = hash_2; + break; + case 3: + json = hash_3; + break; + default: + throw new Error('preimage length not supported: ' + length); + } + return json; +} diff --git a/src/utils.ts b/src/utils.ts new file mode 100644 index 0000000..849825a --- /dev/null +++ b/src/utils.ts @@ -0,0 +1,9 @@ +import { BarretenbergBackend } from '@noir-lang/backend_barretenberg'; +import { Noir } from '@noir-lang/noir_js'; + +export async function circuit(json: any) { + const backend = new BarretenbergBackend(json); + const noir = new Noir(json, backend); + await noir.init(); + return noir; +} diff --git a/tsconfig.json b/tsconfig.json index 6eaca93..66df62e 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -5,6 +5,7 @@ "module": "esnext", "moduleResolution": "node", "target": "esnext", - "allowImportingTsExtensions": false + "allowImportingTsExtensions": false, + "resolveJsonModule": true } } \ No newline at end of file