@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,223 @@
|
|
|
1
|
+
export { P as ProofData } from '../types-CaaigonG.js';
|
|
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 };
|
|
@@ -0,0 +1,222 @@
|
|
|
1
|
+
// src/providers/solana.ts
|
|
2
|
+
var G1_SIZE = 64;
|
|
3
|
+
var G2_SIZE = 128;
|
|
4
|
+
var FIELD_SIZE = 32;
|
|
5
|
+
var PROOF_SIZE = 256;
|
|
6
|
+
var MAX_PUBLIC_INPUTS = 16;
|
|
7
|
+
var IZI_NOIR_PROGRAM_ID = "EYhRED7EuMyyVjx57aDXUD9h6ArnEKng64qtz8999KrS";
|
|
8
|
+
function parseVerifyingKey(vkBase64, nrPubinputs) {
|
|
9
|
+
const vkBytes = base64ToBytes(vkBase64);
|
|
10
|
+
const expectedLen = G1_SIZE + G2_SIZE * 3 + G1_SIZE * (nrPubinputs + 1);
|
|
11
|
+
if (vkBytes.length !== expectedLen) {
|
|
12
|
+
throw new Error(
|
|
13
|
+
`Invalid VK size: expected ${expectedLen} bytes for ${nrPubinputs} public inputs, got ${vkBytes.length}`
|
|
14
|
+
);
|
|
15
|
+
}
|
|
16
|
+
let offset = 0;
|
|
17
|
+
const alphaG1 = vkBytes.slice(offset, offset + G1_SIZE);
|
|
18
|
+
offset += G1_SIZE;
|
|
19
|
+
const betaG2 = vkBytes.slice(offset, offset + G2_SIZE);
|
|
20
|
+
offset += G2_SIZE;
|
|
21
|
+
const gammaG2 = vkBytes.slice(offset, offset + G2_SIZE);
|
|
22
|
+
offset += G2_SIZE;
|
|
23
|
+
const deltaG2 = vkBytes.slice(offset, offset + G2_SIZE);
|
|
24
|
+
offset += G2_SIZE;
|
|
25
|
+
const k = [];
|
|
26
|
+
for (let i = 0; i <= nrPubinputs; i++) {
|
|
27
|
+
k.push(vkBytes.slice(offset, offset + G1_SIZE));
|
|
28
|
+
offset += G1_SIZE;
|
|
29
|
+
}
|
|
30
|
+
return { alphaG1, betaG2, gammaG2, deltaG2, k };
|
|
31
|
+
}
|
|
32
|
+
function parseProof(proofBase64) {
|
|
33
|
+
const proofBytes = base64ToBytes(proofBase64);
|
|
34
|
+
if (proofBytes.length !== PROOF_SIZE) {
|
|
35
|
+
throw new Error(`Invalid proof size: expected ${PROOF_SIZE} bytes, got ${proofBytes.length}`);
|
|
36
|
+
}
|
|
37
|
+
return {
|
|
38
|
+
a: proofBytes.slice(0, G1_SIZE),
|
|
39
|
+
b: proofBytes.slice(G1_SIZE, G1_SIZE + G2_SIZE),
|
|
40
|
+
c: proofBytes.slice(G1_SIZE + G2_SIZE, PROOF_SIZE)
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
function parsePublicInputs(inputs) {
|
|
44
|
+
return inputs.map((input) => {
|
|
45
|
+
if (input.startsWith("0x")) {
|
|
46
|
+
const hex2 = input.slice(2).padStart(64, "0");
|
|
47
|
+
return hexToBytes(hex2);
|
|
48
|
+
}
|
|
49
|
+
const num = BigInt(input);
|
|
50
|
+
const hex = num.toString(16).padStart(64, "0");
|
|
51
|
+
return hexToBytes(hex);
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
function calculateVkAccountSize(nrPubinputs) {
|
|
55
|
+
const fixedSize = 8 + 32 + 1 + G1_SIZE + G2_SIZE * 3 + 4;
|
|
56
|
+
return fixedSize + (nrPubinputs + 1) * G1_SIZE;
|
|
57
|
+
}
|
|
58
|
+
function calculateVkAccountRent(nrPubinputs, rentExemptionPerByte = 6960) {
|
|
59
|
+
const size = calculateVkAccountSize(nrPubinputs);
|
|
60
|
+
return size * rentExemptionPerByte;
|
|
61
|
+
}
|
|
62
|
+
function base64ToBytes(base64) {
|
|
63
|
+
if (typeof atob === "function") {
|
|
64
|
+
const binary = atob(base64);
|
|
65
|
+
const bytes = new Uint8Array(binary.length);
|
|
66
|
+
for (let i = 0; i < binary.length; i++) {
|
|
67
|
+
bytes[i] = binary.charCodeAt(i);
|
|
68
|
+
}
|
|
69
|
+
return bytes;
|
|
70
|
+
}
|
|
71
|
+
return new Uint8Array(Buffer.from(base64, "base64"));
|
|
72
|
+
}
|
|
73
|
+
function bytesToBase64(bytes) {
|
|
74
|
+
if (typeof btoa === "function") {
|
|
75
|
+
let binary = "";
|
|
76
|
+
for (let i = 0; i < bytes.length; i++) {
|
|
77
|
+
binary += String.fromCharCode(bytes[i]);
|
|
78
|
+
}
|
|
79
|
+
return btoa(binary);
|
|
80
|
+
}
|
|
81
|
+
return Buffer.from(bytes).toString("base64");
|
|
82
|
+
}
|
|
83
|
+
function hexToBytes(hex) {
|
|
84
|
+
const cleanHex = hex.startsWith("0x") ? hex.slice(2) : hex;
|
|
85
|
+
const bytes = new Uint8Array(cleanHex.length / 2);
|
|
86
|
+
for (let i = 0; i < bytes.length; i++) {
|
|
87
|
+
bytes[i] = parseInt(cleanHex.substring(i * 2, i * 2 + 2), 16);
|
|
88
|
+
}
|
|
89
|
+
return bytes;
|
|
90
|
+
}
|
|
91
|
+
function bytesToHex(bytes) {
|
|
92
|
+
return Array.from(bytes).map((b) => b.toString(16).padStart(2, "0")).join("");
|
|
93
|
+
}
|
|
94
|
+
function buildInitVkFromBytesData(nrPubinputs, vkBytes) {
|
|
95
|
+
const discriminator = new Uint8Array([
|
|
96
|
+
166,
|
|
97
|
+
58,
|
|
98
|
+
82,
|
|
99
|
+
247,
|
|
100
|
+
19,
|
|
101
|
+
129,
|
|
102
|
+
138,
|
|
103
|
+
59
|
|
104
|
+
]);
|
|
105
|
+
const vkLen = new Uint8Array(4);
|
|
106
|
+
new DataView(vkLen.buffer).setUint32(0, vkBytes.length, true);
|
|
107
|
+
const data = new Uint8Array(discriminator.length + 1 + 4 + vkBytes.length);
|
|
108
|
+
let offset = 0;
|
|
109
|
+
data.set(discriminator, offset);
|
|
110
|
+
offset += discriminator.length;
|
|
111
|
+
data[offset] = nrPubinputs;
|
|
112
|
+
offset += 1;
|
|
113
|
+
data.set(vkLen, offset);
|
|
114
|
+
offset += 4;
|
|
115
|
+
data.set(vkBytes, offset);
|
|
116
|
+
return data;
|
|
117
|
+
}
|
|
118
|
+
function buildVerifyProofData(proofBytes, publicInputs) {
|
|
119
|
+
const discriminator = new Uint8Array([
|
|
120
|
+
30,
|
|
121
|
+
8,
|
|
122
|
+
242,
|
|
123
|
+
54,
|
|
124
|
+
68,
|
|
125
|
+
154,
|
|
126
|
+
75,
|
|
127
|
+
92
|
|
128
|
+
]);
|
|
129
|
+
if (proofBytes.length !== PROOF_SIZE) {
|
|
130
|
+
throw new Error(`Invalid proof size: expected ${PROOF_SIZE}, got ${proofBytes.length}`);
|
|
131
|
+
}
|
|
132
|
+
const proofVecLen = 4 + proofBytes.length;
|
|
133
|
+
const inputsVecLen = 4 + publicInputs.length * FIELD_SIZE;
|
|
134
|
+
const totalSize = discriminator.length + proofVecLen + inputsVecLen;
|
|
135
|
+
const data = new Uint8Array(totalSize);
|
|
136
|
+
let offset = 0;
|
|
137
|
+
data.set(discriminator, offset);
|
|
138
|
+
offset += discriminator.length;
|
|
139
|
+
new DataView(data.buffer).setUint32(offset, proofBytes.length, true);
|
|
140
|
+
offset += 4;
|
|
141
|
+
data.set(proofBytes, offset);
|
|
142
|
+
offset += proofBytes.length;
|
|
143
|
+
new DataView(data.buffer).setUint32(offset, publicInputs.length, true);
|
|
144
|
+
offset += 4;
|
|
145
|
+
for (const input of publicInputs) {
|
|
146
|
+
if (input.length !== FIELD_SIZE) {
|
|
147
|
+
throw new Error(`Invalid public input size: expected ${FIELD_SIZE}, got ${input.length}`);
|
|
148
|
+
}
|
|
149
|
+
data.set(input, offset);
|
|
150
|
+
offset += FIELD_SIZE;
|
|
151
|
+
}
|
|
152
|
+
return data;
|
|
153
|
+
}
|
|
154
|
+
var SolanaVerifier = class {
|
|
155
|
+
config;
|
|
156
|
+
constructor(config) {
|
|
157
|
+
this.config = config;
|
|
158
|
+
}
|
|
159
|
+
/**
|
|
160
|
+
* Initializes a VK account from base64-encoded verifying key.
|
|
161
|
+
*
|
|
162
|
+
* Note: This is a placeholder. Use the generated Anchor client for
|
|
163
|
+
* actual transaction building and submission.
|
|
164
|
+
*/
|
|
165
|
+
async initVkFromBase64(vkBase64, nrPubinputs) {
|
|
166
|
+
const vkBytes = base64ToBytes(vkBase64);
|
|
167
|
+
const expectedLen = G1_SIZE + G2_SIZE * 3 + G1_SIZE * (nrPubinputs + 1);
|
|
168
|
+
if (vkBytes.length !== expectedLen) {
|
|
169
|
+
throw new Error(
|
|
170
|
+
`Invalid VK size: expected ${expectedLen} bytes for ${nrPubinputs} public inputs, got ${vkBytes.length}`
|
|
171
|
+
);
|
|
172
|
+
}
|
|
173
|
+
throw new Error(
|
|
174
|
+
"SolanaVerifier.initVkFromBase64 requires @solana/web3.js and @coral-xyz/anchor. Use the generated Anchor client from solana-contracts package."
|
|
175
|
+
);
|
|
176
|
+
}
|
|
177
|
+
/**
|
|
178
|
+
* Verifies a proof on-chain.
|
|
179
|
+
*
|
|
180
|
+
* Note: This is a placeholder. Use the generated Anchor client for
|
|
181
|
+
* actual transaction building and submission.
|
|
182
|
+
*/
|
|
183
|
+
async verifyProof(vkAccount, proofBase64, publicInputs) {
|
|
184
|
+
const proofBytes = base64ToBytes(proofBase64);
|
|
185
|
+
if (proofBytes.length !== PROOF_SIZE) {
|
|
186
|
+
throw new Error(`Invalid proof size: expected ${PROOF_SIZE}, got ${proofBytes.length}`);
|
|
187
|
+
}
|
|
188
|
+
throw new Error(
|
|
189
|
+
"SolanaVerifier.verifyProof requires @solana/web3.js and @coral-xyz/anchor. Use the generated Anchor client from solana-contracts package."
|
|
190
|
+
);
|
|
191
|
+
}
|
|
192
|
+
/**
|
|
193
|
+
* Closes a VK account and reclaims rent.
|
|
194
|
+
*
|
|
195
|
+
* Note: This is a placeholder. Use the generated Anchor client for
|
|
196
|
+
* actual transaction building and submission.
|
|
197
|
+
*/
|
|
198
|
+
async closeVk(vkAccount) {
|
|
199
|
+
throw new Error(
|
|
200
|
+
"SolanaVerifier.closeVk requires @solana/web3.js and @coral-xyz/anchor. Use the generated Anchor client from solana-contracts package."
|
|
201
|
+
);
|
|
202
|
+
}
|
|
203
|
+
};
|
|
204
|
+
export {
|
|
205
|
+
FIELD_SIZE,
|
|
206
|
+
G1_SIZE,
|
|
207
|
+
G2_SIZE,
|
|
208
|
+
IZI_NOIR_PROGRAM_ID,
|
|
209
|
+
MAX_PUBLIC_INPUTS,
|
|
210
|
+
PROOF_SIZE,
|
|
211
|
+
SolanaVerifier,
|
|
212
|
+
buildInitVkFromBytesData,
|
|
213
|
+
buildVerifyProofData,
|
|
214
|
+
bytesToBase64,
|
|
215
|
+
bytesToHex,
|
|
216
|
+
calculateVkAccountRent,
|
|
217
|
+
calculateVkAccountSize,
|
|
218
|
+
parseProof,
|
|
219
|
+
parsePublicInputs,
|
|
220
|
+
parseVerifyingKey
|
|
221
|
+
};
|
|
222
|
+
//# sourceMappingURL=solana.js.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"]}
|