mirror of
https://github.com/bitcoin/bitcoin.git
synced 2025-02-08 10:31:50 -05:00
Merge #16512: rpc: Shuffle inputs and outputs after joining psbts
c0b5d97103
Test that joinpsbts randomly shuffles the inputs (Andrew Chow)6f405a1d3b
Shuffle inputs and outputs after joining psbts (Andrew Chow) Pull request description: `joinpsbts` currently just adds the inputs and outputs in the order of that the PSBTs were provided. This makes it extremely easy to identify which outputs belong to which inputs. This PR changes that so that all of the inputs and outputs are shuffled in the joined transaction. ACKs for top commit: instagibbs: utACKc0b5d97103
jonatack: ACKc0b5d97103
modulo suggestions for later. Tree-SHA512: 14a0b7aae07d92e6d2c76a3a3b228b481e1964cb7d34f97515bdda18e2ea05a9f97c5a22affc143b86ae8b95c3cb239849fb54219d65512bc2112264dca915c8
This commit is contained in:
commit
72d30d668a
3 changed files with 38 additions and 1 deletions
4
doc/release-notes-16512.md
Normal file
4
doc/release-notes-16512.md
Normal file
|
@ -0,0 +1,4 @@
|
|||
RPC changes
|
||||
-----------
|
||||
The RPC `joinpsbts` will shuffle the order of the inputs and outputs of the resulting joined psbt.
|
||||
Previously inputs and outputs were added in the order that the PSBTs were provided which makes correlating inputs to outputs extremely easy.
|
|
@ -17,6 +17,7 @@
|
|||
#include <policy/rbf.h>
|
||||
#include <primitives/transaction.h>
|
||||
#include <psbt.h>
|
||||
#include <random.h>
|
||||
#include <rpc/rawtransaction_util.h>
|
||||
#include <rpc/server.h>
|
||||
#include <rpc/util.h>
|
||||
|
@ -1615,8 +1616,30 @@ UniValue joinpsbts(const JSONRPCRequest& request)
|
|||
merged_psbt.unknown.insert(psbt.unknown.begin(), psbt.unknown.end());
|
||||
}
|
||||
|
||||
// Generate list of shuffled indices for shuffling inputs and outputs of the merged PSBT
|
||||
std::vector<int> input_indices(merged_psbt.inputs.size());
|
||||
std::iota(input_indices.begin(), input_indices.end(), 0);
|
||||
std::vector<int> output_indices(merged_psbt.outputs.size());
|
||||
std::iota(output_indices.begin(), output_indices.end(), 0);
|
||||
|
||||
// Shuffle input and output indicies lists
|
||||
Shuffle(input_indices.begin(), input_indices.end(), FastRandomContext());
|
||||
Shuffle(output_indices.begin(), output_indices.end(), FastRandomContext());
|
||||
|
||||
PartiallySignedTransaction shuffled_psbt;
|
||||
shuffled_psbt.tx = CMutableTransaction();
|
||||
shuffled_psbt.tx->nVersion = merged_psbt.tx->nVersion;
|
||||
shuffled_psbt.tx->nLockTime = merged_psbt.tx->nLockTime;
|
||||
for (int i : input_indices) {
|
||||
shuffled_psbt.AddInput(merged_psbt.tx->vin[i], merged_psbt.inputs[i]);
|
||||
}
|
||||
for (int i : output_indices) {
|
||||
shuffled_psbt.AddOutput(merged_psbt.tx->vout[i], merged_psbt.outputs[i]);
|
||||
}
|
||||
shuffled_psbt.unknown.insert(merged_psbt.unknown.begin(), merged_psbt.unknown.end());
|
||||
|
||||
CDataStream ssTx(SER_NETWORK, PROTOCOL_VERSION);
|
||||
ssTx << merged_psbt;
|
||||
ssTx << shuffled_psbt;
|
||||
return EncodeBase64((unsigned char*)ssTx.data(), ssTx.size());
|
||||
}
|
||||
|
||||
|
|
|
@ -382,6 +382,16 @@ class PSBTTest(BitcoinTestFramework):
|
|||
joined_decoded = self.nodes[0].decodepsbt(joined)
|
||||
assert len(joined_decoded['inputs']) == 4 and len(joined_decoded['outputs']) == 2 and "final_scriptwitness" not in joined_decoded['inputs'][3] and "final_scriptSig" not in joined_decoded['inputs'][3]
|
||||
|
||||
# Check that joining shuffles the inputs and outputs
|
||||
# 10 attempts should be enough to get a shuffled join
|
||||
shuffled = False
|
||||
for i in range(0, 10):
|
||||
shuffled_joined = self.nodes[0].joinpsbts([psbt, psbt2])
|
||||
shuffled |= joined != shuffled_joined
|
||||
if shuffled:
|
||||
break
|
||||
assert shuffled
|
||||
|
||||
# Newly created PSBT needs UTXOs and updating
|
||||
addr = self.nodes[1].getnewaddress("", "p2sh-segwit")
|
||||
txid = self.nodes[0].sendtoaddress(addr, 7)
|
||||
|
|
Loading…
Add table
Reference in a new issue