Lightning Networks Part III: Channeling Contracts

This is the third part of my series of posts explaining the bitcoin Lightning Networks 0.5 draft paper.

In Part I I described how a Poon-Dryja channel uses a single in-blockchain transaction to create off-blockchain transactions which can be safely updated by either party (as long as both agree), with fallback to publishing the latest versions to the blockchain if something goes wrong.

In Part II I described how Hashed Timelocked Contracts allow you to safely make one payment conditional upon another, so payments can be routed across untrusted parties using a series of transactions with decrementing timeout values.

Now we’ll join the two together: encapsulate Hashed Timelocked Contracts inside a channel, so they don’t have to be placed in the blockchain (unless something goes wrong).

Revision: Why Poon-Dryja Channels Work

Here’s half of a channel setup between me and you where I’m paying you 1c: (there’s always a mirror setup between you and me, so it’s symmetrical)

Half a channel: we will invalidate transaction 1 (in favour of a new transaction 2) to send funds.

The system works because after we agree on a new transaction (eg. to pay you another 1c), you revoke this by handing me your private keys to unlock that 1c output.  Now if you ever released Transaction 1, I can spend both the outputs.  If we want to add a new output to Transaction 1, we need to be able to make it similarly stealable.

Adding a 1c HTLC Output To Transaction 1 In The Channel

I’m going to send you 1c now via a HTLC (which means you’ll only get it if the riddle is answered; if it times out, I get the 1c back).  So we replace transaction 1 with transaction 2, which has three outputs: $9.98 to me, 1c to you, and 1c to the HTLC: (once we agree on the new transactions, we invalidate transaction 1 as detailed in Part I)

Our Channel With an Output for an HTLC

Note that you supply another separate signature (sig3) for this output, so you can reveal that private key later without giving away any other output.

We modify our previous HTLC design so you revealing the sig3 would allow me to steal this output. We do this the same way we did for that 1c going to you: send the output via a timelocked mutually signed transaction.  But there are two transaction paths in an HTLC: the got-the-riddle path and the timeout path, so we need to insert those timelocked mutually signed transactions in both of them.  First let’s append a 1 day delay to the timeout path:

Timeout path of HTLC, with locktime so it can be stolen once you give me your sig3.

Similarly, we need to append a timelocked transaction on the “got the riddle solution” path, which now needs my signature as well (otherwise you could create a replacement transaction and bypass the timelocked transaction):

Full HTLC: If you reveal Transaction 2 after we agree it’s been revoked, and I have your sig3 private key, I can spend that output before you can, down either the settlement or timeout paths.

Remember The Other Side?

Poon-Dryja channels are symmetrical, so the full version has a matching HTLC on the other side (except with my temporary keys, so you can catch me out if I use a revoked transaction).  Here’s the full diagram, just to be complete:

A complete lightning network channel with an HTLC, containing a glorious 13 transactions.

Closing The HTLC

When an HTLC is completed, we just update transaction 2, and don’t include the HTLC output.  The funds either get added to your output (R value revealed before timeout) or my output (timeout).

Note that we can have an arbitrary number of independent HTLCs in progress at once, and open and/or close as many in each transaction update as both parties agree to.

Keys, Keys Everywhere!

Each output for a revocable transaction needs to use a separate address, so we can hand the private key to the other party.  We use two disposable keys for each HTLC[1], and every new HTLC will change one of the other outputs (either mine, if I’m paying you, or yours if you’re paying me), so that needs a new key too.  That’s 3 keys, doubled for the symmetry, to give 6 keys per HTLC.

Adam Back pointed out that we can actually implement this scheme without the private key handover, and instead sign a transaction for the other side which gives them the money immediately.  This would permit more key reuse, but means we’d have to store these transactions somewhere on the off chance we needed them.

Storing just the keys is smaller, but more importantly, Section 6.2 of the paper describes using BIP 32 key hierarchies so the disposable keys are derived: after a while, you only need to store one key for all the keys the other side has given you.  This is vastly more efficient than storing a transaction for every HTLC, and indicates the scale (thousands of HTLCs per second) that the authors are thinking.

Next: Conclusion

My next post will be a TL;DR summary, and some more references to the implementation details and possibilities provided by the paper.

 


[1] The new sighash types are fairly loose, and thus allow you to attach a transaction to a different parent if it uses the same output addresses.  I think we could re-use the same keys in both paths if we ensure that the order of keys required is reversed for one, but we’d still need 4 keys, so it seems a bit too tricky.

