Skip to content

Repository files navigation

SafeTrust ZK

Zero-knowledge privacy layer for hospitality escrows on Stellar.

Booking amounts, wallet balances, and milestone releases are hidden inside Noir circuits. Only Pedersen commitments and proof hashes go on-chain β€” never raw numbers.

Stellar Hacks ZK Hackathon Β· Built on TrustlessWork Β· Powered by Noir / UltraHonk

πŸ“š Docs:


Current Status

Layer Status Notes
circuits/proof_of_funds βœ… Compiles + proves make prove-proof-of-funds
circuits/private_escrow βœ… Compiles + proves make prove-private-escrow
circuits/milestone_release βœ… Compiles + proves make prove-milestone-release
sdk/ βœ… Built + tested @safetrust/zk-sdk β€” all 3 provers wired
contracts/escrow_verifier βœ… Soroban UltraHonk verifier Rust, testnet-ready
demo/ βœ… Running Next.js 14 Β· apartment booking flow Β· Freighter wallet
docker-compose.yml βœ… Monolithic Postgres + demo in one command
db/init.sql βœ… Minimal schema 3 tables only: escrows, milestones, zk_proof_log
ZK_ENABLED hook βœ… Implemented Writes proof hashes to DB after each booking step

Run Everything β€” One Command

git clone https://github.com/safetrustcr/safetrust-ZK.git
cd safetrust-ZK
docker compose up --build
  • Demo β†’ http://localhost:3000
  • PostgreSQL β†’ localhost:5433 Β· db: safetrust_zk Β· user: postgres Β· pass: zkdemo

No backend-SafeTrust clone. No Hasura. No Firebase. The demo writes ZK proof hashes directly to the 3 tables in db/init.sql.


The Problem

Every SafeTrust escrow today is fully transparent on Stellar:

  • Competitors can see hotel pricing on-chain
  • Guests expose travel spending patterns publicly
  • Milestone amounts (70% check-in, 30% checkout) are visible to anyone

The Solution

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚  🏠 Casa Stellar, San JosΓ© CR Β· 150 USDC/night     β”‚
β”‚                                                     β”‚
β”‚  β‘  Prove Funds    β†’ βœ… proof hash: 0xab12…         β”‚
β”‚     balance β‰₯ 450 USDC β€” balance never revealed     β”‚
β”‚  β‘‘ Private Escrow β†’ βœ… commitment: 0xfe34…         β”‚
β”‚     amount = Pedersen(450 USDC) β€” amount hidden     β”‚
β”‚  β‘’ Check-in (70%) β†’ βœ… release proof: 0xcd56…      β”‚
β”‚  β‘£ Checkout (30%) β†’ βœ… release proof: 0xef78…      β”‚
β”‚                                                     β”‚
β”‚  πŸ“„ Receipt: Amount [HIDDEN πŸ”’] Β· Raw DB: ❌        β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Minimal DB Schema (3 tables)

Only what the ZK pipeline actually reads and writes β€” defined in db/init.sql:

trustless_work_escrows   ← ZK writes proof_hash + commitment to escrow_metadata JSONB
escrow_milestones        ← ZK writes release_proof to metadata JSONB
zk_proof_log             ← append-only audit trail of every proof event

No users, no apartments, no bids, no roles. Seed data in demo/lib/seeds.ts replaces all of that.

Verify proofs landed after booking:

SELECT contract_id,
       escrow_metadata->>'zk_proof_hash'        AS proof_hash,
       escrow_metadata->>'zk_amount_commitment'  AS commitment
FROM   public.trustless_work_escrows
WHERE  escrow_metadata ? 'zk_proof_hash';

-- Full audit trail
SELECT circuit, proof_hash, commitment, created_at
FROM   public.zk_proof_log
ORDER  BY created_at DESC;

Three Circuits

Circuit Private inputs Public inputs Proves
proof_of_funds.nr balance, randomness commitment, threshold balance β‰₯ threshold
private_escrow.nr amount, view_key, addresses commitment, encrypted_amount amount committed + encrypted
milestone_release.nr total_amount, randomness commitment, release_commitment, pct pct ∈ {70, 30} is correct

What Is / Is Not Stored

