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:
- Bidder Identity Protection: Participants can bid anonymously without revealing personal information
- Financial Privacy: Bid amounts and payment methods remain confidential through cryptographic escrow
- Seller Verification: Sellers can prove authenticity and credibility without disclosing sensitive business data
- Anti-Manipulation: Prevents bid sniping and market manipulation through anonymous bidding
Key features include:
- Anonymous bidding with zero-knowledge proof verification
- Cryptographic escrow for secure payments
- Real-time auction updates with privacy preservation
- Seller verification without identity disclosure
- 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:
- 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;
}
// 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);
}
- 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;
}
}
- 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 };
}
}
- 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;
}
}
Data Protection as a Core Feature
Privacy and data protection are fundamental to AuctionVault's architecture, not superficial additions:
- 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)
}
- 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)
});
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
});
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()
});
- 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);
}
}
- 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
}
Set Up Instructions / Tutorial
Prerequisites
# Required tools
node >= 18.0.0
npm >= 8.0.0
git
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
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
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/
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)
Step 5: Initialize Application
# Start development server
npm run dev
# Application available at http://localhost:3000
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);
};
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
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
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
}
Troubleshooting
Common Issues:
- Circuit Compilation Errors
# Ensure Midnight toolchain is installed
midnight --version
# Check circuit syntax
compact check circuits/your_circuit.compact
- Proof Generation Failures
# Verify circuit parameters
compact info compiled/circuits/your_circuit.compact
# Check input constraints
npm run test:circuits
- Network Connection Issues
# Test Midnight network connectivity
curl http://localhost:1337/health
# Restart local network
docker-compose restart
Thank You
Top comments (0)