npm.io
1.0.0 • Published 3 years ago

lgio-pfn

Licence
Apache-2.0
Version
1.0.0
Deps
0
Size
14 kB
Vulns
0
Weekly
0
Stars
1

Provably Fair Numbers (PFN)

High-performance cryptographically secure random number generator for gaming applications with provable fairness guarantees.

Features

  • Provably Fair: Uses HMAC-SHA256 for cryptographic security
  • Two Versions: V1 (original) and V2 (performance optimized)
  • Multiple Methods: random(), randomInt(), crash(), shuffle(), etc.
  • Deterministic: Same inputs always produce same outputs
  • Gaming Focused: Specialized methods for crash games, weighted selections
  • Well Tested: Comprehensive test suite with 30+ test cases

Installation

npm install

Quick Start

Basic Usage
const { ProvablyFairNumbers } = require('./index.js')

// Create instance with client and server seeds
const pfn = new ProvablyFairNumbers('client-seed-123', 'server-seed-456')

// Generate uniform random float [0,1)
const randomNum = pfn.random()

// Generate random integer in range [1, 6] (dice roll)
const diceRoll = pfn.randomInt(1, 6)

// Generate crash game multiplier (1% house edge)
const multiplier = pfn.crash(1)
Advanced Usage
// Weighted random selection
const outcome = pfn.weightedRandom({
  'win': 0.1,    // 10% chance
  'lose': 0.9    // 90% chance
})

// Shuffle array using Fisher-Yates algorithm
const deck = ['A', '2', '3', '4', '5', '6', '7', '8', '9', '10', 'J', 'Q', 'K']
const shuffled = pfn.shuffle(deck)

// Generate array of unique random numbers
const lotteryNumbers = pfn.randomIntRange(1, 49, 6, true) // 6 unique numbers from 1-49

API Reference

Constructor
new ProvablyFairNumbers(clientSeed, serverSeed, nonce = 0, index = null)

Parameters:

  • clientSeed (string|array): Client seed or array of seeds
  • serverSeed (string): Server seed for HMAC
  • nonce (number): Starting nonce value (default: 0)
  • index (number|null): Index mode instead of nonce (default: null)
Core Methods
random()

Returns uniform random float in [0,1)

const value = pfn.random() // e.g., 0.723456789
randomInt(min, max)

Returns unbiased integer in [min, max] (inclusive)

const roll = pfn.randomInt(1, 6) // Dice roll: 1-6
randomFloat(min, max, precision)

Returns random float with specified precision

const price = pfn.randomFloat(10.00, 100.00, 2) // e.g., 45.67
randomLong()

Returns random 256-bit BigInt for advanced cryptographic use

const bigNum = pfn.randomLong() // BigInt value
crash(houseEdge, max)

Returns crash game multiplier with specified house edge

const multiplier = pfn.crash(1, 1000) // 1% house edge, max 1000x
shuffle(array)

Returns Fisher-Yates shuffled copy of array (modifies original)

const shuffled = pfn.shuffle([1, 2, 3, 4, 5]) // e.g., [3, 1, 5, 2, 4]
weightedRandom(spec)

Returns weighted random selection from object

const result = pfn.weightedRandom({a: 1, b: 2, c: 3}) // 'c' has 50% chance
randomIntRange(min, max, size, unique)

Returns array of random integers

const numbers = pfn.randomIntRange(1, 10, 5, true) // 5 unique numbers 1-10
State Management Methods
next(), nextInt(), nextFloat()

Increment nonce and return next random value

const val1 = pfn.next()           // Advances nonce, returns random()
const val2 = pfn.nextInt(1, 10)   // Advances nonce, returns randomInt(1, 10)

Performance Comparison

V2 provides significant performance improvements with optimized algorithms:

Operation V1 Time V2 Time Improvement
10K sequential calls ~23ms ~21ms 9% faster
100 shuffle operations ~12ms ~11ms 9% faster
10K BigInt operations ~40ms ~34ms 15% faster

V2 includes advanced optimizations: buffer management, bitwise operations, and direct memory access for superior performance while maintaining identical statistical properties.

// V2 Performance Benefits
const pfnV2 = new ProvablyFairNumbersV2('client-seed', 'server-seed')

// Much faster for sequential operations (typical in gaming)
for (let i = 0; i < 10000; i++) {
  pfnV2.random() // 22% faster than V1
}

// Efficient shuffling with Fisher-Yates algorithm
const deck = ['A', '2', '3', '4', '5', '6', '7', '8', '9', '10', 'J', 'Q', 'K']
const shuffled = pfnV2.shuffle(deck) // Unbiased shuffle algorithm

Security & Fairness

  • Cryptographic Security: Uses HMAC-SHA256 with server seed
  • Provably Fair: Server seed can be revealed after use for verification
  • Deterministic: Same inputs always produce identical outputs
  • No Predictability: Each number is cryptographically secure
  • Gaming Standards: Meets industry standards for fair gaming

Testing

Run Unit Tests
npm test
Run Performance Tests
npm run test:performance

Performance comparison tests covering:

  • Basic functionality (random generation, ranges)
  • Statistical properties (uniformity, bounds)
  • Edge cases (min=max, large ranges, negative values)
  • Deterministic behavior (same seeds = same results)
  • Error handling (invalid parameters)
  • V1 vs V2 performance benchmarks
  • Shuffle optimizations for different array sizes
  • Export verification and compatibility
  • Performance benchmarks
  • Gaming-specific features (crash game, weighted random)
npm run performance
# or directly:
node __tests__/test-both-versions.cjs

Compares V1 vs V2 performance across different operations with detailed benchmarks.

Test Coverage
  • 30+ test cases covering all methods
  • Edge case testing for robustness
  • Performance validation ensuring efficiency
  • Security verification maintaining cryptographic properties
  • V1 vs V2 compatibility ensuring identical statistical properties

Version Differences

V1 (pfn.js)
  • Original implementation
  • Good performance for single operations
  • Simple, straightforward code
V2 (pfn-v2.js)
  • High-performance optimized algorithms
  • 9% faster for sequential operations
  • 15% faster for BigInt operations
  • 9% faster shuffle performance
  • Advanced buffer management and bitwise operations
  • Direct memory access for superior efficiency
  • Maintains identical statistical properties to V1
  • Overall performance: Faster than V1 with significant BigInt improvements

Exports

// Default export (V2 - recommended)
const { ProvablyFairNumbers } = require('./index.js')

// Specific versions
const { ProvablyFairNumbers } = require('./pfn.js')        // V1
const { ProvablyFairNumbersV2 } = require('./pfn-v2.js')   // V2

// All versions
const {
  ProvablyFairNumbers,    // V2 (default)
  ProvablyFairNumbersV1   // V1 (original)
} = require('./index.js')

License

Apache-2.0 License - see LICENSE file for details.