Stored ZK treatment
Wallet address, contract ID, escrow status βœ… plaintext Public by design
Proof hash, Pedersen commitment βœ… plaintext Hash is safe; source stays private
Encrypted amount (ChaCha20) βœ… JSONB Ciphertext only β€” view key required
Booking amount (raw USDC) ❌ never Noir circuit private input only
Guest wallet balance ❌ never Range proof only
ECDH view key ❌ never On-device β€” guest + host + auditor
IP address ❌ not collected ZK privacy principle

Prerequisites

Node.js β‰₯ 18    pnpm β‰₯ 9
Nargo β‰₯ 0.30    curl -L https://raw.githubusercontent.com/noir-lang/noirup/main/install | bash && noirup
bb (matches)    curl -L https://raw.githubusercontent.com/AztecProtocol/aztec-packages/refs/heads/next/barretenberg/bbup/install | bash && bbup
Freighter ext   freighter.app  (browser extension β€” for demo wallet)
Docker v2       full-stack only

Local Dev (without Docker)

pnpm install

# 1. Build the SDK first (required by demo API routes)
pnpm --filter @safetrust/zk-sdk build

# 2. Configure and start demo
cp demo/.env.example demo/.env.local
# Delete demo/.env if it exists β€” it overrides .env.local
pnpm --filter safetrust-zk-demo dev   # β†’ localhost:3000

Important: Delete demo/.env if it exists. Next.js reads both files and .env takes priority, which can activate Pollar mode unintentionally.


Running the Circuits

Requires nargo and bb installed (see Prerequisites above).

make compile-all             # compile all three circuits

make prove-proof-of-funds    # compile β†’ execute β†’ prove β†’ verify (Circuit 1)
make prove-private-escrow    # compile β†’ execute β†’ prove β†’ verify (Circuit 2)
make prove-milestone-release # compile β†’ execute β†’ prove β†’ verify (Circuit 3)

make test-circuits           # run nargo test suites
make test-all                # circuits + SDK + Soroban contract tests

Edit circuits/<name>/Prover.toml to test different amounts:

# circuits/proof_of_funds/Prover.toml
balance    = "20000000000"  # 2000 USDC β€” guest balance (private)
threshold  = "4500000000"   # 450 USDC  β€” booking amount (public threshold)
randomness = "12345"        # blinding factor (private)

SDK

cd sdk
pnpm install
pnpm build   # required before running demo
pnpm test
import { SafeTrustZK } from '@safetrust/zk-sdk';
const zk = new SafeTrustZK();

// 1. Prove solvency β€” balance never leaves the circuit
const { commitment } = await zk.proveOfFunds({
  balance:   20_000_000_000n,  // stroops (private)
  threshold:  4_500_000_000n,  // stroops (public threshold)
});

// 2. Commit booking amount privately
const { commitment: escrowCommitment } = await zk.commitEscrowAmount({
  amount:       4_500_000_000n,
  guestAddress: 'G...',
  hostAddress:  'G...',
});

// 3. Prove milestone release (70% check-in)
await zk.proveMilestoneRelease({
  amountCommitment: escrowCommitment,
  totalAmount:      4_500_000_000n,
  milestonePct:     70,
});

dApp-SafeTrust Integration (post-hackathon)

// Before β€” amount public on-chain
await initializeEscrow(escrowParams);

// After β€” only Pedersen commitment on-chain
const { proof, commitment } = await zk.proveAndCommitEscrow({
  balance, amount, guestAddress, hostAddress,
});
if (proof.valid) {
  await initializeEscrow({ ...escrowParams, amountCommitment: commitment });
}

Tech Stack

Layer Technology
ZK circuits Noir / Barretenberg UltraHonk
On-chain verifier Soroban (rs-soroban-ultrahonk)
SDK TypeScript β€” @noir-lang/noir_js, @aztec/bb.js
Demo Next.js 14 App Router Β· Freighter wallet
Database PostgreSQL 15 β€” 3 tables only (db/init.sql)
Blockchain Stellar Testnet Β· TrustlessWork API
Wallet Freighter β€” @stellar/freighter-api

Compliance

Not a mixer. The view key pattern means the guest, host, and any designated auditor can always reconstruct full transaction details. Everything else is confidential β€” not opaque.


Contributing

See CONTRIBUTING.md and Git Guidelines. Issues tagged circuit Β· sdk Β· demo Β· contracts.

MIT Β© SafeTrust

About

Zero-knowledge privacy layer for hospitality escrows on Stellar. Booking amounts hidden inside Noir circuits only Pedersen commitments and proof hashes go on-chain. Built for Stellar Hacks ZK Hackathon.

Resources

Contributing

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages