Lightning network in depth, part 1: payment channels

Original author: Softblocks Co
  • Transfer

Lightning network is a decentralized of-chain technology that allows you to conduct tens of thousands of transactions per second, as it allows, for example, Visa. At the moment, Bitcoin is the most popular cryptocurrency in the world, it is not suitable for sending more than ~ 7 transactions per second, and high fees and a long confirmation time negate the possibility of sending microtransactions. Lightning network solves both of these problems .


Lightning network


Table of contents


  • Introduction
  • Payment channels
  • Simple payment channel example
  • Trustless channels
  • Using timelocks
  • Asymmetric revocable commitments
  • Conclusion
  • Links

Introduction


Lightning network is a network of payment channels, which are ordinary multisig wallets. To open the channel, the parties create a multisig wallet and send funds to it. The amount received becomes the balance of the channel and all further transactions between channel members are carried out outside the blockchain. The channel can be closed at any time by either side, in which case the last off-chain transaction determining the balance of the channel will go to the network, making all previous transactions invalid, since they all spend the same 'exit'. Thus, we need only one transaction to open the channel and another to close it, and all intermediate transactions are carried out instantly, without writing to the blockchain.


A network of such channels will allow you to send transactions to another network member, even if you are not directly connected to him. It’s enough that it’s possible for you to pave a “path” to it, consisting of a chain of channels, and you are not obliged to trust any of the participants in this chain, thanks to special “smart contracts” (HTLC hash-time-lock-contract), which guarantee safe delivery your funds.


To understand how lightning works, you first need to understand how the payment channels work, as well as the HTLC contracts for which it relies. These are quite voluminous topics, so we will break this article into 2 parts and begin with an explanation of the mechanism of operation of payment channels.


Payment channels


As we said above, a payment channel between two network members is an ordinary multisig wallet. The first transaction, fixing the balance of the channel (our multisig wallet), we will call the “opening” ( funding transaction or anchor transaction ). This transaction must be sent to the network and mined in order for the channel to be created.


Further, the parties exchange mutually signed commit transactions ( commitment transaction ), which change the initial balance of the channel. These transactions are valid and can be sent to the network, but instead are kept offline, waiting for the channel to close. Thus, the balance state of the channel can change thousands of times per second, limited only by how quickly the parties can create, sign and transmit to each other commit transactions.


Each time, exchanging a new commit transaction, the parties invalidate the previous state of the channel and thus only the newest commit transaction can be 'executed'. This is done so that the parties do not try to cheat by sending one of the previous channel states to the blockchain, which is more beneficial to them. Next, I will consider several mechanisms that allow this to be implemented.


Finally, the channel can be closed both by mutual consent - by sending a 'closing' transaction to the blockchain ( settlement transaction ), and on the initiative of only one of the parties - by sending the last commit transaction to the blockchain. Thus, we prevent the case when one of the parties goes offline and the funds of the second are 'locked' on the channel.


Throughout the existence of the channel, only two transactions are sent to the network and recorded on the blockchain (opening and closing). Between them, the parties can exchange any number of commit transactions that will never fall into the blockchain.



Simple payment channel example


Before moving on to more complex implementations, let us consider the operation of a simple one-way channel as an example. In this example, we assume that both parties are honest so as not to complicate the explanation. Next, we consider the mechanisms to prevent any attempt to cheat.


In this example, we have 2 members - Emma and Fabian. Fabian provides video streaming services, paid through the channel using micropayments - one second of video costs 0.00001 BTC, which is 0.036 BTC per hour. Emma is a regular user who wants to watch a video.



Emma and Fabian use a special program that allows you to work with both the payment channel and the video. Emma runs this program in a browser, Fabian on her server. The program has the functionality of an ordinary Bitcoin wallet, it can create and sign transactions. The whole mechanism of the payment channel is hidden from the user, all they see is how the video is paid every second.


Now let's see how this will work. To create a channel, Emma and Fabian must create a multisig address with the condition two of two. On the part of the user, the program creates a P2SH address (multisig wallet) and asks to replenish it for the amount of 1 hour of viewing. Emma puts 0.036 BTC on it and this transaction becomes 'opening'.


