mining: reject invalid block create options

Check BlockCreateOptions before block template creation instead of
clamping runtime values. This makes invalid runtime block creation
options, including those passed by IPC mining clients, fail explicitly
instead of silently mining with different values than the caller
requested.

Runtime option validation now uses the same error wording as startup
option validation. Startup validation also rejects -blockmaxweight
values lower than -blockreservedweight instead of allowing them to be
clamped later.

Co-authored-by: Ryan Ofsky <ryan@ofsky.org>
This commit is contained in:
Sjors Provoost
2026-05-18 15:59:57 +02:00
parent 8daac1d6eb
commit 4637cd157d
10 changed files with 71 additions and 37 deletions

View File

@@ -17,6 +17,7 @@
#include <cstdint>
#include <optional>
#include <utility>
using common::AmountErrMsg;
using util::Error;
@@ -24,22 +25,35 @@ using util::Result;
namespace node {
Result<void> CheckMiningOptions(const BlockCreateOptions& options, bool use_argnames)
Result<void> CheckMiningOptions(BlockCreateOptions options, bool use_argnames)
{
if (options.block_max_weight && *options.block_max_weight > MAX_BLOCK_WEIGHT) {
return Error{Untranslated(strprintf("%s (%d) exceeds consensus maximum block weight (%d)",
use_argnames ? "-blockmaxweight" : "block_max_weight",
*options.block_max_weight, MAX_BLOCK_WEIGHT))};
options = FlattenMiningOptions(std::move(options));
if (*options.block_reserved_weight < MINIMUM_BLOCK_RESERVED_WEIGHT) {
return Error{Untranslated(strprintf("%s (%d) is lower than minimum safety value of (%d)",
use_argnames ? "-blockreservedweight" : "block_reserved_weight",
*options.block_reserved_weight, MINIMUM_BLOCK_RESERVED_WEIGHT))};
}
if (options.block_reserved_weight && *options.block_reserved_weight > MAX_BLOCK_WEIGHT) {
if (*options.block_reserved_weight > MAX_BLOCK_WEIGHT) {
return Error{Untranslated(strprintf("%s (%d) exceeds consensus maximum block weight (%d)",
use_argnames ? "-blockreservedweight" : "block_reserved_weight",
*options.block_reserved_weight, MAX_BLOCK_WEIGHT))};
}
if (options.block_reserved_weight && *options.block_reserved_weight < MINIMUM_BLOCK_RESERVED_WEIGHT) {
return Error{Untranslated(strprintf("%s (%d) is lower than minimum safety value of (%d)",
if (*options.block_max_weight > MAX_BLOCK_WEIGHT) {
return Error{Untranslated(strprintf("%s (%d) exceeds consensus maximum block weight (%d)",
use_argnames ? "-blockmaxweight" : "block_max_weight",
*options.block_max_weight, MAX_BLOCK_WEIGHT))};
}
if (*options.block_reserved_weight > *options.block_max_weight) {
return Error{Untranslated(strprintf("%s (%d) exceeds %s (%d)",
use_argnames ? "-blockreservedweight" : "block_reserved_weight",
*options.block_reserved_weight, MINIMUM_BLOCK_RESERVED_WEIGHT))};
*options.block_reserved_weight,
use_argnames ? "-blockmaxweight" : "block_max_weight",
*options.block_max_weight))};
}
if (options.coinbase_output_max_additional_sigops > MAX_BLOCK_SIGOPS_COST) {
return Error{Untranslated(strprintf("%s (%zu) exceeds consensus maximum block sigops cost (%d)",
"coinbase_output_max_additional_sigops",
options.coinbase_output_max_additional_sigops, MAX_BLOCK_SIGOPS_COST))};
}
return {};
}