Skip to content

Conversation

achow101
Copy link
Member

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.

Copy link
Contributor

@promag promag left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Concept ACK.

@laanwj
Copy link
Member

laanwj commented Aug 1, 2019

Concept ACK, not sure whether there's reasons someone would want to disable this, but in any case I think privacy-by-default behavior is good

@practicalswift
Copy link
Contributor

Concept ACK

@fanquake
Copy link
Member

Concept ACK - Can we get some sort of simple test case to ensure that there's some shuffling going on.

but in any case I think privacy-by-default behavior is good

Definitely agree.

I guess this should also be backported given the patch is fairly simple and it's a privacy improvement?

@fanquake fanquake added this to the 0.18.2 milestone Aug 14, 2019
@achow101
Copy link
Member Author

I've added a test. It runs joinpsbts multiple times and checks whether at least one of the resulting psbts are different.

Copy link
Contributor

@promag promag left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ACK, but could add a release note regarding the behavior change and also improve help text.

@achow101 achow101 force-pushed the joinpsbt-rand branch 2 times, most recently from 078b29f to b1d769f Compare August 15, 2019 00:22
@achow101
Copy link
Member Author

Added a release note.

@DrahtBot
Copy link
Contributor

DrahtBot commented Aug 15, 2019

The following sections might be updated with supplementary metadata relevant to reviewers and maintainers.

Conflicts

Reviewers, this pull request conflicts with the following ones:

  • #16839 (Replace Connman and BanMan globals with Node local by ryanofsky)
  • #16439 (RPC: support "@height" in place of blockhash for getblock etc by ajtowns)

If you consider this pull request important, please also help to review the conflicting pull requests. Ideally, start with the one that should be merged first.

@luke-jr
Copy link
Member

luke-jr commented Aug 20, 2019

Only bugfixes should be backported, not improvements...

@JeremyRubin
Copy link
Contributor

Wouldn't it be better to deterministically sort them?

@achow101
Copy link
Member Author

Wouldn't it be better to deterministically sort them?

Not at all. That gives a different privacy leak as it will indicate that joinpsbts has been used on that transaction.

@JeremyRubin
Copy link
Contributor

Hm gotcha. I was unclear of the status of BIP-69 and related standard adoption efforts for Core

@instagibbs
Copy link
Member

Only bugfixes should be backported, not improvements...

Privacy leak is a bug imo. Everywhere else we(should be) shuffle.

@@ -370,6 +370,16 @@ def test_psbt_input_keys(psbt_input, keys):
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
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it's simpler to just do an infinite loop and break IFF a difference is found, makes it less dependent on number of inputs and lowers false negatives

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you mean just replacing the line below with while True:? If you mean to drop shuffled then what would you assert after the loop?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

just saying remove the 10 times limit, maybe makes the logic simpler. hanging with implementation bug is better than false negative imo

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree with you but it it isn't that informative. Suppose it hangs in travis, you would be clueless.

Copy link
Member

@instagibbs instagibbs Aug 27, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wouldn't be clueless if it printed out what tests are still running, but those PRs have been unable to get merged, sad!

Could just bump it to some fairly ridiculous number that's unlikely to be hit even if the test itself is modified significantly. I think the easiest case to get a false negative is just two entries, 50/50 chance, so run that 128 times and we're fine :P

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think 10 is enough for now.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

first test failure you're getting strung up :P

@@ -1604,8 +1605,28 @@ 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);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

std::iota

not sure we should be adding IOTA support to Core

(this is a joke)

@@ -1604,8 +1605,28 @@ 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
Copy link
Member

@instagibbs instagibbs Aug 27, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Forgive me, why are we not just shuffling the vector of inputs and outputs in merged_psbt using Shuffle directly?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There are two input vectors and output vectors. The on in the global tx, and the one in the psbt metadata. Both need to line up, so by shuffling the indicies, each input and output can be lined up with its respective metadata.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ah! Missed how the actual transaction was being reconstructed, got it.

Copy link
Member

@jonatack jonatack left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Concept ACK b1d769f. Code review, built, ran tests, verified the added test fails without the change. Code looks correct; a few suggestions follow for your perusal. Is testing joinpsbt inequality in rpc_psbt.py enough? Could the manual copy+shuffling be extracted and covered by unit tests? e.g. as a member function of PartiallySignedTransaction?

# 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):
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change:

-        for i in range(0, 10):
+        for _ in range(10):

Copy link
Member Author

@achow101 achow101 Sep 4, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

meh. not important enough to change

@@ -370,6 +370,16 @@ def test_psbt_input_keys(psbt_input, keys):
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
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change:

-        # Check that joining shuffles the inputs and outputs
-        # 10 attempts should be enough to get a shuffled join

+        # Check that joining shuffles the inputs and outputs.
+        # Run up to 10 attempts to ensure seeing a shuffled join.

Copy link
Member Author

@achow101 achow101 Sep 4, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

meh. not important enough to change

@@ -1604,8 +1605,28 @@ 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
Copy link
Member

@jonatack jonatack Sep 4, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change for git grepping, mainly the line "// Shuffle input and output indices lists" to have a comment beginning with "Shuffle" like:

src/wallet/rpcwallet.cpp:913: // Shuffle recipient list
src/wallet/wallet.cpp:3211: // Shuffle selected coins and fill in final vin
    // Generate lists of input and output indices of the merged PSBT
    // to be shuffled.
    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 indices lists
    Shuffle(input_indices.begin(), input_indices.end(), FastRandomContext());
    Shuffle(output_indices.begin(), output_indices.end(), FastRandomContext());

    // Generate shuffled_psbt from shuffled indices lists
    PartiallySignedTransaction shuffled_psbt;

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note that the proposed change places the two Shuffle functions together. First generate the lists, then perform the shuffles.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

@nopara73
Copy link

nopara73 commented Sep 4, 2019

Concept ACK. Related: #12457

std::vector<int> output_indices(merged_psbt.outputs.size());
std::iota(output_indices.begin(), output_indices.end(), 0);

// Shuffle input and output indicies lists
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit (if you need to retouch this): s/indicies/indices/

@jonatack
Copy link
Member

@achow101 what did you think of this question / suggestion above?

@achow101
Copy link
Member Author

Is testing joinpsbt inequality in rpc_psbt.py enough?

It should be.

Could the manual copy+shuffling be extracted and covered by unit tests? e.g. as a member function of PartiallySignedTransaction?

Maybe later? I would like this merged for 0.19 so I do want any further changes to this to be minimal.

@instagibbs
Copy link
Member

utACK c0b5d97

@maflcko maflcko modified the milestones: 0.18.2, 0.19.0 Sep 17, 2019
@jonatack
Copy link
Member

Could the manual copy+shuffling be extracted and covered by unit tests? e.g. as a member function of PartiallySignedTransaction?

Maybe later? I would like this merged for 0.19 so I do want any further changes to this to be minimal.

Fair enough. I might propose it later.

@fanquake fanquake changed the title Shuffle inputs and outputs after joining psbts rpc: Shuffle inputs and outputs after joining psbts Sep 18, 2019
@jonatack
Copy link
Member

ACK c0b5d97 modulo suggestions for later.

@laanwj
Copy link
Member

laanwj commented Sep 18, 2019

ACK c0b5d97

Agree the shuffling should ideally be factored out to a function, but that can be done in a future PR

laanwj added a commit that referenced this pull request Sep 18, 2019
c0b5d97 Test that joinpsbts randomly shuffles the inputs (Andrew Chow)
6f405a1 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:
    utACK c0b5d97
  jonatack:
    ACK c0b5d97 modulo suggestions for later.

Tree-SHA512: 14a0b7aae07d92e6d2c76a3a3b228b481e1964cb7d34f97515bdda18e2ea05a9f97c5a22affc143b86ae8b95c3cb239849fb54219d65512bc2112264dca915c8
@laanwj laanwj merged commit c0b5d97 into bitcoin:master Sep 18, 2019
fanquake pushed a commit to fanquake/bitcoin that referenced this pull request Sep 19, 2019
fanquake pushed a commit to fanquake/bitcoin that referenced this pull request Sep 19, 2019
@fanquake
Copy link
Member

Added for backport in #16617.

@fanquake fanquake mentioned this pull request Sep 19, 2019
@maflcko maflcko modified the milestones: 0.19.0, 0.18.2 Sep 23, 2019
sidhujag pushed a commit to syscoin/syscoin that referenced this pull request Sep 23, 2019
c0b5d97 Test that joinpsbts randomly shuffles the inputs (Andrew Chow)
6f405a1 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:
    utACK bitcoin@c0b5d97
  jonatack:
    ACK c0b5d97 modulo suggestions for later.

