Merge pull request #10890

0b79679 wallet2: guard gamma picker against zero-output windows (selsta)

ACKs: jeffro256*, iamamyth
This commit is contained in:
tobtoht
2026-07-16 13:37:30 +00:00
2 changed files with 11 additions and 4 deletions
+1
View File
@@ -1051,6 +1051,7 @@ gamma_picker::gamma_picker(const std::vector<uint64_t> &rct_offsets, double shap
end = rct_offsets.data() + rct_offsets.size() - (std::max(1, CRYPTONOTE_DEFAULT_TX_SPENDABLE_AGE) - 1); end = rct_offsets.data() + rct_offsets.size() - (std::max(1, CRYPTONOTE_DEFAULT_TX_SPENDABLE_AGE) - 1);
num_rct_outputs = *(end - 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(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<double>(outputs_to_consider); // this assumes constant target over the whole rct range average_output_time = DIFFICULTY_TARGET_V2 * blocks_to_consider / static_cast<double>(outputs_to_consider); // this assumes constant target over the whole rct range
}; };
+10 -4
View File
@@ -261,16 +261,22 @@ TEST(select_outputs, exact_unlock_block)
TEST(select_outputs, exact_unlock_block_tiny) TEST(select_outputs, exact_unlock_block_tiny)
{ {
// Create chain of length CRYPTONOTE_DEFAULT_TX_SPENDABLE_AGE where there is one output in block 0 // Create a chain of length CRYPTONOTE_DEFAULT_TX_SPENDABLE_AGE with one
std::vector<uint64_t> offsets(std::max(CRYPTONOTE_DEFAULT_TX_SPENDABLE_AGE, 1), 0); // output in block 0. Since rct_offsets is cumulative, later blocks retain
offsets[0] = 1; // that output even though they contain no additional outputs.
std::vector<uint64_t> offsets(std::max(CRYPTONOTE_DEFAULT_TX_SPENDABLE_AGE, 1), 1);
tools::gamma_picker picker(offsets); 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; bool found_the_one_output = false;
for (size_t i = 0; i < MAX_PICK_TRIES; ++i) for (size_t i = 0; i < MAX_PICK_TRIES; ++i)
{
if (picker.pick() == 0) if (picker.pick() == 0)
{
found_the_one_output = true; found_the_one_output = true;
break;
}
}
EXPECT_TRUE(found_the_one_output); EXPECT_TRUE(found_the_one_output);
} }