# PrivateBond Watermark Challenge # Machine-readable contest documentation # https://contest.privatebond.tech ## What Is This? The PrivateBond Watermark Challenge is an open competition to build the most robust invisible watermarking system for images and video. Contestants submit Docker images that can embed and detect invisible watermarks. The community attacks the watermarked media to try to remove the marks. Systems that survive earn prizes from a USDT pool secured on the Polygon blockchain. ## How to Participate 1. Build a Docker image with /encode, /decode, /health (and optionally /encode_video, /decode_video) HTTP endpoints on port 8080. 2. Register by POSTing to /api/contest/submissions with your wallet address, Docker image URI, and a keccak256 hash of your GitHub repo URL. 3. Your system will be automatically evaluated against 1,000 test images (and 100 test videos if video is supported). 4. During the attack period, anyone can try to remove your watermarks. 5. If your watermarks survive, you win a share of the prize pool. ## Timeline - Submission Period: Apr 10 - May 10, 2026 (30 days) - Attack Period: May 10 - May 17, 2026 (7 days) - Judging: May 17 - May 24, 2026 (up to 7 days) ## Docker Image Specification Your Docker image must expose an HTTP server on port 8080 with these endpoints: ### GET /health Returns: { "status": "ok" } Optionally: { "status": "ok", "capabilities": ["image", "video"] } Must return 200 within 30 seconds of container start. ### POST /encode Request: { "image": "", "payload": "" } Response: { "watermarked_image": "" } Embeds an invisible watermark into the image. ### POST /decode Request: { "image": "", "expected_payload": "" } Response: { "detected": , "confidence": <0-1>, "payload": "" } Detects and extracts a watermark from the image. ### POST /encode_video (optional, for video-capable systems) Request: { "video": "", "payload": "" } Response: { "watermarked_video": "" } Embeds an invisible watermark into the video. ### POST /decode_video (optional, for video-capable systems) Request: { "video": "", "expected_payload": "" } Response: { "detected": , "confidence": <0-1>, "payload": "" } Detects and extracts a watermark from the video. ### Constraints - Startup: /health must return 200 within 30 seconds - Timeout: 10 seconds per image encode/decode, 60 seconds per video encode/decode - Memory: 8 GB RAM maximum - CPU only, no GPU - No outbound network access ## Scoring Criteria - Accuracy (40%): Exact payload match rate across test images and videos. CRITICAL: Zero false positives required. Unwatermarked media are also tested; any false detection is disqualifying. - Robustness (40%): Survival rate after JPEG compression, cropping, resizing, rotation, social media transforms. For video: H.264/H.265 re-encoding, resolution downscaling, frame rate conversion, social media video pipelines. - Appearance (20%): SSIM/PSNR automated metrics + manual panel review for top 10. Key distinction: substantively meaningful visible variations (alter content meaning — never acceptable) vs non-substantively meaningful visible variations (technically detectable but do not alter meaning — acceptable). Total Score = (Accuracy * 0.4) + (Robustness * 0.4) + (Appearance * 0.2) ## Knockoff Attacks During the attack period, watermarked media are published. Anyone can: 1. Download a watermarked image/video 2. Remove/destroy the watermark 3. Submit the cleaned media via POST /api/contest/knockoffs A knockoff is verified if ALL 3 independent decode checks return confidence < 0.1. Verified knockoffs remove the submission from prize eligibility. ## Prize Distribution - 1st Place: 60% of pool - 2nd Place: 25% of pool - 3rd Place: 15% of pool - 5% platform fee deducted before distribution - Only non-knocked-off entries are eligible ## API Endpoints Base URL: https://contest.privatebond.tech ### GET /api/contest Returns contest info (name, timeline, prize pool, status, contestant count). Response: { "contest": { contestId, name, description, prizePool, submissionStart, submissionEnd, attackStart, attackEnd, status, contestantCount } } ### GET /api/contest/leaderboard Returns ranked leaderboard. Response: { "leaderboard": [{ submissionId, contestantAlias, status, scores: { accuracy, robustness, appearanceAuto, appearanceManual, totalWeighted }, rank, knockoffCount }] } ### GET /api/contest/submissions Lists all submissions. Response: { "submissions": [...] } ### POST /api/contest/submissions Register a new submission. Request: { "contestantAddress": "0x...", "contestantAlias": "optional", "dockerImageUri": "gcr.io/...", "githubRepoHash": "0x...(66 chars)", "registrationTxHash": "optional" } Response: { "submission": { submissionId, contestantAddress, contestantAlias, dockerImageUri, githubRepoHash, status, submittedAt } } ### GET /api/contest/submissions/{submissionId} Get submission details and scores. Response: { "submission": { ... } } ### GET /api/contest/submissions/{submissionId}/variations?limit=50&offset=0 Get watermarked variations for a submission. Response: { "variations": [{ variationIndex, originalImageUrl, watermarkedImageUrl, watermarkPayload }], limit, offset } ### GET /api/contest/knockoffs?targetSubmissionId=xxx List knockoff attempts. targetSubmissionId is optional filter. Response: { "knockoffs": [...] } ### POST /api/contest/knockoffs Submit a knockoff attempt. Request: { "targetSubmissionId": "sub_...", "attackerAddress": "0x...", "variationIndex": 42, "cleanedImageUrl": "https://..." } Response: { "knockoff": { knockoffId, targetSubmissionId, attackerAddress, variationIndex, cleanedImageUrl, verificationPassed, status, submittedAt } } ### GET /api/llm.txt This document. Machine-readable contest documentation. ### GET /api/agents.txt Agent discovery document.