a single payment to a single recipient

Lightning wallets assume a single recipient for a single payment. Alice can send money to Bob in a single payment, and Alice can send money to Carol, but Alice cannot send money to both Bob and Carol in a single payment. Alice, or her wallet, must pay each independently and it's possible that Alice's payment to Carol succeeds while Alice's payment to Bob fails. On lightning, coordinating a single payment (ie input) to more than one recipient (ie outputs), where all recipients are paid or none are paid, is left to Alice and Bob and Carol to figure out. Maybe lightning wallets shouldn't coordinate a single payment with more than a single receiver in a trust minimized way, but it'd be useful, and surprisingly so, if they did.

most lightning payments pay multiple recipients

When Alice pays Carol on the lightning network, Alice's money often travels through several other lightning nodes before arriving at Carol's lightning node. The nodes that Alice sends her money through don't do this for free. Alice pays them. What's more, those other lightning nodes only get paid by Alice if Carol gets paid. Those other lightning nodes are effectively Bob(s) from the previous section's example; that is, the other lightning nodes are additional trust-minimized recipients as part of Alice's payment to Carol. Only, those other lightning nodes are secondary to Alice's payment to Carol.
In the lightning protocol as-is, Carol can't make sure Alice's money travels through a specific Bob, and Bob can't enforce that Alice pays Carol through him. If Carol and Bob don't trust each other nor Alice, yet both can agree to receive money from Alice only if the other also gets paid, the lightning protocol as-is can't help them. If Carol and Bob want to enter such a contract, they have to get creative.

trust minimized split payments enable trust minimized coordination

The lightning network coordinates delivery of bitcoin from Alice to Carol by paying several Bobs to move their bitcoin in Carol's direction. By design, Alice, the Bobs, and Carol don't need to trust each other much to do this. Ideally, they wouldn't need to trust each other at all. Less required trust means less required permission and less required permission means more freedom, opportunity, and competition. People want to coordinate and if they can't do so in a trust minimized way, fewer people will coordinate and the coordination that does happen will tend to be centralized.

splitting a payment atomically and downstream is better ux

Imagine swiping your credit card five times when you buy something, once to pay Visa, another to pay the merchant, another to pay the merchant's landlord, another to pay the supplier, and another to pay the manufacturer. Now imagine the payment to the supplier fails and continues to fail, then swiping your card four times to get a refund from everyone you paid. If the complexity of Visa, the merchant, the landlord, etc coordinating with each other is thrust on the customer, the customer will prefer a merchant that doesn't expose the complexity, and such a preferred merchant will have more trusted relationships with the other parties.
That's a toy example, but we do atomic split payments on bitcoin's base layer because it's plain practical. Imagine paying two invoices to your LSP when you want to open a channel. What should they do with your funds when the second payment doesn't arrive? Or how about creating two bitcoin transactions every time you want to pay someone, one to pay the miner and one to pay the receiver?
Atomicity means that when receivers coordinate they don't need to trust each other fully, and if the split happens downstream, the UX for the sender is identical whether there's one receiver or many.

today's hacks are tomorrow's solutions

One way to be certain people want something is that they trip over themselves for solutions that work poorly. When they really want something, they create elaborate, inelegant, risky hacks that give them the faintest whiff of a satisfying solution. Should a better solution exist, you know they'll use it.

hold invoices

