72 lines
2.3 KiB
JavaScript
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);
|
|
}
|