Skip to content

Commit eb07d22

Browse files
achow101fanquake
authored andcommitted
Shuffle inputs and outputs after joining psbts
Github-Pull: #16512 Rebased-From: 6f405a1
1 parent 1175410 commit eb07d22

File tree

2 files changed

+28
-1
lines changed

2 files changed

+28
-1
lines changed

doc/release-notes-16512.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
RPC changes
2+
-----------
3+
The RPC `joinpsbts` will shuffle the order of the inputs and outputs of the resulting joined psbt.
4+
Previously inputs and outputs were added in the order that the PSBTs were provided which makes correlating inputs to outputs extremely easy.

src/rpc/rawtransaction.cpp

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
#include <policy/rbf.h>
2020
#include <primitives/transaction.h>
2121
#include <psbt.h>
22+
#include <random.h>
2223
#include <rpc/rawtransaction.h>
2324
#include <rpc/server.h>
2425
#include <rpc/util.h>
@@ -1861,8 +1862,30 @@ UniValue joinpsbts(const JSONRPCRequest& request)
18611862
merged_psbt.unknown.insert(psbt.unknown.begin(), psbt.unknown.end());
18621863
}
18631864

1865+
// Generate list of shuffled indices for shuffling inputs and outputs of the merged PSBT
1866+
std::vector<int> input_indices(merged_psbt.inputs.size());
1867+
std::iota(input_indices.begin(), input_indices.end(), 0);
1868+
std::vector<int> output_indices(merged_psbt.outputs.size());
1869+
std::iota(output_indices.begin(), output_indices.end(), 0);
1870+
1871+
// Shuffle input and output indicies lists
1872+
Shuffle(input_indices.begin(), input_indices.end(), FastRandomContext());
1873+
Shuffle(output_indices.begin(), output_indices.end(), FastRandomContext());
1874+
1875+
PartiallySignedTransaction shuffled_psbt;
1876+
shuffled_psbt.tx = CMutableTransaction();
1877+
shuffled_psbt.tx->nVersion = merged_psbt.tx->nVersion;
1878+
shuffled_psbt.tx->nLockTime = merged_psbt.tx->nLockTime;
1879+
for (int i : input_indices) {
1880+
shuffled_psbt.AddInput(merged_psbt.tx->vin[i], merged_psbt.inputs[i]);
1881+
}
1882+
for (int i : output_indices) {
1883+
shuffled_psbt.AddOutput(merged_psbt.tx->vout[i], merged_psbt.outputs[i]);
1884+
}
1885+
shuffled_psbt.unknown.insert(merged_psbt.unknown.begin(), merged_psbt.unknown.end());
1886+
18641887
CDataStream ssTx(SER_NETWORK, PROTOCOL_VERSION);
1865-
ssTx << merged_psbt;
1888+
ssTx << shuffled_psbt;
18661889
return EncodeBase64((unsigned char*)ssTx.data(), ssTx.size());
18671890
}
18681891

0 commit comments

Comments
 (0)