Most non-wallet lightning companies (ones that don't have the luxury of going on-chain for atomic split payments) have currently implemented or at least explored using hold invoices for split payments. Geyser does this to non-custodially take a platform fee. Robosats does this to fulfill an order conditional on an escrow agent's approval (their solution is custodial though because they can't be sure the buyer will be online to accept the payment). Mash once explored this. lnproxy does this to hide a receiver's node from senders and proxies get paid to do so. We plan to cautiously do this to take our sybil fee non-custodially.
Using hold invoices this way allows applications to be Bob when their customer Alice pays their customer Carol. It's elaborate, inelegant, and risky, but any other solution is custodial, trusted, or imposes new requirements on the sender and/or receiver. These hold invoices give Alice, Bob, and Carol a way to coordinate a split payment without Bob or Carol taking custody of the other's funds, or trusting that Alice is willing and able to send funds to both of them. It also hides the identity of Carol's lightning node from Alice which is otherwise exposed.
This use of hold invoices recreates how a lightning node forwards a payment, using the familiar preimage and CTLV enforcement, but does so at the application layer. When Alice tells Bob she wants to pay Carol, Bob requests an invoice from Carol. Bob then wraps the invoice, meaning Bob's invoice is conditional on Carol's invoice being paid, and sends it to Alice. Alice then pays Bob's wrapped invoice and because Bob can't redeem Alice's payment without first paying Carol, Bob pays Carol and then claims his funds from Alice. Hence, at no point is Bob in custody of Alice's funds meant for Carol. And, when Bob wraps Carol's invoice, he can add an additional split payment to himself.

many payments to many recipients

The main, in-use alternative to the hold invoice approach is requesting Alice pay each Bob and Carol independently. One popular example of this approach is nostr prisms. Using programmatic wallet connections, an application requests invoices from an arbitrary number of Bobs and Carols, then sends them all to Alice's wallet to pay one by one. Pending adoption of a soon to be merged(?) lnurl spec, Bob might even be able to request proof that Alice paid Carol (assuming Carol isn't in cahoots with Alice to trick Bob).

bolt12 and blinded paths

If I'm not mistaken, Bolt12's blinded paths, when adopted widely, should replace the hold invoice approach. If Bob is provably the introduction point to a blinded path in an amount-less bolt12 offer that pays Carol, then Bob can enforce that he'll be paid when Alice pays Carol. Using this approach, it might be possible for several Bobs to be predictably paid when Carol does, assuming blinded paths can contain other blinded paths. This isn't my exact dream of a single payment being split along independent routes, to different receivers, with codependent settlement at the protocol layer, but maybe novel forms of decentralized coordination can wait for bolt13.
1210 sats \ 1 reply \ @rheedi0 10 May
I have thought about how to do atomic payments to multiple parties at once over Lightning so much... thanks for laying out the problem space like this and theorizing a potential way Bolt12 could help do it. It's a really interesting idea.
What I struggle with when it comes to all these approaches is -- and this is coming from the perspective that the reason we need atomic split payments is so there is no custodial element when trying to pay multiple recipients simultaneously -- every participant still needs a stable, funded Lightning node for the payment to work at all. I think right now it is still way too difficult for most people to run their own node. And until that hurdle is cleared, non-custodial split payments don't gain most end users very much if those payments are ending up on a node they don't control anyway.
I'll have to read more into the blinded paths pattern in Bolt12. If anything it could serve as a good enough solution in the near future while nodes become easier to run over the longer term.
reply
I have thought about how to do atomic payments to multiple parties at once over Lightning so much.
Glad to know I’m not crazy! I’ve been thinking about it for years and waiting for someone with a worthy spine to suggest it, but it’s never come up, and I need to know if I should fantasize about something else.
What I struggle with when it comes to all these approaches is -- and this is coming from the perspective that the reason we need atomic split payments is so there is no custodial element when trying to pay multiple recipients simultaneously
If there are multiple custodians it’s still useful to atomically split payments between their customers (and other self custodians).
This kind of thing definitely isn’t useful when there’s one or very few custodians, but I very much doubt that’s the future of lightning.
every participant still needs a stable, funded Lightning node for the payment to work at all
I think this is a hard problem to solve but I think it can be solved, especially when invoices and bitcoin script aren’t so primitive.
reply
I've been worried about the repercussions of blinded routes to be used for enforcement instead of privacy. You could indeed do that with blinded paths, it's not a bad idea, and you can still take a reasonable fee on it and enforce it. While staying non-custodial and atomic.
One thing we're looking into at Mutiny is a way to do multiple pubkey locked ecash notes. I think someone could create the an ecash contract that goes to two outputs, one to the service and one to the recipient. If you had a lightning invoice be the funding of that, then it's effectively a payment split.
I've been saying this for awhile, but I think ecash is a way better experience for something like Stacker News. And with fedimint federations, whether SN is a member or not, it's a much more favorable position to be in.
reply
One thing we're looking into at Mutiny is a way to do multiple pubkey locked ecash notes. I think someone could create the an ecash contract that goes to two outputs, one to the service and one to the recipient. If you had a lightning invoice be the funding of that, then it's effectively a payment split.
Cool. I feel like this kind of programmability is something we currently lack in L2! But we've gotta make it eventually. At least I hope so.
I've been saying this for awhile, but I think ecash is a way better experience for something like Stacker News. And with fedimint federations, whether SN is a member or not, it's a much more favorable position to be in.
I might agree with you. I'm mostly trying to get us to a position where we can begin experimenting with these things. Perhaps one type of attached wallet we'll have is a built-in ecash wallet. Stackers will have to backup the privkey to that, but why not.
reply
I think is better than fee credits SN is switching to but is it practical to program?
reply
I don't see anything wrong with this. Alice is locking funds to Carol's secret, which is no different than routing an HTLC.
In practice, wrapped invoices will probably scale very poorly. This is because the lightning node for Alice will only consider routing to Bob, and the lightning node for Bob will only consider routing to Carol. The route will not be optimized at all.
The solution for this of course is to to build a Bolt 11 invoice with all your Bob nodes specified in the route. Then the path-finding logic for Alice's node will try to build an optimal route.
For some reason, LNURL doesn't implement the routes attribute from the LUD-06, even though it is named in the spec. It would be nice if it did, because then you could specify members for a multi-party payment.
However, this still doesn't solve the problem, because adding Bob to the route doesn't mean that Bob will know to intercept that invoice, and charge a certain fee.
So then what you need is an HTLC interceptor, that is looking for a specific payment hash, so that Bob's node can charge the correct fee. But I'm not sure to what extent you can get away with this, as you may have to mess with your node's pathfinding API, and every implementation is different.
So in addition to the above, you may also need to analyze the graph and build the route yourself, then have your node setup the HTLC, then pay the invoice.
Much of the above is pure speculation and I may be completely wrong.
I have also thought about this problem quite a bit myself 😅
reply
In practice, wrapped invoices will probably scale very poorly. This is because the lightning node for Alice will only consider routing to Bob, and the lightning node for Bob will only consider routing to Carol. The route will not be optimized at all.
Yep, routing failures compound, but if LN is to succeed, this kind of thing should be as reliable as sending your traffic through a VPN.
The solution for this of course is to to build a Bolt 11 invoice with all your Bob nodes specified in the route. Then the path-finding logic for Alice's node will try to build an optimal route.
If it's all done in a single route, I don't think this is any different than the wrap actually. But, if Alice can split the payment on multiple routes, one going to Bob and another to Carol, it'd provably be more reliable because each route requires less liquidity. It's like MMP then.
However, this still doesn't solve the problem, because adding Bob to the route doesn't mean that Bob will know to intercept that invoice, and charge a certain fee.
It depends on the problem you're trying to solve. If Alice pays Carol and Bob independently, but Bob only wants to accept the payment if Carol receives her payment, he can hold Alice's payment, cancelling it if Carol isn't paid and accepting it if she is.
reply
With PTLCs you should be able to split payments like that. You could lock an invoice to the sum of a set of invoice secrets, for example (since points can be added).
reply
Ptlcs seem to be a big unlock for all kinds of stuff. Maybe we’ll get it after bolt12
reply
Sounds like a plan! Go for it! 👍
reply
Not sure I'm following, are you suggesting chained wrapped invoices? Sn->bob->carol?
The wrapped invoices thing is theater, at least prisms are honest about about the trust level
reply
I'm suggesting chaining bolt12 blinded paths, but chaining n wrapped invoices would allow atomic, non-custodial splits to n participants.
In our case, I mean alice->sn:wrap(carol)->carol.
at least prisms are honest about about the trust level
What's dishonest about a wrapped invoice's trust level?
reply
The blinded paths don't solve for HTLCs being unable to be split, so there's inherently a wrapper doing a partial forward. Obfuscating the path doesn't skirt this limitation.
With wrapped invoices, the payer is getting the invoice from the party doing the wrapping. This is a completely trusted step in the process as the wrapper could wrap anything, or nothing. May as well trust the prism to serve it in which case, as it's better UX, and doesn't create hazardous stuck payments on the network.
Now, it may work for scamming the regulator, but just as easily could not. It's still forwarding a payment.
Given that wrapped invoices have 0 technical justification, it's a fear induced narrative trap and those always end badly.
reply
HTLCs aren't split in either the hold invoice or bolt12 case. Both are just forwards.
With wrapped invoices, the payer is getting the invoice from the party doing the wrapping.
Fair point. This isn't true in the bolt12 case though. For our use, and geyser's, and robosats', this is okay because Alice trusts Bob which is why she requests to pay Carol through them. If we didn't wrap the invoice, Alice would have to trust we are giving her an invoice that goes to Carol anyway.
Given that wrapped invoices have 0 technical justification.
Atomicity is justification enough for me.
reply
Alice trusts Bob
So why doesn't Bob just run a prism?
Alice would have to trust we are giving her an invoice that goes to Carol anyway
That's the actual problem that needs solving, Nostr offers incoming for this purpose.
Atomicity is justification enough for me
Is it really though? What value do you put on it and have you calculated the costs? If so, at what cost is atomicity justified? If 50% of payments fail, is that acceptable when the alternative is 90% success?
Absorbing that cost comes down to a rationale, a fear based rationale that that leads to high time preference decisions to scam the regulator that inevitably backfire (unless you're Tether?)
Now, it may work for scamming the regulator, but just as easily could not. It's still forwarding a payment.
The idea is that it should be as much scamming the regulator as running a lightning routing node is. It's basically a reductionist approach. The only difference is protocol layer vs application layer.
Dang, I should've put this in ~lightning.
reply
and *CLTV
reply
131 sats \ 1 reply \ @ek 10 May
Interesting that it's called "lock time" (CLTV) in bitcoin but "time lock" (HTLC) in lightning. Maybe they also got the order confused when they invented HTLCs, lol
reply
Check Lock Time Verify. Hashed Timelock Contract.
Hmmm yeah Hashed Lock Time Contract seems to work just as well.
reply