As soon as the 'opening' transaction is confirmed and the channel is open, video streaming begins. At the first second, the user side creates and signs a commit transaction that changes the balance of the channel: 0.00001 BTC to Fabian and 0.03599 Emme. The transaction uses the opening transaction exit at 0.36 and contains 2 new ones just described. The program on the service side receives this transaction and also signs it, after which it sends back along with the first second of the video. Now the parties have a commit transaction signed by both parties that represents the last state of the channel, which they can send to the network if necessary.


At the second second, the next commit transaction is created, using the same output as the previous one, and the new outputs are now 0.00002 to Fabian and 0.03598 Emme. This transaction is a payment for 2 seconds of video downloaded. Then it goes to the second side and so on.


Suppose Emma watched 10 minutes of the video and she was tired, she stopped watching. During this time, 600 commit transactions (600 seconds of viewing) were sent and signed. The last of them has 2 outputs: 0.03 Emme and 0.006 Fabianu. Emma closes the channel by sending this commit transaction to the network, making it 'close'. Thus, only 2 transactions entered the blockchain.



Trustless channels


Of course, in this example, everything works, but only if both sides are honest. It’s easy to come up with a scenario where one of the parties can cheat, gaining an advantage or the channel will not work correctly:


  • As soon as the channel is open, Emma needs Fabian's signature to withdraw funds back, so the channel is a 2-of-2 multisig wallet. If Fabian disappears, Emma’s funds can forever remain locked on the channel.
  • While the channel is open, Emma can take any of the commit transactions signed by both parties. After watching the video for 10 minutes, she can easily take the very first commit transaction and send it to the network without Fabian's knowledge.

Using timelocks


One solution to these problems is to use timers in transaction-level timelocks (nLocktime). To ensure that her funds are not stuck on the channel, together with the opening transaction, Emma creates a refund transaction using the outputs of her opening transaction. First, she sends this transaction to Fabian and as soon as he signs it and returns, Emma sends the opening transaction to the network, creating a channel.


The refund transaction becomes the first commit transaction and its timer sets the upper limit of the channel life. Suppose Emma sets a timer for 30 days (4320 blocks). All subsequent commit transactions will have a shorter timer so that they can be sent to the network earlier.


Now Emma can calmly open the channel, knowing that if Fabian disappears, after 30 days she will be able to return her funds (if it were a bidirectional channel and Fabian introduced some funds, he could create a return transaction in the same way).



Each new commit transaction will have some kind of timer, namely shorter than its predecessor, so that the latest commit transaction can be sent to the network first and invalidate the previous ones, protecting both sides from the unfair use of earlier commits transactions. If everything goes well, then Emma and Fabian can simply send a normal closing transaction, so that commit transactions in this case are used only when one of the parties goes offline.


For example, if the first commit transaction has a timer for 4320 blocks, then the second may have a timer for 4319 blocks, etc. Transaction # 600 in this case can be sent to the network 600 blocks earlier than transaction # 1 becomes valid.



I think you already noticed that this method, although it helps to prevent the use of earlier commit transactions for the purpose of cheating, but nonetheless has 2 serious drawbacks.


  • The timer of the first commit transaction limits the lifetime of the channel.


    If you set the timer for a long time (let’s say a year), you can use the channel for a very long time without opening it again, however, if one of the parties disappears, the second will have to wait all the remaining time to withdraw funds from the channel, sending the last commit to the network transaction.


  • The timer of the first commit transaction limits the number of transactions that can be sent to the channel.


    For our example with a timer of 4320 blocks, no more than 4320 transactions can be sent to the channel, since each new commit transaction reduces the timer by 1 block. Moreover, using an interval of 1 block (10 minutes), we force the channel participants to ensure that they do not oversleep the necessary block and send the last commit transaction in time if something goes wrong. Of course, you can increase the interval, but in this case, the limit on transactions on the channel will decrease even more.



