From 3249e344f558a80ab96b493158312a89b49ad5da Mon Sep 17 00:00:00 2001 From: Ivan Shumkov Date: Mon, 3 Aug 2026 18:30:45 +0700 Subject: [PATCH] feat(dashmate): expose Tenderdash consensus DoS rate-limit knobs Plumb three Tenderdash [consensus] rate-limit config keys through dashmate so operators can override them from dashmate config: - verification-rate-limit (verificationRateLimit, default 300) - peer-vote-rate-limit (peerVoteRateLimit, default 600) - peer-data-rate-limit (peerDataRateLimit, default 500) Changes: - config.toml.dot: emit the three keys as bare numbers in [consensus] - getBaseConfigFactory.js: add the three defaults (300/600/500) - configJsonSchema.js: add three number properties (minimum 0) and extend the consensus required array (consensus is additionalProperties:false) - getConfigFileMigrationsFactory.js: backfill migration so existing configs gain the now-required keys These keys are absent today; a Tenderdash node with the keys omitted falls back to its compiled-in defaults, so this is preparation for later limit tuning, not required for a node to run. NOTE: the migration is keyed at 4.2.0 as a placeholder for the release that ships this change. It must be set to the actual shipping dashmate version before release. Co-Authored-By: Claude Opus 4.8 --- .../configs/defaults/getBaseConfigFactory.js | 3 ++ .../configs/getConfigFileMigrationsFactory.js | 30 +++++++++++++++++++ .../dashmate/src/config/configJsonSchema.js | 14 ++++++++- .../platform/drive/tenderdash/config.toml.dot | 7 +++++ 4 files changed, 53 insertions(+), 1 deletion(-) diff --git a/packages/dashmate/configs/defaults/getBaseConfigFactory.js b/packages/dashmate/configs/defaults/getBaseConfigFactory.js index fbcbbc15dc7..9bb687806d8 100644 --- a/packages/dashmate/configs/defaults/getBaseConfigFactory.js +++ b/packages/dashmate/configs/defaults/getBaseConfigFactory.js @@ -407,6 +407,9 @@ export default function getBaseConfigFactory() { gossipSleepDuration: '100ms', queryMaj23SleepDuration: '2s', }, + verificationRateLimit: 300, + peerVoteRateLimit: 600, + peerDataRateLimit: 500, unsafeOverride: { propose: { timeout: null, diff --git a/packages/dashmate/configs/getConfigFileMigrationsFactory.js b/packages/dashmate/configs/getConfigFileMigrationsFactory.js index 23fe3f0fbaa..7d300dfa28f 100644 --- a/packages/dashmate/configs/getConfigFileMigrationsFactory.js +++ b/packages/dashmate/configs/getConfigFileMigrationsFactory.js @@ -1701,6 +1701,36 @@ export default function getConfigFileMigrationsFactory(homeDir, defaultConfigs) return configFile; }, + '4.2.0': (configFile) => { + // Backfill the Tenderdash consensus rate-limit defaults so a regenerated + // config.toml carries the new [consensus] keys. The schema now requires + // them, so an existing config that predates them would fail validation + // until it gains the values. + // + // Keyed at the release that ships these keys: the runner skips a + // migration whose version equals the operator's current version, so a + // key equal to the version an operator already runs never fires and only + // configs written before this release are backfilled. + Object.entries(configFile.configs) + .forEach(([name, options]) => { + const defaultConfig = getDefaultConfigByNameOrGroup(name, options.group); + const consensus = options.platform?.drive?.tenderdash?.consensus; + if (!consensus) { + return; + } + if (typeof consensus.verificationRateLimit === 'undefined') { + consensus.verificationRateLimit = defaultConfig.getStored('platform.drive.tenderdash.consensus.verificationRateLimit'); + } + if (typeof consensus.peerVoteRateLimit === 'undefined') { + consensus.peerVoteRateLimit = defaultConfig.getStored('platform.drive.tenderdash.consensus.peerVoteRateLimit'); + } + if (typeof consensus.peerDataRateLimit === 'undefined') { + consensus.peerDataRateLimit = defaultConfig.getStored('platform.drive.tenderdash.consensus.peerDataRateLimit'); + } + }); + + return configFile; + }, }; } diff --git a/packages/dashmate/src/config/configJsonSchema.js b/packages/dashmate/src/config/configJsonSchema.js index 191f3845f08..72256d1b08e 100644 --- a/packages/dashmate/src/config/configJsonSchema.js +++ b/packages/dashmate/src/config/configJsonSchema.js @@ -1211,6 +1211,18 @@ export default { additionalProperties: false, required: ['gossipSleepDuration', 'queryMaj23SleepDuration'], }, + verificationRateLimit: { + type: 'number', + minimum: 0, + }, + peerVoteRateLimit: { + type: 'number', + minimum: 0, + }, + peerDataRateLimit: { + type: 'number', + minimum: 0, + }, unsafeOverride: { type: 'object', properties: { @@ -1259,7 +1271,7 @@ export default { }, }, additionalProperties: false, - required: ['createEmptyBlocks', 'createEmptyBlocksInterval', 'peer', 'unsafeOverride'], + required: ['createEmptyBlocks', 'createEmptyBlocksInterval', 'peer', 'unsafeOverride', 'verificationRateLimit', 'peerVoteRateLimit', 'peerDataRateLimit'], }, log: { type: 'object', diff --git a/packages/dashmate/templates/platform/drive/tenderdash/config.toml.dot b/packages/dashmate/templates/platform/drive/tenderdash/config.toml.dot index 64bb46f2a4f..76f28777817 100644 --- a/packages/dashmate/templates/platform/drive/tenderdash/config.toml.dot +++ b/packages/dashmate/templates/platform/drive/tenderdash/config.toml.dot @@ -478,6 +478,13 @@ create-empty-blocks-interval = "{{= it.platform.drive.tenderdash.consensus.creat peer-gossip-sleep-duration = "{{= it.platform.drive.tenderdash.consensus.peer.gossipSleepDuration }}" peer-query-maj23-sleep-duration = "{{= it.platform.drive.tenderdash.consensus.peer.queryMaj23SleepDuration }}" +# Per-peer vote-channel budget (verification-work/sec). 0 disables. +peer-vote-rate-limit = {{= it.platform.drive.tenderdash.consensus.peerVoteRateLimit }} +# Node-wide BLS verification budget (ops/sec). Must be 0 or >= 33. +verification-rate-limit = {{= it.platform.drive.tenderdash.consensus.verificationRateLimit }} +# Per-peer data-channel budget (verification-work/sec). 0 disables. +peer-data-rate-limit = {{= it.platform.drive.tenderdash.consensus.peerDataRateLimit }} + ### Unsafe Timeout Overrides ### # These fields provide temporary overrides for the Timeout consensus parameters.