From c8651b1632315c13bb3eb8ecfa73063066192184 Mon Sep 17 00:00:00 2001 From: Abdul Azeem Date: Thu, 7 Nov 2024 13:28:17 +0530 Subject: [PATCH 1/2] feat: Clear filtersMap when it reaches maximum entries allowed The code changes in `api.ts` introduce a check to clear the `filtersMap` when it reaches the maximum number of entries allowed, as specified by the `maxEntriesAllowed` configuration value. This ensures that the `filtersMap` does not exceed the allowed size and prevents potential performance issues and DoS attacks --- src/api.ts | 12 ++++++++++++ src/config.ts | 2 ++ 2 files changed, 14 insertions(+) diff --git a/src/api.ts b/src/api.ts index 820c3677..a301ddb3 100755 --- a/src/api.ts +++ b/src/api.ts @@ -2799,6 +2799,10 @@ export const methods = { unsubscribe, type: Types.FilterTypes.block, } + if (filtersMap.size >= config.maxEntriesAllowed) { + filtersMap.clear() + console.log(`filtersMap cleared after ${config.maxEntriesAllowed} entries`) + } filtersMap.set(filterId.toString(), internalFilter) callback(null, filterId) @@ -2833,6 +2837,10 @@ export const methods = { unsubscribe, type: Types.FilterTypes.pendingTransaction, } + if (filtersMap.size >= config.maxEntriesAllowed) { + filtersMap.clear() + console.log(`filtersMap cleared after ${config.maxEntriesAllowed} entries`) + } filtersMap.set(filterId.toString(), internalFilter) callback(null, filterId) @@ -2934,6 +2942,10 @@ export const methods = { unsubscribe, type: Types.FilterTypes.log, } + if (filtersMap.size >= config.maxEntriesAllowed) { + filtersMap.clear() + console.log(`filtersMap cleared after ${config.maxEntriesAllowed} entries`) + } filtersMap.set(filterId.toString(), internalFilter) callback(null, filterId) diff --git a/src/config.ts b/src/config.ts index a633cf32..ae3e8be8 100644 --- a/src/config.ts +++ b/src/config.ts @@ -106,6 +106,7 @@ type Config = { } axiosTimeoutInMs: number enableBlacklistingIP: boolean + maxEntriesAllowed: number // maximum number of entries allowed for map to store } export type ServicePointTypes = 'aalg-warmup' @@ -249,4 +250,5 @@ export const CONFIG: Config = { }, axiosTimeoutInMs: 3000, enableBlacklistingIP: false, + maxEntriesAllowed: 10000, } From 46ea364221d2eec6f284b98d4621ae5647b68dda Mon Sep 17 00:00:00 2001 From: Abdul Azeem Date: Wed, 20 Nov 2024 14:21:58 +0300 Subject: [PATCH 2/2] feat: Implement removeOldestFilter to manage filtersMap size --- src/api.ts | 10 ++++------ src/utils.ts | 19 +++++++++++++++++++ 2 files changed, 23 insertions(+), 6 deletions(-) diff --git a/src/api.ts b/src/api.ts index a301ddb3..e8b394e8 100755 --- a/src/api.ts +++ b/src/api.ts @@ -27,6 +27,7 @@ import { getSyncTime, removeFromNodeList, sanitizeIpAndPort, + removeOldestFilter, } from './utils' import crypto from 'crypto' import { logEventEmitter } from './logger' @@ -2800,8 +2801,7 @@ export const methods = { type: Types.FilterTypes.block, } if (filtersMap.size >= config.maxEntriesAllowed) { - filtersMap.clear() - console.log(`filtersMap cleared after ${config.maxEntriesAllowed} entries`) + removeOldestFilter(filtersMap) } filtersMap.set(filterId.toString(), internalFilter) @@ -2838,8 +2838,7 @@ export const methods = { type: Types.FilterTypes.pendingTransaction, } if (filtersMap.size >= config.maxEntriesAllowed) { - filtersMap.clear() - console.log(`filtersMap cleared after ${config.maxEntriesAllowed} entries`) + removeOldestFilter(filtersMap) } filtersMap.set(filterId.toString(), internalFilter) @@ -2943,8 +2942,7 @@ export const methods = { type: Types.FilterTypes.log, } if (filtersMap.size >= config.maxEntriesAllowed) { - filtersMap.clear() - console.log(`filtersMap cleared after ${config.maxEntriesAllowed} entries`) + removeOldestFilter(filtersMap) } filtersMap.set(filterId.toString(), internalFilter) diff --git a/src/utils.ts b/src/utils.ts index 38fda413..a60d10e0 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -29,6 +29,7 @@ import { OriginalTxData, AccountTypesData, Account2, + InternalFilter } from './types' import Sntp from '@hapi/sntp' import { randomBytes, createHash } from 'crypto' @@ -1838,6 +1839,24 @@ export function sanitizeIpAndPort(ipPort: string): { isValid: boolean; error?: s return { isValid: true } } +export function removeOldestFilter(filtersMap: Map): void { + let oldestKey: string | undefined; + let oldestTimestamp = Infinity; + + // Iterate through the map to find the oldest entry + for (const [key, value] of filtersMap) { + if (value.filter.lastQueriedTimestamp < oldestTimestamp) { + oldestTimestamp = value.filter.lastQueriedTimestamp; + oldestKey = key; + } + } + + // Remove the oldest entry + if (oldestKey !== undefined) { + filtersMap.delete(oldestKey); + } +} + class Semaphore { private queue: (() => void)[] = [] private value: number