import crypto from 'crypto'; import { getRealIP } from './network.js'; export function generateChallenge(checkpointConfig) { const challenge = crypto.randomBytes(16).toString('hex'); const salt = crypto.randomBytes(checkpointConfig.SaltLength).toString('hex'); return { challenge, salt }; } export function calculateHash(input) { return crypto.createHash('sha256').update(input).digest('hex'); } export function verifyPoW(challenge, salt, nonce, difficulty) { const hash = calculateHash(challenge + salt + nonce); return hash.startsWith('0'.repeat(difficulty)); } export function checkPoSTimes(times, enableCheck, ratio) { if (!Array.isArray(times) || times.length !== 3) { throw new Error('Invalid PoS run times length'); } const minT = Math.min(...times); const maxT = Math.max(...times); if (enableCheck && maxT > minT * ratio) { throw new Error(`PoS run times inconsistent (ratio ${maxT / minT} > ${ratio})`); } } export const challengeStore = new Map(); export function generateRequestID(request, checkpointConfig) { const { challenge, salt } = generateChallenge(checkpointConfig); const posSeed = crypto.randomBytes(32).toString('hex'); const requestID = crypto.randomBytes(16).toString('hex'); const params = { Challenge: challenge, Salt: salt, Difficulty: checkpointConfig.Difficulty, ExpiresAt: Date.now() + checkpointConfig.ChallengeExpiration, CreatedAt: Date.now(), ClientIP: getRealIP(request), PoSSeed: posSeed, }; challengeStore.set(requestID, params); return requestID; } export function getChallengeParams(requestID) { return challengeStore.get(requestID); } export function deleteChallenge(requestID) { challengeStore.delete(requestID); } export function verifyPoS(hashes, times, checkpointConfig) { if (!Array.isArray(hashes) || hashes.length !== 3) { throw new Error('Invalid PoS hashes length'); } if (!Array.isArray(times) || times.length !== 3) { throw new Error('Invalid PoS run times length'); } if (hashes[0] !== hashes[1] || hashes[1] !== hashes[2]) { throw new Error('PoS hashes do not match'); } if (hashes[0].length !== 64) { throw new Error('Invalid PoS hash length'); } checkPoSTimes(times, checkpointConfig.CheckPoSTimes, checkpointConfig.PoSTimeConsistencyRatio); }