Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement CoinJoin requests #2577

Merged
merged 9 commits into from
Oct 27, 2022
Merged

Conversation

andrewkozlik
Copy link
Contributor

@andrewkozlik andrewkozlik commented Oct 20, 2022

We decided to strengthen the security guarantees that will be provided by the signed affiliate data in CoinJoin. Due to these changes it is becoming a little more complicated to reuse the solution that is based on payment requests, although technically it could still be done if we wanted to. Payment requests are meant for individual outputs or sets of outputs in a transaction, whereas the affiliate data is now working with the entire set of inputs and outputs. I'd call this a "transaction request" and in this particular case a CoinJoinRequest. Since there is only one such transaction request per transaction it makes sense to put it into SignTx, which is what I did here.

There is an optional commit d547584 that I could add, which adds a fee tolerance of 200 sats on Mainnet. The rationale behind it is to prevent Trezor from declining to sign the transaction in case of some sort of rounding error in the fee computation. That would ruin the CoinJoin for all participants. But I think this shouldn't occur. Opinions?

@onvej-sl please review and feel free to comment on the CoinJoin request digest algorithm and the mask computation. It's implemented in three places actually (core, unit tests and device tests). make_coinjoin_request() in tests/device_tests/bitcoin/payment_req.py is pretty well legible.

@matejcik you might want to glance at the protobuf changes in 1de8f10, but I think it's in line with what we discussed IRL.

@andrewkozlik andrewkozlik added core Trezor Core firmware. Runs on Trezor Model T and T2B1. bitcoin Bitcoin related R&D Research and development team related labels Oct 20, 2022
@andrewkozlik andrewkozlik requested a review from onvej-sl October 20, 2022 14:33

if authorization.params.coin_name != tx.coin_name:
raise wire.DataError("Coin name does not match authorization.")
Copy link
Contributor Author

@andrewkozlik andrewkozlik Oct 20, 2022

Choose a reason for hiding this comment

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

I removed this, because it's not needed. Already checked in approve_tx() by calling self.authorization.approve_sign_tx(tx_info.tx).

@andrewkozlik
Copy link
Contributor Author

Added two commits based on discussion with @onvej-sl IRL:
a4dbc3e
34dc961

@matejcik matejcik requested review from grdddj and matejcik October 26, 2022 12:11
Copy link
Contributor

@grdddj grdddj left a comment

Choose a reason for hiding this comment

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

Haven't found anything bad, just one possible improvement.

* Signing request for a CoinJoin transaction.
*/
message CoinJoinRequest {
required uint32 fee_rate = 1; // coordination fee rate in units of 10^-8 percent
Copy link
Contributor

Choose a reason for hiding this comment

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

This overflows uint32 with 43 percent or more - not probable, but we might change it to uint64 as protection.

Copy link
Contributor

Choose a reason for hiding this comment

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

reasonable.
(fwiw the firmware currently still ignores uint sizes so this is not an issue; however, that is going to be fixed at some point)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Firstly, a 43 % fee is crazy huge. However, I understand that we might want to represent percentages in other protobuf messages in the future and it would be nice to use a consistent format. The present scheme already allows 8 decimal digits of a percent, which seems way more precise than we might ever need. So rather than doubling the size of the data type, which would result in a maximum value of 184 billion %, I'd opt for decreasing the precision. If we go with 10–7 or 10–6, then that can fit 429% or 4295% respectively and the precision is still great. We will probably never need more than 4 digits of percent precision anyway.

BTW note that the fee rate is specified in two places in protobuf AuthorizeCoinJoin.max_coordinator_fee_rate and CoinJoinRequest.fee_rate, so we definitely want to keep those consistent.

When CoinJoin was first implemented in July 2020, we had it at 10–9, see #1127. That means a maximum of 4.29 % could be represented. The meaning was also different (fee per anonymity unit vs. flat fee rate now). I recall that we discussed this at the standup back then and the argument was that 4 % (per anonymity unit) is huge.

In #2180 I changed the meaning to the flat fee rate and 8 digit precision to partially compensate the difference in meaning.

This is probably the last chance to easily change the precision, if we want to. It will also require changes in connect. After connect is deployed, it would probably be too complicated.

Copy link
Contributor

Choose a reason for hiding this comment

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

I would vote for decreasing the precision to 10–6, it could also be better rememberable - "a million is one percent" (now it is "a BTC in satoshis is one percent").

Copy link
Member

@prusnak prusnak Oct 27, 2022

Choose a reason for hiding this comment

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

+1 for 10^-6 precision (ppm) - ppm is also the unit how fee rate is specified in lightning (LND). Let's not forget to change the max_coordinator_fee_rate too.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@prusnak interesting point, but I think there is a difference. Here we are talking about precision of 10^-6 of a percent, whereas in LND I understand the precision to be 10^-6 of the whole. In other words if we want to follow LND, then we should be talking about 10^-4 of a percent here.

Copy link
Member

Choose a reason for hiding this comment

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

ah, right, never mind

Copy link
Contributor Author

Choose a reason for hiding this comment

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

So what will it be? 10^-4 (ppm, LND), 10^-6 (millionth of a percent), 10^-8 (current) etc.? To be honest, I have no strong preference. Anything between 4 and 8 is fine by me.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

10^-6 seems like a good middle ground.
Done in 52fca8c

Copy link
Contributor

@matejcik matejcik left a comment

Choose a reason for hiding this comment

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

ACK on protobuf changes.
didn't go through the rest of the code, i'll trust your reviews

@andrewkozlik andrewkozlik force-pushed the andrewkozlik/coinjoin-request2 branch from fa690b8 to d48cc02 Compare October 27, 2022 14:05
@andrewkozlik andrewkozlik merged commit c7fb908 into master Oct 27, 2022
@andrewkozlik andrewkozlik deleted the andrewkozlik/coinjoin-request2 branch October 27, 2022 15:37
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bitcoin Bitcoin related core Trezor Core firmware. Runs on Trezor Model T and T2B1. R&D Research and development team related
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants