Skip to content

Latest commit

 

History

2 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Stellar ZK L2 Settlement Circuits

Universal Circom circuits for the Stellar ZK L2 settlement system.

Architecture

circuits/
├── src/
│   ├── settlement.circom      # Main settlement circuit (universal)
│   ├── transfer.circom        # Single transfer sub-circuit
│   └── withdrawal.circom      # Withdrawal authorization
├── lib/
│   ├── poseidon.circom        # Poseidon hash wrappers
│   ├── merkle.circom          # Sparse Merkle tree verification
│   ├── nullifier.circom       # Nullifier computation
│   └── commitment.circom      # UTXO commitment logic
├── scripts/
│   ├── compile.sh             # Compile circuits
│   ├── setup.sh               # Trusted setup (powers of tau)
│   └── test.sh                # Run circuit tests
├── test/
│   └── settlement.test.js     # Circuit unit tests
├── keys/                      # Generated proving/verification keys
└── build/                     # Compiled circuit artifacts

Circuit Design Principles

1. Universal Circuit Pattern

A single circuit handles all L2 operations (deposit, transfer, withdraw) via an operation_type selector:

operation_type:
  0 = Transfer (L2 → L2)
  1 = Deposit  (L1 → L2, commitment only)
  2 = Withdraw (L2 → L1, nullifier only)

This avoids multiple trusted setups and simplifies Mopro integration.

2. Mopro Compatibility

  • Proof System: Groth16 on BN254 (arkworks compatible)
  • Hash Function: Poseidon with t=3 (2-to-1 hash)
  • Constraint Target: <100,000 for mobile proving (<5s on iPhone)
  • Field: BN254 scalar field (Fr)

3. Offline Mesh Support

The circuit supports both:

  • Individual proofs: Single transfer for P2P mesh transactions
  • Batch proofs: Multiple transfers aggregated by relayer

When batch_size = 1, it's a mesh transaction. When batch_size > 1, it's a relayer settlement.

4. State Commitment Model

UTXO Commitment = Poseidon(owner_pubkey, balance, asset_id, nonce)

State Root = MerkleRoot(all UTXO commitments)

Nullifier = Poseidon(owner_privkey, commitment)

Public Inputs (for Soroban verification)

[0]  old_state_root        - Previous state tree root
[1]  new_state_root        - New state tree root after batch
[2]  old_nullifier_root    - Previous nullifier accumulator
[3]  new_nullifier_root    - New nullifier accumulator
[4]  deposit_hash          - Poseidon hash of deposit commitments
[5+] withdrawal_nullifiers - Nullifiers for L1 withdrawals

Build Instructions

Prerequisites

# Install Circom 2.x
cargo install --git https://github.com/iden3/circom

# Install snarkjs
npm install -g snarkjs

# Install circomlib (in circuits directory)
npm install circomlib

Compile and Setup

cd circuits

# Compile circuit
./scripts/compile.sh

# Trusted setup (uses existing powers of tau or generates new)
./scripts/setup.sh

# Run tests
./scripts/test.sh

Parameters

Parameter Value Rationale
MERKLE_DEPTH 20 Supports ~1M accounts
MAX_BATCH_SIZE 8 Mobile-friendly constraint count
POSEIDON_T 3 Standard 2-to-1 hash
ASSET_ID_BITS 32 4B+ asset types

Integration with Mopro

The compiled circuit integrates with Mopro for mobile proof generation:

// In mopro bindings
crate::set_circom_circuits! {
    ("settlement_final.zkey", witness::settlement_witness),
}

See /workspace/LumenBroMobile/docs/MOPRO_BUILD_GUIDE.md for full pipeline.

Security Considerations

  1. Nullifier Uniqueness: Derived from private key + commitment
  2. Balance Conservation: Enforced in-circuit (inputs = outputs)
  3. Merkle Membership: Verified for all spent UTXOs
  4. Trusted Setup: Use existing Powers of Tau ceremony for production

About

ZK L2 Scaffold on Stellar

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages