diff --git a/src/wallet/wallet2.cpp b/src/wallet/wallet2.cpp index 893642af7..1956febb9 100644 --- a/src/wallet/wallet2.cpp +++ b/src/wallet/wallet2.cpp @@ -121,6 +121,8 @@ using namespace cryptonote; #define FIRST_REFRESH_GRANULARITY 1024 +#define GAMMA_PICK_HALF_WINDOW 5 + static const std::string MULTISIG_SIGNATURE_MAGIC = "SigMultisigPkV1"; static const std::string MULTISIG_EXTRA_INFO_MAGIC = "MultisigxV1"; @@ -6793,10 +6795,29 @@ void wallet2::get_outs(std::vector> error::get_output_distribution, "Decreasing offsets in rct distribution: " + std::to_string(block_offset) + ": " + std::to_string(rct_offsets[block_offset]) + ", " + std::to_string(block_offset + 1) + ": " + std::to_string(rct_offsets[block_offset + 1])); - uint64_t n_rct = rct_offsets[block_offset + 1] - rct_offsets[block_offset]; + uint64_t first_block_offset = block_offset, last_block_offset = block_offset; + for (size_t half_window = 0; half_window < GAMMA_PICK_HALF_WINDOW; ++half_window) + { + // end when we have a non empty block + uint64_t cum0 = first_block_offset > 0 ? rct_offsets[first_block_offset] - rct_offsets[first_block_offset - 1] : rct_offsets[0]; + if (cum0 > 1) + break; + uint64_t cum1 = last_block_offset > 0 ? rct_offsets[last_block_offset] - rct_offsets[last_block_offset - 1] : rct_offsets[0]; + if (cum1 > 1) + break; + if (first_block_offset == 0 && last_block_offset >= rct_offsets.size() - 2) + break; + // expand up to bounds + if (first_block_offset > 0) + --first_block_offset; + if (last_block_offset < rct_offsets.size() - 1) + ++last_block_offset; + } + const uint64_t n_rct = rct_offsets[last_block_offset] - (first_block_offset == 0 ? 0 : rct_offsets[first_block_offset - 1]); if (n_rct == 0) return rct_offsets[block_offset] ? rct_offsets[block_offset] - 1 : 0; - return rct_offsets[block_offset] + crypto::rand() % n_rct; + MDEBUG("Picking 1/" << n_rct << " in " << (last_block_offset - first_block_offset + 1) << " blocks centered around " << block_offset); + return rct_offsets[first_block_offset] + crypto::rand() % n_rct; }; size_t num_selected_transfers = 0;