JoinMarket-Org / joinmarket-clientserver

Bitcoin CoinJoin implementation with incentive structure to convince people to take part
GNU General Public License v3.0
700 stars 174 forks source link

Hardware wallet support #663

Open kristapsk opened 3 years ago

kristapsk commented 3 years ago

There was issue about hardware wallet support for yield generators in old JM github repo - https://github.com/JoinMarket-Org/joinmarket/issues/537, let's move further discussion here. And also extend it also to the taker side.

Trezor has implemented some support for CoinJoins in their firmware, haven't yet carefully looked through details, but at first glance seems to be usable for a single joins as a taker - https://github.com/trezor/trezor-firmware/pull/1127. Which could be useful in cases when you, for example, have tumbled your coins to the hardware wallet first and then after some time want to do some payment from it in a more private way.

AdamISZ commented 3 years ago

As discussed previously, Joinmarket coinjoins can't be instantiated in current hardware due to the requirement of generating PoDLEs.

See a recent PR by Jonas Nick to secp256k1 that includes these PoDLEs (aka DLEQs), in particular here: https://github.com/jonasnick/secp256k1/pull/14/files#diff-a684b19a811e1813f1ab819b12c97ca0R98

But I see no realistic prospect of this getting into hardware any time soon.

kristapsk commented 3 years ago

Ahh, yes, forgot about PoDLEs. But Trezor and Coldcard firmware's are open source, so that's probably solveable even if they aren't so much interested in this (although, nvk has said on twitter previously that they want to support JoinMarket, see twitter links in related old JM issue).

AdamISZ commented 3 years ago

I'm closing this because I don't want Issues open that are not actionable, and I see no way of actioning it.

Perhaps if anyone wants they can reopen this with a specific plan to support hardware wallets in some way. An example might be doing "manual" coinjoins, but that thought would need fleshing out.

AdamISZ commented 3 years ago

Someone just raised this on IRC and it may me reflect on it again - in particular, it should be possible to do this without changes to hardware wallets, but - it's going to be tricky and quite limited! :

Taker:

NB external commitments could be prepared from the same BIP49 wallet, in advance, on Joinmarket, and then that wallet is "opened" on HW and the JM wallet could be deleted. I guess that is actually a reasonable idea.

(Maker

I guess it is possible if there some kind of connector between HW and JM which is automatic. My problem with this line of thinking was always: hasn't this effectively made the HW become a hot wallet, if it automatically signs without human intervention?)

(Let's state the obvious - the Maker doesn't have the PoDLE problem ... also it's exactly in this scenario that we have to worry about the now-famous attack on automated coinjoin - what if HW is tricked into signing two different versions of the same transaction, thinking it has spent less than it actually has.)

AdamISZ commented 3 years ago

I just remembered there is already a "WatchOnly" wallet in jmclient/wallet.py but it's for now specifically just FidelityBondWatchOnlyWallet - this could potentially be useful if someone were trying to code up the "fake wallet class" I was mentioning above.

AdamISZ commented 3 years ago

For the Maker side: It's certainly interesting, and is likely to require fairly minimal code patch(es) to Joinmarket itself to support automated signing using existing standards (BIP32, BIP49, BIP84). (Edit: additional thought is the patch would also have to include usage of the PSBTWalletMixin to pass the transaction, so not that small)

So it seems like the biggest issue there would only be for any particular hardware wallet to support the use case - that is, to have a mechanism for signing to be automated via code, without manual verification and input. It's not hard to imagine that most consumer hardware wallets will not and probably should not support such a thing, because its existence might end up creating a backdoor for attackers. On the other hand, certain hardware wallets in certain situations might want to (and for all I know, perhaps they already do) support such automated signing use cases. This line of thinking is of course relevant to Lightning as well as coinjoins.

xsats commented 3 years ago

Thanks for sharing these insights @AdamISZ, very interesting and helpful for onlookers.

Although I find the idea of JoinMarket hardware wallet integration very interesting and exciting, I share your concerns about how this could defeat the very purpose of using a hardware wallet in the first place (cold-storage becoming hot).

I thought I'd chime in to mention the ColdCard HSM mode, CKBunker in case you're not already aware of it. Perhaps it could be possible to take advantage of the CKBunker (or an equivalent HSM) to create a JoinMarket maker, "constrained" connected hardware wallet, that could potentially be used to mitigate some of the additional risks associated with deploying a hardware wallet as an online maker.

I haven't personally looked into this a great deal yet, but it seems to me as though there could be at least potential for a beneficial CKBunker/JoinMarket combination, for hardware wallet support - perhaps worthy of further exploration.

xsats commented 3 years ago

CoinKite has detailed some of the functionality of the ColdCard HSM mode here: https://coldcardwallet.com/docs/ckbunker-hsm

In effect, the setup permits the creation and loading of a "policy file" to the device which cannot be changed or overridden without physical access to the device. This policy file could perhaps be used to narrowly constrain the role of maker and somewhat enhance the security of the always online makers.

While in "HSM Mode", the ColdCard can automatically sign transactions as required for a maker, but only those that satisfy the constraints defined within the policy file. This could fit the bill well.

kristapsk commented 3 years ago

About taker proposal above - usefulness of that would go beyond hardware wallet support, it would also allow integrating JoinMarket with other wallets, for example, sending CoinJoin's from Bitcoin Core wallet or integrating JoinMarket support in Wasabi Wallet.

How I see it:

1) commitments will be needed to be added using add-utxo.py or some other way as described above (if integrating with some external hot wallet, that can be automated); 2) proper watch-only wallet support is implemented in JM (could be hardest part?); 3) support for returning PSBT is added to sendpayment.py for coinjoins (maybe also for sending BIP78 payjoins, but there is that 1 minute timeout when receiver can broadcast original tx, could be not enough when manually signing with hardware wallets); 4) full signing and broadcast of tx may be handled completely outside JM (for hardware wallets just use hwi?).

Somebody correct me if I'm missing something.

nopara73 commented 3 years ago

In Wasabi I think the transition plan could be:

Add a config entry: UseJmForUnmixedCoins. This would initially default to false. This would attempt to do a 2 participant JM transaction whenever unmixed (red) coins are attempted to be spent.

Then over time it'd turn out if it'd be useful or not and we can default to true from there on.

But before all that, the question that arises for me is that if it even provides any privacy at all or just brainlessly making users spend more on fees. Would the makers yield generation activity be so distinct on the blockchain that Wasabi users who're takers only would be distinguished by their histories and future activities and so get deanonymized easily?

kristapsk commented 3 years ago

@nopara73 This is valid question without a simple answer IMO. It depends on usage patterns of existing JM users, mainly, how often they mix maker and taker roles (there is some hope #487 will improve that) and, if they do, how often they also do non-cj sends and payjoins. One thing that could already de-anonymize Wasabi users is plan for 2 participant JM coinjoins, as they are very rare currently, with default configuration sendpayment.py will refuse to continue if there aren't at least 4 other counterparties.

kristapsk commented 3 years ago

Here's nice approach by Bitcoin Core - https://github.com/bitcoin/bitcoin/pull/16546, probably could steal some ideas. Planning to test and review it.

This PR lets bitcoind call an arbitrary command -signer=<cmd>, e.g. a hardware wallet driver, where it can fetch public keys, ask to display an address, and sign a transaction (using PSBT under the hood).

AdamISZ commented 2 years ago

This has been sitting in the background as 'something many of people want to have, but almost zero people are going to do anything about it' :)

I think the maker side is the most likely to work. Areas of development are: