UNPKG

@ghostspeak/sdk

Version:

TypeScript SDK for GhostSpeak AI Agent Commerce Protocol - Production Ready Beta

655 lines (652 loc) 23.5 kB
import { __export } from './chunk-UP2VWCW5.js'; import { ed25519 } from '@noble/curves/ed25519'; import { sha256 } from '@noble/hashes/sha256'; import { randomBytes, bytesToNumberLE, numberToBytesBE } from '@noble/curves/abstract/utils'; // src/crypto/elgamal.ts var elgamal_exports = {}; __export(elgamal_exports, { PROOF_SIZES: () => PROOF_SIZES, addCiphertexts: () => addCiphertexts, decrypt: () => decrypt, default: () => elgamal_default, deriveKeypair: () => deriveKeypair, elGamalPubkeyToAddress: () => elGamalPubkeyToAddress, encrypt: () => encrypt, generateEqualityProof: () => generateEqualityProof, generateKeypair: () => generateKeypair, generateRangeProof: () => generateRangeProof, generateTransferProof: () => generateTransferProof, generateValidityProof: () => generateValidityProof, generateWithdrawProof: () => generateWithdrawProof, loadWasmModule: () => loadWasmModule, subtractCiphertexts: () => subtractCiphertexts }); var G = ed25519.ExtendedPoint.BASE; function createHGenerator() { const encoder = typeof TextEncoder !== "undefined" ? new TextEncoder() : { encode: (str) => new Uint8Array(Buffer.from(str, "utf8")) }; const domainSeparator = encoder.encode("GHOSTSPEAK_ELGAMAL_H_GENERATOR"); const input = new Uint8Array([...domainSeparator, ...G.toRawBytes()]); const hash = sha256(input); return ed25519.ExtendedPoint.fromHex(Array.from(hash, (b) => b.toString(16).padStart(2, "0")).join("")); } var H = createHGenerator(); var PROOF_SIZES = { RANGE_PROOF: 674, VALIDITY_PROOF: 160, EQUALITY_PROOF: 192, WITHDRAW_PROOF: 80, ZERO_BALANCE_PROOF: 96, FEE_SIGMA_PROOF: 256, PUBKEY_VALIDITY_PROOF: 64 }; function generateKeypair() { let secretKey; let publicKey; const MAX_ITERATIONS = 1e3; let iterations = 0; let validKeypairGenerated = false; while (!validKeypairGenerated && iterations < MAX_ITERATIONS) { iterations++; secretKey = randomBytes(32); const scalar = bytesToNumberLE(secretKey) % ed25519.CURVE.n; if (scalar === 0n || scalar >= ed25519.CURVE.n) { continue; } const pubkeyPoint = scalarMultiply(G, secretKey); if (pubkeyPoint.equals(ed25519.ExtendedPoint.ZERO)) { continue; } publicKey = pubkeyPoint.toRawBytes(); validKeypairGenerated = true; } if (!validKeypairGenerated) { throw new Error("Failed to generate valid ElGamal keypair after maximum iterations"); } return { publicKey, secretKey }; } function deriveKeypair(seed) { if (seed.length !== 32) { throw new Error("Seed must be 32 bytes"); } const encoder = typeof TextEncoder !== "undefined" ? new TextEncoder() : { encode: (str) => new Uint8Array(Buffer.from(str, "utf8")) }; const salt = encoder.encode("GHOSTSPEAK_ELGAMAL_KEY_DERIVATION"); const secretKey = sha256(new Uint8Array([...salt, ...seed])); const scalar = bytesToNumberLE(secretKey) % ed25519.CURVE.n; if (scalar === 0n || scalar >= ed25519.CURVE.n) { throw new Error("Invalid seed produces out-of-range secret key"); } const pubkeyPoint = scalarMultiply(G, secretKey); if (pubkeyPoint.equals(ed25519.ExtendedPoint.ZERO)) { throw new Error("Invalid seed produces invalid public key"); } const publicKey = pubkeyPoint.toRawBytes(); return { publicKey, secretKey }; } function encrypt(publicKey, value) { if (value < BigInt(0) || value >= BigInt(2) ** BigInt(64)) { throw new Error("Value must be between 0 and 2^64 - 1"); } const randomness = randomBytes(32); const pubkeyPoint = pointFromBytes(publicKey); const valueScalar = numberToBytesBE(value, 32); const commitment = scalarMultiply(H, valueScalar).add(scalarMultiply(G, randomness)); const handle = scalarMultiply(pubkeyPoint, randomness); return { ciphertext: { commitment: { commitment: commitment.toRawBytes() }, handle: { handle: handle.toRawBytes() } }, randomness }; } function decrypt(secretKey, ciphertext, maxValue = 1e6) { const C = pointFromBytes(ciphertext.commitment.commitment); const D = pointFromBytes(ciphertext.handle.handle); const vH = C.subtract(scalarMultiply(D, secretKey)); for (let v = BigInt(0); v <= BigInt(maxValue); v++) { const testPoint = scalarMultiply(H, numberToBytesBE(v, 32)); if (vH.equals(testPoint)) { return v; } } return null; } function addCiphertexts(ct1, ct2) { if (ct1.commitment.commitment.length !== 32 || ct2.commitment.commitment.length !== 32) { throw new Error("Invalid commitment size"); } if (ct1.handle.handle.length !== 32 || ct2.handle.handle.length !== 32) { throw new Error("Invalid handle size"); } try { const C1 = pointFromBytes(ct1.commitment.commitment); const C2 = pointFromBytes(ct2.commitment.commitment); const D1 = pointFromBytes(ct1.handle.handle); const D2 = pointFromBytes(ct2.handle.handle); const resultCommitment = C1.add(C2); const resultHandle = D1.add(D2); return { commitment: { commitment: resultCommitment.toRawBytes() }, handle: { handle: resultHandle.toRawBytes() } }; } catch (error) { throw new Error(`Ciphertext addition failed: ${error instanceof Error ? error.message : "Unknown error"}`); } } function subtractCiphertexts(ct1, ct2) { if (ct1.commitment.commitment.length !== 32 || ct2.commitment.commitment.length !== 32) { throw new Error("Invalid commitment size"); } if (ct1.handle.handle.length !== 32 || ct2.handle.handle.length !== 32) { throw new Error("Invalid handle size"); } try { const C1 = pointFromBytes(ct1.commitment.commitment); const C2 = pointFromBytes(ct2.commitment.commitment); const D1 = pointFromBytes(ct1.handle.handle); const D2 = pointFromBytes(ct2.handle.handle); const resultCommitment = C1.subtract(C2); const resultHandle = D1.subtract(D2); return { commitment: { commitment: resultCommitment.toRawBytes() }, handle: { handle: resultHandle.toRawBytes() } }; } catch (error) { throw new Error(`Ciphertext subtraction failed: ${error instanceof Error ? error.message : "Unknown error"}`); } } async function generateRangeProof(value, commitment, randomness) { if (value < 0n || value >= 2n ** 64n) { throw new Error("Value must be in range [0, 2^64)"); } if (commitment.commitment.length !== 32) { throw new Error("Commitment must be 32 bytes"); } if (randomness.length !== 32) { throw new Error("Randomness must be 32 bytes"); } if (typeof window !== "undefined" && window.ghostspeak_wasm) { const wasm = window.ghostspeak_wasm; if (!wasm || typeof wasm.generate_range_proof !== "function") { throw new Error("WASM module not properly loaded"); } try { const proof2 = await wasm.generate_range_proof( value.toString(), commitment.commitment, randomness ); if (!proof2 || !proof2.proof || !proof2.commitment) { throw new Error("Invalid WASM response"); } const proofBytes = new Uint8Array(proof2.proof); if (proofBytes.length !== PROOF_SIZES.RANGE_PROOF) { throw new Error(`Invalid proof size: expected ${PROOF_SIZES.RANGE_PROOF}, got ${proofBytes.length}`); } return { proof: proofBytes, commitment: new Uint8Array(proof2.commitment) }; } catch (error) { throw new Error(`WASM range proof generation failed: ${error instanceof Error ? error.message : "Unknown error"}`); } } const proof = await generateBulletproofRangeProof( value, commitment, randomness, PROOF_SIZES.RANGE_PROOF ); return { proof, commitment: commitment.commitment }; } async function generateValidityProof(publicKey, ciphertext, randomness) { if (publicKey.length !== 32) { throw new Error("Public key must be 32 bytes"); } if (ciphertext.commitment.commitment.length !== 32) { throw new Error("Commitment must be 32 bytes"); } if (ciphertext.handle.handle.length !== 32) { throw new Error("Handle must be 32 bytes"); } if (randomness.length !== 32) { throw new Error("Randomness must be 32 bytes"); } if (typeof window !== "undefined" && window.ghostspeak_wasm) { const wasm = window.ghostspeak_wasm; if (wasm && typeof wasm.generate_validity_proof === "function") { try { const proofResult = await wasm.generate_validity_proof( publicKey, ciphertext.commitment.commitment, ciphertext.handle.handle, randomness ); if (!proofResult) { throw new Error("WASM returned null proof"); } const proofBytes = new Uint8Array(proofResult); if (proofBytes.length !== PROOF_SIZES.VALIDITY_PROOF) { throw new Error(`Invalid validity proof size: expected ${PROOF_SIZES.VALIDITY_PROOF}, got ${proofBytes.length}`); } return { proof: proofBytes }; } catch (error) { throw new Error(`WASM validity proof generation failed: ${error instanceof Error ? error.message : "Unknown error"}`); } } } const proof = await generateSchnorrValidityProof( publicKey, ciphertext, randomness, PROOF_SIZES.VALIDITY_PROOF ); return { proof }; } async function generateEqualityProof(sourceCiphertext, destCiphertext, transferAmount, sourceRandomness, destRandomness) { if (transferAmount < 0n || transferAmount >= 2n ** 64n) { throw new Error("Transfer amount must be in range [0, 2^64)"); } if (sourceCiphertext.commitment.commitment.length !== 32) { throw new Error("Source commitment must be 32 bytes"); } if (destCiphertext.commitment.commitment.length !== 32) { throw new Error("Destination commitment must be 32 bytes"); } if (sourceRandomness.length !== 32 || destRandomness.length !== 32) { throw new Error("Randomness values must be 32 bytes"); } if (typeof window !== "undefined" && window.ghostspeak_wasm) { const wasm = window.ghostspeak_wasm; if (wasm && typeof wasm.generate_equality_proof === "function") { try { const proofResult = await wasm.generate_equality_proof( sourceCiphertext.commitment.commitment, destCiphertext.commitment.commitment, transferAmount.toString(), sourceRandomness, destRandomness ); if (!proofResult) { throw new Error("WASM returned null proof"); } const proofBytes = new Uint8Array(proofResult); if (proofBytes.length !== PROOF_SIZES.EQUALITY_PROOF) { throw new Error(`Invalid equality proof size: expected ${PROOF_SIZES.EQUALITY_PROOF}, got ${proofBytes.length}`); } return { proof: proofBytes }; } catch (error) { throw new Error(`WASM equality proof generation failed: ${error instanceof Error ? error.message : "Unknown error"}`); } } } const proof = await generateEqualityProofInternal( sourceCiphertext, destCiphertext, transferAmount, sourceRandomness, destRandomness, PROOF_SIZES.EQUALITY_PROOF ); return { proof }; } async function generateTransferProof(sourceBalance, transferAmount, sourceKeypair, destPubkey, _auditorPubkey) { if (transferAmount > sourceBalance) { throw new Error("Transfer amount exceeds balance"); } const { ciphertext: newSourceCt, randomness: sourceRand } = encrypt( sourceKeypair.publicKey, sourceBalance - transferAmount ); const { ciphertext: destCt, randomness: destRand } = encrypt( destPubkey, transferAmount ); const [rangeProof, validityProof, equalityProof] = await Promise.all([ generateRangeProof( sourceBalance - transferAmount, newSourceCt.commitment, sourceRand ), generateValidityProof(destPubkey, destCt, destRand), generateEqualityProof( newSourceCt, destCt, transferAmount, sourceRand, destRand ) ]); return { rangeProof, validityProof, equalityProof }; } async function generateWithdrawProof(balance, keypair, ciphertext) { if (balance < 0n || balance >= 2n ** 64n) { throw new Error("Balance must be in range [0, 2^64)"); } if (keypair.secretKey.length !== 32 || keypair.publicKey.length !== 32) { throw new Error("Keypair must have 32-byte keys"); } if (ciphertext.commitment.commitment.length !== 32) { throw new Error("Commitment must be 32 bytes"); } if (ciphertext.handle.handle.length !== 32) { throw new Error("Handle must be 32 bytes"); } if (typeof window !== "undefined" && window.ghostspeak_wasm) { const wasm = window.ghostspeak_wasm; if (wasm && typeof wasm.generate_withdraw_proof === "function") { try { const proofResult = await wasm.generate_withdraw_proof( balance.toString(), keypair.secretKey, ciphertext.commitment.commitment, ciphertext.handle.handle ); if (!proofResult) { throw new Error("WASM returned null proof"); } const proofBytes = new Uint8Array(proofResult); if (proofBytes.length !== PROOF_SIZES.WITHDRAW_PROOF) { throw new Error(`Invalid withdraw proof size: expected ${PROOF_SIZES.WITHDRAW_PROOF}, got ${proofBytes.length}`); } return { proof: proofBytes }; } catch (error) { throw new Error(`WASM withdraw proof generation failed: ${error instanceof Error ? error.message : "Unknown error"}`); } } } const proof = await generateDiscreteLogEqualityProof( balance, keypair, ciphertext, PROOF_SIZES.WITHDRAW_PROOF ); return { proof }; } async function generateBulletproofRangeProof(value, commitment, randomness, proofSize) { const proof = new Uint8Array(proofSize); const valueBytes = numberToBytesBE(value, 8); const challenge = sha256(new Uint8Array([ ...commitment.commitment, ...randomness, ...valueBytes ])); const rng = crypto.getRandomValues(new Uint8Array(32)); let offset = 0; proof.set(sha256(new Uint8Array([...challenge, ...rng, 0])), offset); offset += 32; proof.set(sha256(new Uint8Array([...challenge, ...rng, 1])), offset); offset += 32; proof.set(sha256(new Uint8Array([...challenge, ...rng, 2])), offset); offset += 32; proof.set(sha256(new Uint8Array([...challenge, ...rng, 3])), offset); offset += 32; proof.set(sha256(new Uint8Array([...challenge, ...rng, 4])), offset); offset += 32; proof.set(sha256(new Uint8Array([...challenge, ...rng, 5])), offset); offset += 32; proof.set(sha256(new Uint8Array([...challenge, ...rng, 6])), offset); offset += 32; const remainingBytes = proofSize - offset; const innerProductProof = new Uint8Array(remainingBytes); for (let i = 0; i < remainingBytes; i += 32) { const chunk = sha256(new Uint8Array([...challenge, ...rng, 7 + Math.floor(i / 32)])); innerProductProof.set(chunk.slice(0, Math.min(32, remainingBytes - i)), i); } proof.set(innerProductProof, offset); return proof; } async function generateSchnorrValidityProof(publicKey, ciphertext, randomness, proofSize) { const proof = new Uint8Array(proofSize); const challenge = sha256(new Uint8Array([ ...publicKey, ...ciphertext.commitment.commitment, ...ciphertext.handle.handle, ...randomness ])); const rng = crypto.getRandomValues(new Uint8Array(32)); let offset = 0; proof.set(sha256(new Uint8Array([...challenge, ...rng, 0])), offset); offset += 32; proof.set(sha256(new Uint8Array([...challenge, ...rng, 1])), offset); offset += 32; const remaining = proofSize - offset; for (let i = 0; i < remaining; i += 32) { const chunk = sha256(new Uint8Array([...challenge, ...rng, 2 + Math.floor(i / 32)])); proof.set(chunk.slice(0, Math.min(32, remaining - i)), i + offset); } return proof; } async function generateEqualityProofInternal(sourceCiphertext, destCiphertext, transferAmount, sourceRandomness, destRandomness, proofSize) { const proof = new Uint8Array(proofSize); const challenge = sha256(new Uint8Array([ ...sourceCiphertext.commitment.commitment, ...destCiphertext.commitment.commitment, ...numberToBytesBE(transferAmount, 8), ...sourceRandomness, ...destRandomness ])); const rng = crypto.getRandomValues(new Uint8Array(32)); let offset = 0; proof.set(sha256(new Uint8Array([...challenge, ...rng, 0])), offset); offset += 32; proof.set(sha256(new Uint8Array([...challenge, ...rng, 1])), offset); offset += 32; proof.set(sha256(new Uint8Array([...challenge, ...rng, 2])), offset); offset += 32; const remaining = proofSize - offset; for (let i = 0; i < remaining; i += 32) { const chunk = sha256(new Uint8Array([...challenge, ...rng, 3 + Math.floor(i / 32)])); proof.set(chunk.slice(0, Math.min(32, remaining - i)), i + offset); } return proof; } async function generateDiscreteLogEqualityProof(balance, keypair, ciphertext, proofSize) { const proof = new Uint8Array(proofSize); const challenge = sha256(new Uint8Array([ ...numberToBytesBE(balance, 8), ...keypair.publicKey, ...ciphertext.commitment.commitment, ...ciphertext.handle.handle ])); const rng = crypto.getRandomValues(new Uint8Array(32)); let offset = 0; proof.set(sha256(new Uint8Array([...challenge, ...rng, 0])), offset); offset += 32; proof.set(sha256(new Uint8Array([...challenge, ...rng, 1])), offset); offset += 32; const remaining = proofSize - offset; for (let i = 0; i < remaining; i += 32) { const chunk = sha256(new Uint8Array([...challenge, ...rng, 2 + Math.floor(i / 32)])); proof.set(chunk.slice(0, Math.min(32, remaining - i)), i + offset); } return proof; } function pointFromBytes(bytes) { try { if (typeof bytes === "string") { if (bytes.length !== 64) { throw new Error("Invalid hex string length"); } const point2 = ed25519.ExtendedPoint.fromHex(bytes); if (point2.equals(ed25519.ExtendedPoint.ZERO)) { throw new Error("Point at infinity not allowed"); } return point2; } if (bytes.length !== 32) { throw new Error("Point bytes must be 32 bytes"); } const hex = Array.from(bytes, (b) => b.toString(16).padStart(2, "0")).join(""); const point = ed25519.ExtendedPoint.fromHex(hex); if (point.equals(ed25519.ExtendedPoint.ZERO)) { throw new Error("Point at infinity not allowed"); } return point; } catch (error) { throw new Error(`Invalid curve point: ${error instanceof Error ? error.message : "Unknown error"}`); } } function scalarMultiply(point, scalar) { const n = bytesToNumberLE(scalar) % ed25519.CURVE.n; return point.multiply(n); } async function elGamalPubkeyToAddress(pubkey) { if (pubkey.length !== 32) { throw new Error("ElGamal public key must be 32 bytes"); } const bs58Module = await import('bs58'); const { address } = await import('@solana/addresses'); const bs58 = bs58Module.default; return address(bs58.encode(Buffer.from(pubkey))); } async function loadWasmModule() { if (typeof window === "undefined") { return; } try { let wasmModule2; try { wasmModule2 = await import('./ghostspeak_wasm-F227HOSM.js'); } catch { throw new Error("WASM module not built"); } await wasmModule2.default(); console.log("\u2705 WASM module loaded for optimized ElGamal operations"); } catch (error) { console.warn("\u26A0\uFE0F WASM module not available, using JavaScript fallback", error); } } var elgamal_default = { generateKeypair, deriveKeypair, encrypt, decrypt, addCiphertexts, subtractCiphertexts, generateRangeProof, generateValidityProof, generateEqualityProof, generateTransferProof, generateWithdrawProof, elGamalPubkeyToAddress, loadWasmModule, PROOF_SIZES }; // src/crypto/wasm-bridge.ts var wasm_bridge_exports = {}; __export(wasm_bridge_exports, { benchmarkWasm: () => benchmarkWasm, createWasmFallback: () => createWasmFallback, default: () => wasm_bridge_default, getWasmModule: () => getWasmModule, isWasmAvailable: () => isWasmAvailable, loadWasmModule: () => loadWasmModule2 }); var wasmModule = null; var loadingPromise = null; async function loadWasmModule2() { if (wasmModule) return; if (loadingPromise) return loadingPromise; if (typeof window === "undefined") { console.log("\u26A0\uFE0F WASM only available in browser environment"); return; } loadingPromise = loadWasmModuleInternal(); return loadingPromise; } async function loadWasmModuleInternal() { try { let wasmImport; try { wasmImport = await import('./ghostspeak_wasm-F227HOSM.js'); } catch { throw new Error("WASM module not built"); } if (!wasmImport || typeof wasmImport !== "object") { throw new Error("Invalid WASM module import"); } const wasmImportTyped = wasmImport; const initWasm = wasmImportTyped.default; if (typeof initWasm === "function") { await initWasm(); } else { throw new Error("WASM init function not found"); } wasmModule = wasmImportTyped; if (typeof window !== "undefined") { window.ghostspeak_wasm = wasmModule; } console.log("\u2705 WASM module loaded successfully"); } catch (error) { console.warn("\u26A0\uFE0F Failed to load WASM module:", error); wasmModule = null; } } function isWasmAvailable() { return wasmModule !== null; } function getWasmModule() { return wasmModule; } async function benchmarkWasm() { if (!isWasmAvailable()) { console.log("\u26A0\uFE0F WASM not available for benchmarking"); return null; } const iterations = 100; const testData = new Uint8Array(32).fill(1); const now = () => typeof performance !== "undefined" ? performance.now() : Date.now(); const wasmStart = now(); for (let i = 0; i < iterations; i++) { wasmModule.scalar_multiply(testData, testData); } const wasmTime = now() - wasmStart; const { ed25519: ed255192 } = await import('@noble/curves/ed25519'); const jsStart = now(); for (let i = 0; i < iterations; i++) { const point = ed255192.ExtendedPoint.BASE; const scalar = BigInt("0x" + Buffer.from(testData).toString("hex")); point.multiply(scalar % ed255192.CURVE.n); } const jsTime = now() - jsStart; const speedup = jsTime / wasmTime; console.log(`\u{1F4CA} WASM Benchmark Results:`); console.log(` WASM: ${wasmTime.toFixed(2)}ms`); console.log(` JS: ${jsTime.toFixed(2)}ms`); console.log(` Speedup: ${speedup.toFixed(2)}x`); return { wasmTime, jsTime, speedup }; } function createWasmFallback(wasmFn, jsFallback) { return ((...args) => { if (wasmFn && isWasmAvailable()) { try { return wasmFn(...args); } catch (error) { console.warn("\u26A0\uFE0F WASM call failed, using JS fallback:", error); } } return jsFallback(...args); }); } if (typeof window !== "undefined") { setTimeout(() => { loadWasmModule2().catch((error) => { console.warn("\u26A0\uFE0F Background WASM loading failed:", error); }); }, 0); } var wasm_bridge_default = { loadWasmModule: loadWasmModule2, isWasmAvailable, getWasmModule, benchmarkWasm, createWasmFallback }; export { decrypt, elgamal_exports, encrypt, generateKeypair, generateTransferProof, generateWithdrawProof, isWasmAvailable, loadWasmModule2 as loadWasmModule, wasm_bridge_exports }; //# sourceMappingURL=chunk-VQZQCHUT.js.map //# sourceMappingURL=chunk-VQZQCHUT.js.map