Merge commit 'd803bfe2b1fe7f5e219e50ac20d6801a0a58ac75' as 'vendor/ruvector'
This commit is contained in:
425
vendor/ruvector/examples/edge/pkg/zk-financial-proofs.ts
vendored
Normal file
425
vendor/ruvector/examples/edge/pkg/zk-financial-proofs.ts
vendored
Normal file
@@ -0,0 +1,425 @@
|
||||
/**
|
||||
* Zero-Knowledge Financial Proofs
|
||||
*
|
||||
* Prove financial statements without revealing actual numbers.
|
||||
* All proof generation happens in the browser - private data never leaves.
|
||||
*
|
||||
* @example
|
||||
* ```typescript
|
||||
* import { ZkFinancialProver, ZkProofVerifier } from './zk-financial-proofs';
|
||||
*
|
||||
* // Prover (you - with private data)
|
||||
* const prover = new ZkFinancialProver();
|
||||
* prover.loadIncome([650000, 650000, 680000]); // cents
|
||||
* prover.loadBalances([500000, 520000, 480000, 510000]);
|
||||
*
|
||||
* // Generate proof: "My income is at least 3x the rent"
|
||||
* const proof = await prover.proveAffordability(200000, 3); // $2000 rent
|
||||
*
|
||||
* // Share proof with landlord (contains NO actual numbers)
|
||||
* const proofJson = JSON.stringify(proof);
|
||||
*
|
||||
* // Verifier (landlord - without your private data)
|
||||
* const result = ZkProofVerifier.verify(proofJson);
|
||||
* console.log(result.valid); // true
|
||||
* console.log(result.statement); // "Income ≥ 3× monthly rent of $2000"
|
||||
* ```
|
||||
*/
|
||||
|
||||
import init, {
|
||||
ZkFinancialProver as WasmProver,
|
||||
ZkProofVerifier as WasmVerifier,
|
||||
ZkUtils,
|
||||
} from './ruvector_edge';
|
||||
|
||||
// ============================================================================
|
||||
// Types
|
||||
// ============================================================================
|
||||
|
||||
/**
|
||||
* A zero-knowledge proof
|
||||
*/
|
||||
export interface ZkProof {
|
||||
proof_type: ProofType;
|
||||
proof_data: number[];
|
||||
public_inputs: PublicInputs;
|
||||
generated_at: number;
|
||||
expires_at?: number;
|
||||
}
|
||||
|
||||
export type ProofType =
|
||||
| 'Range'
|
||||
| 'Comparison'
|
||||
| 'Affordability'
|
||||
| 'NonNegative'
|
||||
| 'SumBound'
|
||||
| 'AverageBound'
|
||||
| 'SetMembership';
|
||||
|
||||
export interface PublicInputs {
|
||||
commitments: Commitment[];
|
||||
bounds: number[];
|
||||
statement: string;
|
||||
attestation?: Attestation;
|
||||
}
|
||||
|
||||
export interface Commitment {
|
||||
point: number[];
|
||||
}
|
||||
|
||||
export interface Attestation {
|
||||
issuer: string;
|
||||
signature: number[];
|
||||
timestamp: number;
|
||||
}
|
||||
|
||||
export interface VerificationResult {
|
||||
valid: boolean;
|
||||
statement: string;
|
||||
verified_at: number;
|
||||
error?: string;
|
||||
}
|
||||
|
||||
export interface RentalApplicationProof {
|
||||
income_proof: ZkProof;
|
||||
stability_proof: ZkProof;
|
||||
savings_proof?: ZkProof;
|
||||
metadata: ApplicationMetadata;
|
||||
}
|
||||
|
||||
export interface ApplicationMetadata {
|
||||
applicant_id: string;
|
||||
property_id?: string;
|
||||
generated_at: number;
|
||||
expires_at: number;
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// Prover (Client-Side)
|
||||
// ============================================================================
|
||||
|
||||
/**
|
||||
* Generate zero-knowledge proofs about financial data.
|
||||
*
|
||||
* All proof generation happens locally in WebAssembly.
|
||||
* Your actual financial numbers are NEVER revealed.
|
||||
*/
|
||||
export class ZkFinancialProver {
|
||||
private wasmProver: WasmProver | null = null;
|
||||
private initialized = false;
|
||||
|
||||
/**
|
||||
* Initialize the prover
|
||||
*/
|
||||
async init(): Promise<void> {
|
||||
if (this.initialized) return;
|
||||
|
||||
await init();
|
||||
this.wasmProver = new WasmProver();
|
||||
this.initialized = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Load monthly income data
|
||||
* @param monthlyIncome Array of monthly income in CENTS (e.g., $6500 = 650000)
|
||||
*/
|
||||
loadIncome(monthlyIncome: number[]): void {
|
||||
this.ensureInit();
|
||||
this.wasmProver!.loadIncome(new BigUint64Array(monthlyIncome.map(BigInt)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Load expense data for a category
|
||||
* @param category Category name (e.g., "Food", "Transportation")
|
||||
* @param monthlyExpenses Array of monthly expenses in CENTS
|
||||
*/
|
||||
loadExpenses(category: string, monthlyExpenses: number[]): void {
|
||||
this.ensureInit();
|
||||
this.wasmProver!.loadExpenses(category, new BigUint64Array(monthlyExpenses.map(BigInt)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Load daily balance history
|
||||
* @param dailyBalances Array of daily balances in CENTS (can be negative)
|
||||
*/
|
||||
loadBalances(dailyBalances: number[]): void {
|
||||
this.ensureInit();
|
||||
this.wasmProver!.loadBalances(new BigInt64Array(dailyBalances.map(BigInt)));
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// Proof Generation
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Prove: average income ≥ threshold
|
||||
*
|
||||
* Use case: Prove you make at least $X without revealing exact income
|
||||
*
|
||||
* @param thresholdDollars Minimum income threshold in dollars
|
||||
*/
|
||||
async proveIncomeAbove(thresholdDollars: number): Promise<ZkProof> {
|
||||
this.ensureInit();
|
||||
const thresholdCents = Math.round(thresholdDollars * 100);
|
||||
return this.wasmProver!.proveIncomeAbove(BigInt(thresholdCents));
|
||||
}
|
||||
|
||||
/**
|
||||
* Prove: income ≥ multiplier × rent
|
||||
*
|
||||
* Use case: Prove affordability for apartment application
|
||||
*
|
||||
* @param rentDollars Monthly rent in dollars
|
||||
* @param multiplier Required income multiplier (typically 3)
|
||||
*/
|
||||
async proveAffordability(rentDollars: number, multiplier: number): Promise<ZkProof> {
|
||||
this.ensureInit();
|
||||
const rentCents = Math.round(rentDollars * 100);
|
||||
return this.wasmProver!.proveAffordability(BigInt(rentCents), BigInt(multiplier));
|
||||
}
|
||||
|
||||
/**
|
||||
* Prove: no overdrafts in the past N days
|
||||
*
|
||||
* Use case: Prove account stability
|
||||
*
|
||||
* @param days Number of days to prove (e.g., 90)
|
||||
*/
|
||||
async proveNoOverdrafts(days: number): Promise<ZkProof> {
|
||||
this.ensureInit();
|
||||
return this.wasmProver!.proveNoOverdrafts(days);
|
||||
}
|
||||
|
||||
/**
|
||||
* Prove: current savings ≥ threshold
|
||||
*
|
||||
* Use case: Prove you have emergency fund
|
||||
*
|
||||
* @param thresholdDollars Minimum savings in dollars
|
||||
*/
|
||||
async proveSavingsAbove(thresholdDollars: number): Promise<ZkProof> {
|
||||
this.ensureInit();
|
||||
const thresholdCents = Math.round(thresholdDollars * 100);
|
||||
return this.wasmProver!.proveSavingsAbove(BigInt(thresholdCents));
|
||||
}
|
||||
|
||||
/**
|
||||
* Prove: average spending in category ≤ budget
|
||||
*
|
||||
* Use case: Prove budgeting discipline
|
||||
*
|
||||
* @param category Spending category
|
||||
* @param budgetDollars Maximum budget in dollars
|
||||
*/
|
||||
async proveBudgetCompliance(category: string, budgetDollars: number): Promise<ZkProof> {
|
||||
this.ensureInit();
|
||||
const budgetCents = Math.round(budgetDollars * 100);
|
||||
return this.wasmProver!.proveBudgetCompliance(category, BigInt(budgetCents));
|
||||
}
|
||||
|
||||
/**
|
||||
* Prove: debt-to-income ratio ≤ max%
|
||||
*
|
||||
* Use case: Prove creditworthiness
|
||||
*
|
||||
* @param monthlyDebtDollars Monthly debt payments in dollars
|
||||
* @param maxRatioPercent Maximum DTI ratio (e.g., 30 for 30%)
|
||||
*/
|
||||
async proveDebtRatio(monthlyDebtDollars: number, maxRatioPercent: number): Promise<ZkProof> {
|
||||
this.ensureInit();
|
||||
const debtCents = Math.round(monthlyDebtDollars * 100);
|
||||
return this.wasmProver!.proveDebtRatio(BigInt(debtCents), BigInt(maxRatioPercent));
|
||||
}
|
||||
|
||||
/**
|
||||
* Create complete rental application proof bundle
|
||||
*
|
||||
* Includes all proofs typically needed for rental application
|
||||
*
|
||||
* @param rentDollars Monthly rent
|
||||
* @param incomeMultiplier Required income multiple (usually 3)
|
||||
* @param stabilityDays Days of no overdrafts to prove
|
||||
* @param savingsMonths Months of rent to prove in savings (optional)
|
||||
*/
|
||||
async createRentalApplication(
|
||||
rentDollars: number,
|
||||
incomeMultiplier: number = 3,
|
||||
stabilityDays: number = 90,
|
||||
savingsMonths?: number
|
||||
): Promise<RentalApplicationProof> {
|
||||
this.ensureInit();
|
||||
const rentCents = Math.round(rentDollars * 100);
|
||||
return this.wasmProver!.createRentalApplication(
|
||||
BigInt(rentCents),
|
||||
BigInt(incomeMultiplier),
|
||||
stabilityDays,
|
||||
savingsMonths !== undefined ? BigInt(savingsMonths) : undefined
|
||||
);
|
||||
}
|
||||
|
||||
private ensureInit(): void {
|
||||
if (!this.initialized || !this.wasmProver) {
|
||||
throw new Error('Prover not initialized. Call init() first.');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// Verifier (Can Run Anywhere)
|
||||
// ============================================================================
|
||||
|
||||
/**
|
||||
* Verify zero-knowledge proofs.
|
||||
*
|
||||
* Verifier learns ONLY that the statement is true.
|
||||
* Actual numbers remain completely hidden.
|
||||
*/
|
||||
export class ZkProofVerifier {
|
||||
private static initialized = false;
|
||||
|
||||
/**
|
||||
* Initialize the verifier
|
||||
*/
|
||||
static async init(): Promise<void> {
|
||||
if (this.initialized) return;
|
||||
await init();
|
||||
this.initialized = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Verify a single proof
|
||||
*
|
||||
* @param proof The proof to verify (as object or JSON string)
|
||||
*/
|
||||
static async verify(proof: ZkProof | string): Promise<VerificationResult> {
|
||||
await this.init();
|
||||
const proofJson = typeof proof === 'string' ? proof : JSON.stringify(proof);
|
||||
return WasmVerifier.verify(proofJson);
|
||||
}
|
||||
|
||||
/**
|
||||
* Verify a rental application bundle
|
||||
*/
|
||||
static async verifyRentalApplication(
|
||||
application: RentalApplicationProof | string
|
||||
): Promise<{ all_valid: boolean; results: VerificationResult[] }> {
|
||||
await this.init();
|
||||
const appJson = typeof application === 'string' ? application : JSON.stringify(application);
|
||||
return WasmVerifier.verifyRentalApplication(appJson);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get human-readable statement from proof
|
||||
*/
|
||||
static async getStatement(proof: ZkProof | string): Promise<string> {
|
||||
await this.init();
|
||||
const proofJson = typeof proof === 'string' ? proof : JSON.stringify(proof);
|
||||
return WasmVerifier.getStatement(proofJson);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if proof is expired
|
||||
*/
|
||||
static async isExpired(proof: ZkProof | string): Promise<boolean> {
|
||||
await this.init();
|
||||
const proofJson = typeof proof === 'string' ? proof : JSON.stringify(proof);
|
||||
return WasmVerifier.isExpired(proofJson);
|
||||
}
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// Utilities
|
||||
// ============================================================================
|
||||
|
||||
export const ZkProofUtils = {
|
||||
/**
|
||||
* Convert proof to shareable URL
|
||||
*/
|
||||
toShareableUrl(proof: ZkProof, baseUrl: string = window.location.origin): string {
|
||||
const proofJson = JSON.stringify(proof);
|
||||
return ZkUtils.proofToUrl(proofJson, baseUrl + '/verify');
|
||||
},
|
||||
|
||||
/**
|
||||
* Extract proof from URL parameter
|
||||
*/
|
||||
fromUrl(encoded: string): ZkProof {
|
||||
const json = ZkUtils.proofFromUrl(encoded);
|
||||
return JSON.parse(json);
|
||||
},
|
||||
|
||||
/**
|
||||
* Format proof for display
|
||||
*/
|
||||
formatProof(proof: ZkProof): string {
|
||||
return `
|
||||
┌─────────────────────────────────────────────────┐
|
||||
│ Zero-Knowledge Proof │
|
||||
├─────────────────────────────────────────────────┤
|
||||
│ Type: ${proof.proof_type.padEnd(41)}│
|
||||
│ Statement: ${proof.public_inputs.statement.slice(0, 36).padEnd(36)}│
|
||||
│ Generated: ${new Date(proof.generated_at * 1000).toLocaleDateString().padEnd(36)}│
|
||||
│ Expires: ${proof.expires_at ? new Date(proof.expires_at * 1000).toLocaleDateString().padEnd(38) : 'Never'.padEnd(38)}│
|
||||
│ Proof size: ${(proof.proof_data.length + ' bytes').padEnd(35)}│
|
||||
└─────────────────────────────────────────────────┘
|
||||
`.trim();
|
||||
},
|
||||
|
||||
/**
|
||||
* Calculate proof size in bytes
|
||||
*/
|
||||
proofSize(proof: ZkProof): number {
|
||||
return JSON.stringify(proof).length;
|
||||
},
|
||||
};
|
||||
|
||||
// ============================================================================
|
||||
// Presets for Common Use Cases
|
||||
// ============================================================================
|
||||
|
||||
/**
|
||||
* Pre-configured proof generators for common scenarios
|
||||
*/
|
||||
export const ZkPresets = {
|
||||
/**
|
||||
* Standard rental application (3x income, 90 days stability, 2 months savings)
|
||||
*/
|
||||
async rentalApplication(
|
||||
prover: ZkFinancialProver,
|
||||
monthlyRent: number
|
||||
): Promise<RentalApplicationProof> {
|
||||
return prover.createRentalApplication(monthlyRent, 3, 90, 2);
|
||||
},
|
||||
|
||||
/**
|
||||
* Loan pre-qualification (income above threshold, DTI under 30%)
|
||||
*/
|
||||
async loanPrequalification(
|
||||
prover: ZkFinancialProver,
|
||||
minimumIncome: number,
|
||||
monthlyDebt: number
|
||||
): Promise<{ incomeProof: ZkProof; dtiProof: ZkProof }> {
|
||||
const incomeProof = await prover.proveIncomeAbove(minimumIncome);
|
||||
const dtiProof = await prover.proveDebtRatio(monthlyDebt, 30);
|
||||
return { incomeProof, dtiProof };
|
||||
},
|
||||
|
||||
/**
|
||||
* Employment verification (income above minimum)
|
||||
*/
|
||||
async employmentVerification(
|
||||
prover: ZkFinancialProver,
|
||||
minimumSalary: number
|
||||
): Promise<ZkProof> {
|
||||
return prover.proveIncomeAbove(minimumSalary);
|
||||
},
|
||||
|
||||
/**
|
||||
* Account stability (no overdrafts for 6 months)
|
||||
*/
|
||||
async accountStability(prover: ZkFinancialProver): Promise<ZkProof> {
|
||||
return prover.proveNoOverdrafts(180);
|
||||
},
|
||||
};
|
||||
|
||||
export default { ZkFinancialProver, ZkProofVerifier, ZkProofUtils, ZkPresets };
|
||||
Reference in New Issue
Block a user