bitcoindevkit / bdk

A modern, lightweight, descriptor-based wallet library written in Rust!
Other
842 stars 304 forks source link

Add Whirlpool (CoinJoin) client functionality #854

Open InnocuousFinch opened 1 year ago

InnocuousFinch commented 1 year ago

Description

Whirlpool is a ZeroLink CoinJoin implementation that breaks 100% of deterministic links for all UTXOs that run through it. It's been out for several years and has proven to be extremely reliable in terms of giving on-chain Bitcoin users forward looking privacy.

Recently, a FOSS Whirlpool client library written in Rust (Straylight) has been released. The request here is to integrate Whirlpool into BDK (likely either using Straylight or a fork of it) so that users can easily integrate Whirlpool into any tool that uses BDK.

Use case

Additional context

LLFourn commented 1 year ago

Hi @InnocuousFinch. What APIs are required to do this with BDK? I'm guessing it's just normal wallet stuff like figuring out what utxos you have, reserving them doing some protocol and finalizing a transaction? You should be able to do most of that already (except we're missing API for reserving them: https://github.com/bitcoindevkit/bdk/issues/849).

A nice to have for the initial release would be adding Stonewall support (fake mini coinjoin) with the release of the Whirlpool client so that spending from post-mix looks on-chain like it does from Samourai Wallet and Sparrow Wallet users

I'm not convinced that this is a good idea. Imagine if I'm trying to spy on person X's wallet. If I manage to convince X to make all their transactions look like a fake coinjoin then I can follow their wallet around the blockchain if I have an advantage in distinguishing them from real coinjoins. The standard on-chain privacy goal which I recommend is to try and make your transactions look like normal transactions that could have be done by anybody else. Getting everyone to batch transactions together in coinjoins would be great if we can make it standard practice but I don't see how making fake easily distinguishable batch transactions out of normal transactions is helping us get there.

InnocuousFinch commented 1 year ago

Hi @InnocuousFinch. What APIs are required to do this with BDK? I'm guessing it's just normal wallet stuff like figuring out what utxos you have, reserving them doing some protocol and finalizing a transaction? You should be able to do most of that already (except we're missing API for reserving them: #849).

Not sure if this is what you're asking, but most everything you need to build Whirlpool client functionality into BDK is in the Straylight whirlpool-client-rs repo that I linked in the OP. There is a lot involved with getting Whirlpool integrated into any wallet, which is why I requested this enhancement in the first place. There are also no Whirlpool client libraries currently for iOS/Swift or React Native apps, so adding to BDK with supported ffi bindings would be helpful in bringing Whirlpool functionality to more wallets.

I'm not convinced that this is a good idea. Imagine if I'm trying to spy on person X's wallet. If I manage to convince X to make all their transactions look like a fake coinjoin then I can follow their wallet around the blockchain if I have an advantage in distinguishing them from real coinjoins. The standard on-chain privacy goal which I recommend is to try and make your transactions look like normal transactions that could have be done by anybody else. Getting everyone to batch transactions together in coinjoins would be great if we can make it standard practice but I don't see how making fake easily distinguishable batch transactions out of normal transactions is helping us get there.

Person X would not be able to be tracked effectively since they (and everyone else that uses Whirlpool) create transactions that look like either a real or fake coinjoins when they're coming out of a Whirlpool coinjoin which breaks 100% of deterministic links. You cannot tell the difference between the fake and real one on-chain.

Samourai Wallet and Sparrow Wallet spends from the post-mix wallet are typically either:

  1. Stonewall (fake 2 person coinjoins) or
  2. Stonewall2x (actual 2 person coinjoins)

You are right in that if we only had fake coinjoins, there would be no point as blockchain analysis companies could apply the common input ownership heuristic with very high confidence, not to mention that this person now has a more distinguishable transaction on-chain. However, there are many people creating real 2 person coinjoin transactions via Stonewall2x every day. Because of this, blockchain analysis companies can not confidently apply the common input ownership heuristic to Stonewall transactions, as they look identical to Stonewall2x transactions.

In reality, Stonewall2x functionality should be implemented in BDK in addition to Stonewall. I mentioned Stonewall only because Stonewall2x uses the Soroban encrypted communications layer to coordinate the collaborative coinjoins between peers, and that would likely be a future feature to be added as it would add an additional layer of complexity.

If you want users to have better on-chain privacy with wallets that use BDK, users need the ability to add entropy to their transactions to undermine typical blockchain analysis heuristics like CIOH. Whirlpool coinjoins are extremely effective at doing this, and when adding in post-mix spending tools like Stonewall/Stonewall2x, you can achieve relatively high level of forward looking on-chain privacy.

rot13maxi commented 1 year ago

If folks want to use BDK to build a wallet (or other tool) that has whirlpool functionality, why wouldnt they just use BDK and Straylight? If there are generic hooks in BDK that would be useful for using Straylight or things like it, that makes a ton of sense to go into BDK. It might also make sense to have some code in straylight that can work with bdk Wallet instances.

Just seems a little weird to me to integrate a client for a paid service directly into BDK, rather than figure out if there are missing hooks or accessors that developers would need to use the two libraries together.

notmandatory commented 1 year ago

I agree with @rot13maxi if someone wants to build a wallet with bdk + whirlpool-client-rs it's better to first identify which general wallet features you need that are missing from bdk, probably at least #849 as @LLFourn suggested.

Then if you want to create such a wallet for mobile the bdk-ffi project provides iOS/Android bindings for bdk and you can use the uniffi-bindings-template project @thunderbiscuit created to pretty easily add similar mobile bindings for whirlpool-client-rs.

thunderbiscuit commented 1 year ago

I agree with the sentiments expressed above. At the risk of repeating others, here is how I see it:

  1. A Whirlpool implementation in Rust is probably better suited as a separate crate than in BDK directly.
  2. It's important to make sure BDK can be used by crates who wish to provide coinjoin implementations.

I see the Straylight crate is fairly young; let us know how it goes and features you need as the implementation matures, and hit me up if you'd like to port it to Swift/Android/Kotlin/Java/Python/RN/Flutter using a structure similar to what we've done in bdk-ffi and the template repo I maintain linked above by Steve.