DEV Community

Cover image for AuctionVault - Protecting Bidder Privacy with Midnight's Zero-Knowledge Proofs
Abhi nandan
Abhi nandan

Posted on

AuctionVault - Protecting Bidder Privacy with Midnight's Zero-Knowledge Proofs

Midnight Network Challenge: Protect That Data

This is a submission for the Midnight Network "Privacy First" Challenge - Protect That Data prompt

What I Built

AuctionVault is a confidential auction platform that revolutionizes online bidding by placing privacy at its core. Unlike traditional auction platforms where bidding history, user identities, and financial information are exposed, AuctionVault uses zero-knowledge cryptography to enable completely anonymous participation while maintaining trust and security.

The platform solves critical privacy issues in online auctions:

  1. Bidder Identity Protection: Participants can bid anonymously without revealing personal information
  2. Financial Privacy: Bid amounts and payment methods remain confidential through cryptographic escrow
  3. Seller Verification: Sellers can prove authenticity and credibility without disclosing sensitive business data
  4. Anti-Manipulation: Prevents bid sniping and market manipulation through anonymous bidding

Key features include:

  1. Anonymous bidding with zero-knowledge proof verification
  2. Cryptographic escrow for secure payments
  3. Real-time auction updates with privacy preservation
  4. Seller verification without identity disclosure
  5. Premium auction categories (Art, Jewelry, Collectibles, Luxury Items)

Demo

GitHub Repository: AuctionVault - Confidential Auction Platform

Demo Video: https://youtu.be/t1WWHCLlPgk

How I Used Midnight's Technology

AuctionVault leverages Midnight's privacy-preserving technology stack extensively:

  1. Compact Language Circuits I implemented four core zero-knowledge circuits using Compact:
// anonymous_bidding.compact
circuit AnonymousBidding {
    // Private inputs
    private field bidAmount;
    private field userSecret;
    private field auctionId;

    // Public inputs  
    public field minBid;
    public field maxBid;

    // Constraints
    constraint bidAmount >= minBid;
    constraint bidAmount <= maxBid;
    constraint hash(userSecret) == publicCommitment;
}
Enter fullscreen mode Exit fullscreen mode
// seller_verification.compact
circuit SellerVerification {
    private field businessLicense;
    private field insuranceCoverage;
    private field identityHash;

    public field verificationLevel;

    constraint businessLicense == validLicense;
    constraint insuranceCoverage >= minimumCoverage;
    constraint verificationLevel == computeLevel(businessLicense, insuranceCoverage);
}
Enter fullscreen mode Exit fullscreen mode
  1. Midnight SDK Integration
// midnightIntegration.ts
import { MidnightJS } from '@midnight-ntwrk/midnight-js';
import { CompactCircuit } from '@midnight-ntwrk/compact';

export class AuctionVaultZK {
  private midnightClient: MidnightJS;

  async generateBidProof(bidData: BidData): Promise<ZKProof> {
    const circuit = await CompactCircuit.load('./circuits/anonymous_bidding.compact');

    const proof = await this.midnightClient.generateProof(circuit, {
      private: {
        bidAmount: bidData.amount,
        userSecret: bidData.userSecret,
        auctionId: bidData.auctionId
      },
      public: {
        minBid: bidData.minBid,
        maxBid: bidData.maxBid
      }
    });

    return proof;
  }
}
Enter fullscreen mode Exit fullscreen mode
  1. Privacy-Preserving State Management
// Real-time auction engine with privacy preservation
export class PrivateAuctionEngine {
  async submitBid(auctionId: string, encryptedBid: EncryptedBid): Promise<BidResult> {
    // Verify ZK proof without revealing bid amount
    const isValidProof = await this.verifyBidProof(encryptedBid.proof);

    if (isValidProof) {
      // Update auction state without exposing bidder identity
      await this.updateAuctionState(auctionId, {
        bidCount: this.state.bidCount + 1,
        lastBidTime: Date.now(),
        // Bid amount remains encrypted
        highestBidCommitment: encryptedBid.commitment
      });
    }

    return { success: isValidProof, anonymous: true };
  }
}
Enter fullscreen mode Exit fullscreen mode
  1. Cryptographic Escrow System
