@noir-lang/backend_barretenberg
Advanced tools
Comparing version 0.7.10 to 0.17.0
@@ -1,13 +0,14 @@ | ||
import { Backend, CompiledCircuit } from '@noir-lang/types'; | ||
import { Backend, CompiledCircuit, ProofData } from '@noir-lang/types'; | ||
import { BackendOptions } from './types.js'; | ||
export declare class BarretenbergBackend implements Backend { | ||
private options; | ||
private api; | ||
private acirComposer; | ||
private acirUncompressedBytecode; | ||
private numberOfThreads; | ||
constructor(acirCircuit: CompiledCircuit, numberOfThreads?: number); | ||
private instantiate; | ||
generateFinalProof(decompressedWitness: Uint8Array): Promise<Uint8Array>; | ||
generateIntermediateProof(witness: Uint8Array): Promise<Uint8Array>; | ||
generateProof(decompressedWitness: Uint8Array, makeEasyToVerifyInCircuit: boolean): Promise<Uint8Array>; | ||
generateIntermediateProofArtifacts(proof: Uint8Array, numOfPublicInputs?: number): Promise<{ | ||
constructor(acirCircuit: CompiledCircuit, options?: BackendOptions); | ||
instantiate(): Promise<void>; | ||
generateFinalProof(decompressedWitness: Uint8Array): Promise<ProofData>; | ||
generateIntermediateProof(witness: Uint8Array): Promise<ProofData>; | ||
generateProof(compressedWitness: Uint8Array, makeEasyToVerifyInCircuit: boolean): Promise<ProofData>; | ||
generateIntermediateProofArtifacts(proofData: ProofData, numOfPublicInputs?: number): Promise<{ | ||
proofAsFields: string[]; | ||
@@ -17,6 +18,6 @@ vkAsFields: string[]; | ||
}>; | ||
verifyFinalProof(proof: Uint8Array): Promise<boolean>; | ||
verifyIntermediateProof(proof: Uint8Array): Promise<boolean>; | ||
verifyFinalProof(proofData: ProofData): Promise<boolean>; | ||
verifyIntermediateProof(proofData: ProofData): Promise<boolean>; | ||
verifyProof(proof: Uint8Array, makeEasyToVerifyInCircuit: boolean): Promise<boolean>; | ||
destroy(): Promise<void>; | ||
} |
@@ -5,4 +5,9 @@ "use strict"; | ||
/* eslint-disable @typescript-eslint/no-explicit-any */ | ||
const fflate_1 = require("fflate"); | ||
const serialize_js_1 = require("./serialize.js"); | ||
// This is the number of bytes in a UltraPlonk proof | ||
// minus the public inputs. | ||
const numBytesInProofWithoutPublicInputs = 2144; | ||
class BarretenbergBackend { | ||
options; | ||
// These type assertions are used so that we don't | ||
@@ -15,6 +20,5 @@ // have to initialize `api` and `acirComposer` in the constructor. | ||
acirUncompressedBytecode; | ||
numberOfThreads = 1; | ||
constructor(acirCircuit, numberOfThreads = 1) { | ||
constructor(acirCircuit, options = { threads: 1 }) { | ||
this.options = options; | ||
const acirBytecodeBase64 = acirCircuit.bytecode; | ||
this.numberOfThreads = numberOfThreads; | ||
this.acirUncompressedBytecode = (0, serialize_js_1.acirToUint8Array)(acirBytecodeBase64); | ||
@@ -27,3 +31,3 @@ } | ||
const { Barretenberg, RawBuffer, Crs } = await import('@aztec/bb.js'); | ||
const api = await Barretenberg.new(this.numberOfThreads); | ||
const api = await Barretenberg.new(this.options.threads); | ||
const [_exact, _total, subgroupSize] = await api.acirGetCircuitSizes(this.acirUncompressedBytecode); | ||
@@ -61,6 +65,15 @@ const crs = await Crs.new(subgroupSize + 1); | ||
} | ||
async generateProof(decompressedWitness, makeEasyToVerifyInCircuit) { | ||
async generateProof(compressedWitness, makeEasyToVerifyInCircuit) { | ||
await this.instantiate(); | ||
const proof = await this.api.acirCreateProof(this.acirComposer, this.acirUncompressedBytecode, decompressedWitness, makeEasyToVerifyInCircuit); | ||
return proof; | ||
const proofWithPublicInputs = await this.api.acirCreateProof(this.acirComposer, this.acirUncompressedBytecode, (0, fflate_1.decompressSync)(compressedWitness), makeEasyToVerifyInCircuit); | ||
const splitIndex = proofWithPublicInputs.length - numBytesInProofWithoutPublicInputs; | ||
const publicInputsConcatenated = proofWithPublicInputs.slice(0, splitIndex); | ||
const publicInputSize = 32; | ||
const publicInputs = []; | ||
for (let i = 0; i < publicInputsConcatenated.length; i += publicInputSize) { | ||
const publicInput = publicInputsConcatenated.slice(i, i + publicInputSize); | ||
publicInputs.push(publicInput); | ||
} | ||
const proof = proofWithPublicInputs.slice(splitIndex); | ||
return { proof, publicInputs }; | ||
} | ||
@@ -76,4 +89,5 @@ // Generates artifacts that will be passed to a circuit that will verify this proof. | ||
// The number of public inputs denotes how many public inputs are in the inner proof. | ||
async generateIntermediateProofArtifacts(proof, numOfPublicInputs = 0) { | ||
async generateIntermediateProofArtifacts(proofData, numOfPublicInputs = 0) { | ||
await this.instantiate(); | ||
const proof = reconstructProofWithPublicInputs(proofData); | ||
const proofAsFields = await this.api.acirSerializeProofIntoFields(this.acirComposer, proof, numOfPublicInputs); | ||
@@ -91,3 +105,4 @@ // TODO: perhaps we should put this in the init function. Need to benchmark | ||
} | ||
async verifyFinalProof(proof) { | ||
async verifyFinalProof(proofData) { | ||
const proof = reconstructProofWithPublicInputs(proofData); | ||
const makeEasyToVerifyInCircuit = false; | ||
@@ -97,3 +112,4 @@ const verified = await this.verifyProof(proof, makeEasyToVerifyInCircuit); | ||
} | ||
async verifyIntermediateProof(proof) { | ||
async verifyIntermediateProof(proofData) { | ||
const proof = reconstructProofWithPublicInputs(proofData); | ||
const makeEasyToVerifyInCircuit = true; | ||
@@ -115,1 +131,18 @@ return this.verifyProof(proof, makeEasyToVerifyInCircuit); | ||
exports.BarretenbergBackend = BarretenbergBackend; | ||
function reconstructProofWithPublicInputs(proofData) { | ||
// Flatten publicInputs | ||
const publicInputsConcatenated = flattenUint8Arrays(proofData.publicInputs); | ||
// Concatenate publicInputs and proof | ||
const proofWithPublicInputs = Uint8Array.from([...publicInputsConcatenated, ...proofData.proof]); | ||
return proofWithPublicInputs; | ||
} | ||
function flattenUint8Arrays(arrays) { | ||
const totalLength = arrays.reduce((acc, val) => acc + val.length, 0); | ||
const result = new Uint8Array(totalLength); | ||
let offset = 0; | ||
for (const arr of arrays) { | ||
result.set(arr, offset); | ||
offset += arr.length; | ||
} | ||
return result; | ||
} |
@@ -1,13 +0,14 @@ | ||
import { Backend, CompiledCircuit } from '@noir-lang/types'; | ||
import { Backend, CompiledCircuit, ProofData } from '@noir-lang/types'; | ||
import { BackendOptions } from './types.js'; | ||
export declare class BarretenbergBackend implements Backend { | ||
private options; | ||
private api; | ||
private acirComposer; | ||
private acirUncompressedBytecode; | ||
private numberOfThreads; | ||
constructor(acirCircuit: CompiledCircuit, numberOfThreads?: number); | ||
private instantiate; | ||
generateFinalProof(decompressedWitness: Uint8Array): Promise<Uint8Array>; | ||
generateIntermediateProof(witness: Uint8Array): Promise<Uint8Array>; | ||
generateProof(decompressedWitness: Uint8Array, makeEasyToVerifyInCircuit: boolean): Promise<Uint8Array>; | ||
generateIntermediateProofArtifacts(proof: Uint8Array, numOfPublicInputs?: number): Promise<{ | ||
constructor(acirCircuit: CompiledCircuit, options?: BackendOptions); | ||
instantiate(): Promise<void>; | ||
generateFinalProof(decompressedWitness: Uint8Array): Promise<ProofData>; | ||
generateIntermediateProof(witness: Uint8Array): Promise<ProofData>; | ||
generateProof(compressedWitness: Uint8Array, makeEasyToVerifyInCircuit: boolean): Promise<ProofData>; | ||
generateIntermediateProofArtifacts(proofData: ProofData, numOfPublicInputs?: number): Promise<{ | ||
proofAsFields: string[]; | ||
@@ -17,6 +18,6 @@ vkAsFields: string[]; | ||
}>; | ||
verifyFinalProof(proof: Uint8Array): Promise<boolean>; | ||
verifyIntermediateProof(proof: Uint8Array): Promise<boolean>; | ||
verifyFinalProof(proofData: ProofData): Promise<boolean>; | ||
verifyIntermediateProof(proofData: ProofData): Promise<boolean>; | ||
verifyProof(proof: Uint8Array, makeEasyToVerifyInCircuit: boolean): Promise<boolean>; | ||
destroy(): Promise<void>; | ||
} |
/* eslint-disable @typescript-eslint/no-explicit-any */ | ||
import { decompressSync as gunzip } from 'fflate'; | ||
import { acirToUint8Array } from './serialize.js'; | ||
// This is the number of bytes in a UltraPlonk proof | ||
// minus the public inputs. | ||
const numBytesInProofWithoutPublicInputs = 2144; | ||
export class BarretenbergBackend { | ||
options; | ||
// These type assertions are used so that we don't | ||
@@ -11,6 +16,5 @@ // have to initialize `api` and `acirComposer` in the constructor. | ||
acirUncompressedBytecode; | ||
numberOfThreads = 1; | ||
constructor(acirCircuit, numberOfThreads = 1) { | ||
constructor(acirCircuit, options = { threads: 1 }) { | ||
this.options = options; | ||
const acirBytecodeBase64 = acirCircuit.bytecode; | ||
this.numberOfThreads = numberOfThreads; | ||
this.acirUncompressedBytecode = acirToUint8Array(acirBytecodeBase64); | ||
@@ -23,3 +27,3 @@ } | ||
const { Barretenberg, RawBuffer, Crs } = await import('@aztec/bb.js'); | ||
const api = await Barretenberg.new(this.numberOfThreads); | ||
const api = await Barretenberg.new(this.options.threads); | ||
const [_exact, _total, subgroupSize] = await api.acirGetCircuitSizes(this.acirUncompressedBytecode); | ||
@@ -57,6 +61,15 @@ const crs = await Crs.new(subgroupSize + 1); | ||
} | ||
async generateProof(decompressedWitness, makeEasyToVerifyInCircuit) { | ||
async generateProof(compressedWitness, makeEasyToVerifyInCircuit) { | ||
await this.instantiate(); | ||
const proof = await this.api.acirCreateProof(this.acirComposer, this.acirUncompressedBytecode, decompressedWitness, makeEasyToVerifyInCircuit); | ||
return proof; | ||
const proofWithPublicInputs = await this.api.acirCreateProof(this.acirComposer, this.acirUncompressedBytecode, gunzip(compressedWitness), makeEasyToVerifyInCircuit); | ||
const splitIndex = proofWithPublicInputs.length - numBytesInProofWithoutPublicInputs; | ||
const publicInputsConcatenated = proofWithPublicInputs.slice(0, splitIndex); | ||
const publicInputSize = 32; | ||
const publicInputs = []; | ||
for (let i = 0; i < publicInputsConcatenated.length; i += publicInputSize) { | ||
const publicInput = publicInputsConcatenated.slice(i, i + publicInputSize); | ||
publicInputs.push(publicInput); | ||
} | ||
const proof = proofWithPublicInputs.slice(splitIndex); | ||
return { proof, publicInputs }; | ||
} | ||
@@ -72,4 +85,5 @@ // Generates artifacts that will be passed to a circuit that will verify this proof. | ||
// The number of public inputs denotes how many public inputs are in the inner proof. | ||
async generateIntermediateProofArtifacts(proof, numOfPublicInputs = 0) { | ||
async generateIntermediateProofArtifacts(proofData, numOfPublicInputs = 0) { | ||
await this.instantiate(); | ||
const proof = reconstructProofWithPublicInputs(proofData); | ||
const proofAsFields = await this.api.acirSerializeProofIntoFields(this.acirComposer, proof, numOfPublicInputs); | ||
@@ -87,3 +101,4 @@ // TODO: perhaps we should put this in the init function. Need to benchmark | ||
} | ||
async verifyFinalProof(proof) { | ||
async verifyFinalProof(proofData) { | ||
const proof = reconstructProofWithPublicInputs(proofData); | ||
const makeEasyToVerifyInCircuit = false; | ||
@@ -93,3 +108,4 @@ const verified = await this.verifyProof(proof, makeEasyToVerifyInCircuit); | ||
} | ||
async verifyIntermediateProof(proof) { | ||
async verifyIntermediateProof(proofData) { | ||
const proof = reconstructProofWithPublicInputs(proofData); | ||
const makeEasyToVerifyInCircuit = true; | ||
@@ -110,1 +126,18 @@ return this.verifyProof(proof, makeEasyToVerifyInCircuit); | ||
} | ||
function reconstructProofWithPublicInputs(proofData) { | ||
// Flatten publicInputs | ||
const publicInputsConcatenated = flattenUint8Arrays(proofData.publicInputs); | ||
// Concatenate publicInputs and proof | ||
const proofWithPublicInputs = Uint8Array.from([...publicInputsConcatenated, ...proofData.proof]); | ||
return proofWithPublicInputs; | ||
} | ||
function flattenUint8Arrays(arrays) { | ||
const totalLength = arrays.reduce((acc, val) => acc + val.length, 0); | ||
const result = new Uint8Array(totalLength); | ||
let offset = 0; | ||
for (const arr of arrays) { | ||
result.set(arr, offset); | ||
offset += arr.length; | ||
} | ||
return result; | ||
} |
@@ -6,3 +6,3 @@ { | ||
], | ||
"version": "0.7.10", | ||
"version": "0.17.0", | ||
"packageManager": "yarn@3.5.1", | ||
@@ -31,13 +31,11 @@ "license": "(MIT OR Apache-2.0)", | ||
"prettier:fix": "prettier --write 'src/**/*.ts' 'test/**/*.ts'", | ||
"publish": "yarn npm publish", | ||
"nightly:version": "jq --arg new_version \"-$(git rev-parse --short HEAD)$1\" '.version = .version + $new_version' package.json > package-tmp.json && mv package-tmp.json package.json", | ||
"publish": "echo 📡 publishing `$npm_package_name` && yarn npm publish", | ||
"lint": "NODE_NO_WARNINGS=1 eslint . --ext .ts --ignore-path ./.eslintignore --max-warnings 0" | ||
}, | ||
"dependencies": { | ||
"@aztec/bb.js": "0.7.10", | ||
"@noir-lang/types": "0.14.1", | ||
"@aztec/bb.js": "0.8.10", | ||
"@noir-lang/types": "0.17.0", | ||
"fflate": "^0.8.0" | ||
}, | ||
"peerDependencies": { | ||
"@noir-lang/backend_barretenberg": "0.7.10" | ||
}, | ||
"devDependencies": { | ||
@@ -44,0 +42,0 @@ "@types/node": "^20.6.2", |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
19814
3
19
385
+ Added@aztec/bb.js@0.8.10(transitive)
+ Added@noir-lang/noirc_abi@0.17.0(transitive)
+ Added@noir-lang/types@0.17.0(transitive)
- Removed@aztec/bb.js@0.7.10(transitive)
- Removed@noir-lang/types@0.14.1(transitive)
Updated@aztec/bb.js@0.8.10
Updated@noir-lang/types@0.17.0