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

Receive payjoin #820

Open
wants to merge 6 commits into
base: master
Choose a base branch
from
Open

Conversation

DanGould
Copy link
Contributor

@DanGould DanGould commented Nov 1, 2023

Request + receive payjoin v2. This change includes v1 backwards-compatible payjoin v2 sending.

In order to become a production feature some implementation details should be considered:

Fetch Oblivious HTTP Configuration

The payjoin directory server's OHTTP Key Configuration defines it's encryption keys independent of TLS. This information is fetched in this PR using an HTTPS-in-WebSocket tunnel so it can be retrieved without revealing the client IP to the payjoin directory server in order to preserve the privacy described in BIP 77.

Display &ohttp= gateway configuration in bip21 uri

This is done via MutinyWallet/mutiny-web#947

Oblivious HTTP Relays

Independent oblivious HTTP relays are being run by obscuravpn.io and bobspaces.net. Their URLs are included in the changed files.

closes #194

Copy link
Contributor

@TonyGiorgio TonyGiorgio left a comment

Choose a reason for hiding this comment

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

Very cool, appreciate the description and PR!

I'm curious what ohttp adoption is looking like and what information is gained by running one? I guess the assumption would be that the ohttp proxy and the service are not the same people and not colluding? What, if any, information gained by the payjoin server or ohttp proxy? Trying to think through what it makes sense to host or have others host that we link to in app.

Would users be able to select their own ohttp proxy and their own payjoin servers? Ideally we don't have to host or hard code it in order for it to work, though potentially willing to if it makes sense.

mutiny-core/src/nodemanager.rs Outdated Show resolved Hide resolved
mutiny-core/src/nodemanager.rs Outdated Show resolved Hide resolved
mutiny-core/src/nodemanager.rs Outdated Show resolved Hide resolved
mutiny-core/src/nodemanager.rs Outdated Show resolved Hide resolved
@DanGould
Copy link
Contributor Author

DanGould commented Nov 2, 2023

I'm curious what ohttp adoption is looking like

Oblivious HTTP is still a draft, but is implemented in Chrome, Firefox, Cloudflare and Apple operating systems. It is used for Oblivious DNS over HTTP with a relay deployed by Fastly.

and what information is gained by running one? I guess the assumption would be that the ohttp proxy and the service are not the same people and not colluding? What, if any, information gained by the payjoin server or ohttp proxy? Trying to think through what it makes sense to host or have others host that we link to in app.

OHTTP relies on 2 distinct servers. The OHTTP Relay Resource sees the client IP and the OHTTP Gateway Resource target IP, behind which the target resource may be accessed. The OHTTP Relay sees an encrypted ohttp-req message. It does NOT see the contents of the message. It only sees an ohttp-res message and not the contents of a response either.

The OHTTP Gateway sees that the request came from the OHTTP Relay IP, and may decrypt the contents of the request: a second layer of e2ee between sender and receiver and the pubkey associated with that session (a pseudonymous subdirectory identifier for the session)

The threat model in the BIP assumes they do not collude. If they do collude, they may correlate the subdirectory with sender and receiver IP addresses to discover only that 2 IP addresses may have communicated with one another at the Payjoin relay subdirectory at a given time.

image

Would users be able to select their own ohttp proxy and their own payjoin servers? Ideally we don't have to host or hard code it in order for it to work, though potentially willing to if it makes sense.

I would suggest users don't select their own proxy for the initial rollout for three reasons.

  1. Dependency compatibility: OHTTP's specified Hybrid Pub Key Encryption HMAC-based Extract-and-Expand Key Derivation Function does not support the secp256k1 curve. I've specified a change which uses secp256k1 so that bitcoin software does not need any external crypto in order to use payjoin v2. Secp256k1, sha256, and chacha20poly1305 are all already part of the bitcoin stack and secure for the purposes of such a protocol. There is a formal process to get secp256k1 into the spec Key Encapsulation Mechanisms via IANA and potentially the browsers/operating systems. However, the spec does not prevent us from building working software today. EDIT: someone is already registering secp256k1 with IANA!
  2. UX: Any external relay would need to support secp256k1 or potentially be incompatible with a payjoin peer. Any draft spec external OHTTP Relay will not support secp256k1 at time of writing. If a payjoin Relay relied on an OHTTP Gateway configuration using only curves other than secp256k1, which is guaranteed to be available in bitcoin software, some payjoin-enabled wallets may not be able to communicate with them.
  3. Privacy: Mutiny clients already reveal their IP address to Mutiny and don't need to reveal it to another service. There is also an anonymity set benefit of having as many users using the same OHTTP relay as possible.

@TonyGiorgio
Copy link
Contributor

By running an OHTTP relay, could anyone use that to connect to any other OHTTP gateway? I'm guessing the relay would see what IP is connecting to what gateway, but could there be multiple services behind any given gateway?

@DanGould
Copy link
Contributor Author

DanGould commented Nov 3, 2023

By running an OHTTP relay, could anyone use that to connect to any other OHTTP gateway?

In section 8.2: "The relay will only forward for Oblivious Gateway Resources that it has explicitly configured and allowed."

I'm guessing the relay would see what IP is connecting to what gateway, but could there be multiple services behind any given gateway?

Yes, yes, and specific path, query, methods, request body, headers are all encrypted from the ohttp relay's view

@TonyGiorgio
Copy link
Contributor

Okay thank you, this is very helpful. Just trying to understand the operational side of OHTTP and whether we should stand one up. Regardless of who runs what, I like the approach and the code is clean and makes sense. Appreciate the work there!

@DanGould

This comment was marked as off-topic.

@DanGould DanGould force-pushed the receive-payjoin branch 2 times, most recently from 59641f1 to 6d98501 Compare November 14, 2023 00:32
@DanGould DanGould force-pushed the receive-payjoin branch 4 times, most recently from 4841b4e to cc0c386 Compare December 20, 2023 19:19
@DanGould DanGould marked this pull request as ready for review December 20, 2023 19:52
@DanGould DanGould force-pushed the receive-payjoin branch 2 times, most recently from dfbbf0e to e7e9194 Compare December 22, 2023 03:01
@DanGould
Copy link
Contributor Author

This should now be receiving v2 payjoins, however the persistence and asynchronous completion is still a bit janky in this form factor. It does not seem like resume_payjoins is properly resuming sessions on startup.

We've also got to consider how to display pending payjoin in activity. It seems like that UI list is only considering broadcasted transactions and pending lightning payments at the moment. This introduces a new tx pending state where a PSBT has been signed and posted to a payjoin directory but not yet responded to (from a sender) or responded to but not yet broadcast by the sender (for a receiver).

I think v2 payjoin receivers who sign should show transactions pending, since only 1 step remains before the transaction is broadcast, and they've effectively been probed and revealed their utxo. v2 Senders perhaps should not treat a single signature as pending, since they both need to have receiver sign and check the result, at least until BDK allows us to lock UTXOs. Still, a sender in this state could have their original psbt broadcast by a receiver. I'll have to look into how you're handling pending lightning payments to become inspired with a solution regarding pending payjoins.

@DanGould DanGould marked this pull request as draft December 22, 2023 17:50
@TonyGiorgio
Copy link
Contributor

I think it's valid to consider it as pending in the UI. I think we just do a filter on ActivityItems before returning it. We may have to save these in our DB for it to reflect state accurately.

@DanGould DanGould force-pushed the receive-payjoin branch 6 times, most recently from 5bc812f to 49e8592 Compare January 6, 2024 19:23
@DanGould
Copy link
Contributor Author

DanGould commented Jan 6, 2024

This is now based on the payjoin-0.13.0 release, persists receive payjoin sessions, and adds pending transactions to the wallet using insert_tx and cancel_tx before they hit mempool. Though tracked payjoins are not explicitly marked as such. Their PSBTs are just put in the ActivityItem::Onchain list. One way to explicitly mark them as payjoin would be to manually construct payjoin TransactionDetails, add an is_payjoin field or similar, store them in MutinyStorage, and pull from that list in get_activity() if this solution seems incomplete. This solution should work with the existing add_onchain_labels since it attaches labels to addresses.

For now, the way the receiver here gets payjoin directory's ohttp-keys does reveal IP address to the directory but that will be solved with the next deployment of ohttp-relay @teemie1

This would require the addition of &ohttp= bip21 param parsing, ideally in bitcoin-waila, for ui support.

It might make some sense to separate backwards compatible send payjoin support in another PR before this one to simplify review. #940 makes that possible.

@DanGould DanGould force-pushed the receive-payjoin branch 2 times, most recently from 5084e85 to c2f2b72 Compare January 15, 2024 18:08
@TonyGiorgio
Copy link
Contributor

TonyGiorgio commented Mar 21, 2024

Sorry for the delay on this.

I want to be transparent, that we're pretty unsure about what we want to do with the on chain wallet long term. We're really not optimizing for on chain related activities and it has just caused various friction. Ideally long term we get to move towards something like splicing and can do splice outs for on chain payments, but until then, we've talked about removing the on chain wallet and defaulting to on chain going into a fedimint.

I've seen the discussions here which are great to see but would imagine it might be complex.

Not sure about this TBH, but curious your thoughts here.

@DanGould DanGould marked this pull request as draft March 21, 2024 20:48
@DanGould DanGould force-pushed the receive-payjoin branch 3 times, most recently from 0d047c1 to 3d70bcb Compare March 26, 2024 20:55
@DanGould DanGould force-pushed the receive-payjoin branch 7 times, most recently from 84a1c6e to 44004c2 Compare April 2, 2024 16:13
@DanGould DanGould force-pushed the receive-payjoin branch 3 times, most recently from 74e90c0 to be4f04b Compare April 6, 2024 22:28
@DanGould DanGould force-pushed the receive-payjoin branch 3 times, most recently from 421bcce to 900a185 Compare April 20, 2024 16:30
Payjoin sessions poll while the wallet is active until they expire.
A receiver payjoin proposal PSBT are tracked as pending since it awaits
a sender signature. This lets the pending TX display in the UI as an
ActivityItem.
Bootstrap Oblivious HTTP without revealing a client IP to the directory.
Persist sessions to poll and pending transactions to wallet as in
receiving v2 payjoin.
@DanGould DanGould marked this pull request as ready for review April 20, 2024 18:08
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Payjoin Support
2 participants