Tree-SHA512: 14a0b7aae07d92e6d2c76a3a3b228b481e1964cb7d34f97515bdda18e2ea05a9f97c5a22affc143b86ae8b95c3cb239849fb54219d65512bc2112264dca915c8
fanquake pushed a commit to fanquake/bitcoin that referenced this pull request Sep 23, 2019
fanquake pushed a commit to fanquake/bitcoin that referenced this pull request Sep 23, 2019
laanwj added a commit that referenced this pull request Nov 25, 2019
0b18ea6 util: Filter control characters out of log messages (Wladimir J. van der Laan)
ac30fc4 build: Factor out qt translations from build system (Wladimir J. van der Laan)
3b8af5f build: update boost macros to latest upstream (fanquake)
b12defc Test that joinpsbts randomly shuffles the inputs (Andrew Chow)
eb07d22 Shuffle inputs and outputs after joining psbts (Andrew Chow)
1175410 addrdb: Remove temporary files created in SerializeFileDB. Fixes non-determinism in unit tests. (practicalswift)
c52dd12 Handle the result of posix_fallocate system call (Luca Venturini)
f792b25 torcontrol: Use the default/standard network port for Tor hidden services, even if the internal port is set differently (Luke Dashjr)
9fe8d28 Bugfix: QA: Run tests with UPnP disabled (Luke Dashjr)
1d12e52 Add vertical spacer (Josu Goñi)
d764141 depends: add patch to common dependencies (fanquake)
56815e9 Give QApplication dummy arguments (Andrew Chow)
9d389d0 util: No translation of `Bitcoin Core` in the copyright (MarcoFalke)
87908e9 scripted-diff: Avoid passing PACKAGE_NAME for translation (MarcoFalke)
a44e18f build: Stop translating PACKAGE_NAME (MarcoFalke)
7bd8f4e rpc: Fix getblocktemplate CLI example (#16594) (Emil Engler)
1cc06a1 doc: Fix typos in COPYRIGHT (Chuf)

Pull request description:

  Backports some commits to the `0.18` branch:

  * #16596 - rpc: Fix getblocktemplate CLI example
  * #16615 - doc: Fix typos in COPYRIGHT
  * #16291 - gui: Stop translating PACKAGE_NAME (without the `make translate` commit)
  * #16578 - Do not pass in command line arguments to QApplication
  * #16051 - depends: add patch to common dependencies
  * #16090 - Add vertical spacer
  * #15651 - torcontrol: Use the default/standard network port for Tor hidden services, even if the internal port is set differently
  * #15650 - Handle the result of posix_fallocate system call
  * #16646 - Bugfix: QA: Run tests with UPnP disabled
  * #16212 - addrdb: Remove temporary files created in SerializeFileDB. Fixes non-determinism in unit tests.
  * #16512 - rpc: Shuffle inputs and outputs after joining psbts
  * #16870 - build: update boost macros to latest upstream for improved error reporting
  * #16982 - build: Factor out qt translations from build system
  * #17095 - util: Filter control characters out of log messages

ACKs for top commit:
  laanwj:
    ACK 0b18ea6

Tree-SHA512: 37f0e5afc20975f4d1506e8662eda2ae0125f2f424a852818b5af2c3b8db78fc1c365b83571aa80ca63c885ca314302190b891a50ff3851fda9b9238455a5627
deadalnix pushed a commit to Bitcoin-ABC/bitcoin-abc that referenced this pull request Jun 23, 2020
Summary:
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.

---

Backport of Core [[bitcoin/bitcoin#16512 | PR16512]]

Test Plan:

  ninja
  ./test/functional/test_runner.py rpc_psbt

Reviewers: #bitcoin_abc, Fabien

Reviewed By: #bitcoin_abc, Fabien

Subscribers: Fabien

Differential Revision: https://reviews.bitcoinabc.org/D6665
Munkybooty pushed a commit to Munkybooty/dash that referenced this pull request Dec 7, 2021
c0b5d97 Test that joinpsbts randomly shuffles the inputs (Andrew Chow)
6f405a1 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:
    utACK bitcoin@c0b5d97
  jonatack:
    ACK c0b5d97 modulo suggestions for later.

Tree-SHA512: 14a0b7aae07d92e6d2c76a3a3b228b481e1964cb7d34f97515bdda18e2ea05a9f97c5a22affc143b86ae8b95c3cb239849fb54219d65512bc2112264dca915c8
Munkybooty pushed a commit to Munkybooty/dash that referenced this pull request Dec 15, 2021
c0b5d97 Test that joinpsbts randomly shuffles the inputs (Andrew Chow)
6f405a1 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:
    utACK bitcoin@c0b5d97
  jonatack:
    ACK c0b5d97 modulo suggestions for later.

Tree-SHA512: 14a0b7aae07d92e6d2c76a3a3b228b481e1964cb7d34f97515bdda18e2ea05a9f97c5a22affc143b86ae8b95c3cb239849fb54219d65512bc2112264dca915c8
Munkybooty pushed a commit to Munkybooty/dash that referenced this pull request Dec 15, 2021
c0b5d97 Test that joinpsbts randomly shuffles the inputs (Andrew Chow)
6f405a1 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:
    utACK bitcoin@c0b5d97
  jonatack:
    ACK c0b5d97 modulo suggestions for later.

Tree-SHA512: 14a0b7aae07d92e6d2c76a3a3b228b481e1964cb7d34f97515bdda18e2ea05a9f97c5a22affc143b86ae8b95c3cb239849fb54219d65512bc2112264dca915c8
@bitcoin bitcoin locked as resolved and limited conversation to collaborators Dec 16, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging this pull request may close these issues.