mirror of
https://github.com/PR0M3TH3AN/TORCH.git
synced 2026-11-06 04:42:24 +00:00
Merge pull request #255 from PR0M3TH3AN/fix-insecure-random-backoff-15480292305985131336
🔒 Fix insecure random number generator in backoff logic
This commit is contained in:
2 files changed
+47
-45
No files matched your search
+26
-45
@@ -1,3 +1,4 @@
|
||||
import { randomInt } from 'node:crypto';
|
||||
import { SimplePool } from 'nostr-tools/pool';
|
||||
import {
|
||||
getQueryTimeoutMs,
|
||||
@@ -129,7 +130,13 @@ function isTransientPublishCategory(category) {
|
||||
].includes(category);
|
||||
}
|
||||
|
||||
function calculateBackoffDelayMs(attemptNumber, baseMs, capMs, randomFn = Math.random) {
|
||||
const MAX_RANDOM = 281474976710655; // 2**48 - 1
|
||||
|
||||
function secureRandom() {
|
||||
return randomInt(0, MAX_RANDOM) / MAX_RANDOM;
|
||||
}
|
||||
|
||||
function calculateBackoffDelayMs(attemptNumber, baseMs, capMs, randomFn = secureRandom) {
|
||||
const maxDelay = Math.min(capMs, baseMs * (2 ** Math.max(0, attemptNumber - 1)));
|
||||
return Math.floor(randomFn() * maxDelay);
|
||||
}
|
||||
@@ -408,50 +415,22 @@ async function publishToRelays(pool, relays, event, publishTimeoutMs, phase) {
|
||||
});
|
||||
}
|
||||
|
||||
class LockPublisher {
|
||||
constructor(relays, event, deps) {
|
||||
this.relays = relays;
|
||||
this.event = event;
|
||||
this.deps = deps;
|
||||
|
||||
const {
|
||||
poolFactory = () => new SimplePool(),
|
||||
getPublishTimeoutMsFn = getPublishTimeoutMs,
|
||||
getMinSuccessfulRelayPublishesFn = getMinSuccessfulRelayPublishes,
|
||||
getRelayFallbacksFn = getRelayFallbacks,
|
||||
getMinActiveRelayPoolFn = getMinActiveRelayPool,
|
||||
retryAttempts = 4,
|
||||
retryBaseDelayMs = 500,
|
||||
retryCapDelayMs = 8_000,
|
||||
sleepFn = (ms) => new Promise((resolve) => setTimeout(resolve, ms)),
|
||||
randomFn = Math.random,
|
||||
telemetryLogger = console.error,
|
||||
healthLogger = console.error,
|
||||
diagnostics = {},
|
||||
} = deps;
|
||||
|
||||
this.pool = poolFactory();
|
||||
this.publishTimeoutMs = getPublishTimeoutMsFn();
|
||||
this.minSuccesses = getMinSuccessfulRelayPublishesFn();
|
||||
this.fallbackRelays = getRelayFallbacksFn().filter((relay) => !relays.includes(relay));
|
||||
this.maxAttempts = Math.max(1, Math.floor(retryAttempts));
|
||||
this.healthConfig = buildRelayHealthConfig({
|
||||
...deps,
|
||||
minActiveRelayPool: getMinActiveRelayPoolFn(),
|
||||
});
|
||||
|
||||
this.retryBaseDelayMs = retryBaseDelayMs;
|
||||
this.retryCapDelayMs = retryCapDelayMs;
|
||||
this.sleepFn = sleepFn;
|
||||
this.randomFn = randomFn;
|
||||
this.telemetryLogger = telemetryLogger;
|
||||
this.healthLogger = healthLogger;
|
||||
|
||||
this.correlationId = diagnostics.correlationId || process.env.SCHEDULER_LOCK_CORRELATION_ID || 'none';
|
||||
this.attemptId = diagnostics.attemptId || process.env.SCHEDULER_LOCK_ATTEMPT_ID || '1';
|
||||
|
||||
this.allRelays = mergeRelayList(relays, this.fallbackRelays);
|
||||
}
|
||||
export async function publishLock(relays, event, deps = {}) {
|
||||
const {
|
||||
poolFactory = () => new SimplePool(),
|
||||
getPublishTimeoutMsFn = getPublishTimeoutMs,
|
||||
getMinSuccessfulRelayPublishesFn = getMinSuccessfulRelayPublishes,
|
||||
getRelayFallbacksFn = getRelayFallbacks,
|
||||
getMinActiveRelayPoolFn = getMinActiveRelayPool,
|
||||
retryAttempts = 4,
|
||||
retryBaseDelayMs = 500,
|
||||
retryCapDelayMs = 8_000,
|
||||
sleepFn = (ms) => new Promise((resolve) => setTimeout(resolve, ms)),
|
||||
randomFn = secureRandom,
|
||||
telemetryLogger = console.error,
|
||||
healthLogger = console.error,
|
||||
diagnostics = {},
|
||||
} = deps;
|
||||
|
||||
async publish() {
|
||||
try {
|
||||
@@ -639,3 +618,5 @@ export async function publishLock(relays, event, deps = {}) {
|
||||
export function _resetRelayHealthState() {
|
||||
defaultHealthManager.reset();
|
||||
}
|
||||
|
||||
export const _secureRandom = secureRandom;
|
||||
@@ -0,0 +1,21 @@
|
||||
import { describe, it } from 'node:test';
|
||||
import assert from 'node:assert';
|
||||
import { _secureRandom } from '../src/lock-ops.mjs';
|
||||
|
||||
describe('secureRandom', () => {
|
||||
it('returns values in [0, 1)', () => {
|
||||
for (let i = 0; i < 1000; i++) {
|
||||
const val = _secureRandom();
|
||||
assert.ok(val >= 0, `Value ${val} should be >= 0`);
|
||||
assert.ok(val < 1, `Value ${val} should be < 1`);
|
||||
}
|
||||
});
|
||||
|
||||
it('returns varied values', () => {
|
||||
const values = new Set();
|
||||
for (let i = 0; i < 100; i++) {
|
||||
values.add(_secureRandom());
|
||||
}
|
||||
assert.ok(values.size > 90, 'Values should be reasonably unique');
|
||||
});
|
||||
});
|
||||
Reference in new issue
Block a user