Initial commit: Upload Checkpoint project

This commit is contained in:
Caileb 2025-05-26 22:25:42 -05:00
commit c0e3781244
32 changed files with 6121 additions and 0 deletions

41
utils/logs.js Normal file
View file

@ -0,0 +1,41 @@
const seenConfigs = new Set();
export function init(msg) {
console.log(msg);
}
export function plugin(_name, msg) {
console.log(msg);
}
export function config(name, msg) {
if (!seenConfigs.has(name)) {
console.log(`Config ${msg} for ${name}`);
seenConfigs.add(name);
}
}
export function db(msg) {
console.log(msg);
}
export function server(msg) {
console.log(msg);
}
export function section(title) {
console.log(`\n=== ${title.toUpperCase()} ===`);
}
export function warn(_category, msg) {
console.warn(`WARNING: ${msg}`);
}
export function error(_category, msg) {
console.error(`ERROR: ${msg}`);
}
// General message function for bullet items
export function msg(msg) {
console.log(msg);
}

13
utils/network.js Normal file
View file

@ -0,0 +1,13 @@
export function getRealIP(request, server) {
let ip = request.headers.get('x-forwarded-for') || request.headers.get('x-real-ip');
if (ip?.includes(',')) ip = ip.split(',')[0].trim();
if (!ip && server) {
ip = server.remoteAddress;
}
if (!ip) {
const url = new URL(request.url);
ip = url.hostname;
}
if (ip?.startsWith('::ffff:')) ip = ip.slice(7);
return ip;
}

28
utils/plugins.js Normal file
View file

@ -0,0 +1,28 @@
import { resolve, extname, sep, isAbsolute } from 'path';
import { pathToFileURL } from 'url';
import { rootDir } from '../index.js';
/**
* Securely import a JavaScript module from within the application root.
* Prevents path traversal and disallows non-.js extensions.
*
* @param {string} relPath - The relative path to the module from the application root.
* @returns {Promise<any>} The imported module.
*/
export async function secureImportModule(relPath) {
if (isAbsolute(relPath)) {
throw new Error('Absolute paths are not allowed for module imports');
}
if (relPath.includes('..')) {
throw new Error('Relative paths containing .. are not allowed for module imports');
}
if (extname(relPath) !== '.js') {
throw new Error(`Only .js files can be imported: ${relPath}`);
}
const absPath = resolve(rootDir, relPath);
if (!absPath.startsWith(rootDir + sep)) {
throw new Error(`Module path outside of application root: ${relPath}`);
}
const url = pathToFileURL(absPath).href;
return import(url);
}

72
utils/proof.js Normal file
View file

@ -0,0 +1,72 @@
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);
}

20
utils/time.js Normal file
View file

@ -0,0 +1,20 @@
export function parseDuration(str) {
if (!str) return 0;
const m = /^([0-9]+)(ms|s|m|h|d)$/.exec(str);
if (!m) return 0;
const val = parseInt(m[1], 10);
switch (m[2]) {
case 'ms':
return val;
case 's':
return val * 1000;
case 'm':
return val * 60 * 1000;
case 'h':
return val * 60 * 60 * 1000;
case 'd':
return val * 24 * 60 * 60 * 1000;
default:
return 0;
}
}