Skip to content

adipundir/MantleMask

Repository files navigation

MantleMask - zkSNARK Privacy Mixer

A privacy-preserving cryptocurrency mixer using zero-knowledge proofs on the Mantle Network.

πŸš€ Quick Start Guide

Prerequisites

  • Node.js (v16+)
  • npm or yarn
  • Circom compiler

Step 1: Install Dependencies

npm install

# Install Circom globally
npm install -g circom

Step 2: Compile Circuit

npm run build

This generates:

  • build/withdraw.wasm - WebAssembly for proof generation
  • build/withdraw.r1cs - R1CS constraint system

Step 3: Setup Trusted Setup

npm run setup

This:

  • Downloads Powers of Tau ceremony file
  • Generates proving key (withdraw_final.zkey)
  • Generates verification key (verification_key.json)
  • Creates Solidity verifier (contracts/Verifier.sol)

Step 4: Generate Proof

npm run generate-proof

Creates a zkSNARK proof in build/proof.json

Step 5: Verify Proof

npm run verify-proof

Verifies the generated proof off-chain

πŸ”§ Usage

1. Deploy Contracts

// Deploy MantleMask
MantleMask mixer = new MantleMask(1 ether, 20);

2. Make Deposit

const { generateCommitment } = require('./scripts/generateProof');

const nullifier = "123456789";
const secret = "987654321";
const { commitment } = generateCommitment(nullifier, secret);

// Deposit on-chain
await mixer.deposit(commitment, { value: ethers.utils.parseEther("1") });

3. Generate Withdrawal Proof

const { generateProof } = require('./scripts/generateProof');

const proof = await generateProof(
    nullifier,
    secret,
    recipientAddress
);

4. Withdraw

// Use the generated proof to withdraw
await mixer.withdraw(
    proof.proof,           // zkSNARK proof
    proof.publicSignals[0], // Merkle root  
    proof.nullifierHash,   // Nullifier hash
    recipientAddress       // Recipient
);

πŸ“ File Structure

β”œβ”€β”€ circuits/
β”‚   β”œβ”€β”€ withdraw.circom      # Main withdrawal circuit
β”‚   └── merkleTree.circom    # Merkle tree verification
β”œβ”€β”€ contracts/
β”‚   β”œβ”€β”€ MantleMask.sol       # Main privacy mixer contract
β”‚   └── Verifier.sol         # Generated zkSNARK verifier
β”œβ”€β”€ scripts/
β”‚   β”œβ”€β”€ setup.js             # Trusted setup generation
β”‚   β”œβ”€β”€ generateProof.js     # Proof generation
β”‚   └── verifyProof.js       # Proof verification
└── build/                   # Generated files
    β”œβ”€β”€ withdraw.wasm
    β”œβ”€β”€ withdraw.r1cs
    β”œβ”€β”€ withdraw_final.zkey
    β”œβ”€β”€ verification_key.json
    └── proof.json

πŸ” How It Works

Circuit Logic

  1. Input Validation: Verifies knowledge of nullifier and secret
  2. Commitment Generation: commitment = Poseidon(nullifier, secret)
  3. Nullifier Hash: nullifierHash = Poseidon(nullifier)
  4. Merkle Proof: Proves commitment is in the deposit tree
  5. Output: Generates zkSNARK proof without revealing secrets

Privacy Guarantees

  • βœ… Anonymity: No link between deposit and withdrawal addresses
  • βœ… Untraceability: Nullifier and secret never revealed
  • βœ… Double-spend Protection: Nullifier hash prevents reuse
  • βœ… Merkle Tree Inclusion: Proves legitimate deposit

πŸ› οΈ Development

Circuit Modification

Edit circuits/withdraw.circom and recompile:

npm run build
npm run setup

Testing

# Generate and verify a proof
npm run generate-proof
npm run verify-proof

🚨 Security Notes

⚠️ For Production Use:

  • Use a proper Powers of Tau ceremony
  • Implement ceremony verification
  • Add circuit auditing
  • Use hardware for key generation

πŸ“Š Circuit Constraints

  • Total Constraints: ~2,500 (for 20-level Merkle tree)
  • Public Inputs: 3 (root, nullifierHash, recipient)
  • Private Inputs: 42 (nullifier, secret, pathElements[20], pathIndices[20])

🎯 Integration Example

// Complete workflow example
const MantleMask = require('./scripts/generateProof');

async function privateTransfer() {
    // 1. Generate secrets
    const nullifier = Math.random().toString();
    const secret = Math.random().toString();
    
    // 2. Create commitment and deposit
    const { commitment } = MantleMask.generateCommitment(nullifier, secret);
    await mixer.deposit(commitment, { value: ethers.utils.parseEther("1") });
    
    // 3. Generate proof and withdraw
    const proof = await MantleMask.generateProof(nullifier, secret, recipient);
    await mixer.withdraw(proof.proof, proof.publicSignals[0], proof.nullifierHash, recipient);
    
    console.log("βœ… Private transfer complete!");
}

πŸ“„ License

MIT License

About

A privacy-focused token mixer built on the Mantle Network.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published