@izi-noir/sdk 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +458 -0
- package/dist/IProvingSystem-D9TnEig0.d.ts +140 -0
- package/dist/IProvingSystem-TKNofoo8.d.cts +140 -0
- package/dist/index.cjs +2793 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +1196 -0
- package/dist/index.d.ts +1196 -0
- package/dist/index.js +2730 -0
- package/dist/index.js.map +1 -0
- package/dist/providers/arkworks.cjs +824 -0
- package/dist/providers/arkworks.cjs.map +1 -0
- package/dist/providers/arkworks.d.cts +121 -0
- package/dist/providers/arkworks.d.ts +121 -0
- package/dist/providers/arkworks.js +791 -0
- package/dist/providers/arkworks.js.map +1 -0
- package/dist/providers/barretenberg.cjs +822 -0
- package/dist/providers/barretenberg.cjs.map +1 -0
- package/dist/providers/barretenberg.d.cts +18 -0
- package/dist/providers/barretenberg.d.ts +18 -0
- package/dist/providers/barretenberg.js +790 -0
- package/dist/providers/barretenberg.js.map +1 -0
- package/dist/providers/solana.cjs +262 -0
- package/dist/providers/solana.cjs.map +1 -0
- package/dist/providers/solana.d.cts +223 -0
- package/dist/providers/solana.d.ts +223 -0
- package/dist/providers/solana.js +222 -0
- package/dist/providers/solana.js.map +1 -0
- package/dist/providers/sunspot.cjs +475 -0
- package/dist/providers/sunspot.cjs.map +1 -0
- package/dist/providers/sunspot.d.cts +210 -0
- package/dist/providers/sunspot.d.ts +210 -0
- package/dist/providers/sunspot.js +443 -0
- package/dist/providers/sunspot.js.map +1 -0
- package/dist/types-CaaigonG.d.cts +93 -0
- package/dist/types-CaaigonG.d.ts +93 -0
- package/dist/wasm/nodejs/arkworks_groth16_wasm.js +448 -0
- package/dist/wasm/nodejs/arkworks_groth16_wasm_bg.wasm +0 -0
- package/dist/wasm/web/arkworks_groth16_wasm.js +536 -0
- package/dist/wasm/web/arkworks_groth16_wasm_bg.wasm +0 -0
- package/dist/wasmInit-KV6DTj4J.d.ts +282 -0
- package/dist/wasmInit-iEYiiB8M.d.cts +282 -0
- package/package.json +87 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/infra/provingSystems/Barretenberg.ts","../../src/infra/provingSystems/ArkworksWasm.ts","../../src/infra/chainFormatters/SolanaFormatter.ts","../../src/providers/barretenberg.ts","../../src/domain/types/provider.ts","../../src/infra/wasm/wasmInit.ts","../../src/IziNoir.ts"],"sourcesContent":["import { compile, createFileManager } from '@noir-lang/noir_wasm';\nimport { Noir } from '@noir-lang/noir_js';\nimport { Barretenberg as BarretenbergBackend, UltraHonkBackend } from '@aztec/bb.js';\nimport type { IProvingSystem } from '../../domain/interfaces/proving/IProvingSystem.js';\nimport type { CompiledCircuit, InputMap, ProofData } from '../../domain/types.js';\n\n/**\n * Helper to create a ReadableStream from a string\n * Used to write files to the virtual filesystem (browser-compatible)\n */\nfunction stringToStream(content: string): ReadableStream<Uint8Array> {\n return new ReadableStream({\n start(controller) {\n controller.enqueue(new TextEncoder().encode(content));\n controller.close();\n },\n });\n}\n\n/**\n * Check if running in Node.js environment\n */\nfunction isNodeJs(): boolean {\n return (\n typeof globalThis.process !== 'undefined' &&\n globalThis.process.versions != null &&\n globalThis.process.versions.node != null\n );\n}\n\n/**\n * Create temp directory in Node.js, or return '/' for browser virtual fs\n */\nasync function createTempDir(): Promise<{ basePath: string; cleanup: (() => Promise<void>) | null }> {\n if (!isNodeJs()) {\n // Browser: use virtual filesystem\n return { basePath: '/', cleanup: null };\n }\n\n // Node.js: create real temp directory\n // Use dynamic import which works in both Node.js ESM and CJS\n const fs = await import('node:fs/promises');\n const os = await import('node:os');\n const path = await import('node:path');\n\n const basePath = await fs.mkdtemp(path.join(os.tmpdir(), 'noir-circuit-'));\n const cleanup = async () => {\n await fs.rm(basePath, { recursive: true, force: true });\n };\n\n return { basePath, cleanup };\n}\n\n/**\n * Barretenberg proving system using WASM.\n * Browser compatible, produces UltraHonk proofs (~16KB).\n */\nexport class Barretenberg implements IProvingSystem {\n async compile(noirCode: string): Promise<CompiledCircuit> {\n const { basePath, cleanup } = await createTempDir();\n const fm = createFileManager(basePath);\n\n const nargoToml = `[package]\nname = \"circuit\"\ntype = \"bin\"\nauthors = [\"\"]\n\n[dependencies]\n`;\n\n try {\n // Write files using ReadableStream (browser-compatible)\n // In Node.js: writeFile is async and must be awaited\n // In browser: writeFile works with virtual fs, should not await for noir_wasm compatibility\n if (isNodeJs()) {\n await fm.writeFile('./src/main.nr', stringToStream(noirCode));\n await fm.writeFile('./Nargo.toml', stringToStream(nargoToml));\n } else {\n fm.writeFile('./src/main.nr', stringToStream(noirCode));\n fm.writeFile('./Nargo.toml', stringToStream(nargoToml));\n }\n\n const result = await compile(fm);\n const compiled = (result as any).program as CompiledCircuit;\n\n if (!compiled || !compiled.bytecode) {\n throw new Error('Compilation failed: no bytecode generated');\n }\n\n return compiled;\n } finally {\n if (cleanup) {\n await cleanup();\n }\n }\n }\n\n async generateProof(circuit: CompiledCircuit, inputs: InputMap): Promise<ProofData> {\n const noir = new Noir(circuit);\n const { witness } = await noir.execute(inputs);\n\n const barretenberg = await BarretenbergBackend.new({ threads: 1 });\n const backend = new UltraHonkBackend(circuit.bytecode, barretenberg);\n\n try {\n const proofData = await backend.generateProof(witness);\n return {\n proof: proofData.proof,\n publicInputs: proofData.publicInputs || [],\n };\n } finally {\n await barretenberg.destroy();\n }\n }\n\n async verifyProof(\n circuit: CompiledCircuit,\n proof: Uint8Array,\n publicInputs: string[]\n ): Promise<boolean> {\n const barretenberg = await BarretenbergBackend.new({ threads: 1 });\n const backend = new UltraHonkBackend(circuit.bytecode, barretenberg);\n\n try {\n return await backend.verifyProof({ proof, publicInputs });\n } finally {\n await barretenberg.destroy();\n }\n }\n}\n","/**\n * ArkworksWasm proving system.\n *\n * 100% browser-compatible Groth16 prover using arkworks compiled to WASM.\n * Produces proofs compatible with gnark-verifier-solana for on-chain verification.\n *\n * Features:\n * - Runs entirely in the browser (no CLI dependencies)\n * - Generates compact Groth16 proofs (~256 bytes)\n * - Compatible with gnark-verifier-solana\n * - Uses BN254 curve\n */\n\nimport { compile, createFileManager } from '@noir-lang/noir_wasm';\nimport { Noir } from '@noir-lang/noir_js';\nimport type { IProvingSystem } from '../../domain/interfaces/proving/IProvingSystem.js';\nimport type { CompiledCircuit, InputMap, ProofData } from '../../domain/types.js';\n\n/**\n * Helper to create a ReadableStream from a string\n * Used to write files to the virtual filesystem (browser-compatible)\n */\nfunction stringToStream(content: string): ReadableStream<Uint8Array> {\n return new ReadableStream({\n start(controller) {\n controller.enqueue(new TextEncoder().encode(content));\n controller.close();\n },\n });\n}\n\n/**\n * Check if running in Node.js environment\n */\nfunction isNodeJs(): boolean {\n return (\n typeof globalThis.process !== 'undefined' &&\n globalThis.process.versions != null &&\n globalThis.process.versions.node != null\n );\n}\n\n/**\n * Create temp directory in Node.js, or return '/' for browser virtual fs\n */\nasync function createTempDir(): Promise<{ basePath: string; cleanup: (() => Promise<void>) | null }> {\n if (!isNodeJs()) {\n // Browser: use virtual filesystem\n return { basePath: '/', cleanup: null };\n }\n\n // Node.js: create real temp directory\n // Use dynamic import which works in both Node.js ESM and CJS\n const fs = await import('node:fs/promises');\n const os = await import('node:os');\n const path = await import('node:path');\n\n const basePath = await fs.mkdtemp(path.join(os.tmpdir(), 'arkworks-circuit-'));\n const cleanup = async () => {\n await fs.rm(basePath, { recursive: true, force: true });\n };\n\n return { basePath, cleanup };\n}\n\n/**\n * Result of Groth16 setup from arkworks WASM module\n */\nexport interface ArkworksSetupResult {\n /** Base64-encoded proving key */\n proving_key: string;\n /** Base64-encoded verifying key (arkworks format) */\n verifying_key: string;\n /** Base64-encoded verifying key (gnark format for Solana) */\n verifying_key_gnark: string;\n}\n\n/**\n * Result of Groth16 proof generation from arkworks WASM module\n */\nexport interface ArkworksProofResult {\n /** Base64-encoded proof (arkworks format) */\n proof: string;\n /** Base64-encoded proof (gnark format, 256 bytes) */\n proof_gnark: string;\n /** Public inputs as hex strings */\n public_inputs: string[];\n /** Base64-encoded public inputs (gnark format) */\n public_inputs_gnark: string;\n}\n\n/**\n * Interface for the arkworks-groth16-wasm WASM module\n */\nexport interface ArkworksWasmModule {\n setup(acirJson: string): ArkworksSetupResult;\n prove(provingKeyB64: string, acirJson: string, witnessJson: string): ArkworksProofResult;\n verify(verifyingKeyB64: string, proofB64: string, publicInputsJson: string): boolean;\n verify_gnark(\n verifyingKeyGnarkB64: string,\n proofGnarkB64: string,\n publicInputsGnarkB64: string,\n numPublicInputs: number\n ): boolean;\n acir_to_r1cs_info(acirJson: string): {\n num_witnesses: number;\n num_constraints: number;\n public_inputs: number[];\n private_inputs: number[];\n return_values: number[];\n };\n version(): string;\n}\n\n/**\n * Configuration for ArkworksWasm prover\n */\nexport interface ArkworksWasmConfig {\n /** Keep intermediate artifacts for debugging */\n keepArtifacts?: boolean;\n /** Cache proving/verifying keys for repeated proofs */\n cacheKeys?: boolean;\n}\n\n/**\n * Extended CompiledCircuit for ArkworksWasm backend\n */\nexport interface ArkworksCompiledCircuit extends CompiledCircuit {\n /** Marker to identify ArkworksWasm circuits */\n __arkworks: true;\n /** ACIR program as JSON string (used for setup/prove) */\n acirJson: string;\n /** Cached proving key (base64) if cacheKeys is enabled */\n provingKey?: string;\n /** Cached verifying key (base64) if cacheKeys is enabled */\n verifyingKey?: string;\n /** Cached verifying key in gnark format (base64) */\n verifyingKeyGnark?: string;\n}\n\n/**\n * Type guard to check if a circuit is an ArkworksWasm circuit\n */\nexport function isArkworksCircuit(circuit: CompiledCircuit): circuit is ArkworksCompiledCircuit {\n return '__arkworks' in circuit && (circuit as ArkworksCompiledCircuit).__arkworks === true;\n}\n\n// WASM module singleton\nlet wasmModule: ArkworksWasmModule | null = null;\nlet wasmInitPromise: Promise<ArkworksWasmModule> | null = null;\n\n/**\n * Initialize the arkworks WASM module\n * Automatically detects Node.js vs browser and uses the appropriate WASM target.\n */\nasync function initWasm(): Promise<ArkworksWasmModule> {\n if (wasmModule) {\n return wasmModule;\n }\n\n if (wasmInitPromise) {\n return wasmInitPromise;\n }\n\n wasmInitPromise = (async () => {\n try {\n if (isNodeJs()) {\n // Node.js: use the nodejs target which doesn't require fetch\n // Path resolves to dist/wasm/nodejs/ after bundling\n // @ts-ignore - Dynamic import path resolved at runtime\n const module = await import('../wasm/nodejs/arkworks_groth16_wasm.js');\n wasmModule = module as unknown as ArkworksWasmModule;\n } else {\n // Browser: use the web target with init function\n // Path resolves to dist/wasm/web/ after bundling\n // @ts-ignore - Dynamic import path resolved at runtime\n const module = await import('../wasm/web/arkworks_groth16_wasm.js');\n // Initialize WASM (wasm-pack generates an init function for web target)\n if (typeof module.default === 'function') {\n await module.default();\n }\n wasmModule = module as unknown as ArkworksWasmModule;\n }\n return wasmModule;\n } catch (error) {\n wasmInitPromise = null;\n throw new Error(\n `Failed to initialize arkworks-groth16-wasm: ${error instanceof Error ? error.message : String(error)}\\n` +\n 'Make sure the WASM module is built: cd packages/arkworks-groth16-wasm && npm run build'\n );\n }\n })();\n\n return wasmInitPromise;\n}\n\n/**\n * ArkworksWasm proving system using arkworks Groth16 compiled to WASM.\n *\n * This proving system:\n * - Compiles Noir code using @noir-lang/noir_wasm\n * - Generates witness using @noir-lang/noir_js\n * - Performs Groth16 setup/prove/verify using arkworks-groth16-wasm\n *\n * All operations run in the browser with no external dependencies.\n */\nexport class ArkworksWasm implements IProvingSystem {\n private readonly config: ArkworksWasmConfig;\n\n constructor(config: ArkworksWasmConfig = {}) {\n this.config = {\n keepArtifacts: false,\n cacheKeys: true,\n ...config,\n };\n }\n\n /**\n * Compile Noir code to a circuit with ACIR for Groth16 proving\n */\n async compile(noirCode: string): Promise<CompiledCircuit> {\n const wasm = await initWasm();\n const { basePath, cleanup } = await createTempDir();\n const fm = createFileManager(basePath);\n\n const nargoToml = `[package]\nname = \"circuit\"\ntype = \"bin\"\nauthors = [\"\"]\n\n[dependencies]\n`;\n\n try {\n // Write files using ReadableStream (browser-compatible)\n // In Node.js: writeFile is async and must be awaited\n // In browser: writeFile works with virtual fs, should not await for noir_wasm compatibility\n if (isNodeJs()) {\n await fm.writeFile('./src/main.nr', stringToStream(noirCode));\n await fm.writeFile('./Nargo.toml', stringToStream(nargoToml));\n } else {\n fm.writeFile('./src/main.nr', stringToStream(noirCode));\n fm.writeFile('./Nargo.toml', stringToStream(nargoToml));\n }\n\n // Compile using noir_wasm\n const result = await compile(fm);\n const compiled = (result as any).program as CompiledCircuit;\n\n if (!compiled || !compiled.bytecode) {\n throw new Error('Compilation failed: no bytecode generated');\n }\n\n // Store the ACIR JSON for setup/prove\n // The bytecode is base64-gzipped ACIR\n const acirJson = JSON.stringify({\n functions: [\n {\n current_witness_index: compiled.abi.parameters.length + 1,\n opcodes: [], // Will be extracted from bytecode during prove\n private_parameters: compiled.abi.parameters\n .filter((p) => p.visibility === 'private')\n .map((_, i) => i + 1),\n public_parameters: {\n witnesses: compiled.abi.parameters\n .filter((p) => p.visibility === 'public')\n .map((_, i) => i + 1),\n },\n return_values: { witnesses: [] },\n },\n ],\n });\n\n // Perform setup if caching is enabled\n let provingKey: string | undefined;\n let verifyingKey: string | undefined;\n let verifyingKeyGnark: string | undefined;\n\n if (this.config.cacheKeys) {\n try {\n // Note: For real ACIR, we need to decode the bytecode first\n // This is a placeholder - actual implementation needs to decode\n // the base64-gzipped bytecode to get the ACIR JSON\n const setupResult = wasm.setup(acirJson);\n provingKey = setupResult.proving_key;\n verifyingKey = setupResult.verifying_key;\n verifyingKeyGnark = setupResult.verifying_key_gnark;\n } catch (error) {\n // Setup might fail if ACIR is complex - we'll do it lazily during prove\n console.warn('Deferred setup: will run during proof generation');\n }\n }\n\n const arkworksCircuit: ArkworksCompiledCircuit = {\n ...compiled,\n __arkworks: true,\n acirJson,\n provingKey,\n verifyingKey,\n verifyingKeyGnark,\n };\n\n return arkworksCircuit;\n } finally {\n if (cleanup) {\n await cleanup();\n }\n }\n }\n\n /**\n * Generate a Groth16 proof\n */\n async generateProof(circuit: CompiledCircuit, inputs: InputMap): Promise<ProofData> {\n const wasm = await initWasm();\n\n if (!isArkworksCircuit(circuit)) {\n throw new Error(\n 'ArkworksWasm.generateProof requires an ArkworksCompiledCircuit. Use ArkworksWasm.compile() first.'\n );\n }\n\n // Execute the circuit to generate witness using noir_js\n const noir = new Noir(circuit);\n const { witness } = await noir.execute(inputs);\n\n // Convert witness to the format expected by arkworks-groth16-wasm\n // Witness is a Map<number, string> where values are hex field elements\n const witnessMap: Record<string, string> = {};\n for (const [index, value] of witness.entries()) {\n witnessMap[index.toString()] = String(value);\n }\n const witnessJson = JSON.stringify(witnessMap);\n\n // Ensure we have a proving key\n let provingKey = circuit.provingKey;\n if (!provingKey) {\n const setupResult = wasm.setup(circuit.acirJson);\n provingKey = setupResult.proving_key;\n // Cache for future use\n circuit.provingKey = provingKey;\n circuit.verifyingKey = setupResult.verifying_key;\n circuit.verifyingKeyGnark = setupResult.verifying_key_gnark;\n }\n\n // Generate proof\n const proofResult = wasm.prove(provingKey, circuit.acirJson, witnessJson);\n\n // Return proof in gnark format for Solana compatibility\n const proofBytes = base64ToUint8Array(proofResult.proof_gnark);\n\n return {\n proof: proofBytes,\n publicInputs: proofResult.public_inputs,\n };\n }\n\n /**\n * Verify a Groth16 proof\n */\n async verifyProof(\n circuit: CompiledCircuit,\n proof: Uint8Array,\n publicInputs: string[]\n ): Promise<boolean> {\n const wasm = await initWasm();\n\n if (!isArkworksCircuit(circuit)) {\n throw new Error(\n 'ArkworksWasm.verifyProof requires an ArkworksCompiledCircuit. Use ArkworksWasm.compile() first.'\n );\n }\n\n // Ensure we have a verifying key\n let verifyingKeyGnark = circuit.verifyingKeyGnark;\n if (!verifyingKeyGnark) {\n const setupResult = wasm.setup(circuit.acirJson);\n circuit.provingKey = setupResult.proving_key;\n circuit.verifyingKey = setupResult.verifying_key;\n verifyingKeyGnark = setupResult.verifying_key_gnark;\n circuit.verifyingKeyGnark = verifyingKeyGnark;\n }\n\n // Convert proof to base64\n const proofB64 = uint8ArrayToBase64(proof);\n\n // Convert public inputs to gnark format\n const publicInputsGnarkB64 = publicInputsToGnarkBase64(publicInputs);\n\n // Verify using gnark format\n return wasm.verify_gnark(\n verifyingKeyGnark,\n proofB64,\n publicInputsGnarkB64,\n publicInputs.length\n );\n }\n\n /**\n * Get the verifying key in gnark format for on-chain deployment\n */\n async getVerifyingKeyGnark(circuit: CompiledCircuit): Promise<Uint8Array> {\n const wasm = await initWasm();\n\n if (!isArkworksCircuit(circuit)) {\n throw new Error('getVerifyingKeyGnark requires an ArkworksCompiledCircuit');\n }\n\n if (!circuit.verifyingKeyGnark) {\n const setupResult = wasm.setup(circuit.acirJson);\n circuit.provingKey = setupResult.proving_key;\n circuit.verifyingKey = setupResult.verifying_key;\n circuit.verifyingKeyGnark = setupResult.verifying_key_gnark;\n }\n\n return base64ToUint8Array(circuit.verifyingKeyGnark);\n }\n}\n\n// Utility functions\n\nfunction base64ToUint8Array(b64: string): Uint8Array {\n const binaryString = atob(b64);\n const bytes = new Uint8Array(binaryString.length);\n for (let i = 0; i < binaryString.length; i++) {\n bytes[i] = binaryString.charCodeAt(i);\n }\n return bytes;\n}\n\nfunction uint8ArrayToBase64(bytes: Uint8Array): string {\n let binary = '';\n for (let i = 0; i < bytes.length; i++) {\n binary += String.fromCharCode(bytes[i]);\n }\n return btoa(binary);\n}\n\n/**\n * Convert public inputs (hex strings) to gnark format (32 bytes each, big-endian)\n * Returns base64-encoded result\n */\nfunction publicInputsToGnarkBase64(publicInputs: string[]): string {\n const FIELD_SIZE = 32;\n const bytes = new Uint8Array(publicInputs.length * FIELD_SIZE);\n\n for (let i = 0; i < publicInputs.length; i++) {\n const input = publicInputs[i];\n const hex = input.startsWith('0x') ? input.slice(2) : input;\n const inputBytes = hexToBytes(hex.padStart(64, '0'));\n\n // Copy big-endian bytes\n bytes.set(inputBytes, i * FIELD_SIZE);\n }\n\n return uint8ArrayToBase64(bytes);\n}\n\nfunction hexToBytes(hex: string): Uint8Array {\n const bytes = new Uint8Array(hex.length / 2);\n for (let i = 0; i < hex.length; i += 2) {\n bytes[i / 2] = parseInt(hex.substring(i, i + 2), 16);\n }\n return bytes;\n}\n","import type { IChainFormatter } from '../../domain/interfaces/chain/IChainFormatter';\nimport type { ProofData, SolanaProofData, CompiledCircuit } from '../../domain/types';\nimport type { CircuitMetadata, SolanaChainMetadata } from '../../domain/types/chain';\nimport type { ArkworksWasm } from '../provingSystems/ArkworksWasm';\n\n// Constants for VK account sizing\nconst G1_SIZE = 64;\nconst G2_SIZE = 128;\n\n/**\n * Formatter for Solana-compatible proof data.\n *\n * Converts generic ProofData into SolanaProofData format with:\n * - Verifying key in gnark format (compatible with gnark-verifier-solana)\n * - Proof bytes (256 bytes Groth16)\n * - Public inputs as 32-byte arrays\n * - VK account size and rent estimates\n *\n * @example\n * ```typescript\n * const formatter = new SolanaFormatter(arkworksProvider);\n * const solanaProof = await formatter.formatProof(proofData, circuit, metadata);\n * ```\n */\nexport class SolanaFormatter implements IChainFormatter<'solana'> {\n readonly chainId = 'solana' as const;\n\n constructor(private arkworksProvider: ArkworksWasm) {}\n\n /**\n * Format a generic proof for Solana on-chain verification.\n *\n * @param proofData - Generic proof data from Arkworks\n * @param circuit - The compiled circuit (must be Arkworks circuit)\n * @param metadata - Circuit metadata with public input count\n * @returns SolanaProofData ready for on-chain verification\n */\n async formatProof(\n proofData: ProofData,\n circuit: CompiledCircuit,\n metadata: CircuitMetadata\n ): Promise<SolanaProofData> {\n // Get verifying key in gnark format\n const vkBytes = await this.arkworksProvider.getVerifyingKeyGnark(circuit);\n const vkBase64 = this.uint8ArrayToBase64(vkBytes);\n\n // Number of public inputs\n const nrPublicInputs = metadata.numPublicInputs;\n\n // Convert public inputs to 32-byte arrays\n const publicInputsBytes = proofData.publicInputs.map((input) => {\n const hex = input.startsWith('0x') ? input.slice(2) : input;\n return this.hexToBytes(hex.padStart(64, '0'));\n });\n\n // Calculate account size and rent\n const { accountSize, estimatedRent } = this.getChainMetadata(nrPublicInputs);\n\n return {\n verifyingKey: {\n base64: vkBase64,\n bytes: vkBytes,\n nrPublicInputs,\n },\n proof: {\n base64: this.uint8ArrayToBase64(proofData.proof),\n bytes: proofData.proof,\n },\n publicInputs: {\n hex: proofData.publicInputs,\n bytes: publicInputsBytes,\n },\n accountSize,\n estimatedRent,\n };\n }\n\n /**\n * Get Solana-specific metadata for a circuit.\n *\n * @param publicInputCount - Number of public inputs in the circuit\n * @returns Solana metadata with account size and rent estimates\n */\n getChainMetadata(publicInputCount: number): SolanaChainMetadata {\n const accountSize = this.calculateVkAccountSize(publicInputCount);\n const estimatedRent = this.calculateVkAccountRent(publicInputCount);\n\n return {\n chainId: 'solana',\n accountSize,\n estimatedRent,\n };\n }\n\n /**\n * Calculate the size of a VK account for a given number of public inputs.\n * Matches the Rust `vk_account_size` function in the Solana program.\n */\n private calculateVkAccountSize(nrPublicInputs: number): number {\n // discriminator (8) + authority (32) + nr_pubinputs (1) + alpha_g1 (64) +\n // beta_g2 (128) + gamma_g2 (128) + delta_g2 (128) + vec_len (4) + k elements\n const fixedSize = 8 + 32 + 1 + G1_SIZE + G2_SIZE * 3 + 4;\n return fixedSize + (nrPublicInputs + 1) * G1_SIZE;\n }\n\n /**\n * Calculate the minimum rent for a VK account.\n */\n private calculateVkAccountRent(\n nrPublicInputs: number,\n rentExemptionPerByte: number = 6960 // approximate lamports per byte\n ): number {\n const size = this.calculateVkAccountSize(nrPublicInputs);\n return size * rentExemptionPerByte;\n }\n\n /**\n * Convert Uint8Array to base64 string.\n */\n private uint8ArrayToBase64(bytes: Uint8Array): string {\n // Browser-compatible\n if (typeof btoa === 'function') {\n let binary = '';\n for (let i = 0; i < bytes.length; i++) {\n binary += String.fromCharCode(bytes[i]);\n }\n return btoa(binary);\n }\n // Node.js fallback\n return Buffer.from(bytes).toString('base64');\n }\n\n /**\n * Convert hex string to Uint8Array.\n */\n private hexToBytes(hex: string): Uint8Array {\n const cleanHex = hex.startsWith('0x') ? hex.slice(2) : hex;\n const bytes = new Uint8Array(cleanHex.length / 2);\n for (let i = 0; i < bytes.length; i++) {\n bytes[i] = parseInt(cleanHex.substring(i * 2, i * 2 + 2), 16);\n }\n return bytes;\n }\n}\n","/**\n * Barretenberg-only entry point for tree-shaking.\n *\n * Import from this module to only include Barretenberg in your bundle,\n * excluding Arkworks and Sunspot dependencies.\n *\n * @example\n * ```typescript\n * import { IziNoir, Provider } from '@izi-noir/sdk/barretenberg';\n *\n * const izi = await IziNoir.init({ provider: Provider.Barretenberg });\n * ```\n *\n * @module @izi-noir/sdk/barretenberg\n */\n\nexport { Barretenberg } from '../infra/provingSystems/Barretenberg.js';\nexport { IziNoir, Provider, type IziNoirConfig, type CircuitPaths } from '../IziNoir.js';\nexport { initNoirWasm, isWasmInitialized } from '../infra/wasm/wasmInit.js';\nexport type { CompiledCircuit, InputMap, ProofData } from '../domain/types.js';\nexport type { IProvingSystem } from '../domain/interfaces/proving/IProvingSystem.js';\n","import { Chain } from './chain.js';\n\n/**\n * Available proving system providers\n */\nexport enum Provider {\n /** Barretenberg backend - browser compatible, UltraHonk proofs (~16KB) */\n Barretenberg = 'barretenberg',\n /** Arkworks WASM backend - browser compatible, Groth16 proofs (~256 bytes) */\n Arkworks = 'arkworks',\n /** Sunspot CLI backend - Node.js only, Groth16 proofs (~256 bytes) */\n Sunspot = 'sunspot',\n}\n\n/**\n * Configuration for circuit paths (required for Sunspot)\n */\nexport interface CircuitPaths {\n /** Path to the proving key file */\n pkPath: string;\n /** Path to the verification key file */\n vkPath: string;\n /** Path to the compiled circuit JSON file */\n circuitPath: string;\n}\n\n/**\n * Configuration for IziNoir initialization\n */\nexport interface IziNoirConfig {\n /** The proving system provider to use */\n provider: Provider;\n /**\n * Target blockchain for proof formatting.\n * If omitted, operates in offchain mode (raw proofs, no chain formatting).\n */\n chain?: Chain;\n /** Circuit paths - required for Sunspot provider */\n circuitPaths?: CircuitPaths;\n}\n\n// Re-export Chain for convenience\nexport { Chain };\n","let wasmInitPromise: Promise<void> | null = null;\nlet wasmInitialized = false;\n\n/**\n * Check if running in Node.js environment\n */\nfunction isNodeJs(): boolean {\n return (\n typeof globalThis.process !== 'undefined' &&\n globalThis.process.versions != null &&\n globalThis.process.versions.node != null\n );\n}\n\n/**\n * Initialize WASM modules for Noir compilation and execution.\n * Automatically detects Node.js vs browser and uses the appropriate WASM target.\n *\n * Uses lazy loading with singleton pattern - safe to call multiple times.\n * Only initializes once, subsequent calls return immediately.\n */\nexport async function initNoirWasm(): Promise<void> {\n if (wasmInitialized) return;\n\n if (!wasmInitPromise) {\n wasmInitPromise = initWasmInternal();\n }\n\n await wasmInitPromise;\n wasmInitialized = true;\n}\n\nasync function initWasmInternal(): Promise<void> {\n if (isNodeJs()) {\n // Node.js: use the nodejs target which doesn't require fetch\n // The nodejs target auto-initializes when imported\n await import('@noir-lang/acvm_js/nodejs/acvm_js.js');\n await import('@noir-lang/noirc_abi/nodejs/noirc_abi_wasm.js');\n } else {\n // Browser: use the web target with default initialization\n // Note: For Vite/bundlers, external initialization with WASM URLs is preferred\n // Use markWasmInitialized() after initializing externally\n const [{ default: initACVM }, { default: initNoirC }] = await Promise.all([\n import('@noir-lang/acvm_js'),\n import('@noir-lang/noirc_abi'),\n ]);\n await Promise.all([initACVM(), initNoirC()]);\n }\n}\n\n/**\n * Check if WASM modules are already initialized\n */\nexport function isWasmInitialized(): boolean {\n return wasmInitialized;\n}\n\n/**\n * Mark WASM as already initialized externally.\n * Use this when WASM has been initialized outside the SDK (e.g., with Vite URL imports).\n *\n * @example\n * ```typescript\n * // In Vite/browser environment\n * import initNoirC from \"@noir-lang/noirc_abi\";\n * import initACVM from \"@noir-lang/acvm_js\";\n * import acvm from \"@noir-lang/acvm_js/web/acvm_js_bg.wasm?url\";\n * import noirc from \"@noir-lang/noirc_abi/web/noirc_abi_wasm_bg.wasm?url\";\n * import { markWasmInitialized } from \"@izi-noir/sdk\";\n *\n * await Promise.all([initACVM(fetch(acvm)), initNoirC(fetch(noirc))]);\n * markWasmInitialized();\n * ```\n */\nexport function markWasmInitialized(): void {\n wasmInitialized = true;\n}\n\n/**\n * Reset WASM initialization state (for testing purposes)\n * @internal\n */\nexport function resetWasmInit(): void {\n wasmInitPromise = null;\n wasmInitialized = false;\n}\n","import {\n Provider,\n Chain,\n type IziNoirConfig,\n type CircuitPaths,\n} from './domain/types/provider.js';\nimport type { IProvingSystem } from './domain/interfaces/proving/IProvingSystem.js';\nimport type {\n CompiledCircuit,\n InputMap,\n ProofData,\n SolanaProofData,\n VerifyingKeyData,\n} from './domain/types.js';\nimport type { IChainFormatter } from './domain/interfaces/chain/IChainFormatter.js';\nimport type { ChainId, CircuitMetadata } from './domain/types/chain.js';\nimport { initNoirWasm } from './infra/wasm/wasmInit.js';\n\n/**\n * Data needed to deploy a verifying key to Solana.\n * Use with SolanaTransactionBuilder or your own transaction logic.\n */\nexport interface SolanaDeployData {\n /** The proof data with VK and public inputs */\n proofData: SolanaProofData;\n /** Program ID to use */\n programId: string;\n /** Compute units for the transaction */\n computeUnits: number;\n}\n\n/**\n * Main class for ZK proof generation with multiple backend providers.\n *\n * @example\n * ```typescript\n * import { IziNoir, Provider, Chain } from '@izi-noir/sdk';\n *\n * // On-chain mode: Initialize with chain for blockchain-specific formatting\n * const izi = await IziNoir.init({\n * provider: Provider.Arkworks,\n * chain: Chain.Solana\n * });\n *\n * await izi.compile(noirCode);\n * const proof = await izi.prove(inputs); // Returns SolanaProofData\n * console.log(izi.vk); // Verifying key available\n *\n * // Offchain mode: No chain specified\n * const iziOffchain = await IziNoir.init({ provider: Provider.Arkworks });\n * const rawProof = await iziOffchain.prove(inputs); // Returns ProofData\n * const verified = await iziOffchain.verify(rawProof.proof, rawProof.publicInputs);\n * ```\n */\nexport class IziNoir {\n private provingSystem: IProvingSystem;\n private compiledCircuit: CompiledCircuit | null = null;\n private chainFormatters: Map<string, IChainFormatter> = new Map();\n private readonly chain?: Chain;\n private _verifyingKey?: VerifyingKeyData;\n private _lastProof?: SolanaProofData | ProofData;\n\n private constructor(provingSystem: IProvingSystem, chain?: Chain) {\n this.provingSystem = provingSystem;\n this.chain = chain;\n }\n\n /**\n * Get the verifying key from the last proof generation.\n * Only available after calling prove() with a chain configured.\n */\n get vk(): VerifyingKeyData | undefined {\n return this._verifyingKey;\n }\n\n /**\n * Get the configured chain, if any.\n */\n get targetChain(): Chain | undefined {\n return this.chain;\n }\n\n /**\n * Check if operating in offchain mode (no chain configured).\n */\n get isOffchain(): boolean {\n return this.chain === undefined;\n }\n\n /**\n * Register a chain formatter for chain-specific proof formatting.\n *\n * @param formatter - The chain formatter to register\n */\n registerChainFormatter<T extends ChainId>(formatter: IChainFormatter<T>): void {\n this.chainFormatters.set(formatter.chainId, formatter);\n }\n\n /**\n * Get a registered chain formatter.\n *\n * @param chainId - The chain ID to get the formatter for\n * @returns The formatter or undefined if not registered\n */\n getChainFormatter<T extends ChainId>(chainId: T): IChainFormatter<T> | undefined {\n return this.chainFormatters.get(chainId) as IChainFormatter<T> | undefined;\n }\n\n /**\n * Initialize IziNoir with the specified provider and optional chain.\n *\n * @param config - Configuration specifying the provider, chain, and optional circuit paths\n * @returns Initialized IziNoir instance\n *\n * @example\n * ```typescript\n * // On-chain mode (Solana)\n * const izi = await IziNoir.init({\n * provider: Provider.Arkworks,\n * chain: Chain.Solana\n * });\n *\n * // Offchain mode (no chain formatting)\n * const iziOffchain = await IziNoir.init({\n * provider: Provider.Arkworks\n * });\n *\n * // Barretenberg (browser-compatible, ~16KB proofs, offchain only)\n * const bb = await IziNoir.init({ provider: Provider.Barretenberg });\n * ```\n */\n static async init(config: IziNoirConfig): Promise<IziNoir> {\n // Initialize WASM (no-op if already initialized)\n await initNoirWasm();\n\n let provingSystem: IProvingSystem;\n\n switch (config.provider) {\n case Provider.Barretenberg: {\n if (config.chain) {\n throw new Error(\n 'Barretenberg provider does not support chain formatting. ' +\n 'Use Provider.Arkworks for on-chain proofs.'\n );\n }\n const { Barretenberg } = await import('./infra/provingSystems/Barretenberg.js');\n provingSystem = new Barretenberg();\n return new IziNoir(provingSystem);\n }\n case Provider.Arkworks: {\n const { ArkworksWasm } = await import('./infra/provingSystems/ArkworksWasm.js');\n const arkworksInstance = new ArkworksWasm();\n provingSystem = arkworksInstance;\n\n const instance = new IziNoir(provingSystem, config.chain);\n\n // Auto-register SolanaFormatter if chain is Solana or for backwards compatibility\n if (config.chain === Chain.Solana || !config.chain) {\n const { SolanaFormatter } = await import('./infra/chainFormatters/SolanaFormatter.js');\n instance.registerChainFormatter(new SolanaFormatter(arkworksInstance));\n }\n\n return instance;\n }\n case Provider.Sunspot: {\n throw new Error(\n 'Sunspot is not available in the main entry point. ' +\n 'Import from \"@izi-noir/sdk/sunspot\" for Sunspot support.'\n );\n }\n default:\n throw new Error(`Unknown provider: ${config.provider}`);\n }\n }\n\n /**\n * Get the underlying proving system instance.\n * Useful for advanced use cases.\n */\n getProvingSystem(): IProvingSystem {\n return this.provingSystem;\n }\n\n /**\n * Get the currently compiled circuit, if any.\n */\n getCompiledCircuit(): CompiledCircuit | null {\n return this.compiledCircuit;\n }\n\n /**\n * Compile Noir code into a circuit.\n *\n * @param noirCode - The Noir source code to compile\n * @returns The compiled circuit\n */\n async compile(noirCode: string): Promise<CompiledCircuit> {\n this.compiledCircuit = await this.provingSystem.compile(noirCode);\n return this.compiledCircuit;\n }\n\n /**\n * Generate a proof for the given inputs.\n *\n * If a chain is configured, returns chain-formatted proof data and stores\n * the verifying key in `this.vk`. Otherwise, returns raw proof data.\n *\n * @param inputs - The inputs (both public and private) for the circuit\n * @param circuit - Optional circuit to use (defaults to last compiled circuit)\n * @returns The proof data - type depends on configured chain\n * @throws Error if no circuit is available\n *\n * @example\n * ```typescript\n * // With chain configured - returns SolanaProofData\n * const izi = await IziNoir.init({ provider: Provider.Arkworks, chain: Chain.Solana });\n * await izi.compile(noirCode);\n * const proof = await izi.prove({ expected: '100', secret: '10' });\n * // proof is SolanaProofData, izi.vk is available\n *\n * // Offchain mode - returns ProofData\n * const iziOffchain = await IziNoir.init({ provider: Provider.Arkworks });\n * await iziOffchain.compile(noirCode);\n * const rawProof = await iziOffchain.prove({ expected: '100', secret: '10' });\n * // rawProof is ProofData, iziOffchain.vk is undefined\n * ```\n */\n async prove(inputs: InputMap, circuit?: CompiledCircuit): Promise<ProofData | SolanaProofData> {\n const circuitToUse = circuit || this.compiledCircuit;\n if (!circuitToUse) {\n throw new Error('No circuit available. Call compile() first or provide a circuit.');\n }\n\n // Generate raw proof\n const rawProof = await this.provingSystem.generateProof(circuitToUse, inputs);\n\n // If no chain configured, return raw proof (offchain mode)\n if (!this.chain) {\n this._lastProof = rawProof;\n return rawProof;\n }\n\n // Get formatter for the configured chain\n const formatter = this.chainFormatters.get(this.chain);\n if (!formatter) {\n throw new Error(\n `No formatter registered for chain: ${this.chain}. ` +\n 'This is an internal error - please report it.'\n );\n }\n\n // Build circuit metadata\n const metadata: CircuitMetadata = {\n numPublicInputs: rawProof.publicInputs.length,\n };\n\n // Format for target chain\n const formattedProof = await formatter.formatProof(rawProof, circuitToUse, metadata);\n const chainProof = formattedProof as unknown as SolanaProofData;\n\n // Store VK on instance\n this._verifyingKey = chainProof.verifyingKey;\n this._lastProof = chainProof;\n\n return chainProof;\n }\n\n /**\n * Verify a proof.\n * Available in both on-chain and offchain modes.\n *\n * @param proof - The proof bytes to verify\n * @param publicInputs - The public inputs that were used\n * @param circuit - Optional circuit to use (defaults to last compiled circuit)\n * @returns true if the proof is valid, false otherwise\n * @throws Error if no circuit is available\n */\n async verify(\n proof: Uint8Array,\n publicInputs: string[],\n circuit?: CompiledCircuit\n ): Promise<boolean> {\n const circuitToUse = circuit || this.compiledCircuit;\n if (!circuitToUse) {\n throw new Error('No circuit available. Call compile() first or provide a circuit.');\n }\n return this.provingSystem.verifyProof(circuitToUse, proof, publicInputs);\n }\n\n /**\n * Convenience method: compile, prove, and verify in one call.\n *\n * @param noirCode - The Noir source code to compile\n * @param inputs - The inputs (both public and private) for the circuit\n * @returns Object containing proof data and verification result\n *\n * @example\n * ```typescript\n * const { proof, verified } = await izi.createProof(noirCode, {\n * x: '100',\n * y: '10',\n * });\n * console.log(`Verified: ${verified}`);\n * ```\n */\n async createProof(\n noirCode: string,\n inputs: InputMap\n ): Promise<{ proof: ProofData | SolanaProofData; verified: boolean }> {\n const circuit = await this.compile(noirCode);\n const proof = await this.prove(inputs, circuit);\n\n // For verification, extract raw proof bytes\n const proofBytes =\n 'proof' in proof && proof.proof instanceof Uint8Array\n ? proof.proof\n : (proof as SolanaProofData).proof.bytes;\n const pubInputs = Array.isArray(proof.publicInputs)\n ? (proof.publicInputs as string[])\n : (proof as SolanaProofData).publicInputs.hex;\n\n const verified = await this.verify(proofBytes, pubInputs, circuit);\n return { proof, verified };\n }\n\n /**\n * Get deployment data for the verifying key.\n * Returns the data needed to deploy to the configured blockchain.\n * Use with SolanaTransactionBuilder to build and send the transaction.\n *\n * @param options - Optional configuration\n * @returns Deployment data that can be used with SolanaTransactionBuilder\n * @throws Error if no chain is configured (offchain mode)\n * @throws Error if prove() hasn't been called yet\n *\n * @example\n * ```typescript\n * const izi = await IziNoir.init({ provider: Provider.Arkworks, chain: Chain.Solana });\n * await izi.compile(noirCode);\n * await izi.prove(inputs);\n *\n * // Get deployment data\n * const deployData = izi.getDeployData();\n *\n * // Use with SolanaTransactionBuilder in your frontend\n * const builder = new SolanaTransactionBuilder({ programId: deployData.programId });\n * const { initVk, rentLamports, accountSize } = builder.buildInitAndVerifyInstructions(\n * deployData.proofData,\n * vkAccountPubkey,\n * authority,\n * payer\n * );\n * ```\n */\n getDeployData(options?: { programId?: string; computeUnits?: number }): SolanaDeployData {\n if (!this.chain) {\n throw new Error('Cannot deploy in offchain mode. Initialize with a chain parameter.');\n }\n\n if (!this._verifyingKey || !this._lastProof) {\n throw new Error('Must call prove() before getDeployData().');\n }\n\n if (this.chain !== Chain.Solana) {\n throw new Error(`Deployment for ${this.chain} is not yet supported.`);\n }\n\n return {\n proofData: this._lastProof as SolanaProofData,\n programId: options?.programId ?? 'EYhRED7EuMyyVjx57aDXUD9h6ArnEKng64qtz8999KrS',\n computeUnits: options?.computeUnits ?? 400_000,\n };\n }\n}\n\n// Re-export Provider, Chain and types for convenience\nexport { Provider, Chain, type IziNoirConfig, type CircuitPaths };\nexport type { SolanaProofData, VerifyingKeyData } from './domain/types.js';\nexport type {\n ChainId,\n CircuitMetadata,\n ChainMetadata,\n SolanaChainMetadata,\n EthereumChainMetadata,\n ChainMetadataFor,\n} from './domain/types/chain.js';\nexport type {\n IChainFormatter,\n ChainProofDataFor,\n} from './domain/interfaces/chain/IChainFormatter.js';\n"],"mappings":"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","names":["compile","createFileManager","Noir","stringToStream","isNodeJs","createTempDir","wasmInitPromise","Provider","isNodeJs","Barretenberg","ArkworksWasm","SolanaFormatter"]}
|
|
@@ -0,0 +1,262 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
|
|
20
|
+
// src/providers/solana.ts
|
|
21
|
+
var solana_exports = {};
|
|
22
|
+
__export(solana_exports, {
|
|
23
|
+
FIELD_SIZE: () => FIELD_SIZE,
|
|
24
|
+
G1_SIZE: () => G1_SIZE,
|
|
25
|
+
G2_SIZE: () => G2_SIZE,
|
|
26
|
+
IZI_NOIR_PROGRAM_ID: () => IZI_NOIR_PROGRAM_ID,
|
|
27
|
+
MAX_PUBLIC_INPUTS: () => MAX_PUBLIC_INPUTS,
|
|
28
|
+
PROOF_SIZE: () => PROOF_SIZE,
|
|
29
|
+
SolanaVerifier: () => SolanaVerifier,
|
|
30
|
+
buildInitVkFromBytesData: () => buildInitVkFromBytesData,
|
|
31
|
+
buildVerifyProofData: () => buildVerifyProofData,
|
|
32
|
+
bytesToBase64: () => bytesToBase64,
|
|
33
|
+
bytesToHex: () => bytesToHex,
|
|
34
|
+
calculateVkAccountRent: () => calculateVkAccountRent,
|
|
35
|
+
calculateVkAccountSize: () => calculateVkAccountSize,
|
|
36
|
+
parseProof: () => parseProof,
|
|
37
|
+
parsePublicInputs: () => parsePublicInputs,
|
|
38
|
+
parseVerifyingKey: () => parseVerifyingKey
|
|
39
|
+
});
|
|
40
|
+
module.exports = __toCommonJS(solana_exports);
|
|
41
|
+
var G1_SIZE = 64;
|
|
42
|
+
var G2_SIZE = 128;
|
|
43
|
+
var FIELD_SIZE = 32;
|
|
44
|
+
var PROOF_SIZE = 256;
|
|
45
|
+
var MAX_PUBLIC_INPUTS = 16;
|
|
46
|
+
var IZI_NOIR_PROGRAM_ID = "EYhRED7EuMyyVjx57aDXUD9h6ArnEKng64qtz8999KrS";
|
|
47
|
+
function parseVerifyingKey(vkBase64, nrPubinputs) {
|
|
48
|
+
const vkBytes = base64ToBytes(vkBase64);
|
|
49
|
+
const expectedLen = G1_SIZE + G2_SIZE * 3 + G1_SIZE * (nrPubinputs + 1);
|
|
50
|
+
if (vkBytes.length !== expectedLen) {
|
|
51
|
+
throw new Error(
|
|
52
|
+
`Invalid VK size: expected ${expectedLen} bytes for ${nrPubinputs} public inputs, got ${vkBytes.length}`
|
|
53
|
+
);
|
|
54
|
+
}
|
|
55
|
+
let offset = 0;
|
|
56
|
+
const alphaG1 = vkBytes.slice(offset, offset + G1_SIZE);
|
|
57
|
+
offset += G1_SIZE;
|
|
58
|
+
const betaG2 = vkBytes.slice(offset, offset + G2_SIZE);
|
|
59
|
+
offset += G2_SIZE;
|
|
60
|
+
const gammaG2 = vkBytes.slice(offset, offset + G2_SIZE);
|
|
61
|
+
offset += G2_SIZE;
|
|
62
|
+
const deltaG2 = vkBytes.slice(offset, offset + G2_SIZE);
|
|
63
|
+
offset += G2_SIZE;
|
|
64
|
+
const k = [];
|
|
65
|
+
for (let i = 0; i <= nrPubinputs; i++) {
|
|
66
|
+
k.push(vkBytes.slice(offset, offset + G1_SIZE));
|
|
67
|
+
offset += G1_SIZE;
|
|
68
|
+
}
|
|
69
|
+
return { alphaG1, betaG2, gammaG2, deltaG2, k };
|
|
70
|
+
}
|
|
71
|
+
function parseProof(proofBase64) {
|
|
72
|
+
const proofBytes = base64ToBytes(proofBase64);
|
|
73
|
+
if (proofBytes.length !== PROOF_SIZE) {
|
|
74
|
+
throw new Error(`Invalid proof size: expected ${PROOF_SIZE} bytes, got ${proofBytes.length}`);
|
|
75
|
+
}
|
|
76
|
+
return {
|
|
77
|
+
a: proofBytes.slice(0, G1_SIZE),
|
|
78
|
+
b: proofBytes.slice(G1_SIZE, G1_SIZE + G2_SIZE),
|
|
79
|
+
c: proofBytes.slice(G1_SIZE + G2_SIZE, PROOF_SIZE)
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
function parsePublicInputs(inputs) {
|
|
83
|
+
return inputs.map((input) => {
|
|
84
|
+
if (input.startsWith("0x")) {
|
|
85
|
+
const hex2 = input.slice(2).padStart(64, "0");
|
|
86
|
+
return hexToBytes(hex2);
|
|
87
|
+
}
|
|
88
|
+
const num = BigInt(input);
|
|
89
|
+
const hex = num.toString(16).padStart(64, "0");
|
|
90
|
+
return hexToBytes(hex);
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
function calculateVkAccountSize(nrPubinputs) {
|
|
94
|
+
const fixedSize = 8 + 32 + 1 + G1_SIZE + G2_SIZE * 3 + 4;
|
|
95
|
+
return fixedSize + (nrPubinputs + 1) * G1_SIZE;
|
|
96
|
+
}
|
|
97
|
+
function calculateVkAccountRent(nrPubinputs, rentExemptionPerByte = 6960) {
|
|
98
|
+
const size = calculateVkAccountSize(nrPubinputs);
|
|
99
|
+
return size * rentExemptionPerByte;
|
|
100
|
+
}
|
|
101
|
+
function base64ToBytes(base64) {
|
|
102
|
+
if (typeof atob === "function") {
|
|
103
|
+
const binary = atob(base64);
|
|
104
|
+
const bytes = new Uint8Array(binary.length);
|
|
105
|
+
for (let i = 0; i < binary.length; i++) {
|
|
106
|
+
bytes[i] = binary.charCodeAt(i);
|
|
107
|
+
}
|
|
108
|
+
return bytes;
|
|
109
|
+
}
|
|
110
|
+
return new Uint8Array(Buffer.from(base64, "base64"));
|
|
111
|
+
}
|
|
112
|
+
function bytesToBase64(bytes) {
|
|
113
|
+
if (typeof btoa === "function") {
|
|
114
|
+
let binary = "";
|
|
115
|
+
for (let i = 0; i < bytes.length; i++) {
|
|
116
|
+
binary += String.fromCharCode(bytes[i]);
|
|
117
|
+
}
|
|
118
|
+
return btoa(binary);
|
|
119
|
+
}
|
|
120
|
+
return Buffer.from(bytes).toString("base64");
|
|
121
|
+
}
|
|
122
|
+
function hexToBytes(hex) {
|
|
123
|
+
const cleanHex = hex.startsWith("0x") ? hex.slice(2) : hex;
|
|
124
|
+
const bytes = new Uint8Array(cleanHex.length / 2);
|
|
125
|
+
for (let i = 0; i < bytes.length; i++) {
|
|
126
|
+
bytes[i] = parseInt(cleanHex.substring(i * 2, i * 2 + 2), 16);
|
|
127
|
+
}
|
|
128
|
+
return bytes;
|
|
129
|
+
}
|
|
130
|
+
function bytesToHex(bytes) {
|
|
131
|
+
return Array.from(bytes).map((b) => b.toString(16).padStart(2, "0")).join("");
|
|
132
|
+
}
|
|
133
|
+
function buildInitVkFromBytesData(nrPubinputs, vkBytes) {
|
|
134
|
+
const discriminator = new Uint8Array([
|
|
135
|
+
166,
|
|
136
|
+
58,
|
|
137
|
+
82,
|
|
138
|
+
247,
|
|
139
|
+
19,
|
|
140
|
+
129,
|
|
141
|
+
138,
|
|
142
|
+
59
|
|
143
|
+
]);
|
|
144
|
+
const vkLen = new Uint8Array(4);
|
|
145
|
+
new DataView(vkLen.buffer).setUint32(0, vkBytes.length, true);
|
|
146
|
+
const data = new Uint8Array(discriminator.length + 1 + 4 + vkBytes.length);
|
|
147
|
+
let offset = 0;
|
|
148
|
+
data.set(discriminator, offset);
|
|
149
|
+
offset += discriminator.length;
|
|
150
|
+
data[offset] = nrPubinputs;
|
|
151
|
+
offset += 1;
|
|
152
|
+
data.set(vkLen, offset);
|
|
153
|
+
offset += 4;
|
|
154
|
+
data.set(vkBytes, offset);
|
|
155
|
+
return data;
|
|
156
|
+
}
|
|
157
|
+
function buildVerifyProofData(proofBytes, publicInputs) {
|
|
158
|
+
const discriminator = new Uint8Array([
|
|
159
|
+
30,
|
|
160
|
+
8,
|
|
161
|
+
242,
|
|
162
|
+
54,
|
|
163
|
+
68,
|
|
164
|
+
154,
|
|
165
|
+
75,
|
|
166
|
+
92
|
|
167
|
+
]);
|
|
168
|
+
if (proofBytes.length !== PROOF_SIZE) {
|
|
169
|
+
throw new Error(`Invalid proof size: expected ${PROOF_SIZE}, got ${proofBytes.length}`);
|
|
170
|
+
}
|
|
171
|
+
const proofVecLen = 4 + proofBytes.length;
|
|
172
|
+
const inputsVecLen = 4 + publicInputs.length * FIELD_SIZE;
|
|
173
|
+
const totalSize = discriminator.length + proofVecLen + inputsVecLen;
|
|
174
|
+
const data = new Uint8Array(totalSize);
|
|
175
|
+
let offset = 0;
|
|
176
|
+
data.set(discriminator, offset);
|
|
177
|
+
offset += discriminator.length;
|
|
178
|
+
new DataView(data.buffer).setUint32(offset, proofBytes.length, true);
|
|
179
|
+
offset += 4;
|
|
180
|
+
data.set(proofBytes, offset);
|
|
181
|
+
offset += proofBytes.length;
|
|
182
|
+
new DataView(data.buffer).setUint32(offset, publicInputs.length, true);
|
|
183
|
+
offset += 4;
|
|
184
|
+
for (const input of publicInputs) {
|
|
185
|
+
if (input.length !== FIELD_SIZE) {
|
|
186
|
+
throw new Error(`Invalid public input size: expected ${FIELD_SIZE}, got ${input.length}`);
|
|
187
|
+
}
|
|
188
|
+
data.set(input, offset);
|
|
189
|
+
offset += FIELD_SIZE;
|
|
190
|
+
}
|
|
191
|
+
return data;
|
|
192
|
+
}
|
|
193
|
+
var SolanaVerifier = class {
|
|
194
|
+
config;
|
|
195
|
+
constructor(config) {
|
|
196
|
+
this.config = config;
|
|
197
|
+
}
|
|
198
|
+
/**
|
|
199
|
+
* Initializes a VK account from base64-encoded verifying key.
|
|
200
|
+
*
|
|
201
|
+
* Note: This is a placeholder. Use the generated Anchor client for
|
|
202
|
+
* actual transaction building and submission.
|
|
203
|
+
*/
|
|
204
|
+
async initVkFromBase64(vkBase64, nrPubinputs) {
|
|
205
|
+
const vkBytes = base64ToBytes(vkBase64);
|
|
206
|
+
const expectedLen = G1_SIZE + G2_SIZE * 3 + G1_SIZE * (nrPubinputs + 1);
|
|
207
|
+
if (vkBytes.length !== expectedLen) {
|
|
208
|
+
throw new Error(
|
|
209
|
+
`Invalid VK size: expected ${expectedLen} bytes for ${nrPubinputs} public inputs, got ${vkBytes.length}`
|
|
210
|
+
);
|
|
211
|
+
}
|
|
212
|
+
throw new Error(
|
|
213
|
+
"SolanaVerifier.initVkFromBase64 requires @solana/web3.js and @coral-xyz/anchor. Use the generated Anchor client from solana-contracts package."
|
|
214
|
+
);
|
|
215
|
+
}
|
|
216
|
+
/**
|
|
217
|
+
* Verifies a proof on-chain.
|
|
218
|
+
*
|
|
219
|
+
* Note: This is a placeholder. Use the generated Anchor client for
|
|
220
|
+
* actual transaction building and submission.
|
|
221
|
+
*/
|
|
222
|
+
async verifyProof(vkAccount, proofBase64, publicInputs) {
|
|
223
|
+
const proofBytes = base64ToBytes(proofBase64);
|
|
224
|
+
if (proofBytes.length !== PROOF_SIZE) {
|
|
225
|
+
throw new Error(`Invalid proof size: expected ${PROOF_SIZE}, got ${proofBytes.length}`);
|
|
226
|
+
}
|
|
227
|
+
throw new Error(
|
|
228
|
+
"SolanaVerifier.verifyProof requires @solana/web3.js and @coral-xyz/anchor. Use the generated Anchor client from solana-contracts package."
|
|
229
|
+
);
|
|
230
|
+
}
|
|
231
|
+
/**
|
|
232
|
+
* Closes a VK account and reclaims rent.
|
|
233
|
+
*
|
|
234
|
+
* Note: This is a placeholder. Use the generated Anchor client for
|
|
235
|
+
* actual transaction building and submission.
|
|
236
|
+
*/
|
|
237
|
+
async closeVk(vkAccount) {
|
|
238
|
+
throw new Error(
|
|
239
|
+
"SolanaVerifier.closeVk requires @solana/web3.js and @coral-xyz/anchor. Use the generated Anchor client from solana-contracts package."
|
|
240
|
+
);
|
|
241
|
+
}
|
|
242
|
+
};
|
|
243
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
244
|
+
0 && (module.exports = {
|
|
245
|
+
FIELD_SIZE,
|
|
246
|
+
G1_SIZE,
|
|
247
|
+
G2_SIZE,
|
|
248
|
+
IZI_NOIR_PROGRAM_ID,
|
|
249
|
+
MAX_PUBLIC_INPUTS,
|
|
250
|
+
PROOF_SIZE,
|
|
251
|
+
SolanaVerifier,
|
|
252
|
+
buildInitVkFromBytesData,
|
|
253
|
+
buildVerifyProofData,
|
|
254
|
+
bytesToBase64,
|
|
255
|
+
bytesToHex,
|
|
256
|
+
calculateVkAccountRent,
|
|
257
|
+
calculateVkAccountSize,
|
|
258
|
+
parseProof,
|
|
259
|
+
parsePublicInputs,
|
|
260
|
+
parseVerifyingKey
|
|
261
|
+
});
|
|
262
|
+
//# sourceMappingURL=solana.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/providers/solana.ts"],"sourcesContent":["/**\n * Solana on-chain verification provider for IZI-NOIR.\n *\n * This module provides functionality to verify Groth16 proofs on-chain using\n * the IZI-NOIR Solana program. It's compatible with proofs generated by the\n * Arkworks provider.\n *\n * @example Basic usage\n * ```typescript\n * import { SolanaVerifier } from '@izi-noir/sdk/solana';\n * import { Connection, Keypair } from '@solana/web3.js';\n *\n * const connection = new Connection('https://api.devnet.solana.com');\n * const wallet = Keypair.generate(); // In practice, use a real wallet\n *\n * const verifier = new SolanaVerifier({\n * connection,\n * wallet,\n * programId: 'EYhRED7EuMyyVjx57aDXUD9h6ArnEKng64qtz8999KrS',\n * });\n *\n * // Initialize a VK account from base64-encoded VK\n * const vkAccount = await verifier.initVkFromBase64(vkGnarkBase64, nrPubinputs);\n *\n * // Verify a proof on-chain\n * const txSig = await verifier.verifyProof(\n * vkAccount,\n * proofGnarkBase64,\n * publicInputsHex\n * );\n * ```\n *\n * @module @izi-noir/sdk/solana\n */\n\n// Constants matching the Solana program\nexport const G1_SIZE = 64;\nexport const G2_SIZE = 128;\nexport const FIELD_SIZE = 32;\nexport const PROOF_SIZE = 256;\nexport const MAX_PUBLIC_INPUTS = 16;\n\n// Program ID - deployed on devnet\nexport const IZI_NOIR_PROGRAM_ID = 'EYhRED7EuMyyVjx57aDXUD9h6ArnEKng64qtz8999KrS';\n\n/**\n * Configuration for the SolanaVerifier.\n */\nexport interface SolanaVerifierConfig {\n /**\n * Solana RPC connection.\n * Must be compatible with @solana/web3.js Connection.\n */\n connection: unknown;\n\n /**\n * Wallet for signing transactions.\n * Can be a Keypair or any wallet adapter compatible signer.\n */\n wallet: unknown;\n\n /**\n * Program ID of the deployed IZI-NOIR verifier program.\n * Defaults to the placeholder ID.\n */\n programId?: string;\n}\n\n/**\n * Result from initializing a VK account.\n */\nexport interface InitVkResult {\n /** The public key of the created VK account */\n vkAccount: string;\n /** The transaction signature */\n txSignature: string;\n}\n\n/**\n * Result from verifying a proof on-chain.\n */\nexport interface VerifyResult {\n /** Whether the proof was verified successfully */\n success: boolean;\n /** The transaction signature */\n txSignature: string;\n /** Error message if verification failed */\n error?: string;\n}\n\n/**\n * Parses a base64-encoded verifying key into its components.\n *\n * The VK format from arkworks gnark_compat is:\n * | alpha_g1 (64) | beta_g2 (128) | gamma_g2 (128) | delta_g2 (128) | k[0..n+1] (64 each) |\n *\n * @param vkBase64 - Base64-encoded verifying key\n * @param nrPubinputs - Number of public inputs\n * @returns Parsed VK components\n */\nexport function parseVerifyingKey(vkBase64: string, nrPubinputs: number): {\n alphaG1: Uint8Array;\n betaG2: Uint8Array;\n gammaG2: Uint8Array;\n deltaG2: Uint8Array;\n k: Uint8Array[];\n} {\n const vkBytes = base64ToBytes(vkBase64);\n const expectedLen = G1_SIZE + G2_SIZE * 3 + G1_SIZE * (nrPubinputs + 1);\n\n if (vkBytes.length !== expectedLen) {\n throw new Error(\n `Invalid VK size: expected ${expectedLen} bytes for ${nrPubinputs} public inputs, got ${vkBytes.length}`\n );\n }\n\n let offset = 0;\n\n const alphaG1 = vkBytes.slice(offset, offset + G1_SIZE);\n offset += G1_SIZE;\n\n const betaG2 = vkBytes.slice(offset, offset + G2_SIZE);\n offset += G2_SIZE;\n\n const gammaG2 = vkBytes.slice(offset, offset + G2_SIZE);\n offset += G2_SIZE;\n\n const deltaG2 = vkBytes.slice(offset, offset + G2_SIZE);\n offset += G2_SIZE;\n\n const k: Uint8Array[] = [];\n for (let i = 0; i <= nrPubinputs; i++) {\n k.push(vkBytes.slice(offset, offset + G1_SIZE));\n offset += G1_SIZE;\n }\n\n return { alphaG1, betaG2, gammaG2, deltaG2, k };\n}\n\n/**\n * Parses a base64-encoded proof into its components.\n *\n * The proof format is: A (G1, 64) || B (G2, 128) || C (G1, 64) = 256 bytes\n *\n * @param proofBase64 - Base64-encoded proof\n * @returns Parsed proof components\n */\nexport function parseProof(proofBase64: string): {\n a: Uint8Array;\n b: Uint8Array;\n c: Uint8Array;\n} {\n const proofBytes = base64ToBytes(proofBase64);\n\n if (proofBytes.length !== PROOF_SIZE) {\n throw new Error(`Invalid proof size: expected ${PROOF_SIZE} bytes, got ${proofBytes.length}`);\n }\n\n return {\n a: proofBytes.slice(0, G1_SIZE),\n b: proofBytes.slice(G1_SIZE, G1_SIZE + G2_SIZE),\n c: proofBytes.slice(G1_SIZE + G2_SIZE, PROOF_SIZE),\n };\n}\n\n/**\n * Parses public inputs from hex or decimal string format to 32-byte arrays.\n *\n * @param inputs - Array of public inputs as hex (0x...) or decimal strings\n * @returns Array of 32-byte big-endian field elements\n */\nexport function parsePublicInputs(inputs: string[]): Uint8Array[] {\n return inputs.map((input) => {\n // Handle hex strings\n if (input.startsWith('0x')) {\n const hex = input.slice(2).padStart(64, '0');\n return hexToBytes(hex);\n }\n\n // Handle decimal strings - convert to big-endian bytes\n const num = BigInt(input);\n const hex = num.toString(16).padStart(64, '0');\n return hexToBytes(hex);\n });\n}\n\n/**\n * Calculates the size of a VK account for a given number of public inputs.\n *\n * This matches the Rust `vk_account_size` function.\n *\n * @param nrPubinputs - Number of public inputs\n * @returns Account size in bytes\n */\nexport function calculateVkAccountSize(nrPubinputs: number): number {\n // discriminator (8) + authority (32) + nr_pubinputs (1) + alpha_g1 (64) +\n // beta_g2 (128) + gamma_g2 (128) + delta_g2 (128) + vec_len (4) + k elements\n const fixedSize = 8 + 32 + 1 + G1_SIZE + G2_SIZE * 3 + 4;\n return fixedSize + (nrPubinputs + 1) * G1_SIZE;\n}\n\n/**\n * Calculates the minimum rent for a VK account.\n *\n * @param nrPubinputs - Number of public inputs\n * @param rentExemptionPerByte - Rent per byte (default Solana rate)\n * @returns Rent in lamports\n */\nexport function calculateVkAccountRent(\n nrPubinputs: number,\n rentExemptionPerByte: number = 6960 // approximate lamports per byte\n): number {\n const size = calculateVkAccountSize(nrPubinputs);\n return size * rentExemptionPerByte;\n}\n\n// ========== Helper Functions ==========\n\n/**\n * Converts a base64 string to a Uint8Array.\n */\nfunction base64ToBytes(base64: string): Uint8Array {\n // Browser-compatible base64 decoding\n if (typeof atob === 'function') {\n const binary = atob(base64);\n const bytes = new Uint8Array(binary.length);\n for (let i = 0; i < binary.length; i++) {\n bytes[i] = binary.charCodeAt(i);\n }\n return bytes;\n }\n // Node.js fallback\n return new Uint8Array(Buffer.from(base64, 'base64'));\n}\n\n/**\n * Converts a Uint8Array to a base64 string.\n */\nexport function bytesToBase64(bytes: Uint8Array): string {\n // Browser-compatible base64 encoding\n if (typeof btoa === 'function') {\n let binary = '';\n for (let i = 0; i < bytes.length; i++) {\n binary += String.fromCharCode(bytes[i]);\n }\n return btoa(binary);\n }\n // Node.js fallback\n return Buffer.from(bytes).toString('base64');\n}\n\n/**\n * Converts a hex string to Uint8Array.\n */\nfunction hexToBytes(hex: string): Uint8Array {\n const cleanHex = hex.startsWith('0x') ? hex.slice(2) : hex;\n const bytes = new Uint8Array(cleanHex.length / 2);\n for (let i = 0; i < bytes.length; i++) {\n bytes[i] = parseInt(cleanHex.substring(i * 2, i * 2 + 2), 16);\n }\n return bytes;\n}\n\n/**\n * Converts a Uint8Array to hex string.\n */\nexport function bytesToHex(bytes: Uint8Array): string {\n return Array.from(bytes)\n .map((b) => b.toString(16).padStart(2, '0'))\n .join('');\n}\n\n// ========== Instruction Data Builders ==========\n\n/**\n * Builds the instruction data for `init_vk_from_bytes`.\n *\n * Note: This is a simplified version. In practice, you'd use Anchor's IDL\n * and instruction builders from the generated types.\n *\n * @param nrPubinputs - Number of public inputs\n * @param vkBytes - Raw VK bytes\n * @returns Instruction data\n */\nexport function buildInitVkFromBytesData(nrPubinputs: number, vkBytes: Uint8Array): Uint8Array {\n // Anchor instruction discriminator for \"init_vk_from_bytes\"\n // This is sha256(\"global:init_vk_from_bytes\")[0..8]\n const discriminator = new Uint8Array([\n 0xa6, 0x3a, 0x52, 0xf7, 0x13, 0x81, 0x8a, 0x3b\n ]);\n\n // Build instruction data: discriminator + nr_pubinputs (u8) + vk_bytes (Vec<u8>)\n const vkLen = new Uint8Array(4);\n new DataView(vkLen.buffer).setUint32(0, vkBytes.length, true); // little-endian\n\n const data = new Uint8Array(discriminator.length + 1 + 4 + vkBytes.length);\n let offset = 0;\n\n data.set(discriminator, offset);\n offset += discriminator.length;\n\n data[offset] = nrPubinputs;\n offset += 1;\n\n data.set(vkLen, offset);\n offset += 4;\n\n data.set(vkBytes, offset);\n\n return data;\n}\n\n/**\n * Builds the instruction data for `verify_proof`.\n *\n * @param proofBytes - 256-byte proof\n * @param publicInputs - Array of 32-byte field elements\n * @returns Instruction data\n */\nexport function buildVerifyProofData(\n proofBytes: Uint8Array,\n publicInputs: Uint8Array[]\n): Uint8Array {\n // Anchor instruction discriminator for \"verify_proof\"\n // This is sha256(\"global:verify_proof\")[0..8]\n const discriminator = new Uint8Array([\n 0x1e, 0x08, 0xf2, 0x36, 0x44, 0x9a, 0x4b, 0x5c\n ]);\n\n // Validate proof size\n if (proofBytes.length !== PROOF_SIZE) {\n throw new Error(`Invalid proof size: expected ${PROOF_SIZE}, got ${proofBytes.length}`);\n }\n\n // Calculate total size\n const proofVecLen = 4 + proofBytes.length;\n const inputsVecLen = 4 + publicInputs.length * FIELD_SIZE;\n const totalSize = discriminator.length + proofVecLen + inputsVecLen;\n\n const data = new Uint8Array(totalSize);\n let offset = 0;\n\n // Discriminator\n data.set(discriminator, offset);\n offset += discriminator.length;\n\n // proof_bytes as Vec<u8>\n new DataView(data.buffer).setUint32(offset, proofBytes.length, true);\n offset += 4;\n data.set(proofBytes, offset);\n offset += proofBytes.length;\n\n // public_inputs as Vec<[u8; 32]>\n new DataView(data.buffer).setUint32(offset, publicInputs.length, true);\n offset += 4;\n for (const input of publicInputs) {\n if (input.length !== FIELD_SIZE) {\n throw new Error(`Invalid public input size: expected ${FIELD_SIZE}, got ${input.length}`);\n }\n data.set(input, offset);\n offset += FIELD_SIZE;\n }\n\n return data;\n}\n\n/**\n * Type definition for the Anchor IDL accounts structure.\n * This helps with type safety when building transactions.\n */\nexport interface IziNoirAccounts {\n initVk: {\n vkAccount: string;\n authority: string;\n payer: string;\n systemProgram: string;\n };\n verifyProof: {\n vkAccount: string;\n };\n closeVk: {\n vkAccount: string;\n authority: string;\n };\n}\n\n/**\n * Placeholder class for SolanaVerifier.\n *\n * This class provides the interface for on-chain verification but requires\n * @solana/web3.js and @coral-xyz/anchor to be installed as peer dependencies.\n *\n * For full functionality, install the required dependencies:\n * ```bash\n * npm install @solana/web3.js @coral-xyz/anchor\n * ```\n *\n * Then use the generated Anchor client from the solana-contracts package.\n */\nexport class SolanaVerifier {\n private config: SolanaVerifierConfig;\n\n constructor(config: SolanaVerifierConfig) {\n this.config = config;\n }\n\n /**\n * Initializes a VK account from base64-encoded verifying key.\n *\n * Note: This is a placeholder. Use the generated Anchor client for\n * actual transaction building and submission.\n */\n async initVkFromBase64(vkBase64: string, nrPubinputs: number): Promise<InitVkResult> {\n // Parse and validate VK\n const vkBytes = base64ToBytes(vkBase64);\n const expectedLen = G1_SIZE + G2_SIZE * 3 + G1_SIZE * (nrPubinputs + 1);\n\n if (vkBytes.length !== expectedLen) {\n throw new Error(\n `Invalid VK size: expected ${expectedLen} bytes for ${nrPubinputs} public inputs, got ${vkBytes.length}`\n );\n }\n\n // This is a placeholder - actual implementation would use Anchor client\n throw new Error(\n 'SolanaVerifier.initVkFromBase64 requires @solana/web3.js and @coral-xyz/anchor. ' +\n 'Use the generated Anchor client from solana-contracts package.'\n );\n }\n\n /**\n * Verifies a proof on-chain.\n *\n * Note: This is a placeholder. Use the generated Anchor client for\n * actual transaction building and submission.\n */\n async verifyProof(\n vkAccount: string,\n proofBase64: string,\n publicInputs: string[]\n ): Promise<VerifyResult> {\n // Parse and validate proof\n const proofBytes = base64ToBytes(proofBase64);\n if (proofBytes.length !== PROOF_SIZE) {\n throw new Error(`Invalid proof size: expected ${PROOF_SIZE}, got ${proofBytes.length}`);\n }\n\n // This is a placeholder - actual implementation would use Anchor client\n throw new Error(\n 'SolanaVerifier.verifyProof requires @solana/web3.js and @coral-xyz/anchor. ' +\n 'Use the generated Anchor client from solana-contracts package.'\n );\n }\n\n /**\n * Closes a VK account and reclaims rent.\n *\n * Note: This is a placeholder. Use the generated Anchor client for\n * actual transaction building and submission.\n */\n async closeVk(vkAccount: string): Promise<string> {\n throw new Error(\n 'SolanaVerifier.closeVk requires @solana/web3.js and @coral-xyz/anchor. ' +\n 'Use the generated Anchor client from solana-contracts package.'\n );\n }\n}\n\n// Re-export common types\nexport type { CompiledCircuit, InputMap, ProofData } from '../domain/types.js';\n"],"mappings":"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","names":["hex"]}
|
|
@@ -0,0 +1,223 @@
|
|
|
1
|
+
export { P as ProofData } from '../types-CaaigonG.cjs';
|
|
2
|
+
export { CompiledCircuit, InputMap } from '@noir-lang/types';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Solana on-chain verification provider for IZI-NOIR.
|
|
6
|
+
*
|
|
7
|
+
* This module provides functionality to verify Groth16 proofs on-chain using
|
|
8
|
+
* the IZI-NOIR Solana program. It's compatible with proofs generated by the
|
|
9
|
+
* Arkworks provider.
|
|
10
|
+
*
|
|
11
|
+
* @example Basic usage
|
|
12
|
+
* ```typescript
|
|
13
|
+
* import { SolanaVerifier } from '@izi-noir/sdk/solana';
|
|
14
|
+
* import { Connection, Keypair } from '@solana/web3.js';
|
|
15
|
+
*
|
|
16
|
+
* const connection = new Connection('https://api.devnet.solana.com');
|
|
17
|
+
* const wallet = Keypair.generate(); // In practice, use a real wallet
|
|
18
|
+
*
|
|
19
|
+
* const verifier = new SolanaVerifier({
|
|
20
|
+
* connection,
|
|
21
|
+
* wallet,
|
|
22
|
+
* programId: 'EYhRED7EuMyyVjx57aDXUD9h6ArnEKng64qtz8999KrS',
|
|
23
|
+
* });
|
|
24
|
+
*
|
|
25
|
+
* // Initialize a VK account from base64-encoded VK
|
|
26
|
+
* const vkAccount = await verifier.initVkFromBase64(vkGnarkBase64, nrPubinputs);
|
|
27
|
+
*
|
|
28
|
+
* // Verify a proof on-chain
|
|
29
|
+
* const txSig = await verifier.verifyProof(
|
|
30
|
+
* vkAccount,
|
|
31
|
+
* proofGnarkBase64,
|
|
32
|
+
* publicInputsHex
|
|
33
|
+
* );
|
|
34
|
+
* ```
|
|
35
|
+
*
|
|
36
|
+
* @module @izi-noir/sdk/solana
|
|
37
|
+
*/
|
|
38
|
+
declare const G1_SIZE = 64;
|
|
39
|
+
declare const G2_SIZE = 128;
|
|
40
|
+
declare const FIELD_SIZE = 32;
|
|
41
|
+
declare const PROOF_SIZE = 256;
|
|
42
|
+
declare const MAX_PUBLIC_INPUTS = 16;
|
|
43
|
+
declare const IZI_NOIR_PROGRAM_ID = "EYhRED7EuMyyVjx57aDXUD9h6ArnEKng64qtz8999KrS";
|
|
44
|
+
/**
|
|
45
|
+
* Configuration for the SolanaVerifier.
|
|
46
|
+
*/
|
|
47
|
+
interface SolanaVerifierConfig {
|
|
48
|
+
/**
|
|
49
|
+
* Solana RPC connection.
|
|
50
|
+
* Must be compatible with @solana/web3.js Connection.
|
|
51
|
+
*/
|
|
52
|
+
connection: unknown;
|
|
53
|
+
/**
|
|
54
|
+
* Wallet for signing transactions.
|
|
55
|
+
* Can be a Keypair or any wallet adapter compatible signer.
|
|
56
|
+
*/
|
|
57
|
+
wallet: unknown;
|
|
58
|
+
/**
|
|
59
|
+
* Program ID of the deployed IZI-NOIR verifier program.
|
|
60
|
+
* Defaults to the placeholder ID.
|
|
61
|
+
*/
|
|
62
|
+
programId?: string;
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Result from initializing a VK account.
|
|
66
|
+
*/
|
|
67
|
+
interface InitVkResult {
|
|
68
|
+
/** The public key of the created VK account */
|
|
69
|
+
vkAccount: string;
|
|
70
|
+
/** The transaction signature */
|
|
71
|
+
txSignature: string;
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Result from verifying a proof on-chain.
|
|
75
|
+
*/
|
|
76
|
+
interface VerifyResult {
|
|
77
|
+
/** Whether the proof was verified successfully */
|
|
78
|
+
success: boolean;
|
|
79
|
+
/** The transaction signature */
|
|
80
|
+
txSignature: string;
|
|
81
|
+
/** Error message if verification failed */
|
|
82
|
+
error?: string;
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Parses a base64-encoded verifying key into its components.
|
|
86
|
+
*
|
|
87
|
+
* The VK format from arkworks gnark_compat is:
|
|
88
|
+
* | alpha_g1 (64) | beta_g2 (128) | gamma_g2 (128) | delta_g2 (128) | k[0..n+1] (64 each) |
|
|
89
|
+
*
|
|
90
|
+
* @param vkBase64 - Base64-encoded verifying key
|
|
91
|
+
* @param nrPubinputs - Number of public inputs
|
|
92
|
+
* @returns Parsed VK components
|
|
93
|
+
*/
|
|
94
|
+
declare function parseVerifyingKey(vkBase64: string, nrPubinputs: number): {
|
|
95
|
+
alphaG1: Uint8Array;
|
|
96
|
+
betaG2: Uint8Array;
|
|
97
|
+
gammaG2: Uint8Array;
|
|
98
|
+
deltaG2: Uint8Array;
|
|
99
|
+
k: Uint8Array[];
|
|
100
|
+
};
|
|
101
|
+
/**
|
|
102
|
+
* Parses a base64-encoded proof into its components.
|
|
103
|
+
*
|
|
104
|
+
* The proof format is: A (G1, 64) || B (G2, 128) || C (G1, 64) = 256 bytes
|
|
105
|
+
*
|
|
106
|
+
* @param proofBase64 - Base64-encoded proof
|
|
107
|
+
* @returns Parsed proof components
|
|
108
|
+
*/
|
|
109
|
+
declare function parseProof(proofBase64: string): {
|
|
110
|
+
a: Uint8Array;
|
|
111
|
+
b: Uint8Array;
|
|
112
|
+
c: Uint8Array;
|
|
113
|
+
};
|
|
114
|
+
/**
|
|
115
|
+
* Parses public inputs from hex or decimal string format to 32-byte arrays.
|
|
116
|
+
*
|
|
117
|
+
* @param inputs - Array of public inputs as hex (0x...) or decimal strings
|
|
118
|
+
* @returns Array of 32-byte big-endian field elements
|
|
119
|
+
*/
|
|
120
|
+
declare function parsePublicInputs(inputs: string[]): Uint8Array[];
|
|
121
|
+
/**
|
|
122
|
+
* Calculates the size of a VK account for a given number of public inputs.
|
|
123
|
+
*
|
|
124
|
+
* This matches the Rust `vk_account_size` function.
|
|
125
|
+
*
|
|
126
|
+
* @param nrPubinputs - Number of public inputs
|
|
127
|
+
* @returns Account size in bytes
|
|
128
|
+
*/
|
|
129
|
+
declare function calculateVkAccountSize(nrPubinputs: number): number;
|
|
130
|
+
/**
|
|
131
|
+
* Calculates the minimum rent for a VK account.
|
|
132
|
+
*
|
|
133
|
+
* @param nrPubinputs - Number of public inputs
|
|
134
|
+
* @param rentExemptionPerByte - Rent per byte (default Solana rate)
|
|
135
|
+
* @returns Rent in lamports
|
|
136
|
+
*/
|
|
137
|
+
declare function calculateVkAccountRent(nrPubinputs: number, rentExemptionPerByte?: number): number;
|
|
138
|
+
/**
|
|
139
|
+
* Converts a Uint8Array to a base64 string.
|
|
140
|
+
*/
|
|
141
|
+
declare function bytesToBase64(bytes: Uint8Array): string;
|
|
142
|
+
/**
|
|
143
|
+
* Converts a Uint8Array to hex string.
|
|
144
|
+
*/
|
|
145
|
+
declare function bytesToHex(bytes: Uint8Array): string;
|
|
146
|
+
/**
|
|
147
|
+
* Builds the instruction data for `init_vk_from_bytes`.
|
|
148
|
+
*
|
|
149
|
+
* Note: This is a simplified version. In practice, you'd use Anchor's IDL
|
|
150
|
+
* and instruction builders from the generated types.
|
|
151
|
+
*
|
|
152
|
+
* @param nrPubinputs - Number of public inputs
|
|
153
|
+
* @param vkBytes - Raw VK bytes
|
|
154
|
+
* @returns Instruction data
|
|
155
|
+
*/
|
|
156
|
+
declare function buildInitVkFromBytesData(nrPubinputs: number, vkBytes: Uint8Array): Uint8Array;
|
|
157
|
+
/**
|
|
158
|
+
* Builds the instruction data for `verify_proof`.
|
|
159
|
+
*
|
|
160
|
+
* @param proofBytes - 256-byte proof
|
|
161
|
+
* @param publicInputs - Array of 32-byte field elements
|
|
162
|
+
* @returns Instruction data
|
|
163
|
+
*/
|
|
164
|
+
declare function buildVerifyProofData(proofBytes: Uint8Array, publicInputs: Uint8Array[]): Uint8Array;
|
|
165
|
+
/**
|
|
166
|
+
* Type definition for the Anchor IDL accounts structure.
|
|
167
|
+
* This helps with type safety when building transactions.
|
|
168
|
+
*/
|
|
169
|
+
interface IziNoirAccounts {
|
|
170
|
+
initVk: {
|
|
171
|
+
vkAccount: string;
|
|
172
|
+
authority: string;
|
|
173
|
+
payer: string;
|
|
174
|
+
systemProgram: string;
|
|
175
|
+
};
|
|
176
|
+
verifyProof: {
|
|
177
|
+
vkAccount: string;
|
|
178
|
+
};
|
|
179
|
+
closeVk: {
|
|
180
|
+
vkAccount: string;
|
|
181
|
+
authority: string;
|
|
182
|
+
};
|
|
183
|
+
}
|
|
184
|
+
/**
|
|
185
|
+
* Placeholder class for SolanaVerifier.
|
|
186
|
+
*
|
|
187
|
+
* This class provides the interface for on-chain verification but requires
|
|
188
|
+
* @solana/web3.js and @coral-xyz/anchor to be installed as peer dependencies.
|
|
189
|
+
*
|
|
190
|
+
* For full functionality, install the required dependencies:
|
|
191
|
+
* ```bash
|
|
192
|
+
* npm install @solana/web3.js @coral-xyz/anchor
|
|
193
|
+
* ```
|
|
194
|
+
*
|
|
195
|
+
* Then use the generated Anchor client from the solana-contracts package.
|
|
196
|
+
*/
|
|
197
|
+
declare class SolanaVerifier {
|
|
198
|
+
private config;
|
|
199
|
+
constructor(config: SolanaVerifierConfig);
|
|
200
|
+
/**
|
|
201
|
+
* Initializes a VK account from base64-encoded verifying key.
|
|
202
|
+
*
|
|
203
|
+
* Note: This is a placeholder. Use the generated Anchor client for
|
|
204
|
+
* actual transaction building and submission.
|
|
205
|
+
*/
|
|
206
|
+
initVkFromBase64(vkBase64: string, nrPubinputs: number): Promise<InitVkResult>;
|
|
207
|
+
/**
|
|
208
|
+
* Verifies a proof on-chain.
|
|
209
|
+
*
|
|
210
|
+
* Note: This is a placeholder. Use the generated Anchor client for
|
|
211
|
+
* actual transaction building and submission.
|
|
212
|
+
*/
|
|
213
|
+
verifyProof(vkAccount: string, proofBase64: string, publicInputs: string[]): Promise<VerifyResult>;
|
|
214
|
+
/**
|
|
215
|
+
* Closes a VK account and reclaims rent.
|
|
216
|
+
*
|
|
217
|
+
* Note: This is a placeholder. Use the generated Anchor client for
|
|
218
|
+
* actual transaction building and submission.
|
|
219
|
+
*/
|
|
220
|
+
closeVk(vkAccount: string): Promise<string>;
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
export { FIELD_SIZE, G1_SIZE, G2_SIZE, IZI_NOIR_PROGRAM_ID, type InitVkResult, type IziNoirAccounts, MAX_PUBLIC_INPUTS, PROOF_SIZE, SolanaVerifier, type SolanaVerifierConfig, type VerifyResult, buildInitVkFromBytesData, buildVerifyProofData, bytesToBase64, bytesToHex, calculateVkAccountRent, calculateVkAccountSize, parseProof, parsePublicInputs, parseVerifyingKey };
|