From 2fb9c1e6681370478e24a19172ed6d78d95d50d3 Mon Sep 17 00:00:00 2001 From: Gregory Sanders Date: Thu, 15 Mar 2018 16:18:48 -0400 Subject: [PATCH] shuffle selected coins before transaction finalization --- src/wallet/wallet.cpp | 37 +++++++++++++++++++++++-------------- 1 file changed, 23 insertions(+), 14 deletions(-) diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index 3f1a2c199..5472062a2 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -2889,20 +2889,11 @@ bool CWallet::CreateTransaction(const std::vector& vecSend, CTransac nChangePosInOut = -1; } - // Fill vin + // Dummy fill vin for maximum size estimation // - // Note how the sequence number is set to non-maxint so that - // the nLockTime set above actually works. - // - // BIP125 defines opt-in RBF as any nSequence < maxint-1, so - // we use the highest possible value in that range (maxint-2) - // to avoid conflicting with other possible uses of nSequence, - // and in the spirit of "smallest possible change from prior - // behavior." - const uint32_t nSequence = coin_control.signalRbf ? MAX_BIP125_RBF_SEQUENCE : (CTxIn::SEQUENCE_FINAL - 1); - for (const auto& coin : setCoins) - txNew.vin.push_back(CTxIn(coin.outpoint,CScript(), - nSequence)); + for (const auto& coin : setCoins) { + txNew.vin.push_back(CTxIn(coin.outpoint,CScript())); + } nBytes = CalculateMaximumSignedTxSize(txNew, this); if (nBytes < 0) { @@ -2992,11 +2983,29 @@ bool CWallet::CreateTransaction(const std::vector& vecSend, CTransac if (nChangePosInOut == -1) reservekey.ReturnKey(); // Return any reserved key if we don't have change + // Shuffle selected coins and fill in final vin + txNew.vin.clear(); + std::vector selected_coins(setCoins.begin(), setCoins.end()); + std::shuffle(selected_coins.begin(), selected_coins.end(), FastRandomContext()); + + // Note how the sequence number is set to non-maxint so that + // the nLockTime set above actually works. + // + // BIP125 defines opt-in RBF as any nSequence < maxint-1, so + // we use the highest possible value in that range (maxint-2) + // to avoid conflicting with other possible uses of nSequence, + // and in the spirit of "smallest possible change from prior + // behavior." + const uint32_t nSequence = coin_control.signalRbf ? MAX_BIP125_RBF_SEQUENCE : (CTxIn::SEQUENCE_FINAL - 1); + for (const auto& coin : selected_coins) { + txNew.vin.push_back(CTxIn(coin.outpoint, CScript(), nSequence)); + } + if (sign) { CTransaction txNewConst(txNew); int nIn = 0; - for (const auto& coin : setCoins) + for (const auto& coin : selected_coins) { const CScript& scriptPubKey = coin.txout.scriptPubKey; SignatureData sigdata;