7 thoughts on “Lightning Networks Part III: Channeling Contracts”

  1. very nice blog and thoughts on the lightning network. we have also been trying to think about the best ways to use lightning network like transactions.

  2. Hi Rusty. One thing I don’t understand about the final diagram:

    Suppose you (as Rusty) are “me” in the diagram, and I am “you.” You’re trying to pay me 1c via the HTLC, so we create and sign all the transactions as in the diagram. Shouldn’t I be able to get that 1c that you paid me via the HTLC even if you get hit by a bus before anyone drops their version of Transaction 1 onto the blockchain?

    If I publish my Transaction 1, I can get my $0.01 from the non-HTLC output since you already signed Transaction 1a. However both the Settlement Transaction and Timeout Transaction still need your signature. It seems like if you die suddenly, I can never spend that output even if I have R.

    Is the diagram supposed to represent the state of affairs right before you pay me? If the transactions shown represent me already being paid 1c via the HTLC, what am I missing?

    1. The trick you’re missing (because I didn’t clarify this!) was that you always hand me the signatures for those transactions before we revoke the previous ones. Thus, you can get the HTLC output after 2 days.

      Hope that helps!

  3. Hi Rusty. I didn’t understand what you meant, so I read over the relevant parts of the Lightning paper. I believe there’s a mistake in the final diagram in this post (and also the one above it):

    The key point is that the signatures on each side’s copy of the HTLC should not be symmetrical. Each HTLC is for payment in one direction (only one person knows R). If both people need to be able to pay each other via HTLC, another HTLC must be opened in the other direction.

    Each person will have copies of the settlement transaction that spend the outputs of their version of the commitment transaction, but Alice will sign both settlement transactions, and Bob will sign both refund transactions. (I’m switching to Alice and Bob from “me and you” to avoid confusion — Alice corresponds to “me” in your diagrams).

    Look at page 8 in the Lightning paper, where the four step sequence of signature exchanges is discussed. Step one is “Alice signs and sends Bob her signature for CR2b, S1, SD1.” I think the notation means that her signature goes on S1a, S1b, SD1a, and SD1b. Similarly in step 2, Bob signs both versions of T1 and TR1.

    It seems like this is necessary because no matter who broadcasts their commitment transaction, Bob always needs to be able to broadcast a settlement transaction when he knows R, and Alice always needs to be able to broadcast a timeout transaction if Bob hasn’t provided R within the specified timeframe. This shouldn’t change depending on who broadcasts their commitment transaction. Anything else seems to go against the meaning of the HTLC. So Alice’s signature needs to be on all settlement transactions, and Bob’s needs to be on all timeout transactions.

    Do you still think I’m missing something? If so can you phrase it in terms of Alice and Bob?

  4. If you do lots of HTLCs, does the number of outputs of the transaction just keep growing (1 per HTLC) or do the parties reveal the hashes off-blockchain and then somehow consolidate their balances into a single output again? Maybe you covered that and I missed it. Thanks.

  5. Ash: they HTLC outputs can easily be consolidated into the main, non-HTLC transaction (Transaction 1 in the last diagram above). This consolidation can happen once the payer knows that the payee knows R. Both parties just sign new versions of Transaction 1 (and child transactions) that have the non-HTLC outputs updated with the current balance moved over from the HTLC outputs. They can then invalidate the previous one by revealing their temporary private keys.

  6. I agree with Elliot that there are mistakes in the diagrams. But I think I understand Rusty’s defence too. I will use his convention that Alice is “me” sending payment to Bob, “you”.

    As Elliot says, Alice’s signature needs to be on all settlement transactions, and Bob’s needs to be on all timeout transactions. But as Rusty says, really all of the signatures should be on all of the lower eight transactions. The only decision point is whether or not the R value is known, so that should be written as “R value goes here”. There should not be any “My sig goes here” or “Your sig goes here” in those lower eight transactions, because those are not optional.

    The part that I don’t get is the double locktime, 2+1. I understand the 2-day locktime is needed in the case where the first transaction times out and Bob knows R. Bob needs to time to see which version of the first transaction is accepted by the blockchain before deciding which version of the R transaction to publish. But then what’s the +1 day timeout for? That only adds more delay in the event that the first and second transactions both time out with R unknown. I can’t figure out why that’s useful.

Comments are closed.