// Secure payment processing with zero-knowledge proofs
export class CryptographicEscrow {
  async createEscrow(auctionId: string, bidProof: ZKProof): Promise<EscrowContract> {
    const escrowContract = await this.midnightClient.deployContract({
      circuit: './circuits/escrow_payment.compact',
      initialState: {
        auctionId,
        bidderCommitment: bidProof.publicOutputs.bidderCommitment,
        sellerCommitment: await this.getSellerCommitment(auctionId)
      }
    });

    return escrowContract;
  }
}
Enter fullscreen mode Exit fullscreen mode

Data Protection as a Core Feature

Privacy and data protection are fundamental to AuctionVault's architecture, not superficial additions:

  1. Zero-Knowledge Bidding Architecture
// Core bidding system preserves complete anonymity
interface AnonymousBid {
  // Public: Proof that bid is valid without revealing amount
  zkProof: ZKProof;
  // Public: Commitment to bid amount (hash)
  bidCommitment: string;
  // Public: Auction identifier
  auctionId: string;
  // Private: Actual bid amount (never transmitted)
  // Private: Bidder identity (never stored)
}
Enter fullscreen mode Exit fullscreen mode
  1. Identity Protection Layers

Layer 1: Anonymous Authentication

// Users authenticate without revealing identity
const anonymousIdentity = await zkAuth.createIdentity({
  userType: 'bidder', // or 'seller'
  credential: 'financial_capacity',
  // Personal details never stored or transmitted
  zkProof: await generateIdentityProof(credentials)
});
Enter fullscreen mode Exit fullscreen mode

Layer 2: Encrypted Communications

// All auction communications are end-to-end encrypted
const encryptedMessage = await encrypt(message, {
  recipientPublicKey: auction.sellerPublicKey,
  senderPrivateKey: user.anonymousPrivateKey,
  // No metadata linking to real identity
});
Enter fullscreen mode Exit fullscreen mode

Layer 3: Private State Channels

// Auction state updates through private channels
const stateUpdate = await privateChannel.update({
  auctionId,
  // Only commitment hashes, no raw data
  newBidCommitment: hash(bidAmount + nonce),
  // Timestamp for ordering, no identity info
  timestamp: Date.now()
});
Enter fullscreen mode Exit fullscreen mode
  1. Financial Privacy Protection
// Payment processing without exposing financial details
export class PrivatePayments {
  async processPayment(escrowContract: EscrowContract): Promise<PaymentResult> {
    // Generate payment proof without revealing payment method
    const paymentProof = await this.generatePaymentProof({
      // Private: Actual payment details
      paymentMethod: user.encryptedPaymentMethod,
      amount: escrowContract.lockedAmount,
      // Public: Proof of payment capability
      zkProof: await this.provePaymentCapacity(amount)
    });

    // Execute payment through zero-knowledge contract
    return await escrowContract.executePayment(paymentProof);
  }
}
Enter fullscreen mode Exit fullscreen mode
  1. Metadata Protection
// Even metadata is privacy-protected
interface PrivacyPreservingAuction {
  // Public: Basic auction info
  id: string;
  category: AuctionCategory;
  endTime: number;

  // Protected: Sensitive details through commitments
  itemCommitment: string; // hash(itemDetails + salt)
  sellerCommitment: string; // hash(sellerInfo + salt)

  // Private: Never exposed
  // - Bidder identities
  // - Exact bid amounts  
  // - Payment methods
  // - Personal seller information
}
Enter fullscreen mode Exit fullscreen mode

Set Up Instructions / Tutorial

Prerequisites

# Required tools
node >= 18.0.0
npm >= 8.0.0
git
Enter fullscreen mode Exit fullscreen mode

Step 1: Clone and Install

# Clone the repository
git clone https://github.com/your-username/auction-vault.git
cd auction-vault

# Install dependencies
npm install

# Install Midnight SDK (when available)
npm install @midnight-ntwrk/midnight-js @midnight-ntwrk/compact
Enter fullscreen mode Exit fullscreen mode

