bria icon indicating copy to clipboard operation
bria copied to clipboard

feat: receive payjoin

Open DanGould opened this issue 1 year ago • 8 comments

This is my hacking around trying to copy admin mod into a payjoin server that could trigger payouts when it senses a payjoin incoming. It does not build yet.

I'm going to have to link Bria & Payjoin services because payjoin needs utxos and access to a wallet. I think it makes sense for bria to be a dependency of the payjoin service that hosts the endpoint rather than vice-versa and I'll be digging into it to find out.

Totally possible I'm going down the wrong path, but I figure I've got to start somewhere to get a server running based on our conversation in #266

DanGould avatar Jan 07 '24 18:01 DanGould

Totally possible I'm going down the wrong path, but I figure I've got to start somewhere to get a server running based on our conversation in https://github.com/GaloyMoney/bria/issues/266

I think this is the right approach - get something running, figure out the boilerplate and perhaps e2e testing and we can talk about the details of the integration later. Its always easier to move code around / refactor to the right design with a working skeleton than on a blank slate.

bodymindarts avatar Jan 08 '24 10:01 bodymindarts

One way of identifying which account an inbound payjoin is headed for would be to use a subdirectory. Rather than receiving all payjoins to a pj.galoy.com/ endpoint each account could show a bip21 including a pj.galoy.com/account_id/ endpoint for each tenant.

Of course, privacy of the account should be taken into consideration. One could also save payjoin-specific bitcoin addresses to a repo and check against those on proposal receipt, or generate linked id subdirectory that wouldn't reveal the whole account id.

DanGould avatar Jan 13 '24 19:01 DanGould

One way of identifying which account an inbound payjoin is headed for would be to use a subdirectory. Rather than receiving all payjoins to a pj.galoy.com/ endpoint each account could show a bip21 including a pj.galoy.com/account_id/ endpoint for each tenant.

Of course, privacy of the account should be taken into consideration. One could also save payjoin-specific bitcoin addresses to a repo and check against those on proposal receipt, or generate linked id subdirectory that wouldn't reveal the whole account id.

Perhaps an account can have a ‘public_alias’ that can be used as a path (instead of account id).

Though we should probably discuss the merit of activating pj on account vs wallet vs address

bodymindarts avatar Jan 13 '24 20:01 bodymindarts

payjoin v2 receivers listen to sessions identified by an authentication/encryption keypair on a subdirectory. This public alias problem sounds like one that the v2 protocol can solve. Each payjoin session would be associated with an account and saved in a repository.

DanGould avatar Jan 13 '24 22:01 DanGould

payjoin v2 receivers listen to sessions identified by an authentication/encryption keypair on a subdirectory. This public alias problem sounds like one that the v2 protocol can solve. Each payjoin session would be associated with an account and saved in a repository.

Yes a PayjoinSessionRepo makes a lot of sense

bodymindarts avatar Jan 14 '24 07:01 bodymindarts

I peeled another layer back today addressing payjoin integration with the payout_queue and related abstractions.

Once a sender's proposal is checked to be a suitable as a fallback to turn into a payjoin, we can think of it as being added to bria's mempool. This is distinct from our instance of bitcoind's mempool, since it's only in bria's section of memory, but we know it still is able to pay us if broadcast, gives us some funds via control of a foreign utxo to partially account for (since some will be paid back to the sender as change), and specifies at least one Payout, including a self-spend to one of our wallets that we may update and perhaps change that the sender has specified. It seems to me the foreign utxo may be accounted for by being already encumbered with value owed to the sender's change address as a precondition. TL;DR account for the sender's original_psbt input as our utxo rather than the original_psbt output. Either way bria should spend this utxo in the original_psbt fallback or a payjoin.

We must first account for the sender's utxo(s) we can spend and then queue the fallback transaction extracted from the original_psbt for broadcast after an interval. After accounting we may construct payouts in a payjoin psbt that are dependent on those specific foreign utxos.

Once utxo and payout accounting is set up on the fallback, we initialize a PsbtBuilderConfig that includes a new field payjoin_sender_utxos: Vec<OutPoint> (or foreign_utxos) for which we have no KeychainId. Or, perhaps we create a new KeychainId for each specific payjoin since they must be spent exclusive of other foreign payjoin inputs, since a valid response must only be missing signatures from a payjoin sender's own inputs. This new set of utxos represents neither reserved nor cpfp utxos, but those spent in the payjoin's original_psbt. By making a request, the sender effectively promised to sign a psbt containing those utxos upon receiving a valid response. The PsbtBuilderConfig's fee_rate must also consider the payjoin request's fee parameters. Perhaps the signer for payjoin_sender_utxos, the sender, can be thought of as another RemoteSigningClient valid within the context of a payjoin session. If signing fails, the batch may be cancelled and the original_psbt should be broadcast.

I believe if the Payout and utxo repositories are update appropriately according to this logic, the existing PsbtBuilder::construct_psbt and accounting might work for us without any major rework.

DanGould avatar Jan 15 '24 23:01 DanGould

Okay if I understood it correctly I like the general approach. Just a note on the accounting - I would figure that bit out last. When we have the capability to receive / process / sign /broadcast a pj tx e2e it should be a lot more straightforward to see what is missing on the accounting side. I find it hard to conceive upfront what the right way to deal with it is...

So my recommendation would be to code the end-to-end process accepting that accounting will be off and then come back to that later.

Regarding adding additional capabilities to the PsbtBuilder - it would be advisable to add a test here.

bodymindarts avatar Jan 16 '24 07:01 bodymindarts

I think my point is that there are 2 moments of accounting rather than 1. Upon request, and then mempool update. Should it be possible to add a utxo to the repository without accounting for it?

DanGould avatar Jan 16 '24 15:01 DanGould