A little bit of HTLCs
Atomic Multihop Payments
The Lightning Network is made up of payment channels between nodes. A channel holds the balance between two nodes. This is done without the nodes having to trust each other by exchanging valid, but not broadcasted, bitcoin transactions. To avoid paying onchain transaction fees, the nodes just keep swapping updated transactions. I ain’t gonna sink into it here, but let’s just accept that swapping transactions also happens in a trustless manner. More on that in the Lightning manual.
But how do routed (across multiple nodes) payments remain trustless and atomic? How are multiple channel tied together for a payment to shoot across the network?
(A) -> (B) -> (C)
Routed payment from from A to C through B
Enter Hash Time-Lock Contracts (HTLCs).
These contracts operate on top of existing payment channels. To perform a payment from (A) to (C), the (A) to (B) and (B) to (C) channels need to be updated. The unbroadcasted bitcoin transactions which make up the channels start with two outputs, one to each node. These OG outputs just require the node operator signatures in order to be spent. In order to create the HTLC, a third output is added to pay the node which the payment is flowing in equal to the amount of the transaction plus downstream node operator fees. The new HTLC output requires a special key unique to the payment in order to be spent. This is called the preimage and it is generated by the receiver, in this case, node (C).
The new output is kinda a form of escrow. The funds are now tied down and separated from the rest of the funds in the channel. How does this help all the nodes to play nice and complete the payment?
The general flow:
- C creates an invoice for A, the invoice contains a hash of the preimage (which is just a random secret that only C knows)
- C gives A the invoice out-of-band of the Lightning Network
- A figures out the path to C on the Lightning Network (this pathfinding algorithm is another can of worms we will just accept for now)
- A tells B “I’ll give you a few sats if you forward this payment to C”, B agrees
- A and B add the HTLC output to their channel
At this point, B has an incentive to get that preimage in order to earn a few sats.
- B tells C “I’ll pay that invoice you have”
- B and C add the HTLC output to their channel
At this point, C could just publish the most recent commitment transaction between it and B which includes the HTLC output unlocked by the preimage. If C does broadcast the transaction, then the preimage is now on the blockchain for B to read and use to broadcast the A to B commitment transaction. But like all broadcasts, these will cost onchain fees. Every node in the chain is incentivized to just update the channel balance and fold the escrow’d HTLC funds back in.
- B will only update the channel balance with C if it gets the preimage, so C sends over the preimage and they update the balance
This step is key to the incentive chain. If C sends over a bogus preimage and B still updates the channel balance, B would be giving away funds with no way to get reimbursed from A. So B would always first check the preimage hash to make sure it unlocks the commitment transaction from A.
- A and B fold the HTLC back into the channel balance, the payment from A to C is now complete
Nodes charge a fee to forward payments since they are doing some work and escrowing their funds. What if a payment stalls? It could get expensive for a middle node to have their funds needlessly tied down. For this reason HTLCs contain a time-lock for which they are valid, expiring after some time.
Every hop in the chain must have a time-lock significantly less than the hop before it. This is to prevent scenarios where node C waits a long time to release the preimage to B. B settles up with C, but time runs out and the HTLC between A and B is no longer valid, which results in B losing their funds to C with no reimbursement from A.
If One Hop?
Step 7 might seem a little overkill since at this point there is only one hop left in the payment chain, could we skip right to just updating the channel balance? However, B doesn’t know that C is the final destination of the payment. This is a nice privacy benefit. C could tell B that it is the final destination, but there is no incentive to do so. So the protocol just errors on the side of simplicity and privacy and always uses HTLCs.
HTLCs can be winded back folding the funds back in if there is an error downstream. The commitment transactions are updated in the same way as if the HTLC worked, but the funds are instead sent the other way.
The Wormhole attack effects routing nodes. It involves an attacker realizing that they have multiple nodes along a payment route, which they can do since the preimage hash is the same for each hop.
(A) -> (E1) -> (B) -> (E2) -> (C)
E1 and E2 are evil nodes coordinating to perform a wormhole attack
As the preimage is being passed back across the route, E2 skips B and passes it straight to E1. To nodes A and C, the payment looks successful. To node B, the payment looks like a failure and it unlocks its funds in the HTLC to E2. However, the fees that were originally meant for B have now been pocketed by E1.#lightning