Skip to content

Auctions

Sealed-Bid Auctions

Sealed-bid auctions ensure bidders can't see others' bids until everyone has committed. The commit-reveal protocol guarantees no bid can be changed after submission.

from commit_reveal import CommitRevealScheme
from datetime import datetime, timedelta
import json


class SecureAuction:
    def __init__(self, item_description, reserve_price=0):
        self.cr = CommitRevealScheme(use_zkp=True)
        self.item = item_description
        self.reserve_price = reserve_price
        self.bids = {}
        self.phase = "commit"

    def submit_bid(self, bidder_id, bid_amount):
        """Submit a sealed bid with ZKP proof of validity."""
        if bid_amount < self.reserve_price:
            raise ValueError(f"Bid below reserve price of {self.reserve_price}")

        bid_data = json.dumps({"amount": bid_amount}, sort_keys=True)
        commitment, salt = self.cr.commit(bid_data)

        # ZKP proof that bidder knows their bid
        proof = self.cr.create_zkp_proof(bid_data, salt, commitment)

        self.bids[bidder_id] = {
            "commitment": commitment,
            "salt": salt,
            "proof": proof,
            "revealed": None,
        }
        return commitment.hex()

    def reveal_bid(self, bidder_id, bid_amount):
        """Reveal a bid and verify it matches the commitment."""
        bid_data = json.dumps({"amount": bid_amount}, sort_keys=True)
        bid_info = self.bids[bidder_id]

        if self.cr.reveal(bid_data, bid_info["salt"], bid_info["commitment"]):
            bid_info["revealed"] = bid_amount
            return True
        return False

    def determine_winner(self):
        """Find the highest valid revealed bid."""
        valid_bids = {
            bidder: data["revealed"]
            for bidder, data in self.bids.items()
            if data["revealed"] is not None
        }
        if not valid_bids:
            return None, 0
        winner = max(valid_bids, key=valid_bids.get)
        return winner, valid_bids[winner]

Running the Auction

auction = SecureAuction("Vintage 1967 Mustang", reserve_price=15000)

# Commit phase -- bidders submit sealed bids
auction.submit_bid("alice", 18000)
auction.submit_bid("bob", 22000)
auction.submit_bid("charlie", 19500)

# Reveal phase -- bidders reveal their bids
auction.reveal_bid("alice", 18000)
auction.reveal_bid("bob", 22000)
auction.reveal_bid("charlie", 19500)

# Determine winner
winner, amount = auction.determine_winner()
print(f"Winner: {winner} with ${amount}")  # bob with $22000

Dutch Auction with Commitment

In a Dutch auction, the price starts high and decreases until a buyer commits. Using commit-reveal prevents front-running:

class DutchCommitmentAuction:
    def __init__(self, item, start_price, min_price, decrement):
        self.cr = CommitRevealScheme(use_zkp=True)
        self.item = item
        self.current_price = start_price
        self.min_price = min_price
        self.decrement = decrement
        self.commitments = {}

    def commit_to_buy(self, buyer_id, max_price):
        """Commit to buying at any price up to max_price."""
        commitment_data = json.dumps({"max_price": max_price}, sort_keys=True)
        commitment, salt = self.cr.commit(commitment_data)
        proof = self.cr.create_zkp_proof(commitment_data, salt, commitment)

        self.commitments[buyer_id] = {
            "commitment": commitment,
            "salt": salt,
            "proof": proof,
        }
        return commitment.hex()

The ZKP proof allows the auctioneer to verify that each buyer has committed to a valid maximum price without learning the actual amount.