From 0b7967907f82867d2884c559396543212600509e Mon Sep 17 00:00:00 2001 From: selsta Date: Fri, 10 Jul 2026 21:09:46 +0200 Subject: [PATCH] wallet2: guard gamma picker against zero-output windows --- src/wallet/wallet2.cpp | 1 + tests/unit_tests/output_selection.cpp | 14 ++++++++++---- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/src/wallet/wallet2.cpp b/src/wallet/wallet2.cpp index c128eda67..834679f1d 100644 --- a/src/wallet/wallet2.cpp +++ b/src/wallet/wallet2.cpp @@ -1051,6 +1051,7 @@ gamma_picker::gamma_picker(const std::vector &rct_offsets, double shap end = rct_offsets.data() + rct_offsets.size() - (std::max(1, CRYPTONOTE_DEFAULT_TX_SPENDABLE_AGE) - 1); num_rct_outputs = *(end - 1); THROW_WALLET_EXCEPTION_IF(num_rct_outputs == 0, error::wallet_internal_error, "No rct outputs"); + THROW_WALLET_EXCEPTION_IF(outputs_to_consider == 0, error::wallet_internal_error, "No outputs in consideration window"); average_output_time = DIFFICULTY_TARGET_V2 * blocks_to_consider / static_cast(outputs_to_consider); // this assumes constant target over the whole rct range }; diff --git a/tests/unit_tests/output_selection.cpp b/tests/unit_tests/output_selection.cpp index dd12d07f3..bd1eac67b 100644 --- a/tests/unit_tests/output_selection.cpp +++ b/tests/unit_tests/output_selection.cpp @@ -261,16 +261,22 @@ TEST(select_outputs, exact_unlock_block) TEST(select_outputs, exact_unlock_block_tiny) { - // Create chain of length CRYPTONOTE_DEFAULT_TX_SPENDABLE_AGE where there is one output in block 0 - std::vector offsets(std::max(CRYPTONOTE_DEFAULT_TX_SPENDABLE_AGE, 1), 0); - offsets[0] = 1; + // Create a chain of length CRYPTONOTE_DEFAULT_TX_SPENDABLE_AGE with one + // output in block 0. Since rct_offsets is cumulative, later blocks retain + // that output even though they contain no additional outputs. + std::vector offsets(std::max(CRYPTONOTE_DEFAULT_TX_SPENDABLE_AGE, 1), 1); tools::gamma_picker picker(offsets); - constexpr size_t MAX_PICK_TRIES = 10; + constexpr size_t MAX_PICK_TRIES = 1000; bool found_the_one_output = false; for (size_t i = 0; i < MAX_PICK_TRIES; ++i) + { if (picker.pick() == 0) + { found_the_one_output = true; + break; + } + } EXPECT_TRUE(found_the_one_output); }