Step 2: Environment Configuration

# Midnight Network Configuration
MIDNIGHT_RPC_URL=http://localhost:1337
MIDNIGHT_PROOF_SERVER_URL=http://localhost:8080
MIDNIGHT_INDEXER_URL=http://localhost:3001

# Application Configuration
NEXT_PUBLIC_APP_URL=http://localhost:3000
NEXT_PUBLIC_ENABLE_ZK_PROOFS=true

# Circuit Paths
CIRCUIT_PATH_BIDDING=./circuits/anonymous_bidding.compact
CIRCUIT_PATH_VERIFICATION=./circuits/seller_verification.compact
CIRCUIT_PATH_ESCROW=./circuits/escrow_payment.compact
Enter fullscreen mode Exit fullscreen mode

Step 3: Compile Zero-Knowledge Circuits

# Compile Compact circuits (requires Midnight toolchain)
mkdir -p compiled/circuits

# Compile bidding circuit
compact compile circuits/anonymous_bidding.compact -o compiled/circuits/

# Compile verification circuit  
compact compile circuits/seller_verification.compact -o compiled/circuits/

# Compile escrow circuit
compact compile circuits/escrow_payment.compact -o compiled/circuits/
Enter fullscreen mode Exit fullscreen mode

Step 4: Start Midnight Network (Local Development)

# Start local Midnight network using Docker
docker-compose up -d

# Services started:
# - Midnight RPC Node (port 1337)
# - Proof Server (port 8080) 
# - Indexer (port 3001)
Enter fullscreen mode Exit fullscreen mode

Step 5: Initialize Application

# Start development server
npm run dev

# Application available at http://localhost:3000
Enter fullscreen mode Exit fullscreen mode

Step 6: Test Privacy Features

// Test anonymous bidding
const testBid = async () => {
  // 1. Create anonymous identity
  const identity = await zkAuth.createIdentity({
    userType: 'bidder',
    credential: 'financial_capacity'
  });

  // 2. Generate bid proof
  const bidProof = await auctionVault.generateBidProof({
    amount: 1000,
    auctionId: 'auction_123',
    userSecret: identity.secret
  });

  // 3. Submit anonymous bid
  const result = await auctionVault.submitBid('auction_123', {
    zkProof: bidProof,
    commitment: hash(1000 + identity.nonce)
  });

  console.log('Bid submitted anonymously:', result.success);
};
Enter fullscreen mode Exit fullscreen mode

Step 7: Deploy to Production

# Build for production
npm run build

# Deploy to Vercel/Netlify
npm run deploy

# Configure production Midnight network endpoints
# Update environment variables for mainnet/testnet
Enter fullscreen mode Exit fullscreen mode

Development Workflow

# Run tests
npm test

# Type checking
npm run type-check

# Lint code
npm run lint

# Generate circuit proofs
npm run generate-proofs

# Start with hot reload
npm run dev
Enter fullscreen mode Exit fullscreen mode

Circuit Development

// Example: Adding new privacy feature
circuit NewPrivacyFeature {
    // Define private inputs (never revealed)
    private field secretData;
    private field userNonce;

    // Define public inputs (can be verified)
    public field publicCommitment;

    // Add constraints to prove validity without revealing secrets
    constraint hash(secretData, userNonce) == publicCommitment;
    constraint secretData > 0; // Validity check
}
Enter fullscreen mode Exit fullscreen mode

Troubleshooting
Common Issues:

  1. Circuit Compilation Errors
# Ensure Midnight toolchain is installed
midnight --version

# Check circuit syntax
compact check circuits/your_circuit.compact
Enter fullscreen mode Exit fullscreen mode
  1. Proof Generation Failures
# Verify circuit parameters
compact info compiled/circuits/your_circuit.compact

# Check input constraints
npm run test:circuits
Enter fullscreen mode Exit fullscreen mode
  1. Network Connection Issues
# Test Midnight network connectivity
curl http://localhost:1337/health

# Restart local network
docker-compose restart
Enter fullscreen mode Exit fullscreen mode

Thank You

Top comments (0)