Architecture Overview
The provably fair system is implemented across three main components:- Core Library (
lib/provably-fair.ts) - Cryptographic functions - Seed Management API (
api/provably-fair/seed/route.ts) - Seed generation and rotation - Case Opening API (
api/cases/open/route.ts) - Result calculation and recording
Cryptographic Functions
Server Seed Generation
Server seeds are generated using Node.js’s cryptographically secure random number generator:- Uses
crypto.randomBytes()which sources from the OS’s CSPRNG - Generates 32 bytes (256 bits) of entropy
- Converts to 64 hexadecimal characters for easy handling
- Provides ~10^77 possible combinations
Client Seed Generation
Client seeds follow a similar approach but are shorter by default:- Generates 16 bytes (128 bits) of entropy
- Results in 32 hexadecimal characters
- Can be replaced with any user-provided string
- Provides ~10^38 possible combinations
Seed Hashing (Commitment)
Before case opening, the server seed is hashed using SHA-256:- One-way function: Cannot reverse hash to get original seed
- Deterministic: Same input always produces same output
- Collision-resistant: Virtually impossible to find two inputs with same hash
- Industry standard for cryptographic commitments
Roll Calculation Algorithm
The core of the provably fair system is the roll calculation function:Algorithm Breakdown
Step 1: Construct Message
- Client Seed:
a3f5e9c1b2d4f6a8 - Nonce:
42 - Message:
a3f5e9c1b2d4f6a8-42
Step 2: Calculate HMAC-SHA256
- Determinism: Same inputs always produce same output
- Unpredictability: Cannot predict output without knowing server seed
- Uniformity: Output is evenly distributed across possible values
- HMAC uses the server seed as a secret key
- Prevents rainbow table attacks
- Standard practice in provably fair implementations
Step 3: Extract Numeric Value
- 8 hex chars = 4 bytes = 32 bits
- Range: 0 to 4,294,967,295 (0xFFFFFFFF)
- SHA-256 produces 64 hex characters (256 bits)
- Using 32 bits provides sufficient randomness
- More bits don’t improve distribution for our use case
- Matches industry standards (similar to Stake.com, CSGORoll)
Step 4: Normalize to 0-1 Range
- Ensures 0 ≤ result < 1
- Provides uniform distribution
- Compatible with probability-based item selection
Mathematical Properties
Uniformity: The division by (MAX_VAL + 1) ensures each possible roll value has equal probability:f always produces the same output.
Item Selection Algorithm
Once we have a roll value (0 to 1), we select the winning item based on probability weights:How It Works
Example: Consider a case with 3 items:- Common Item: probability = 70
- Rare Item: probability = 25
- Legendary Item: probability = 5
- Total Weight = 100
- Common: 0 to 0.70 (70% chance)
- Rare: 0.70 to 0.95 (25% chance)
- Legendary: 0.95 to 1.00 (5% chance)
roll = 0.732:
target = 0.732 * 100 = 73.2- Check Common:
73.2 < 70? No - Check Rare:
73.2 < (70 + 25)? Yes → Rare Item wins
API Integration
Seed Management Endpoint
GET/api/provably-fair/seed
Retrieves current seed information:
/api/provably-fair/seed
Rotates seeds and resets nonce:
Case Opening Flow
POST/api/cases/open
From app/api/cases/open/route.ts:52-53:
- Fetch user’s current seeds (line 29-38)
- Update client seed if provided (line 41-49)
- Calculate roll result (line 52-53)
- Select winning item (line 71)
- Update nonce (line 74-77)
- Record game roll (line 80-90)
- Return result with fairness proof (line 94-102)
Database Schema
user_seeds Table
game_rolls Table (Audit Log)
Fromapp/api/cases/open/route.ts:80-90:
Security Considerations
Seed Rotation Best Practices
-
When to rotate:
- User explicitly requests seed change
- After a certain number of games (e.g., 1000)
- User suspects compromise
-
What gets revealed:
- Previous server seed (after rotation)
- All game rolls using that seed can now be verified
-
Nonce reset:
- Nonce resets to 0 on seed rotation
- Prevents nonce overflow
- Maintains clean audit trail
Timing Attack Prevention
Fromapp/api/provably-fair/seed/route.ts:21-38, seeds are created atomically:
Performance Optimization
Cryptographic Operations
- HMAC-SHA256: ~0.1ms per operation
- SHA-256 hash: ~0.05ms per operation
- Random byte generation: ~0.01ms per operation
Database Queries
Optimizations in the implementation:- Single query to fetch seeds
- Single update for nonce increment
- Asynchronous game roll insertion (doesn’t block response)
Testing and Validation
Verify Determinism
Verify Distribution
Next Steps
Verification Guide
Learn how to verify your case opening results using these algorithms
