Skip to content

Commit

Permalink
Use upstream Shuffle which doesn't cause DEBUG panic
Browse files Browse the repository at this point in the history
  • Loading branch information
instagibbs committed Mar 20, 2019
1 parent de56cd8 commit 6491b4d
Show file tree
Hide file tree
Showing 2 changed files with 28 additions and 2 deletions.
25 changes: 25 additions & 0 deletions src/random.h
Original file line number Diff line number Diff line change
Expand Up @@ -150,4 +150,29 @@ bool Random_SanityCheck();
/** Initialize the RNG. */
void RandomInit();

/** Shuffle function Poached from upstream: #14624 **/

/** More efficient than using std::shuffle on a FastRandomContext.
*
* This is more efficient as std::shuffle will consume entropy in groups of
* 64 bits at the time and throw away most.
*
* This also works around a bug in libstdc++ std::shuffle that may cause
* type::operator=(type&&) to be invoked on itself, which the library's
* debug mode detects and panics on. This is a known issue, see
* https://stackoverflow.com/questions/22915325/avoiding-self-assignment-in-stdshuffle
*/
template<typename I, typename R>
void Shuffle(I first, I last, R&& rng)
{
while (first != last) {
size_t j = rng.randrange(last - first);
if (j) {
using std::swap;
swap(*first, *(first + j));
}
++first;
}
}

#endif // BITCOIN_RANDOM_H
5 changes: 3 additions & 2 deletions src/wallet/wallet.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
#include <blind.h>
#include <issuance.h>
#include <crypto/hmac_sha256.h>
#include <random.h>

static const size_t OUTPUT_GROUP_MAX_ENTRIES = 10;

Expand Down Expand Up @@ -2551,7 +2552,7 @@ bool CWallet::SelectCoins(const std::vector<COutput>& vAvailableCoins, const CAm
// Cases where we have 11+ outputs all pointing to the same destination may result in
// privacy leaks as they will potentially be deterministically sorted. We solve that by
// explicitly shuffling the outputs before processing
std::shuffle(vCoins.begin(), vCoins.end(), FastRandomContext());
Shuffle(vCoins.begin(), vCoins.end(), FastRandomContext());
}
std::vector<OutputGroup> groups = GroupOutputs(vCoins, !coin_control.m_avoid_partial_spends);

Expand Down Expand Up @@ -3188,7 +3189,7 @@ bool CWallet::CreateTransaction(const std::vector<CRecipient>& vecSend, CTransac

// Elements: Shuffle here to preserve random ordering for surjection proofs
selected_coins = std::vector<CInputCoin>(setCoins.begin(), setCoins.end());
std::shuffle(selected_coins.begin(), selected_coins.end(), FastRandomContext());
Shuffle(selected_coins.begin(), selected_coins.end(), FastRandomContext());

// Dummy fill vin for maximum size estimation
//
Expand Down

0 comments on commit 6491b4d

Please sign in to comment.