diff --git a/src/transaction_builder.cpp b/src/transaction_builder.cpp index c17051ff9..3ff6269b2 100644 --- a/src/transaction_builder.cpp +++ b/src/transaction_builder.cpp @@ -59,6 +59,13 @@ void TransactionBuilder::AddSaplingOutput( mtx.valueBalance -= value; } +// randomize the order of outputs +void TransactionBuilder::ShuffleOutputs() +{ + LogPrintf("%s: Shuffling %d zouts\n", __func__, outputs.size() ); + random_shuffle( outputs.begin(), outputs.end(), GetRandInt ); +} + void TransactionBuilder::AddTransparentInput(COutPoint utxo, CScript scriptPubKey, CAmount value, uint32_t _nSequence) { if (keystore == nullptr) { @@ -212,6 +219,9 @@ boost::optional TransactionBuilder::Build() mtx.vShieldedSpend.push_back(sdesc); } + // Prevent leaking metadata about the position of change output + ShuffleOutputs(); + // Create Sapling OutputDescriptions for (auto output : outputs) { auto cm = output.note.cm(); diff --git a/src/transaction_builder.h b/src/transaction_builder.h index dba7e7b43..89a8d6580 100644 --- a/src/transaction_builder.h +++ b/src/transaction_builder.h @@ -92,6 +92,8 @@ public: CAmount value, std::array memo = {{0}}); + void ShuffleOutputs(); + // Assumes that the value correctly corresponds to the provided UTXO. void AddTransparentInput(COutPoint utxo, CScript scriptPubKey, CAmount value, uint32_t nSequence = 0xffffffff);