Thus, with the help of a timer, we can invalidate earlier commit transactions, as well as guarantee the safe closing of the channel by either side: if both parties agree on the last state of the channel, they can simply send a closing transaction (in fact, the last commit transaction) to the network without any timer and close the channel, and if one of the parties has disappeared, then the second just has to wait for the timer for the last commit transaction to expire in order to send it to the network.


Asymmetric revocable commitments


Another way to resolve the previously described channel trust issues is to reverse earlier commit transactions. In fact, cancellation is not quite the word, because in Bitcoin, as soon as the transaction is mined and confirmed, it cannot be canceled in any way. Therefore, you can design it in such a way that it is not profitable to use it. This can be done by giving each side a revocation key .


This time the channel was decided to create Hiteshi and Irene. They both sent 5 bitcoins to the channel, which make up the initial balance of the channel. Now, instead of the standard commit transaction that they both must sign, Hiteshi and Irene create 2 different asymmetric commit transactions.


Hitesha has a 2-way commit transaction signed by Irene. The first output pays 5 bitcoins Iren instantly, and the second output pays 5 bitcoins Hiteshi, but with a delay of 1000 blocks. It looks like this:


Input: 2-of-2 funding output, signed by Irene

Output 0 <5 bitcoin>:
    <Irene's Public Key> CHECKSIG

Output 1:
    <1000 blocks>
    CHECKSEQUENCEVERIFY
    DROP
    <Hitesh's Public Key> CHECKSIG

At the same time, Irene also has a commit transaction with 2 outputs, signed by Hiteshi. The first output pays 5 Hiteshi bitcoins instantly, and the second output pays Iren 5 bitcoins with a delay of 1000 blocks.


Input: 2-of-2 funding output, signed by Hitesh

Output 0 <5 bitcoin>:
    <Hitesh's Public Key> CHECKSIG

Output 1:
    <1000 blocks>
    CHECKSEQUENCEVERIFY
    DROP
    <Irene's Public Key> CHECKSIG

So everyone has a commit transaction signed by the other party. At any time, Khiteshi or Iren can sign their commit transaction and send it to the network, but in this case the other side will receive money instantly, and the sender will have to wait for 1000 blocks, which is not very profitable, but this is obviously not enough to make both sides play fair.



And now it is time to introduce the final touch - our cancellation key, which will punish the party that tried to cheat by taking her money.


Each commit transaction has one pending exit. We will make it so that it can be spent either by the sender with a delay of 1000 blocks, or by the second participant of the channel, if he has a cancellation key. Thus, when Khiteshi creates a commit transaction for signing by Irena, he creates a second exit to himself with a delay of 1000 blocks, or Irena, if she presents a cancellation key. Hiteshi will keep this key a secret and will send Irene only when he wants to update the state of the channel with a new commit transaction. Such a transaction will look like this:


Input: 2-of-2 funding output, signed by Irene

Output 0 <5 bitcoin>:
    <Irene's Public Key> CHECKSIG

Output 1 <5 bitcoin>:
IF
    # Revocation penalty output
    <Revocation Public Key>
ELSE
    <1000 blocks>
    CHECKSEQUENCEVERIFY
    DROP
    <Hitesh's Public Key>
ENDIF
CHECKSIG

Let's look at an example of how this works. Let's say Iren wants to send Hitesha 2 bitcoins. To do this, they need to update the state of the channel by creating a new commit transaction. They both create asymmetric commit transactions and before they sign, they exchange the cancellation keys from previous commit transactions, thus 'canceling' them. In this case, Khiteshi is interested in the latest channel balance state, however, for Irene, the previous state is more profitable. She could try to send her previous commit transaction to the network, but Hitesha already has the cancellation key and if he notices that she was sent, he will have 1000 blocks to collect the entire balance of the channel (yes, 'cancellation' does not happens automatically, Khiteshi should notice that Irene sent her commit transaction to the network, and use the key).


Thus, the implementation of channels using asymmetric canceled commit transactions is much more efficient since it does not limit either the channel lifetime or the number of transactions that can be sent to it.


Conclusion


This concludes the first article. I think it will take you some time to digest everything, so if you have questions, ask in the comments. In the next part, we will analyze the operation of HTLC contracts and finally show how the Lightning Network works.