Checkpoint/utils/proof.js

72 lines
2.3 KiB
JavaScript

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);
}