2023.05 Vol.1

Bit of hodl

HODL Invoices

HTLCs, “Hash Time-Lock Contracts”, is the current standard protocol on the lightning network to enable atomic multi-hop payments. Let’s say node A is routing a payment which happens to end at node B. When A reaches out to B, B obviously reacts a little differently than if the payment was continuing on to some other node C. A asks B, “Hey, I’ll give you some sats if get the preimage for this payment”. If B was routing to C, B would have to request the same from C in order to get the preimage. But in this scenario B already has the preimage, it created it when it made the original invoice for the payment. At this point, B has every incentive to “release” the preimage to the wild either by broadcasting the commitment transaction it has with A and paying the HTLC’s UTXO (a.k.a. the hard way) or just telling A the preimage in exchange for folding the HTLC balance into the payment channel. In either case, no use waiting around for that HTLC to actually hit that time lock and expire…or is there?

When A reaches out to B with the HTLC offer, B knows at that point that there is a payment “locked in” (it could be traveling some weird path across the lightning network, B doesn’t know or care), all it has to do is release the preimage. Instead of doing so right away though, B could hold the HTLC open and perform some extra logic. If and only if the extra logic is successful does it then release the preimage, otherwise B just lets the HTLC expire (or cancels it). This is called a hold, or “hodl”, invoice. It is a hook exposed by the node implementation that lets a node operator inject some logic into the HTLC lifecycle, “Hey node, right before you release the preimage for the invoice with preimage 123ABC, hold on a sec and ask me first”.

One of the cooler and most straightforward use cases I have seen for hodl invoice is a proxy service, lnproxy. The service provides an API with an endpoint that takes an existing invoice and returns a new invoice. The invoices use the same payment hash (so can be unlocked with the same preimage), but the new invoice is a hodl invoice on the proxy service’s lightning node. When someone pays this hodl invoice, the node pauses and asks if there is any work to be done first. In this case, yea, we gotta first pay that original invoice! So it does that first, gets the preimage, and is now able to settle the hodl invoice with the same preimage.

One thing I am wondering about is if this use case breaks down with PTLCs, “Point Time-Lock Contracts”, the next generation protocol for multi-hop payments. My guess is no just because instead of a shared hash, there would be a shared public key. This is kinda weird in a PTLC world since one of the benefits of the PTLC protocol is that each hop has its own pubkey, but I don’t think it breaks anything.