This document describes the Zero-Knowledge proof functionality added to the Finchippay Solution contract to enable privacy-preserving proof of payment.
The implementation allows users to prove they made a payment of at least a certain amount without revealing the exact amount or their identity to third parties. This is achieved through a combination of commitment schemes and Merkle tree proofs.
-
PaymentCommitment: Stores commitment information on-chain
commitment_hash: Hash of the payment commitment (amount + salt)timestamp: When the commitment was creatednullifier: Unique identifier to prevent double-spending
-
ZKProof: Structure for zero-knowledge proof verification
commitment_hash: Reference to the stored commitmentamount_hash: Hash of the amount being provedsalt: Random salt used in commitmentmerkle_proof: Merkle proof for inclusion verificationleaf_index: Index of the leaf in the Merkle tree
-
DataKey: Storage keys for contract state
PaymentCommitment(BytesN<32>): Individual commitment storageMerkleRoot: Current Merkle tree rootCommitmentCounter: Counter for commitment IDsNullifier(BytesN<32>): Used nullifiers for double-spending prevention
pub fn commit_payment(
env: Env,
commitment_hash: BytesN<32>,
nullifier: BytesN<32>,
) -> u32Stores a payment commitment on-chain. Prevents double-spending by checking nullifiers.
Parameters:
commitment_hash: Hash of (amount + salt)nullifier: Unique identifier to prevent reuse
Returns: Commitment ID for tracking
pub fn verify_payment(
env: Env,
proof: ZKProof,
minimum_amount: i128,
) -> boolVerifies a zero-knowledge proof without revealing the exact amount.
Parameters:
proof: Complete ZK proof structureminimum_amount: Minimum amount to verify against
Returns: True if proof is valid and amount >= minimum_amount
pub fn get_merkle_root(env: Env) -> Option<BytesN<32>>Returns the current Merkle root of all commitments.
pub fn generate_commitment_hash(
env: Env,
amount: i128,
salt: BytesN<32>,
) -> BytesN<32>Helper function to generate commitment hashes (typically used client-side).
The lib/stellar.ts file provides TypeScript utilities for client-side proof generation:
generateSalt(): Creates random salt for commitmentsgenerateNullifier(): Creates unique nullifiershashAmountWithSalt(): Hashes amount with saltcreatePaymentCommitment(): Creates complete payment commitmentcreateZKPaymentProof(): Generates zero-knowledge proofverifyZKPaymentProof(): Verifies proofs client-sideserializeZKProof()/deserializeZKProof(): For transmission
import {
createPaymentCommitment,
createZKPaymentProof,
verifyZKPaymentProof
} from './lib/stellar';
// Create commitment
const commitment = createPaymentCommitment(1000000n); // 0.01 XLM
// Create ZK proof for minimum amount
const proof = createZKPaymentProof(
1000000n, // actual amount
500000n, // minimum amount to prove
merkleRoot, // from contract
0 // leaf index
);
// Verify (would be done on-chain)
const isValid = verifyZKPaymentProof(proof, 500000n, merkleRoot);- Nullifiers are tracked to prevent commitment reuse
- Each nullifier can only be used once
- Amounts are hidden behind cryptographic hashes
- No direct link between commitment and payer identity
- Merkle proofs provide inclusion without revealing full data
- Merkle tree ensures commitment inclusion
- Hash verification prevents tampering
- Timestamps provide temporal ordering
The current implementation uses a simplified Merkle tree structure for demonstration. In production, this should be replaced with a proper binary Merkle tree implementation.
The current implementation uses a simplified commitment scheme. For production use, this should be replaced with proper zk-SNARK circuits for stronger privacy guarantees.
The amount verification is simplified. Production implementations should include proper range proofs to ensure amounts are within valid bounds.
Comprehensive tests are included in the contract:
test_commit_payment: Basic commitment creationtest_commit_payment_double_nullifier: Double-spending preventiontest_verify_payment_valid_proof: Valid proof verificationtest_verify_payment_invalid_commitment: Invalid commitment rejectiontest_verify_payment_invalid_amount_hash: Tampered amount rejectiontest_generate_commitment_hash: Hash consistencytest_merkle_root_update: Merkle tree functionalitytest_multiple_commitments_merkle_root: Multiple commitment handlingtest_commitment_counter: ID generation
- Proper zk-SNARK Integration: Replace simplified scheme with actual zk-SNARKs
- Full Merkle Tree: Implement complete binary Merkle tree
- Range Proofs: Add proper range proof verification
- Batch Verification: Support for batch proof verification
- Revocation: Add commitment revocation mechanisms
- Gas Optimization: Optimize for lower gas costs
soroban-sdkv20.0.0soroban-sdk::cryptofor cryptographic functions
js-sha256for SHA256 hashing- Node.js
cryptofor random bytes @types/nodefor TypeScript support
MIT License - see LICENSE file for details.