Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

@noir-lang/backend_barretenberg

Package Overview
Dependencies
Maintainers
0
Versions
263
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@noir-lang/backend_barretenberg - npm Package Compare versions

Comparing version 0.34.0-e74b4ae.nightly to 0.34.0-fd03ea0.nightly

20

lib/cjs/backend.d.ts
import { Backend, CompiledCircuit, ProofData, VerifierBackend } from '@noir-lang/types';
import { BackendOptions } from './types.js';
import { type Barretenberg } from '@aztec/bb.js';
import { BackendOptions, UltraPlonkBackend, UltraHonkBackend as UltraHonkBackendInternal } from '@aztec/bb.js';
export declare class BarretenbergBackend implements Backend, VerifierBackend {
protected options: BackendOptions;
protected api: Barretenberg;
protected acirComposer: any;
protected acirUncompressedBytecode: Uint8Array;
protected backend: UltraPlonkBackend;
constructor(acirCircuit: CompiledCircuit, options?: BackendOptions);
/** @ignore */
instantiate(): Promise<void>;
/** @description Generates a proof */

@@ -41,12 +35,8 @@ generateProof(compressedWitness: Uint8Array): Promise<ProofData>;

export declare class UltraHonkBackend implements Backend, VerifierBackend {
protected options: BackendOptions;
protected api: Barretenberg;
protected acirUncompressedBytecode: Uint8Array;
protected backend: UltraHonkBackendInternal;
constructor(acirCircuit: CompiledCircuit, options?: BackendOptions);
/** @ignore */
instantiate(): Promise<void>;
generateProof(decompressedWitness: Uint8Array): Promise<ProofData>;
generateProof(compressedWitness: Uint8Array): Promise<ProofData>;
verifyProof(proofData: ProofData): Promise<boolean>;
getVerificationKey(): Promise<Uint8Array>;
generateRecursiveProofArtifacts(_proofData: ProofData, _numOfPublicInputs: number): Promise<{
generateRecursiveProofArtifacts(proofData: ProofData, numOfPublicInputs: number): Promise<{
proofAsFields: string[];

@@ -53,0 +43,0 @@ vkAsFields: string[];

"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.UltraHonkBackend = exports.BarretenbergBackend = void 0;
const fflate_1 = require("fflate");
const serialize_js_1 = require("./serialize.js");
const public_inputs_js_1 = require("./public_inputs.js");
const verifier_js_1 = require("./verifier.js");
const bb_js_1 = require("@aztec/bb.js");
const fflate_1 = require("fflate");
// This is the number of bytes in a UltraPlonk proof

@@ -35,47 +13,11 @@ // minus the public inputs.

class BarretenbergBackend {
options;
// These type assertions are used so that we don't
// have to initialize `api` and `acirComposer` in the constructor.
// These are initialized asynchronously in the `init` function,
// constructors cannot be asynchronous which is why we do this.
api;
// eslint-disable-next-line @typescript-eslint/no-explicit-any
acirComposer;
acirUncompressedBytecode;
backend;
constructor(acirCircuit, options = { threads: 1 }) {
this.options = options;
const acirBytecodeBase64 = acirCircuit.bytecode;
this.acirUncompressedBytecode = (0, serialize_js_1.acirToUint8Array)(acirBytecodeBase64);
const acirUncompressedBytecode = (0, serialize_js_1.acirToUint8Array)(acirBytecodeBase64);
this.backend = new bb_js_1.UltraPlonkBackend(acirUncompressedBytecode, options);
}
/** @ignore */
async instantiate() {
if (!this.api) {
if (typeof navigator !== 'undefined' && navigator.hardwareConcurrency) {
this.options.threads = navigator.hardwareConcurrency;
}
else {
try {
const os = await Promise.resolve().then(() => __importStar(require('os')));
this.options.threads = os.cpus().length;
}
catch (e) {
console.log('Could not detect environment. Falling back to one thread.', e);
}
}
const { Barretenberg, RawBuffer, Crs } = await Promise.resolve().then(() => __importStar(require('@aztec/bb.js')));
const api = await Barretenberg.new(this.options);
const honkRecursion = false;
const [_exact, _total, subgroupSize] = await api.acirGetCircuitSizes(this.acirUncompressedBytecode, honkRecursion);
const crs = await Crs.new(subgroupSize + 1);
await api.commonInitSlabAllocator(subgroupSize);
await api.srsInitSrs(new RawBuffer(crs.getG1Data()), crs.numPoints, new RawBuffer(crs.getG2Data()));
this.acirComposer = await api.acirNewAcirComposer(subgroupSize);
await api.acirInitProvingKey(this.acirComposer, this.acirUncompressedBytecode);
this.api = api;
}
}
/** @description Generates a proof */
async generateProof(compressedWitness) {
await this.instantiate();
const proofWithPublicInputs = await this.api.acirCreateProof(this.acirComposer, this.acirUncompressedBytecode, (0, fflate_1.decompressSync)(compressedWitness));
const proofWithPublicInputs = await this.backend.generateProof((0, fflate_1.decompressSync)(compressedWitness));
const splitIndex = proofWithPublicInputs.length - numBytesInProofWithoutPublicInputs;

@@ -104,15 +46,4 @@ const publicInputsConcatenated = proofWithPublicInputs.slice(0, splitIndex);

async generateRecursiveProofArtifacts(proofData, numOfPublicInputs = 0) {
await this.instantiate();
const proof = (0, verifier_js_1.reconstructProofWithPublicInputs)(proofData);
const proofAsFields = (await this.api.acirSerializeProofIntoFields(this.acirComposer, proof, numOfPublicInputs)).slice(numOfPublicInputs);
// TODO: perhaps we should put this in the init function. Need to benchmark
// TODO how long it takes.
await this.api.acirInitVerificationKey(this.acirComposer);
// Note: If you don't init verification key, `acirSerializeVerificationKeyIntoFields`` will just hang on serialization
const vk = await this.api.acirSerializeVerificationKeyIntoFields(this.acirComposer);
return {
proofAsFields: proofAsFields.map((p) => p.toString()),
vkAsFields: vk[0].map((vk) => vk.toString()),
vkHash: vk[1].toString(),
};
return this.backend.generateRecursiveProofArtifacts(proof, numOfPublicInputs);
}

@@ -122,16 +53,9 @@ /** @description Verifies a proof */

const proof = (0, verifier_js_1.reconstructProofWithPublicInputs)(proofData);
await this.instantiate();
await this.api.acirInitVerificationKey(this.acirComposer);
return await this.api.acirVerifyProof(this.acirComposer, proof);
return this.backend.verifyProof(proof);
}
async getVerificationKey() {
await this.instantiate();
await this.api.acirInitVerificationKey(this.acirComposer);
return await this.api.acirGetVerificationKey(this.acirComposer);
return this.backend.getVerificationKey();
}
async destroy() {
if (!this.api) {
return;
}
await this.api.destroy();
await this.backend.destroy();
}

@@ -146,3 +70,2 @@ }

class UltraHonkBackend {
options;
// These type assertions are used so that we don't

@@ -152,39 +75,10 @@ // have to initialize `api` in the constructor.

// constructors cannot be asynchronous which is why we do this.
api;
acirUncompressedBytecode;
backend;
constructor(acirCircuit, options = { threads: 1 }) {
this.options = options;
const acirBytecodeBase64 = acirCircuit.bytecode;
this.acirUncompressedBytecode = (0, serialize_js_1.acirToUint8Array)(acirBytecodeBase64);
const acirUncompressedBytecode = (0, serialize_js_1.acirToUint8Array)(acirBytecodeBase64);
this.backend = new bb_js_1.UltraHonkBackend(acirUncompressedBytecode, options);
}
/** @ignore */
async instantiate() {
if (!this.api) {
if (typeof navigator !== 'undefined' && navigator.hardwareConcurrency) {
this.options.threads = navigator.hardwareConcurrency;
}
else {
try {
const os = await Promise.resolve().then(() => __importStar(require('os')));
this.options.threads = os.cpus().length;
}
catch (e) {
console.log('Could not detect environment. Falling back to one thread.', e);
}
}
const { Barretenberg, RawBuffer, Crs } = await Promise.resolve().then(() => __importStar(require('@aztec/bb.js')));
const api = await Barretenberg.new(this.options);
const honkRecursion = true;
const [_exact, _total, subgroupSize] = await api.acirGetCircuitSizes(this.acirUncompressedBytecode, honkRecursion);
const crs = await Crs.new(subgroupSize + 1);
await api.commonInitSlabAllocator(subgroupSize);
await api.srsInitSrs(new RawBuffer(crs.getG1Data()), crs.numPoints, new RawBuffer(crs.getG2Data()));
// We don't init a proving key here in the Honk API
// await api.acirInitProvingKey(this.acirComposer, this.acirUncompressedBytecode);
this.api = api;
}
}
async generateProof(decompressedWitness) {
await this.instantiate();
const proofWithPublicInputs = await this.api.acirProveUltraHonk(this.acirUncompressedBytecode, (0, fflate_1.decompressSync)(decompressedWitness));
async generateProof(compressedWitness) {
const proofWithPublicInputs = await this.backend.generateProof((0, fflate_1.decompressSync)(compressedWitness));
const proofAsStrings = (0, public_inputs_js_1.deflattenFields)(proofWithPublicInputs.slice(4));

@@ -206,43 +100,17 @@ const numPublicInputs = Number(proofAsStrings[1]);

async verifyProof(proofData) {
const { RawBuffer } = await Promise.resolve().then(() => __importStar(require('@aztec/bb.js')));
const proof = (0, verifier_js_1.reconstructProofWithPublicInputsHonk)(proofData);
await this.instantiate();
const vkBuf = await this.api.acirWriteVkUltraHonk(this.acirUncompressedBytecode);
return await this.api.acirVerifyUltraHonk(proof, new RawBuffer(vkBuf));
return this.backend.verifyProof(proof);
}
async getVerificationKey() {
await this.instantiate();
return await this.api.acirWriteVkUltraHonk(this.acirUncompressedBytecode);
return this.backend.getVerificationKey();
}
// TODO(https://github.com/noir-lang/noir/issues/5661): Update this to handle Honk recursive aggregation in the browser once it is ready in the backend itself
async generateRecursiveProofArtifacts(_proofData, _numOfPublicInputs) {
await this.instantiate();
// TODO(https://github.com/noir-lang/noir/issues/5661): This needs to be updated to handle recursive aggregation.
// There is still a proofAsFields method but we could consider getting rid of it as the proof itself
// is a list of field elements.
// UltraHonk also does not have public inputs directly prepended to the proof and they are still instead
// inserted at an offset.
// const proof = reconstructProofWithPublicInputs(proofData);
// const proofAsFields = (await this.api.acirProofAsFieldsUltraHonk(proof)).slice(numOfPublicInputs);
// TODO: perhaps we should put this in the init function. Need to benchmark
// TODO how long it takes.
const vkBuf = await this.api.acirWriteVkUltraHonk(this.acirUncompressedBytecode);
const vk = await this.api.acirVkAsFieldsUltraHonk(vkBuf);
return {
// TODO(https://github.com/noir-lang/noir/issues/5661)
proofAsFields: [],
vkAsFields: vk.map((vk) => vk.toString()),
// We use an empty string for the vk hash here as it is unneeded as part of the recursive artifacts
// The user can be expected to hash the vk inside their circuit to check whether the vk is the circuit
// they expect
vkHash: '',
};
async generateRecursiveProofArtifacts(proofData, numOfPublicInputs) {
const proof = (0, verifier_js_1.reconstructProofWithPublicInputsHonk)(proofData);
return this.backend.generateRecursiveProofArtifacts(proof, numOfPublicInputs);
}
async destroy() {
if (!this.api) {
return;
}
await this.api.destroy();
await this.backend.destroy();
}
}
exports.UltraHonkBackend = UltraHonkBackend;
export { BarretenbergBackend, UltraHonkBackend } from './backend.js';
export { BarretenbergVerifier, UltraHonkVerifier } from './verifier.js';
export { Backend, CompiledCircuit, ProofData } from '@noir-lang/types';
export { BackendOptions } from './types.js';
export { BackendOptions } from '@aztec/bb.js';
import { ProofData } from '@noir-lang/types';
import { BackendOptions } from './types.js';
import { BackendOptions } from '@aztec/bb.js';
export declare class BarretenbergVerifier {
private options;
private api;
private acirComposer;
private verifier;
constructor(options?: BackendOptions);
/** @ignore */
instantiate(): Promise<void>;
/** @description Verifies a proof */

@@ -16,7 +12,4 @@ verifyProof(proofData: ProofData, verificationKey: Uint8Array): Promise<boolean>;

export declare class UltraHonkVerifier {
private options;
private api;
private verifier;
constructor(options?: BackendOptions);
/** @ignore */
instantiate(): Promise<void>;
/** @description Verifies a proof */

@@ -23,0 +16,0 @@ verifyProof(proofData: ProofData, verificationKey: Uint8Array): Promise<boolean>;

"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.reconstructProofWithPublicInputsHonk = exports.UltraHonkVerifier = exports.reconstructProofWithPublicInputs = exports.BarretenbergVerifier = void 0;
const public_inputs_js_1 = require("./public_inputs.js");
const bb_js_1 = require("@aztec/bb.js");
class BarretenbergVerifier {
options;
// These type assertions are used so that we don't
// have to initialize `api` and `acirComposer` in the constructor.
// These are initialized asynchronously in the `init` function,
// constructors cannot be asynchronous which is why we do this.
api;
// eslint-disable-next-line @typescript-eslint/no-explicit-any
acirComposer;
verifier;
constructor(options = { threads: 1 }) {
this.options = options;
this.verifier = new bb_js_1.BarretenbergVerifier(options);
}
/** @ignore */
async instantiate() {
if (!this.api) {
if (typeof navigator !== 'undefined' && navigator.hardwareConcurrency) {
this.options.threads = navigator.hardwareConcurrency;
}
else {
try {
const os = await Promise.resolve().then(() => __importStar(require('os')));
this.options.threads = os.cpus().length;
}
catch (e) {
console.log('Could not detect environment. Falling back to one thread.', e);
}
}
const { Barretenberg, RawBuffer, Crs } = await Promise.resolve().then(() => __importStar(require('@aztec/bb.js')));
// This is the number of CRS points necessary to verify a Barretenberg proof.
const NUM_CRS_POINTS_FOR_VERIFICATION = 0;
const [api, crs] = await Promise.all([Barretenberg.new(this.options), Crs.new(NUM_CRS_POINTS_FOR_VERIFICATION)]);
await api.commonInitSlabAllocator(NUM_CRS_POINTS_FOR_VERIFICATION);
await api.srsInitSrs(new RawBuffer([] /* crs.getG1Data() */), NUM_CRS_POINTS_FOR_VERIFICATION, new RawBuffer(crs.getG2Data()));
this.acirComposer = await api.acirNewAcirComposer(NUM_CRS_POINTS_FOR_VERIFICATION);
this.api = api;
}
}
/** @description Verifies a proof */
async verifyProof(proofData, verificationKey) {
const { RawBuffer } = await Promise.resolve().then(() => __importStar(require('@aztec/bb.js')));
await this.instantiate();
// The verifier can be used for a variety of ACIR programs so we should not assume that it
// is preloaded with the correct verification key.
await this.api.acirLoadVerificationKey(this.acirComposer, new RawBuffer(verificationKey));
const proof = reconstructProofWithPublicInputs(proofData);
return await this.api.acirVerifyProof(this.acirComposer, proof);
return this.verifier.verifyUltraplonkProof(proof, verificationKey);
}
async destroy() {
if (!this.api) {
return;
}
await this.api.destroy();
await this.verifier.destroy();
}

@@ -92,47 +30,13 @@ }

class UltraHonkVerifier {
options;
// These type assertions are used so that we don't
// have to initialize `api` in the constructor.
// These are initialized asynchronously in the `init` function,
// constructors cannot be asynchronous which is why we do this.
api;
verifier;
constructor(options = { threads: 1 }) {
this.options = options;
this.verifier = new bb_js_1.BarretenbergVerifier(options);
}
/** @ignore */
async instantiate() {
if (!this.api) {
if (typeof navigator !== 'undefined' && navigator.hardwareConcurrency) {
this.options.threads = navigator.hardwareConcurrency;
}
else {
try {
const os = await Promise.resolve().then(() => __importStar(require('os')));
this.options.threads = os.cpus().length;
}
catch (e) {
console.log('Could not detect environment. Falling back to one thread.', e);
}
}
const { Barretenberg, RawBuffer, Crs } = await Promise.resolve().then(() => __importStar(require('@aztec/bb.js')));
// This is the number of CRS points necessary to verify a Barretenberg proof.
const NUM_CRS_POINTS_FOR_VERIFICATION = 0;
const [api, crs] = await Promise.all([Barretenberg.new(this.options), Crs.new(NUM_CRS_POINTS_FOR_VERIFICATION)]);
await api.commonInitSlabAllocator(NUM_CRS_POINTS_FOR_VERIFICATION);
await api.srsInitSrs(new RawBuffer([] /* crs.getG1Data() */), NUM_CRS_POINTS_FOR_VERIFICATION, new RawBuffer(crs.getG2Data()));
this.api = api;
}
}
/** @description Verifies a proof */
async verifyProof(proofData, verificationKey) {
const { RawBuffer } = await Promise.resolve().then(() => __importStar(require('@aztec/bb.js')));
await this.instantiate();
const proof = reconstructProofWithPublicInputsHonk(proofData);
return await this.api.acirVerifyUltraHonk(proof, new RawBuffer(verificationKey));
return this.verifier.verifyUltrahonkProof(proof, verificationKey);
}
async destroy() {
if (!this.api) {
return;
}
await this.api.destroy();
await this.verifier.destroy();
}

@@ -139,0 +43,0 @@ }

import { Backend, CompiledCircuit, ProofData, VerifierBackend } from '@noir-lang/types';
import { BackendOptions } from './types.js';
import { type Barretenberg } from '@aztec/bb.js';
import { BackendOptions, UltraPlonkBackend, UltraHonkBackend as UltraHonkBackendInternal } from '@aztec/bb.js';
export declare class BarretenbergBackend implements Backend, VerifierBackend {
protected options: BackendOptions;
protected api: Barretenberg;
protected acirComposer: any;
protected acirUncompressedBytecode: Uint8Array;
protected backend: UltraPlonkBackend;
constructor(acirCircuit: CompiledCircuit, options?: BackendOptions);
/** @ignore */
instantiate(): Promise<void>;
/** @description Generates a proof */

@@ -41,12 +35,8 @@ generateProof(compressedWitness: Uint8Array): Promise<ProofData>;

export declare class UltraHonkBackend implements Backend, VerifierBackend {
protected options: BackendOptions;
protected api: Barretenberg;
protected acirUncompressedBytecode: Uint8Array;
protected backend: UltraHonkBackendInternal;
constructor(acirCircuit: CompiledCircuit, options?: BackendOptions);
/** @ignore */
instantiate(): Promise<void>;
generateProof(decompressedWitness: Uint8Array): Promise<ProofData>;
generateProof(compressedWitness: Uint8Array): Promise<ProofData>;
verifyProof(proofData: ProofData): Promise<boolean>;
getVerificationKey(): Promise<Uint8Array>;
generateRecursiveProofArtifacts(_proofData: ProofData, _numOfPublicInputs: number): Promise<{
generateRecursiveProofArtifacts(proofData: ProofData, numOfPublicInputs: number): Promise<{
proofAsFields: string[];

@@ -53,0 +43,0 @@ vkAsFields: string[];

@@ -1,5 +0,6 @@

import { decompressSync as gunzip } from 'fflate';
import { acirToUint8Array } from './serialize.js';
import { deflattenFields } from './public_inputs.js';
import { reconstructProofWithPublicInputs, reconstructProofWithPublicInputsHonk } from './verifier.js';
import { UltraPlonkBackend, UltraHonkBackend as UltraHonkBackendInternal } from '@aztec/bb.js';
import { decompressSync as gunzip } from 'fflate';
// This is the number of bytes in a UltraPlonk proof

@@ -9,47 +10,11 @@ // minus the public inputs.

export class BarretenbergBackend {
options;
// These type assertions are used so that we don't
// have to initialize `api` and `acirComposer` in the constructor.
// These are initialized asynchronously in the `init` function,
// constructors cannot be asynchronous which is why we do this.
api;
// eslint-disable-next-line @typescript-eslint/no-explicit-any
acirComposer;
acirUncompressedBytecode;
backend;
constructor(acirCircuit, options = { threads: 1 }) {
this.options = options;
const acirBytecodeBase64 = acirCircuit.bytecode;
this.acirUncompressedBytecode = acirToUint8Array(acirBytecodeBase64);
const acirUncompressedBytecode = acirToUint8Array(acirBytecodeBase64);
this.backend = new UltraPlonkBackend(acirUncompressedBytecode, options);
}
/** @ignore */
async instantiate() {
if (!this.api) {
if (typeof navigator !== 'undefined' && navigator.hardwareConcurrency) {
this.options.threads = navigator.hardwareConcurrency;
}
else {
try {
const os = await import('os');
this.options.threads = os.cpus().length;
}
catch (e) {
console.log('Could not detect environment. Falling back to one thread.', e);
}
}
const { Barretenberg, RawBuffer, Crs } = await import('@aztec/bb.js');
const api = await Barretenberg.new(this.options);
const honkRecursion = false;
const [_exact, _total, subgroupSize] = await api.acirGetCircuitSizes(this.acirUncompressedBytecode, honkRecursion);
const crs = await Crs.new(subgroupSize + 1);
await api.commonInitSlabAllocator(subgroupSize);
await api.srsInitSrs(new RawBuffer(crs.getG1Data()), crs.numPoints, new RawBuffer(crs.getG2Data()));
this.acirComposer = await api.acirNewAcirComposer(subgroupSize);
await api.acirInitProvingKey(this.acirComposer, this.acirUncompressedBytecode);
this.api = api;
}
}
/** @description Generates a proof */
async generateProof(compressedWitness) {
await this.instantiate();
const proofWithPublicInputs = await this.api.acirCreateProof(this.acirComposer, this.acirUncompressedBytecode, gunzip(compressedWitness));
const proofWithPublicInputs = await this.backend.generateProof(gunzip(compressedWitness));
const splitIndex = proofWithPublicInputs.length - numBytesInProofWithoutPublicInputs;

@@ -78,15 +43,4 @@ const publicInputsConcatenated = proofWithPublicInputs.slice(0, splitIndex);

async generateRecursiveProofArtifacts(proofData, numOfPublicInputs = 0) {
await this.instantiate();
const proof = reconstructProofWithPublicInputs(proofData);
const proofAsFields = (await this.api.acirSerializeProofIntoFields(this.acirComposer, proof, numOfPublicInputs)).slice(numOfPublicInputs);
// TODO: perhaps we should put this in the init function. Need to benchmark
// TODO how long it takes.
await this.api.acirInitVerificationKey(this.acirComposer);
// Note: If you don't init verification key, `acirSerializeVerificationKeyIntoFields`` will just hang on serialization
const vk = await this.api.acirSerializeVerificationKeyIntoFields(this.acirComposer);
return {
proofAsFields: proofAsFields.map((p) => p.toString()),
vkAsFields: vk[0].map((vk) => vk.toString()),
vkHash: vk[1].toString(),
};
return this.backend.generateRecursiveProofArtifacts(proof, numOfPublicInputs);
}

@@ -96,16 +50,9 @@ /** @description Verifies a proof */

const proof = reconstructProofWithPublicInputs(proofData);
await this.instantiate();
await this.api.acirInitVerificationKey(this.acirComposer);
return await this.api.acirVerifyProof(this.acirComposer, proof);
return this.backend.verifyProof(proof);
}
async getVerificationKey() {
await this.instantiate();
await this.api.acirInitVerificationKey(this.acirComposer);
return await this.api.acirGetVerificationKey(this.acirComposer);
return this.backend.getVerificationKey();
}
async destroy() {
if (!this.api) {
return;
}
await this.api.destroy();
await this.backend.destroy();
}

@@ -119,3 +66,2 @@ }

export class UltraHonkBackend {
options;
// These type assertions are used so that we don't

@@ -125,39 +71,10 @@ // have to initialize `api` in the constructor.

// constructors cannot be asynchronous which is why we do this.
api;
acirUncompressedBytecode;
backend;
constructor(acirCircuit, options = { threads: 1 }) {
this.options = options;
const acirBytecodeBase64 = acirCircuit.bytecode;
this.acirUncompressedBytecode = acirToUint8Array(acirBytecodeBase64);
const acirUncompressedBytecode = acirToUint8Array(acirBytecodeBase64);
this.backend = new UltraHonkBackendInternal(acirUncompressedBytecode, options);
}
/** @ignore */
async instantiate() {
if (!this.api) {
if (typeof navigator !== 'undefined' && navigator.hardwareConcurrency) {
this.options.threads = navigator.hardwareConcurrency;
}
else {
try {
const os = await import('os');
this.options.threads = os.cpus().length;
}
catch (e) {
console.log('Could not detect environment. Falling back to one thread.', e);
}
}
const { Barretenberg, RawBuffer, Crs } = await import('@aztec/bb.js');
const api = await Barretenberg.new(this.options);
const honkRecursion = true;
const [_exact, _total, subgroupSize] = await api.acirGetCircuitSizes(this.acirUncompressedBytecode, honkRecursion);
const crs = await Crs.new(subgroupSize + 1);
await api.commonInitSlabAllocator(subgroupSize);
await api.srsInitSrs(new RawBuffer(crs.getG1Data()), crs.numPoints, new RawBuffer(crs.getG2Data()));
// We don't init a proving key here in the Honk API
// await api.acirInitProvingKey(this.acirComposer, this.acirUncompressedBytecode);
this.api = api;
}
}
async generateProof(decompressedWitness) {
await this.instantiate();
const proofWithPublicInputs = await this.api.acirProveUltraHonk(this.acirUncompressedBytecode, gunzip(decompressedWitness));
async generateProof(compressedWitness) {
const proofWithPublicInputs = await this.backend.generateProof(gunzip(compressedWitness));
const proofAsStrings = deflattenFields(proofWithPublicInputs.slice(4));

@@ -179,42 +96,16 @@ const numPublicInputs = Number(proofAsStrings[1]);

async verifyProof(proofData) {
const { RawBuffer } = await import('@aztec/bb.js');
const proof = reconstructProofWithPublicInputsHonk(proofData);
await this.instantiate();
const vkBuf = await this.api.acirWriteVkUltraHonk(this.acirUncompressedBytecode);
return await this.api.acirVerifyUltraHonk(proof, new RawBuffer(vkBuf));
return this.backend.verifyProof(proof);
}
async getVerificationKey() {
await this.instantiate();
return await this.api.acirWriteVkUltraHonk(this.acirUncompressedBytecode);
return this.backend.getVerificationKey();
}
// TODO(https://github.com/noir-lang/noir/issues/5661): Update this to handle Honk recursive aggregation in the browser once it is ready in the backend itself
async generateRecursiveProofArtifacts(_proofData, _numOfPublicInputs) {
await this.instantiate();
// TODO(https://github.com/noir-lang/noir/issues/5661): This needs to be updated to handle recursive aggregation.
// There is still a proofAsFields method but we could consider getting rid of it as the proof itself
// is a list of field elements.
// UltraHonk also does not have public inputs directly prepended to the proof and they are still instead
// inserted at an offset.
// const proof = reconstructProofWithPublicInputs(proofData);
// const proofAsFields = (await this.api.acirProofAsFieldsUltraHonk(proof)).slice(numOfPublicInputs);
// TODO: perhaps we should put this in the init function. Need to benchmark
// TODO how long it takes.
const vkBuf = await this.api.acirWriteVkUltraHonk(this.acirUncompressedBytecode);
const vk = await this.api.acirVkAsFieldsUltraHonk(vkBuf);
return {
// TODO(https://github.com/noir-lang/noir/issues/5661)
proofAsFields: [],
vkAsFields: vk.map((vk) => vk.toString()),
// We use an empty string for the vk hash here as it is unneeded as part of the recursive artifacts
// The user can be expected to hash the vk inside their circuit to check whether the vk is the circuit
// they expect
vkHash: '',
};
async generateRecursiveProofArtifacts(proofData, numOfPublicInputs) {
const proof = reconstructProofWithPublicInputsHonk(proofData);
return this.backend.generateRecursiveProofArtifacts(proof, numOfPublicInputs);
}
async destroy() {
if (!this.api) {
return;
}
await this.api.destroy();
await this.backend.destroy();
}
}
export { BarretenbergBackend, UltraHonkBackend } from './backend.js';
export { BarretenbergVerifier, UltraHonkVerifier } from './verifier.js';
export { Backend, CompiledCircuit, ProofData } from '@noir-lang/types';
export { BackendOptions } from './types.js';
export { BackendOptions } from '@aztec/bb.js';
import { ProofData } from '@noir-lang/types';
import { BackendOptions } from './types.js';
import { BackendOptions } from '@aztec/bb.js';
export declare class BarretenbergVerifier {
private options;
private api;
private acirComposer;
private verifier;
constructor(options?: BackendOptions);
/** @ignore */
instantiate(): Promise<void>;
/** @description Verifies a proof */

@@ -16,7 +12,4 @@ verifyProof(proofData: ProofData, verificationKey: Uint8Array): Promise<boolean>;

export declare class UltraHonkVerifier {
private options;
private api;
private verifier;
constructor(options?: BackendOptions);
/** @ignore */
instantiate(): Promise<void>;
/** @description Verifies a proof */

@@ -23,0 +16,0 @@ verifyProof(proofData: ProofData, verificationKey: Uint8Array): Promise<boolean>;

import { flattenFieldsAsArray } from './public_inputs.js';
import { BarretenbergVerifier as BarretenbergVerifierInternal } from '@aztec/bb.js';
export class BarretenbergVerifier {
options;
// These type assertions are used so that we don't
// have to initialize `api` and `acirComposer` in the constructor.
// These are initialized asynchronously in the `init` function,
// constructors cannot be asynchronous which is why we do this.
api;
// eslint-disable-next-line @typescript-eslint/no-explicit-any
acirComposer;
verifier;
constructor(options = { threads: 1 }) {
this.options = options;
this.verifier = new BarretenbergVerifierInternal(options);
}
/** @ignore */
async instantiate() {
if (!this.api) {
if (typeof navigator !== 'undefined' && navigator.hardwareConcurrency) {
this.options.threads = navigator.hardwareConcurrency;
}
else {
try {
const os = await import('os');
this.options.threads = os.cpus().length;
}
catch (e) {
console.log('Could not detect environment. Falling back to one thread.', e);
}
}
const { Barretenberg, RawBuffer, Crs } = await import('@aztec/bb.js');
// This is the number of CRS points necessary to verify a Barretenberg proof.
const NUM_CRS_POINTS_FOR_VERIFICATION = 0;
const [api, crs] = await Promise.all([Barretenberg.new(this.options), Crs.new(NUM_CRS_POINTS_FOR_VERIFICATION)]);
await api.commonInitSlabAllocator(NUM_CRS_POINTS_FOR_VERIFICATION);
await api.srsInitSrs(new RawBuffer([] /* crs.getG1Data() */), NUM_CRS_POINTS_FOR_VERIFICATION, new RawBuffer(crs.getG2Data()));
this.acirComposer = await api.acirNewAcirComposer(NUM_CRS_POINTS_FOR_VERIFICATION);
this.api = api;
}
}
/** @description Verifies a proof */
async verifyProof(proofData, verificationKey) {
const { RawBuffer } = await import('@aztec/bb.js');
await this.instantiate();
// The verifier can be used for a variety of ACIR programs so we should not assume that it
// is preloaded with the correct verification key.
await this.api.acirLoadVerificationKey(this.acirComposer, new RawBuffer(verificationKey));
const proof = reconstructProofWithPublicInputs(proofData);
return await this.api.acirVerifyProof(this.acirComposer, proof);
return this.verifier.verifyUltraplonkProof(proof, verificationKey);
}
async destroy() {
if (!this.api) {
return;
}
await this.api.destroy();
await this.verifier.destroy();
}

@@ -64,47 +25,13 @@ }

export class UltraHonkVerifier {
options;
// These type assertions are used so that we don't
// have to initialize `api` in the constructor.
// These are initialized asynchronously in the `init` function,
// constructors cannot be asynchronous which is why we do this.
api;
verifier;
constructor(options = { threads: 1 }) {
this.options = options;
this.verifier = new BarretenbergVerifierInternal(options);
}
/** @ignore */
async instantiate() {
if (!this.api) {
if (typeof navigator !== 'undefined' && navigator.hardwareConcurrency) {
this.options.threads = navigator.hardwareConcurrency;
}
else {
try {
const os = await import('os');
this.options.threads = os.cpus().length;
}
catch (e) {
console.log('Could not detect environment. Falling back to one thread.', e);
}
}
const { Barretenberg, RawBuffer, Crs } = await import('@aztec/bb.js');
// This is the number of CRS points necessary to verify a Barretenberg proof.
const NUM_CRS_POINTS_FOR_VERIFICATION = 0;
const [api, crs] = await Promise.all([Barretenberg.new(this.options), Crs.new(NUM_CRS_POINTS_FOR_VERIFICATION)]);
await api.commonInitSlabAllocator(NUM_CRS_POINTS_FOR_VERIFICATION);
await api.srsInitSrs(new RawBuffer([] /* crs.getG1Data() */), NUM_CRS_POINTS_FOR_VERIFICATION, new RawBuffer(crs.getG2Data()));
this.api = api;
}
}
/** @description Verifies a proof */
async verifyProof(proofData, verificationKey) {
const { RawBuffer } = await import('@aztec/bb.js');
await this.instantiate();
const proof = reconstructProofWithPublicInputsHonk(proofData);
return await this.api.acirVerifyUltraHonk(proof, new RawBuffer(verificationKey));
return this.verifier.verifyUltrahonkProof(proof, verificationKey);
}
async destroy() {
if (!this.api) {
return;
}
await this.api.destroy();
await this.verifier.destroy();
}

@@ -111,0 +38,0 @@ }

@@ -6,3 +6,3 @@ {

],
"version": "0.34.0-e74b4ae.nightly",
"version": "0.34.0-fd03ea0.nightly",
"packageManager": "yarn@3.5.1",

@@ -45,4 +45,4 @@ "license": "(MIT OR Apache-2.0)",

"dependencies": {
"@aztec/bb.js": "0.55.0",
"@noir-lang/types": "0.34.0-e74b4ae.nightly",
"@aztec/bb.js": "0.56.0",
"@noir-lang/types": "0.34.0-fd03ea0.nightly",
"fflate": "^0.8.0"

@@ -49,0 +49,0 @@ },

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc