Merge branch 'develop'

pull/899/head
Andreas M. Antonopoulos 3 years ago
commit 635a3f28b7

8
.gitignore vendored

@ -1 +1,9 @@
*.pdf
*.html
!author_bio.html
!colo.html
!copyright.html
!cover.html
!ix.html
!titlepage.html
!toc.html

@ -36,7 +36,7 @@ Hash Function:: A cryptographic hash function is a mathematical algorithm that m
Node:: A computer that participates in a network. A Lightning node is a computer that participates in the Lightning Network. A Bitcoin node is a computer that participates in the Bitcoin Network. Typically a Lightning Network user will run a Lightning node _and_ a Bitcoin node.
On-Chain vs. Off-Chain:: A payment is "on-chain" if it is recorded as a transaction on the Bitcoin (or other underlying) blockchain. Payments sent via payment channels between Lightning nodes, and which are not visible in the underlying blockchain, are called "off-chain" payments. Usually in the Lightning Network, the only on-chain transactions are those used to open and close a Lightning payment channel.
On-Chain vs. Off-Chain:: A payment is "on-chain" if it is recorded as a transaction on the Bitcoin (or other underlying) blockchain. Payments sent via payment channels between Lightning nodes, and which are not visible in the underlying blockchain, are called "off-chain" payments. Usually in the Lightning Network, the only on-chain transactions are those used to open and close a Lightning payment channel. A third type of channel modifying transaction exists, called splicing, which can be used to add/remove the amount of funds committed in a channel.
Payment:: When value is exchanged on the Lightning Network, we call this a "payment" as compared to a "transaction" on the Bitcoin blockchain.

@ -1,5 +1,5 @@
[[getting-started]]
== Getting Started
== Getting started
.A note for Early Release readers
****
@ -12,78 +12,79 @@ If you have comments about how we might improve the content and/or examples in t
In this chapter, we will begin where most people start when encountering the Lightning Network for the first time - choosing software to participate in the Lightning Network economy. We will examine the choices of two users who represent a common use-case for the Lightning Network and learn by example. Alice, a coffee shop customer, will be using a Lightning wallet on her mobile device to buy coffee from Bob's Cafe. Bob, a merchant, will be using a Lightning node and wallet to run a point-of-sale system at his cafe, so he can accept payments over the Lightning Network.
=== Alice's First Lightning Wallet
=== Alice's first Lightning wallet
Alice is a long time Bitcoin user. We first met Alice in Chapter 1 of _"Mastering Bitcoin"_ footnote:["Mastering Bitcoin 2nd Edition, Chapter 1" Andreas M. Antonopoulos (https://github.com/bitcoinbook/bitcoinbook/blob/develop/ch01.asciidoc).], when she bought a cup of coffee from Bob's cafe using a bitcoin transaction. If you are not yet familiar with how Bitcoin transactions work or need a refresher, please read Mastering Bitcoin or the summary in <<bitcoin_fundamentals_review>>.
Alice is a long time Bitcoin user. We first met Alice in Chapter 1 of _"Mastering Bitcoin"_ footnote:["Mastering Bitcoin 2nd Edition, Chapter 1" Andreas M. Antonopoulos (https://github.com/bitcoinbook/bitcoinbook/blob/develop/ch01.asciidoc).], when she bought a cup of coffee from Bob's cafe using a Bitcoin transaction. If you are not yet familiar with how Bitcoin transactions work or need a refresher, please read Mastering Bitcoin or the summary in <<bitcoin_fundamentals_review>>.
Alice recently learned that Bob's Cafe just started accepting Lightning Network payments! Alice is eager to learn about and experiment with the Lightning Network, she wants to be one of Bob's first Lightning Network customers. In order to do this, first, Alice has to select a Lightning wallet that meets her needs.
Alice recently learned that Bob's Cafe just started accepting Lightning Network payments! Alice is eager to learn about and experiment with the Lightning Network; she wants to be one of Bob's first Lightning Network customers. In order to do this, first, Alice has to select a Lightning wallet that meets her needs.
Alice does not want to entrust custody of her bitcoin to third parties. She has learned enough about cryptocurrency to know how to use a wallet. She also wants a mobile wallet so that she can use it for small payments on-the-go, so she chooses the _Eclair_ wallet, a popular non-custodial mobile Lightning wallet. Let's learn more about how and why she's made these choices.
=== Lightning Nodes
=== Lightning nodes
The Lightning Network is accessed via software applications that can speak the Lightning Network protocol. A _Lightning Network Node_ (or simply "node") is a software application that has three important characteristics. First, Lightning nodes are "wallets", so they send and receive payments over the Lightning Network as well as on the Bitcoin network. Second, nodes must communicate on a peer-to-peer basis with other Lightning nodes creating the network. Finally, Lightning nodes also need access to the Bitcoin blockchain (or other blockchains for other cryptocurrencies) to secure the funds used for payments.
The Lightning Network is accessed via software applications that can speak the Lightning Network protocol. A _Lightning Network node_ (or simply "node") is a software application that has three important characteristics. First, Lightning nodes are "wallets", so they send and receive payments over the Lightning Network as well as on the Bitcoin network. Second, nodes must communicate on a peer-to-peer basis with other Lightning nodes creating the network. Finally, Lightning nodes also need access to the Bitcoin blockchain (or other blockchains for other cryptocurrencies) to secure the funds used for payments.
Users have the highest degree of control by running their own Bitcoin node and Lightning node. However, Lightning nodes can also use a lightweight Bitcoin client (commonly referred to as Simplified Payment Verification (SPV)) to interact with the Bitcoin blockchain.
Users have the highest degree of control by running their own Bitcoin node and Lightning node. However, Lightning nodes can also use a lightweight Bitcoin client, commonly referred to as Simplified Payment Verification (SPV), to interact with the Bitcoin blockchain.
[[ln_explorer]]
=== Lightning Explorer
=== Lightning explorers
A Lightning network explorer is a useful tool to show the statistics of nodes, channels and network capacity.
Lightning network explorers are useful tools to show the statistics of nodes, channels and network capacity.
The below is an inexhaustive list (in alphanumerical order):
Below is an inexhaustive list (in alphanumerical order):
* 1ML Lightning explorer, https://1ml.com/
* ACINQ's Lightning explorer, with fancy visualization, https://explorer.acinq.co/
* AmbossSpace Lightning explorer, with community metrics and intuitive visualizations, https://amboss.space/
* Fiatjaf's Lightning explorer with many diagrams, https://ln.bigsun.xyz/
* hashXP Lightning explorer, https://hashxp.org/lightning/node/
[TIP]
====
Note that when using Lightning explorers, just like with existing block explorers, privacy can be a concern.
Note that when using Lightning explorers, just like with other block explorers, privacy can be a concern.
If users are careless, the website may track their IP addresses and collect their behavior records (for example, the nodes users are interested in).
Also, it should be noted that as there is no global consensus of the current Lightning graph or the current state of any existing channel policy, users should never rely on Lightning explorers to retrieve the most updated information.
Also, it should be noted that as there is no global consensus of the current Lightning graph or the current state of any existing channel policy; users should never rely on Lightning explorers to retrieve the most current information.
Furthermore as users open, close, and update channels, the graph will change and individual Lightning explorers may not be up to date.
Use Lightning explorers to visualize the network or gather information, but not as an authoritative source of what is happening on the Lightning Network.
To have an authoritative view of the Lightning Network, run your own Lightning node that will build a channel graph and collect various statistics, which you can view with a web-based interface.
====
=== Lightning Wallets
=== Lightning wallets
The term "Lightning Wallet" is somewhat ambiguous, as it can describe a broad variety of components combined with some user interface. The most common components of lightning wallet software include:
The term "Lightning wallet" is somewhat ambiguous, as it can describe a broad variety of components combined with some user interface. The most common components of Lightning wallet software include:
* A keystore that holds secrets, such as private keys.
* A Lightning Network node (Lightning node) that communicates on the Peer-to-Peer network, as described previously.
* A Bitcoin node that stores blockchain data and communicates with other Bitcoin nodes.
* A database "map" of nodes and channels that are announced on the Lightning network.
* A database "map" of nodes and channels that are announced on the Lightning Network.
* A channel manager that can open and close Lightning Network channels.
* A path-finding system that can find a path of connected channels from payment source to payment destination.
A Lightning wallet may contain all of these functions, acting as a "full" wallet, with no reliance on any third-party services. Or, one or more of these components may rely (partially or entirely) on third-party services that mediate those functions.
A _key_ distinction (pun intended) is whether the keystore function is internal or outsourced. In blockchains, control of keys determines custody of funds, as memorialized by the phrase "your keys, your coins; not your keys, not your coins". Any wallet that outsources management of keys is called a "custodial" wallet because a third party acting as custodian has control of the user's funds, not the user himself. A "non-custodial" or "self-custody" wallet, by comparison, is one where the keystore is part of the wallet, and keys are controlled directly by the user. The term "non-custodial" wallet just implies that the keystore is local and under the user's control. However, one or more of the other wallet components might or might not be outsourced and rely on some trusted third parties even if some of the components (other than the keystore) rely on some trusted third parties.
A _key_ distinction (pun intended) is whether the keystore function is internal or outsourced. In blockchains, control of keys determines custody of funds, as memorialized by the phrase "your keys, your coins; not your keys, not your coins". Any wallet that outsources management of keys is called a "custodial" wallet because a third party acting as custodian has control of the user's funds, not the user. A "non-custodial" or "self-custody" wallet, by comparison, is one where the keystore is part of the wallet, and keys are controlled directly by the user. The term "non-custodial" wallet just implies that the keystore is local and under the user's control. However, one or more of the other wallet components may or may not be outsourced and rely on trusted third parties.
Blockchains, especially open blockchains like Bitcoin, attempt to minimize or eliminate trust in third parties and empower users. This is often called a "trustless" model, though "trust-minimized" is a better term. In such systems, the user trusts the software rules, not third parties. Therefore, the issue of control over keys is a principal consideration when choosing a Lightning wallet.
Every other component of a Lightning wallet brings similar considerations of trust. If all the components are under the control of the user, then the amount of trust in third parties is minimized, bringing maximum power to the user. Of course, this brings a direct trade-off, as with that power comes the corresponding responsibility to manage complex software.
Every user must consider their own technical skills before deciding what type of Lightning wallet to use. Those with strong technical skills should use a Lightning wallet that puts all of the components under the direct control of the user. Those with fewer technical skills but a desire to control their funds should choose a _non-custodial_ Lightning wallet.
Often the trust in those cases relates to privacy.
If users decide to outsource some functionality to a third party they usually give up some privacy as the third party will learn some information about them.
Every user must consider their own technical skills before deciding what type of Lightning wallet to use. Those with strong technical skills should use a Lightning wallet that puts all of the components under the direct control of the user. Those with fewer technical skills, but with a desire to control their funds, should choose a _non-custodial_ Lightning wallet.
Often the trust in these cases relates to privacy.
If users decide to outsource some functionality to a third party, they usually give up some privacy as the third party will learn some information about them.
Finally, those seeking simplicity and convenience, even at the expense of control and security, may choose a custodial Lightning wallet. This is the least technically challenging option, but it _undermines the trust model of cryptocurrency_ and should therefore be considered only as a stepping stone towards more control and self-reliance.
There are many ways wallets can be characterized or categorized.
The most important questions to ask about a specific wallet are:
. Does this Lightning wallet have a full Lightning Node or does it use a third-party Lightning Node?
. Does this Lightning wallet have a full Bitcoin Node or does it use a third-party Bitcoin Node?
. Does this Lightning wallet have a full Lightning node or does it use a third-party Lightning node?
. Does this Lightning wallet have a full Bitcoin node or does it use a third-party Bitcoin node?
. Does this Lightning wallet store its own keys under user control (self-custody) or are the keys held by a third-party custodian?
[TIP]
====
If a Lightning wallet uses a third-party Lightning node, it is this third-party Lightning node that decides how to communicate with Bitcoin. Hence, using a third-party Lightning node implies that you are also using a third-party Bitcoin node. Only when the Lightning wallet uses its own Lightning node, does the choice "full Bitcoin-node" vs. "third-party Bitcoin node" exist.
If a Lightning wallet uses a third-party Lightning node, it is this third-party Lightning node that decides how to communicate with Bitcoin. Hence, using a third-party Lightning node implies that you are also using a third-party Bitcoin node. Only when the Lightning wallet uses its own Lightning node, does the choice "full Bitcoin node" vs. "third-party Bitcoin node" exist.
====
At the highest level of abstraction, questions 1 and 3 are the most elementary ones.
@ -100,26 +101,26 @@ But remember that this is just one way of categorizing Lightning wallets.
| *Custodial* | Q3: Above medium technical skills, above medium trust in 3rd parties, requires some permissions | Q4: Low technical skills, high trust in 3rd parties, least permissionless
|===
Q3, quadrant 3, where a full Lightning node is used but the keys are held by a custodian is currently not common.
Future wallets from that quadrant would let a user worry about the operational aspects of their node, but then delegate the access to the keys to a third party which may use primarily cold storage.
Quadrant 3 (Q3), where a full Lightning node is used, but the keys are held by a custodian, is currently not common.
Future wallets from that quadrant may let a user worry about the operational aspects of their node, but then delegate access to the keys to a third party which primarily uses cold storage.
Lightning wallets can be installed on a variety of devices, including laptops, servers, and mobile devices. To run a full Lightning node you will need to use a server or desktop computer, as mobile devices and laptops are usually not powerful enough in terms of capacity, processing, battery life, and connectivity.
The category "Third-party Lightning Nodes" can again be subdivided into:
- Lightweight: means that the wallet does not operate a Lightning node and so needs to obtain information about the Lightning Network over the Internet from someone else's Lightning node.
- None: means that not only is the Lightning Node operated by a third party but most of the wallet is operated by a third party in the cloud. This is a "custodial" wallet where someone else controls the custody of funds.
- Lightweight: This means that the wallet does not operate a Lightning node and so needs to obtain information about the Lightning Network over the Internet from someone else's Lightning node.
- None: This means that not only is the Lightning node operated by a third party, but most of the wallet is operated by a third party in the cloud. This is a "custodial" wallet where someone else controls custody of the funds.
These subcategories are used in Table <<lnwallet-examples>>.
Other terms that need explanation in Table <<lnwallet-examples>> in column "Bitcoin Node" are:
Other terms that need explanation in Table <<lnwallet-examples>> in the column "Bitcoin Node" are:
- Neutrino: This wallet does not operate a Bitcoin Node. Instead, a Bitcoin Node operated by someone else (third-party) is accessed via the "Neutrino" protocol.
- Electrum: This wallet does not operate a Bitcoin Node. Instead, a Bitcoin Node operated by someone else (third-party) is accessed via the "Electrum" protocol.
- Bitcoin Core: implementation of a Bitcoin Node
- btcd: another implementation of Bitcoin Node
- Neutrino: This wallet does not operate a Bitcoin node. Instead, a Bitcoin node operated by someone else (a third-party) is accessed via the "Neutrino" protocol.
- Electrum: This wallet does not operate a Bitcoin node. Instead, a Bitcoin node operated by someone else (a third-party) is accessed via the "Electrum" protocol.
- Bitcoin Core: This is an implementation of a Bitcoin node.
- btcd: This is another implementation of a Bitcoin node.
In <<lnwallet-examples>> we see some examples of currently popular Lightning node and wallet applications for different types of devices. the list is sorted first by device type and then alphabetically.
In <<lnwallet-examples>>, we see some examples of currently popular Lightning node and wallet applications for different types of device. The list is sorted first by device type and then alphabetically.
[[lnwallet-examples]]
.Examples of Popular Lightning Wallets
@ -143,7 +144,7 @@ In <<lnwallet-examples>> we see some examples of currently popular Lightning nod
[[testnet-bitcoin]]
==== Testnet Bitcoin
The Bitcoin system offers an alternative chain for testing purposes called a _testnet_, in contrast with the "normal" Bitcoin chain which is referred to as "mainnet". On testnet, the currency is _testnet bitcoin (TBTC)_, which is a worthless copy of bitcoin used exclusively for testing. Every function of Bitcoin is replicated exactly, but the money is worth nothing, so you literally have nothing to lose!
The Bitcoin system offers an alternative chain for testing purposes called _testnet_, in contrast with the "normal" Bitcoin chain which is referred to as _mainnet_. On testnet, the currency is _testnet bitcoin (TBTC)_, which is a worthless copy of bitcoin used exclusively for testing. Every function of Bitcoin is replicated exactly, but the money is worth nothing, so you literally have nothing to lose!
Some Lightning wallets can also operate on testnet, allowing you to make Lightning payments with testnet bitcoin, without risking real funds. This is a great way to experiment with Lightning safely. Eclair mobile, which Alice uses in this chapter, is one example of a Lightning wallet that supports testnet operation.
@ -157,21 +158,21 @@ https://bitcoinfaucet.uo1.net/
https://testnet.help/en/btcfaucet/testnet
All of the examples in this book can be replicated exactly on testnet with TBTC, so you can try and follow along if you want without risking real money.
All of the examples in this book can be replicated exactly on testnet with TBTC, so you can follow along if you want without risking real money.
=== Balancing complexity and control
Lightning wallets have to strike a careful balance between complexity and user control. Those that give the user the most control over their funds, the highest degree of privacy, and the greatest independence from third party services are necessarily more complex and difficult to operate. As the technology advances, some of these trade-offs will become less stark, and users may be able to get more control without more complexity. However, for now, different companies and projects are exploring different positions along this control-complexity spectrum and hoping to find the "sweet spot" for the users they are targeting.
When selecting a wallet, keep in mind that even if you don't see these trade-offs, they still exist. For example, many wallets will attempt to remove the burden of channel management from its users. To do so, they introduce central "hub" nodes that all their wallets connect to automatically. While this trade-off simplifies the user interface and user experience, it introduces a Single Point of Failure (SPoF) as these "hub nodes" become indispensable for the wallet operation. Furthermore, relying on a "hub" like this can reduce user privacy since the hub knows the sender and potentially (if constructing the payment route on behalf of the user) also the recipient of each payment made by the user's wallet.
When selecting a wallet, keep in mind that even if you don't see these trade-offs, they still exist. For example, many wallets will attempt to remove the burden of channel management from its users. To do so, they introduce central "hub" nodes that all their wallets connect to automatically. While this trade-off simplifies the user interface and user experience, it introduces a Single Point of Failure (SPoF) as these "hub nodes" become indispensable for the wallet's operation. Furthermore, relying on a "hub" like this can reduce user privacy since the hub knows the sender and potentially (if constructing the payment route on behalf of the user) also the recipient of each payment made by the user's wallet.
In the next section, we will return to our first user and walk through her first Lightning wallet setup. She has chosen a wallet that is more sophisticated than the easier custodial wallets. This allows us to show some of the underlying complexity and introduce some of the inner workings of an advanced wallet during our example. You may find that your first ideal wallet is further towards "ease of use", by accepting some of the control and privacy trade-offs. Or perhaps you are more of a "power user" and want to run your own Lightning and Bitcoin nodes as part of your wallet solution.
In the next section, we will return to our first user and walk through her first Lightning wallet setup. She has chosen a wallet that is more sophisticated than the easier custodial wallets. This allows us to show some of the underlying complexity and introduce some of the inner workings of an advanced wallet. You may find that your first ideal wallet is further towards "ease of use", accepting some of the control and privacy trade-offs. Or perhaps you are more of a "power user" and want to run your own Lightning and Bitcoin nodes as part of your wallet solution.
=== Downloading and Installing a Lightning Wallet
=== Downloading and installing a Lightning wallet
When looking for a new cryptocurrency wallet, you must be very careful to select a secure source for the software.
Unfortunately, many fake wallet applications will steal your money, and some of these even find their way onto reputable and supposedly vetted software sites like the Apple and Google application stores. Whether you are installing your first or your tenth wallet, always exercise extreme caution. A rogue app cannot only steal any money you entrust it with, but it might also be able to steal keys and passwords from other applications by compromising your mobile device operating system.
Unfortunately, many fake wallet applications will steal your money, and some of these even find their way onto reputable and supposedly vetted software sites like the Apple and Google application stores. Whether you are installing your first or your tenth wallet, always exercise extreme caution. A rogue app may not just steal any money you entrust it with, but it might also be able to steal keys and passwords from other applications by compromising your mobile device operating system.
Alice uses an Android device and will use the Google Play Store to download and install the Eclair wallet. Searching on Google Play, she finds an entry for "Eclair Mobile", as shown in <<eclair-playstore>>.
@ -182,21 +183,21 @@ image::images/eclair-playstore.png["Eclair wallet in the Google Play Store"]
[TIP]
====
It is possible to experiment and test all Bitcoin-type software with zero risk (except for your own time) by using Testnet bitcoins. You can also download Eclair Testnet wallet to try lightning (on Testnet) by going to the Google Play Store.
It is possible to experiment and test all Bitcoin-type software with zero risk (except for your own time) by using testnet bitcoins. You can also download Eclair testnet wallet to try Lightning (on testnet) by going to the Google Play Store.
====
Alice notices a few different elements on this page, that help her ascertain that this is, most likely, the correct "Eclair Mobile" wallet she is looking for. Firstly, the organization "ACINQ" footnote:[ACINQ: Developers of the Eclair Mobile Lightning wallet (https://acinq.co/).] is listed as the developer of this mobile wallet, which Alice knows from her research is the correct developer. Secondly, the wallet has been installed "10,000+" times and has more than 320 positive reviews. It is unlikely this is a rogue app that has snuck into the Play Store. As a third step, she goes to the ACINQ website (https://acinq.co/). She verifies that the webpage is secure by checking that the address begins with HTTPS, or prefixed by a padlock in some browsers. On the website she goes to the Download section or looks for the link to the Google App store. She finds the link and clicks it. She compares that this link brings her to the very same app in the Google App Store. Satisfied by these findings, Alice installs the Eclair app on her mobile device.
Alice notices a few different elements on this page, that help her ascertain that this is, most likely, the correct "Eclair Mobile" wallet she is looking for. Firstly, the organization "ACINQ" footnote:[ACINQ: Developers of the Eclair Mobile Lightning wallet (https://acinq.co/).] is listed as the developer of this mobile wallet, which Alice knows from her research is the correct developer. Secondly, the wallet has been installed "10,000+" times and has more than 320 positive reviews. It is unlikely this is a rogue app that has snuck into the Google Play Store. As a third step, she goes to the ACINQ website (https://acinq.co/). She verifies that the webpage is secure by checking that the address begins with https, or prefixed by a padlock in some browsers. On the website she goes to the Download section or looks for the link to the Google App store. She finds the link and clicks it. She compares that this link brings her to the very same app in the Google App Store. Satisfied by these findings, Alice installs the Eclair app on her mobile device.
[WARNING]
====
Always exercise great care when installing software on any device. There are many fake cryptocurrency wallets that will not only steal your money but might also compromise all other applications on your device.
====
=== Creating a New Wallet
=== Creating a new wallet
When Alice opens the Eclair Mobile app for the first time, she is presented with a choice to "Create a New Wallet" or to "Import an Existing Wallet". Alice will create a new wallet, but let's first discuss why these options are presented here and what it means to "import an existing wallet".
==== Responsibility with Key Custody
==== Responsibility with key custody
As we mentioned at the beginning of this section, Eclair is a _non-custodial_ wallet, meaning that Alice has sole custody of the keys used to control her bitcoin. This also means that Alice is responsible for protecting and backing up those keys. If Alice loses the keys, no one can help her recover the bitcoin, and they will be lost forever.
@ -205,13 +206,13 @@ As we mentioned at the beginning of this section, Eclair is a _non-custodial_ wa
With the Eclair Mobile wallet, Alice has custody and control of the keys and, therefore, full responsibility to keep the keys safe and backed up. If she loses the keys, she loses the bitcoin, and no one can help her recover from that loss!
====
==== Mnemonic Words
==== Mnemonic words
Similar to most Bitcoin wallets, Eclair Mobile provides a _mnemonic phrase_ (also sometimes called a "seed" or "seed phrase") for Alice to back up. The mnemonic phrase consists of 24 English words, selected randomly by the software, and used as the basis for the keys that are generated by the wallet. The mnemonic phrase can be used by Alice to restore all the transactions and funds in the Eclair Mobile wallet in the case of an event such as a lost mobile device, a software bug, or memory corruption.
[TIP]
====
The correct term for these backup words is "mnemonic phrase". We avoid the use of the term "seed" to refer to a mnemonic phrase, because even though its use is common it is incorrect.
The correct term for these backup words is "mnemonic phrase". We avoid the use of the term "seed" to refer to a mnemonic phrase because even though its use is common, it is incorrect.
====
When Alice chooses to "Create a New Wallet", she will be shown a screen with her mnemonic phrase, which looks like the screenshot in <<eclair-mnemonic>>.
@ -223,24 +224,24 @@ image::images/eclair-mnemonic.png["New Wallet Mnemonic Phrase"]
In <<eclair-mnemonic>>, we have purposely obscured part of the mnemonic phrase to prevent readers of this book from reusing the mnemonic.
[[mnemonic-storage]]
==== Storing the Mnemonic Safely
==== Storing the mnemonic safely
Alice needs to be careful to store the mnemonic phrase in a way that balances the need to prevent theft and accidental loss. The recommended way to properly balance these risks is to write two copies of the mnemonic phrase on paper, with each of the words numbered as the order matters.
Alice needs to be careful to store the mnemonic phrase in a way that prevents theft but also avoids accidental loss. The recommended way to properly balance these risks is to write two copies of the mnemonic phrase on paper, with each of the words numbered - the order matters.
Once Alice has recorded the mnemonic phrase, after touching "OK GOT IT" on her screen, she will be presented with a _quiz_ to make sure that she correctly recorded the mnemonic. The quiz will ask for three or four of the words at random. Alice wasn't expecting a quiz, but since she recorded the mnemonic correctly, she passes without any difficulty.
Once Alice has recorded the mnemonic phrase, after touching "OK GOT IT" on her screen, she will be presented with a quiz to make sure that she correctly recorded the mnemonic. The quiz will ask for three or four of the words at random. Alice wasn't expecting a quiz, but since she recorded the mnemonic correctly, she passes without any difficulty.
Once Alice has recorded the mnemonic phrase and passed the quiz, she should store each copy in a separate secure location such as a locked desk drawer or a fireproof safe.
[WARNING]
====
Never attempt a "DIY" security scheme that deviates in any way from the best practice recommendation in <<mnemonic-storage>>. Do not cut your mnemonic in half, make screenshots, store on USB drives or cloud drives, encrypt it, or try any other non-standard method. You will tip the balance in such a way as to risk permanent loss or theft. Many people have lost funds, not from theft but because they tried a non-standard solution without having the expertise to balance the risks involved. The best practice recommendation is carefully balanced by experts and suitable for the vast majority of users.
Never attempt a "DIY" security scheme that deviates in any way from the best practice recommendation in <<mnemonic-storage>>. Do not cut your mnemonic in half, make screenshots, store on USB drives or cloud drives, encrypt it, or try any other non-standard method. You will tip the balance in such a way as to risk permanent loss. Many people have lost funds, not from theft, but because they tried a non-standard solution without having the expertise to balance the risks involved. The best practice recommendation is carefully considered by experts and suitable for the vast majority of users.
====
After Alice initializes her Eclair Mobile wallet, she will see a brief tutorial that highlights the various elements of the user interface. We won't replicate the tutorial here, but we will explore all of those elements as we follow Alice's attempt to buy a cup of coffee!
=== Loading Bitcoin Into the Wallet
=== Loading bitcoin onto the wallet
Alice now has a Lightning wallet. But, it's empty! She now faces one of the more challenging aspects of this experiment: she has to find a way to acquire some bitcoin and load it onto her Eclair wallet.
Alice now has a Lightning wallet. But, it's empty! She now faces one of the more challenging aspects of this experiment; she has to find a way to acquire some bitcoin and load it onto her Eclair wallet.
[TIP]
====
@ -248,39 +249,39 @@ If Alice already has bitcoin in another wallet, she could choose to send that bi
====
[[acquiring-bitcoin]]
==== Acquiring Bitcoin
==== Acquiring bitcoin
There are several ways Alice can acquire bitcoin:
* She can exchange some of her national currency (e.g. USD) at a cryptocurrency exchange
* She can buy some from a friend, or an acquaintance from a Bitcoin Meetup, in exchange for cash
* She can find a _Bitcoin ATM_ in her area, which acts as a vending machine, selling bitcoin for cash
* She can offer her skills or a product she sells and accept payment in bitcoin
* She can ask her employer or clients to pay her in bitcoin
* She can exchange some of her national currency (e.g. USD) on a cryptocurrency exchange.
* She can buy some from a friend, or an acquaintance from a Bitcoin Meetup, in exchange for cash.
* She can find a _Bitcoin ATM_ in her area, which acts as a vending machine, selling bitcoin for cash.
* She can offer her skills or a product she sells and accept payment in bitcoin.
* She can ask her employer or clients to pay her in bitcoin.
All of these methods have varying degrees of difficulty, and many will involve paying a fee. Some will also require Alice to provide identification documents to comply with local banking regulations. However, with all these methods, Alice will be able to receive bitcoin.
==== Receiving Bitcoin
==== Receiving bitcoin
Let's assume Alice has found a local Bitcoin ATM and has decided to buy some bitcoin in exchange for cash. An example of a Bitcoin ATM, one built by the Lamassu company, is shown in <<bitcoin-atm>>. Such Bitcoin ATMs accept national currency (cash) through a cash slot and send bitcoin to a Bitcoin Address scanned from a user's wallet using a built-in camera.
Let's assume Alice has found a local Bitcoin ATM and has decided to buy some bitcoin in exchange for cash. An example of a Bitcoin ATM, one built by the Lamassu company, is shown in <<bitcoin-atm>>. Such Bitcoin ATMs accept national currency (cash) through a cash slot and send bitcoin to a Bitcoin address scanned from a user's wallet using a built-in camera.
[[bitcoin-atm]]
.A Lamassu Bitcoin ATM
image::images/bitcoin-atm.png["Lamassu Bitcoin ATM"]
To receive the bitcoin in her Eclair Lightning wallet, Alice will need to present a _Bitcoin Address_ from the Eclair Lightning wallet to the ATM. The ATM can then send Alice's newly acquired bitcoin to this bitcoin address.
To receive the bitcoin in her Eclair Lightning wallet, Alice will need to present a Bitcoin address from the Eclair Lightning wallet to the ATM. The ATM can then send Alice's newly acquired bitcoin to this Bitcoin address.
To see a Bitcoin Address on the Eclair wallet, Alice must swipe to the left column titled "YOUR BITCOIN ADDRESS" (see <<eclair-receive>>), where she will see a square barcode (called a _QR code_) and a string of letters and numbers below.
To see a Bitcoin address on the Eclair wallet, Alice must swipe to the left column titled "YOUR BITCOIN ADDRESS" (see <<eclair-receive>>), where she will see a square barcode (called a _QR code_) and a string of letters and numbers below.
[[eclair-receive]]
.Alice's bitcoin address, shown in Eclair
image::images/eclair-receive.png["Eclair bitcoin address QR code"]
The QR code contains the same string of letters and numbers as shown below it, in an easy to scan format. This way, Alice doesn't have to type the Bitcoin Address. In the screenshot <<eclair-receive>>, we have purposely blurred both, to prevent readers from inadvertently sending bitcoin to this address.
The QR code contains the same string of letters and numbers as shown below it, in an easy to scan format. This way, Alice doesn't have to type the Bitcoin address. In the screenshot <<eclair-receive>>, we have purposely blurred both, to prevent readers from inadvertently sending bitcoin to this address.
[NOTE]
====
Both Bitcoin addresses and QR codes contain error detection information that prevents any typing or scanning errors from producing a "wrong" Bitcoin address. If there is a mistake in the address, any Bitcoin wallet will notice the error and refuse to accept the Bitcoin Address as valid.
Both Bitcoin addresses and QR codes contain error detection information that prevents any typing or scanning errors from producing a "wrong" Bitcoin address. If there is a mistake in the address, any Bitcoin wallet will notice the error and refuse to accept the Bitcoin address as valid.
====
Alice can take her mobile device to the ATM and show it to the built-in camera, as shown in <<bitcoin-atm-receive>>. After inserting some cash into the slot, she will receive bitcoin in Eclair!
@ -301,18 +302,18 @@ The number of "confirmations" on a transaction is the number of blocks mined sin
.Alice receives bitcoin
image::images/eclair-tx1-btc.png["Bitcoin transaction received"]
While in this example Alice used an ATM to acquire her first bitcoin, the same basic concepts would apply even if she used one of the other methods in <<acquiring-bitcoin>>. For example, if Alice wanted to sell a product or provide a professional service in exchange for bitcoin, her customers could scan the Bitcoin Address with their wallets and pay her in bitcoin.
While in this example Alice used an ATM to acquire her first bitcoin, the same basic concepts would apply even if she used one of the other methods in <<acquiring-bitcoin>>. For example, if Alice wanted to sell a product or provide a professional service in exchange for bitcoin, her customers could scan the Bitcoin address with their wallets and pay her in bitcoin.
Similarly, if she billed a client for a service offered over the Internet, Alice could send an email or instant message with the Bitcoin Address or the QR code to her client, and they could paste or scan the information into a Bitcoin wallet to pay her.
Similarly, if she billed a client for a service offered over the Internet, Alice could send an email or instant message with the Bitcoin address or the QR code to her client, and they could paste or scan the information into a Bitcoin wallet to pay her.
Alice could even print the QR code and affix it to a sign and display it publicly to receive tips. For example, she could have a QR code affixed to her guitar and receive tips while performing on the street!
footnote:[It is generally not advisable to reuse the same Bitcoin address for multiple payments as all Bitcoin transactions are public.
A nosy person passing by could scan Alice's QR code and see how many tips Alice has already received to this address on the Bitcoin blockchain.
Fortunately, the Lightning Network offers more private solutions to this, discussed later in the book!]
Finally, if Alice bought bitcoin from a cryptocurrency exchange, she could (and should) "withdraw" the bitcoin by pasting her Bitcoin Address into the exchange website. The exchange will then send the bitcoin to her address directly.
Finally, if Alice bought bitcoin from a cryptocurrency exchange, she could (and should) "withdraw" the bitcoin by pasting her Bitcoin address into the exchange website. The exchange will then send the bitcoin to her address directly.
=== From Bitcoin to Lightning Network
=== From Bitcoin to Lightning network
Alice's bitcoin is now controlled by her Eclair wallet and has been recorded on the Bitcoin blockchain. At this point, Alice's bitcoin is "on-chain," meaning that the transaction has been broadcast to the entire Bitcoin network, verified by all Bitcoin nodes, and "mined" (recorded) onto the Bitcoin blockchain.
@ -320,7 +321,7 @@ So far, the Eclair Mobile wallet has behaved only as a Bitcoin wallet, and Alice
Now, Alice is ready to start using the Lightning Network by taking her bitcoin "off-chain" in order to take advantage of the fast, cheap, and private payments that the Lightning Network offers.
==== Lightning Network Channels
==== Lightning Network channels
Swiping right, Alice accesses the "LIGHTNING CHANNELS" section of Eclair. Here she can manage the channels that will connect her wallet to the Lightning Network.
@ -332,10 +333,10 @@ Furthermore, Alice's channel peer can _forward_ payments via other channels furt
[TIP]
====
Not all channel peers are _good_ peers for routing payments. Well-connected peers will be able to route payments over shorter paths to the destination, increasing the chance of success. Channel peers with ample funds in their other channels will be able to route larger payments.
Not all channel peers are _good_ peers for routing payments. Well-connected peers will be able to route payments over shorter paths to the destination, increasing the chance of success. Channel peers with ample funds will be able to route larger payments.
====
In other words: Alice needs one or more channels that connects her to one or more other nodes on the Lightning Network. She doesn't need a channel to connect her wallet directly to Bob's Cafe in order to send Bob a payment, though she can choose to open a direct channel too. Any node in the Lightning Network can be used for Alice's first channel. The more well-connected a node is the more people Alice can reach. In this example, since we want to also demonstrate payment routing, we won't have Alice open a channel directly to Bob's wallet. Instead, we will have Alice open a channel to a well-connected node and then later use that node to forward her payment, routing it through any other nodes as necessary to reach Bob.
In other words, Alice needs one or more channels that connects her to one or more other nodes on the Lightning Network. She doesn't need a channel to connect her wallet directly to Bob's Cafe in order to send Bob a payment, though she can choose to open a direct channel, too. Any node in the Lightning Network can be used for Alice's first channel. The more well-connected a node is the more people Alice can reach. In this example, since we want to also demonstrate payment routing, we won't have Alice open a channel directly to Bob's wallet. Instead, we will have Alice open a channel to a well-connected node and then later use that node to forward her payment, routing it through any other nodes as necessary to reach Bob.
At first, there are no open channels, so as we see in <<eclair-channels>>, the "LIGHTNING CHANNELS" tab displays an empty list. If you notice, on the bottom right corner, there is a plus symbol (+), which is a button to open a new channel.
@ -368,7 +369,7 @@ Choosing the ACINQ node will slightly reduce Alice's privacy, as it will give AC
Alice selects "ACINQ Node" and is ready to open her first channel on the Lightning network.
==== Opening a Lightning Channel
==== Opening a Lightning channel
When Alice selects a node to open a new channel, she is asked to select how much bitcoin she wants to allocate to this channel. In subsequent chapters, we will discuss the implications of these choices, but for now, Alice will allocate almost all her funds to the channel. Since she will have to pay transaction fees to open the channel, she will select an amount slightly less than her total balance footnote:[The Eclair wallet doesn't offer an option to automatically calculate the necessary fees and allocate the maximum amount of funds to a channel, so Alice has to calculate this herself.]
@ -397,7 +398,7 @@ image::images/eclair-channel-open.png["Channel is Open"]
Did you notice that the channel amount seems to have changed? It hasn't: the channel contains 0.018 BTC, but in the time between screenshots the BTC exchange rate changed, so the USD value is different. You can choose to show balances in BTC or USD, but keep in mind that USD values are calculated in real-time and will change!
====
=== Buying a Cup of Coffee using LN
=== Buying a cup of coffee using LN
Alice now has everything ready to start using the Lightning Network. As you can see, it took a bit of work and a bit of time waiting for confirmations. However, now subsequent actions are fast and easy. The Lightning Network enables payments without having to wait for confirmations, as funds get settled in seconds.
@ -419,7 +420,7 @@ On the counter at Bob's Cafe, there is a tablet device showing <<bob-cafe-posapp
.Bob's Point-of-Sale Application
image::images/bob-cafe-posapp.png["Bob's Point-of-Sale Application"]
==== A Lightning Invoice
==== A Lightning invoice
Alice selects the "Cafe Latte" option from the screen and is presented with a _Lightning Invoice_ (also known as a "payment request") as shown in <<bob-cafe-invoice>>

@ -1,4 +1,3 @@
[role="pagenumrestart"]
[[ch03_How_Lightning_Works]]
== How the Lightning Network works
@ -109,7 +108,7 @@ A channel is only limited by three things:
Payment channels have a few very interesting and useful properties:
* Because the time to update a channel is primarily bound by the communication speed of the internet, making a payment on a payment channel is almost instant.
* Because the time to update a channel is primarily bound by the communication speed of the internet, making a payment on a payment channel can be almost instant.
* If the channel is open, making a payment does not require the confirmation of Bitcoin blocks. In fact - as long as you and your channel partner follow the protocol - it does not require any interaction with the Bitcoin network or anyone else other than your channel partner.
@ -117,7 +116,8 @@ Payment channels have a few very interesting and useful properties:
* Payments made in a payment channel are only known to you and your partner. In that sense, you gain privacy compared to Bitcoin, where every transaction is public. Only the final balance, which is the aggregate of all payments in that channel, will become visible on the Bitcoin blockchain.
Bitcoin was about five years old when talented developers first figured out how payment channels could be constructed and by now there are at least three different methods known.
Bitcoin was about five years old when talented developers first figured out how bi-directional, indefinite lifetime, routable payment channels could be constructed and by now there are at least three different methods known.
This chapter will focus on the channel construction method first described in the https://lightning.network/lightning-network-paper.pdf[Lightning Network whitepaper] by Joseph Poon and Thaddeus Dryja in 2015. These are known as _Poon-Dryja_ channels, and are the channel construction method currently used in the Lightning Network.
The other two proposed methods are _Duplex Micropayment_ channels, introduced by Christian Decker around the same time as the "Poon-Dryja" channels and _eltoo_ channels, introduced in https://blockstream.com/eltoo.pdf[eltoo: A Simple Layer2 Protocol for Bitcoin] by Christian Decker, Rusty Russel and (author of this book) Olaoluwa Osuntokun in 2018.
@ -133,9 +133,9 @@ Multisignature scripts and addresses are explained in more detail in <<multisig>
==== Funding transaction
The fundamental building block of a payment channel, is a 2-of-2 multisignature address. The two channel partners fund the payment channel by sending bitcoin to the multisignature address. This transaction is called the _funding transaction_, and is recorded on the Bitcoin blockchain. footnote:[While the original Lightning whitepaper described channels funded by both channel partners, the current specification, as of 2020, assumes that just one partner commits funds to the channel.]
The fundamental building block of a payment channel, is a 2-of-2 multisignature address. One of the two channel partners will fund the payment channel by sending bitcoin to the multisignature address. This transaction is called the _funding transaction_, and is recorded on the Bitcoin blockchain. footnote:[While the original Lightning whitepaper described channels funded by both channel partners, the current specification, as of 2020, assumes that just one partner commits funds to the channel. As of May 2021 dual-funded lightning channels are experimental in the c-lightning LN implementation.]
Even though the funding transaction is public, it is not obvious that it is a Lightning payment channel until it is closed. Furthermore, channel payments are still not visible to anyone other than the channel partners, nor is the distribution of the channel balance between them.
Even though the funding transaction is public, it is not obvious that it is a Lightning payment channel until it is closed unless the channel is publicly advertised. Channels are typically publicly announced by routing nodes that wish to forward payments. However, non-advertised channels also exist, and are usually created by mobile nodes that don't actively participate in routing. Furthermore, channel payments are still not visible to anyone other than the channel partners, nor is the distribution of the channel balance between them.
The amount deposited in the multisignature address is called the _channel capacity_ and sets the maximum amount that can be sent across the payment channel. However, since funds can be sent back and forth, the channel capacity is not the upper limit on how much value can flow across the channel. That's because if the channel capacity is exhausted with payments in one direction, it can be used to send payments in the opposite direction again.
@ -171,10 +171,9 @@ Initially, Alice owns 100k satoshi, the entirety of the funds in the channel. He
. Alice creates a new private/public key pair and informs Bob that she wishes to open a channel via the `open_channel` message (a message in the Lightning Network protocol).
. Bob also creates a new private/public key pair and agrees to accept a channel from Alice, sending his public key to Alice via the `accept_channel` message.
. Alice now creates a funding transaction from her wallet that sends 100k satoshi to the multisignature address with a locking script +2 <PubKey Alice> <PubKey Bob> 2 CHECKMULTISIG+.
. Alice does not yet broadcast this funding transaction but sends Bob the transaction ID in a `funding_created` message.
. Alice does not yet broadcast this funding transaction but sends Bob the transaction ID in a `funding_created` message along with her signature for Bob's commitment transaction.
. Both Alice and Bob create their version of a commitment transaction. This transaction will spend from the funding transaction and send all the bitcoin back to an address controlled by Alice.
. Alice and Bob don't need to exchange these commitment transactions, since they each know how they are constructed and can build both independently. They only need to exchange signatures.
. Alice provides a signature for Bob's commitment transaction. This signature was already included in the `funding_created` message.
. Alice and Bob don't need to exchange these commitment transactions, since they each know how they are constructed and can build both independently (as they've agreed on a canonical ordering of the inputs+outputs). They only need to exchange signatures.
. Bob provides a signature for Alice's commitment transaction and sends this back to Alice via the `funding_signed` message.
. Now that signatures have been exchanged, Alice will broadcast the funding transaction to the Bitcoin network.
@ -213,7 +212,7 @@ Let us go through the channel construction scenario again, adding a penalty mech
* Alice sends 30k satoshi to Bob.
* Alice tries to cheat Bob out of his earned 30k satoshi by publishing an old commitment transaction claiming the full 100k satoshi for herself.
* Bob detects the fraud and punishes Alice by taking the full 100k satoshi for himself.
* Bob ends up with 100k satoshi, gaining 70k satoshi for catching Alice cheat.
* Bob ends up with 100k satoshi, gaining 70k satoshi for catching Alice cheating.
* Alice ends up with 0 satoshi.
* Trying to cheat Bob out of 30k satoshi, she loses the 70k satoshi she owned.
@ -248,7 +247,7 @@ For every new update of the channel balance, new commitment transactions and new
Nevertheless, managing and storing the revocation secrets is one of the more elaborate parts of Lightning nodes that require node operators to maintain backups.
[NOTE]
====
===
Technologies such as watchtower services or changing the channel construction protocol to the "eltoo" protocol might be future strategies to mitigate these issues and reduce the need for revocation secrets, penalty transactions and channel backups.
====
@ -396,8 +395,6 @@ This software is either:
* A single-purpose watchtower node that you run to watch your channels.
* A third-party watchtower node that you pay to watch your channels.
We will look at watchtowers in more detail in XREF HERE.
Remember that the commitment transaction has a timeout period specified in a given number of blocks, up to a maximum of 2016 blocks.
As long as you run your Lightning node once before the timeout period is reached, it will catch all cheating attempts.
It is not advisable to take this kind of risk; it is important to keep a well maintained node running continuously (See XREF HERE).
@ -529,7 +526,7 @@ One common criticism of path-finding in the Lightning network is that it is unso
Pathfinding and routing can be implemented in a number of different ways and multiple path-finding and routing algorithms can co-exist on the Lightning Network, just as multiple path-finding and routing algorithms exist on the internet. Source-based pathfinding is one of many possible solutions and is successful at the current scale of the Lightning Network.
The pathfinding strategy currently implemented by Lightning nodes is to "probe" paths until one is found that has enough liquidity to forward the payment. This is an iterative process of trial and error, until success is achieved or no path is found. The algorithm currently does not necessarily result in the path with the lowest fees. While this is not optimal and certainly can be improved, even this simplistic strategy works quite well.
The pathfinding strategy currently implemented by Lightning nodes is to iteratively try paths until one is found that has enough liquidity to forward the payment. This is an iterative process of trial and error, until success is achieved or no path is found. The algorithm currently does not necessarily result in the path with the lowest fees. While this is not optimal and certainly can be improved, even this simplistic strategy works quite well.
This "probing" is done by the Lightning node or wallet and is not directly seen by the user.
The user might only realize that probing is taking place if the payment does not complete instantly.
@ -574,7 +571,7 @@ The onion routing protocol used in Lightning has the following properties:
. Onions have an HMAC (Hashed Message Authentication code) at each layer so that manipulations of onions are prevented and practically impossible.
. Onions can have up to 20 hops or onion layers if you prefer. This allows for sufficiently long paths.
. Onions can have up to around 26 hops or onion layers if you prefer. This allows for sufficiently long paths. The precise path length avaiblael dpeneds on the amount of bytes allocated to teh routing payload at each hop.
. The encryption of the onion for every hop uses different ephemeral encryption keys. Should a key (in particular the private key of a node) leak at some point in time an attacker cannot decrypt them. In simpler terms, keys are never reused in order to achieve more security.
@ -717,7 +714,7 @@ On the Bitcoin network, a user can send any amount of bitcoin that they own to a
On the Lightning Network, a user can only send as much bitcoin as currently exists on their side of a particular channel to a channel partner. For instance, if a user owns one channel with 0.4 BTC on their side, and another channel with 0.2 BTC on their side, then the maximum they can send with one payment is 0.4 BTC. This is true regardless of how much bitcoin the user currently has in their Bitcoin wallet.
Atomic Multi-Path Payments (AMPs) is a feature which, in the above example, allows the user to combine both their 0.4 BTC and 0.2 BTC channels to send a maximum of 0.6 BTC with one payment. AMPs are currently being tested across the Lightning Network, and are expected to be widely available and used by the time this book is completed. For more detail on AMPs, see XREF HERE.
Multi-Part Payments (MPP) is a feature which, in the above example, allows the user to combine both their 0.4 BTC and 0.2 BTC channels to send a maximum of 0.6 BTC with one payment. AMPs are currently being tested across the Lightning Network, and are expected to be widely available and used by the time this book is completed. For more detail on MPP, see <<mpp>>.
If the payment is routed, every routing node along the routing path must have channels with capacity at least the same as the payment amount being routed. This must hold true for every single channel that the payment is routed through. The capacity of the lowest-capacity channel in a path sets the upper limit for the capacity of the entire path.
@ -726,7 +723,7 @@ Hence, capacity and connectivity are critical and scarce resources in the Lightn
==== Incentives for large value payment vs. small value payments
The fee structure in Bitcoin is independent of the transaction value.
A $1 million transaction has the same fee as a $1 transaction on Bitcoin, assuming a similar transaction size in bytes.
A $1 million transaction has the same fee as a $1 transaction on Bitcoin, assuming a similar transaction size in bytes (more specifically "virtual" bytes after segwit).
In Lightning the fee is a fixed base fee plus a percentage of the transaction value.
Therefore, in Lightning the payment fee increases with payment value.
These opposing fee structures create different incentives and lead to different usage in regards to transaction value.

File diff suppressed because it is too large Load Diff

@ -1,4 +1,5 @@
[[operating_ln_node]]
[[node_operations]]
== Operating a Lightning Network node
After having read this far, you have probably set up a Lightning wallet. In this chapter, we will take things one step further and set up a full Lightning node. In addition to setting one up, we will learn how to operate it and maintain it over time.
@ -28,7 +29,7 @@ please do your homework diligently first. Running a profitable business by opera
definitely _not_ easy. Calculate all your initial and ongoing costs in a spreadsheet. Study Lightning Network statistics carefully.
What is the current payment volume? What is the volume per node? What are the current average routing fees? Consult forums and ask
for advice or feedback from other community members who have already gained real-world experience. Form your own educated opinion only
_after_ you have done this due-diligence exercise. Most people will find their motivation for running a node not in financial gain,
_after_ you have done this due diligence exercise. Most people will find their motivation for running a node not in financial gain,
but somewhere else.
====
@ -57,7 +58,7 @@ Thus, software and hardware failures in the Lightning Network can easily result
There are three main types of hardware Lightning nodes:
* **General-purpose computers**: A Lightning Network node can be run on a home computer or laptop running Windows, Mac OS, or Linux. Typically this is run alongside a Bitcoin node.
* **Dedicated hardware**: A Lightning node can also be run on dedicated hardware like a Raspberry Pi, Rock64, or mini-PC. This setup would usually run a software stack including a Bitcoin node and other applications. This setup is popular as the hardware is dedicated to running and maintaining the Lightning node only and is usually set up with an installation "helper".
* **Dedicated hardware**: A Lightning node can also be run on dedicated hardware like a Raspberry Pi, Rock64, or mini PC. This setup would usually run a software stack including a Bitcoin node and other applications. This setup is popular as the hardware is dedicated to running and maintaining the Lightning node only and is usually set up with an installation "helper".
* **Pre-configured hardware**: A Lightning Network node can also be run on purpose-built hardware specifically selected and configured for it. This would include "out-of-the-box" Lightning node solutions that can be purchased as a kit or a turn-key system.
==== Running in the "cloud"
@ -80,12 +81,17 @@ All this combined together results in a set-up that is not ideal. The same will
Instead, most users will choose to run a node on a dedicated computer.
Fortunately, you don't need a "server" class computer to do this.
You can run a Lightning node on a single-board computer, such as a Raspberry Pi or on a Mini PC (usually marketed as home theater PC's).
You can run a Lightning node on a single-board computer, such as a Raspberry Pi or on a Mini PC (usually marketed as home theater PCs).
These are simple computers which are commonly used as a home automation hub or a media server.
They are relatively inexpensive, when compared to a PC or a laptop.
The advantage of a dedicated device as a platform for Lightning and Bitcoin nodes is that it can run continuously, silently, and unobtrusively on your home network, tucked behind your router or TV.
No one will even know that this little box is actually part of a global banking system!
[WARNING]
====
Operating a node on a 32-bit operating system and/or 32-bit CPU is not recommended, as the node software may run into resource issues, causing a crash and possibly a loss of funds.
====
==== What hardware is required to run a Lightning node?
At a minimum, the following will be required to run a Lightning node:
@ -123,7 +129,7 @@ For example, on Amazon's cloud, we would use a 8-16GB RAM, 8-core CPU (e.g. t3-l
===== Permanent data storage (drive)
If you use a mini-PC or rent a server, the storage can be the most expensive part, costing as much as the computer and connectivity (data) added together.
If you use a mini PC or rent a server, the storage can be the most expensive part, costing as much as the computer and connectivity (data) added together.
Let's have a look at the different options available. First there are two main types of drives, Hard Disk Drives (HDDs) and Solid State Drives (SSDs). HDDs are cheaper and SSDs are faster, but both do the job.
@ -132,11 +138,12 @@ Traditional SATA-based SSDs are cheaper, but not as fast. SATA SSDs perform suff
Smaller computers might not be able to take advantage of NVMe SSDs.
For example, the Raspberry Pi 4 cannot benefit from them because of the limited bandwidth of its USB port.
To choose the size, let's look at the Bitcoin blockchain. As of April 2021, its size is 338GB including the transaction index and grows by roughly 60GB/year. If you want to have some margin available for future growth or to install other data on your node, purchase at least a 512GB drive or better yet a 1TB drive.
To choose the size, let's look at the Bitcoin blockchain. As of August 2021, its size is 360GB including the transaction index and grows by roughly 60GB/year. If you want to have some margin available for future growth or to install other data on your node, purchase at least a 512GB drive or better yet a 1TB drive.
[[helpers]]
=== Using an installer or helper
Installing a Lightning node or a Bitcoin node may be daunting if you are not familiar with a command-line environment. Luckily, there are a number of projects that make "helpers", i.e. software that installs and configures the various components for you. You will still need to learn some command-line incantations to interact with your node, but most of the initial work is done for you.
Installing a Lightning node or a Bitcoin node may be daunting if you are not familiar with a command line environment. Luckily, there are a number of projects that make "helpers", i.e. software that installs and configures the various components for you. You will still need to learn some command line incantations to interact with your node, but most of the initial work is done for you.
==== RaspiBlitz
@ -148,32 +155,32 @@ image::images/raspiblitz.jpg[]
In addition to a Bitcoin and Lightning node, RaspiBlitz can install a number of additional services, such as:
* TOR (run as hidden service)
* Tor (run as hidden service)
* ElectRS (Electrum server in Rust)
* BTCPayServer (cryptocurrency payment processor)
* BTC-RPC-Explorer (Bitcoin blockchain explorer)
* BTC RPC Explorer (Bitcoin blockchain explorer)
* Ride The Lightning (Lightning node management GUI)
* LNbits (Lightning wallet/accounts system)
* SpecterDesktop (multisig Trezor, Ledger, Coldcard wallet & Specter-DIY)
* LNDmanage (command-line interface for advanced channel management)
* Specter Desktop (multisig Trezor, Ledger, Coldcard wallet & Specter-DIY)
* LNDmanage (command line interface for advanced channel management)
* Loop (submarine swaps service)
* JoinMarket (CoinJoin service)
==== MyNode
==== myNode
_MyNode_ is another popular open source "helper" project including a lot of Bitcoin related software. It is easy to install: you "flash" the installer onto an SD card and boot your mini-PC from the SD card. You do not need any monitor to use myNode as the administrative tools are accessible remotely from a browser. If your mini-PC has no monitor, mouse, or keyboard; you can manage it from another computer or even from your smartphone. Once installed, go to http://mynode.local/ and create a Lightning wallet and node in two clicks.
_myNode_ is another popular open source "helper" project including a lot of Bitcoin related software. It is easy to install: you "flash" the installer onto an SD card and boot your mini-PC from the SD card. You do not need any monitor to use myNode as the administrative tools are accessible remotely from a browser. If your mini-PC has no monitor, mouse, or keyboard; you can manage it from another computer or even from your smartphone. Once installed, go to http://mynode.local/ and create a Lightning wallet and node in two clicks.
You can find the MyNode project here:
You can find the myNode project here:
https://mynodebtc.com/
In addition to a Bitcoin and Lightning node, MyNode can optionally install a variety of additional services, such as:
In addition to a Bitcoin and Lightning node, myNode can optionally install a variety of additional services, such as:
* Ride The Lightning (Lightning node management GUI)
* OpenVPN (VPN Support for remote management or wallet)
* LNDmanage (command-line interface for advanced channel management)
* btc-rpc-explorer (A Bitcoin blockchain explorer)
* LNDmanage (command line interface for advanced channel management)
* BTC RPC Explorer (A Bitcoin blockchain explorer)
==== Umbrel
@ -189,7 +196,7 @@ In addition to a Bitcoin and Lightning node, Umbrel introduced the Umbrel App St
* Ride The Lightning (Lightning node management GUI)
* Specter Desktop (watch-only coordinator for multi-signature and single-key Bitcoin wallets)
* BTCPayServer (cryptocurrency payment processor)
* BTC-RPC-Explorer (Bitcoin blockchain explorer)
* BTC RPC Explorer (Bitcoin blockchain explorer)
* ThunderHub (monitor and manage your node)
* Sphinx Relay (handling connectivity and storage for Sphinx chat)
* mempool.space (mempool visualizer and block explorer)
@ -199,7 +206,7 @@ Umbrel is currently still in beta and not considered secure.
==== BTCPay Server
While not initially designed as an installation "helper", the e-commerce and payment platform _BTCPay Server_ has an incredibly easy installation system that uses Docker containers and +docker-compose+ to install a Bitcoin node, Lightning node, and payment gateway, among many other services. It can be installed on a variety of hardware platforms, from a simple Raspberry Pi 4 (4GB recommended) to a mini-PC, old laptop, desktop or server.
While not initially designed as an installation "helper", the e-commerce and payment platform _BTCPay Server_ has an incredibly easy installation system that uses Docker containers and +docker-compose+ to install a Bitcoin node, Lightning node, and payment gateway, among many other services. It can be installed on a variety of hardware platforms, from a simple Raspberry Pi 4 (4GB recommended) to a mini PC, old laptop, desktop or server.
BTCPay Server is a fully-featured self-hosted self-custody e-commerce platform that can be integrated with many e-commerce platforms such as Wordpress Woocommerce and others. The installation of the full node is only a step of the e-commerce platform installation.
While originally developed as a feature-for-feature replacement of the _Bitpay_ commercial payment service and API, it has evolved past that to be a complete platform for BTC and Lighting services related to e-commerce. For many sellers or shops it is a one-shop turn-key solution to e-commerce.
@ -235,7 +242,7 @@ The bottom line for this decision is: If you can afford a disk larger than 500GB
==== Operating system choice
The next step is to select an operating system for your node. The vast majority of Internet servers run on some variant of Linux. Linux is the platform of choice for the Internet because it is a powerful, open-source operating system. Linux, however, has a steep learning curve and requires familiarity with a command-line environment. It is often intimidating for new users.
The next step is to select an operating system for your node. The vast majority of Internet servers run on some variant of Linux. Linux is the platform of choice for the Internet because it is a powerful, open-source operating system. Linux, however, has a steep learning curve and requires familiarity with a command line environment. It is often intimidating for new users.
Ultimately, most of the services can be run on any modern POSIX operating system, which includes Mac OS, Windows, and of course Linux. Your choice should be driven more by your familiarity and comfort with an operating system and your learning objectives. If you want to expand your knowledge and learn how to operate a Linux system, this is a great opportunity to do so with a specific project and a clear goal. If you just want to get a node up and running, go with what you know.
@ -255,14 +262,14 @@ The programming language doesn't just influence the choice of build system, but
* format and syntax of configuration files
* file locations (in the filesystem)
* command-line arguments and their syntax
* command line arguments and their syntax
* error message formatting
* prerequisite libraries
* Remote Procedure Call interfaces
When you choose your Lightning node, you are also choosing all of the above characteristics. So your familiarity with these tools and design philosophies will make it easier to run a node. Or harder, if you land in an unfamiliar domain.
On the other hand, if this is your first foray into the command-line and server/service environment, you will find yourself unfamiliar with any implementation and have the opportunity to learn something completely new. In that case you might want to decide based on a number of other factors, such as:
On the other hand, if this is your first foray into the command line and server/service environment, you will find yourself unfamiliar with any implementation and have the opportunity to learn something completely new. In that case you might want to decide based on a number of other factors, such as:
* quality of support forums and chat rooms
* quality of documentation
@ -272,11 +279,11 @@ As a final consideration, you may want to examine the performance and reliabilit
=== Installing a Bitcoin or Lightning node
You decided not to use an installation "helper" and instead to dive into the command-line of a Linux operating system? That is a brave decision and we'll try to help you make it work. If you'd rather not try to do this manually, consider using an application that helps you install the node software or a container-based solution, as described in <<helpers>>.
You decided not to use an installation "helper" and instead to dive into the command line of a Linux operating system? That is a brave decision and we'll try to help you make it work. If you'd rather not try to do this manually, consider using an application that helps you install the node software or a container-based solution, as described in <<helpers>>.
[WARNING]
====
This section will delve into the advanced topic of system administration from the command-line. Linux administration is its own skill set that is outside the scope of this book. It is a complicated topic and there are many pitfalls. Proceed with caution!
This section will delve into the advanced topic of system administration from the command line. Linux administration is its own skill set that is outside the scope of this book. It is a complicated topic and there are many pitfalls. Proceed with caution!
====
In the next few sections we will briefly describe how to install and configure a Bitcoin and Lightning node on a Linux operating system. You will need to review the installation instructions for the specific Bitcoin and Lightning node applications you decided to use. You can usually find these in a file called +INSTALL+ or in the +docs+ sub-directory of each project. We will only describe some of the common steps that apply to all such services, and the instructions we offer will be necessarily incomplete.
@ -289,9 +296,9 @@ This can create some confusion for users who are not used to running background
==== Process isolation
Background services usually run under a specific user account in order to isolate them from the operating system and each other. For example, Bitcoin Core is configured to run as user +bitcoin+. You will need to use the command-line to create a user for each of the services you run.
Background services usually run under a specific user account in order to isolate them from the operating system and each other. For example, Bitcoin Core is configured to run as user +bitcoin+. You will need to use the command line to create a user for each of the services you run.
In addition, if you have connected an external drive, you will need to tell the operating system to relocate the user's home directory to that drive. That's because a service like Bitcoin Core will create files under the user's home directory. If you are setting it up to download the full Bitcoin blockchain, these files will take up several hundred Gigabytes. Here, we assume you have connected the external drive and it is located on the +/external_drive/+ path of the operating system.
In addition, if you have connected an external drive, you will need to tell the operating system to relocate the user's home directory to that drive. That's because a service like Bitcoin Core will create files under the user's home directory. If you are setting it up to download the full Bitcoin blockchain, these files will take up several hundred gigabytes. Here, we assume you have connected the external drive and it is located on the +/external_drive/+ path of the operating system.
On most Linux systems you can create a new user with the +useradd+ command, like this:
@ -382,7 +389,7 @@ To configure your node, you need to create and reference a configuration file. B
+/etc/bitcoin/bitcoin.conf+
+/etc/lnd/lnd.conf+
These configuration files are text files with each line expressing one configuration option and its value. Default values are assumed for anything not defined in the configuration file. You can see what options can be set in the configuration in two ways. First, running the node application with a +help+ argument will show the options that can be defined on the command-line. These same options can be defined in the configuration file. Second, you can usually find an example configuration file, with all the default options, in the code repository of the software.
These configuration files are text files with each line expressing one configuration option and its value. Default values are assumed for anything not defined in the configuration file. You can see what options can be set in the configuration in two ways. First, running the node application with a +help+ argument will show the options that can be defined on the command line. These same options can be defined in the configuration file. Second, you can usually find an example configuration file, with all the default options, in the code repository of the software.
You can find one example of a configuration file in each of the Docker images we used in <<set_up_a_lightning_node>>. For example, the file +code/docker/bitcoind/bitcoind/bitcoin.conf+:
@ -425,7 +432,7 @@ If you want to run a Bitcoin or Lightning node, you need to make it possible for
By default, your home Internet router does not expect incoming connections from the outside, and in fact incoming connections are blocked. Your Internet router IP address is the only externally accessible IP address, and all the computers you run inside your home network share that single IP address. This is achieved by a mechanism called _Network Address Translation (NAT)_ which allows your Internet router to act as an intermediary for all outbound connections. If you want to allow an inbound connection you have to set up _Port Forwarding_, which tells your Internet router that incoming connections on specific ports should be forwarded to specific computers inside the network. You can do this manually by changing your Internet router configuration or, if your router supports it, through an automatic port forwarding mechanism called _Universal Plug and Play (UPNP)_.
An alternative mechanism to port forwarding is to enable The Onion Router (TOR), which provides a kind of virtual private network overlay that allows incoming connections to an _onion address_. If you run TOR, you don't need to do port forwarding nor enable incoming connections to Bitcoin or Lightning ports. If you run your nodes using TOR, all traffic goes through TOR and no other ports are used.
An alternative mechanism to port forwarding is to enable The Onion Router (Tor), which provides a kind of virtual private network overlay that allows incoming connections to an _onion address_. If you run Tor, you don't need to do port forwarding nor enable incoming connections to Bitcoin or Lightning ports. If you run your nodes using Tor, all traffic goes through Tor and no other ports are used.
Let's look at different ways you can make it possible for others to connect to your node. We'll look at these alternatives in order, from easiest to most difficult.
@ -466,19 +473,19 @@ Sometimes, even if your Internet router supports UPNP, it may be turned off by d
Restart your Bitcoin and/or Lighting node and repeat the open port test with one of the websites we used in the previous section.
===== Using TOR for incoming connections
===== Using Tor for incoming connections
_The Onion Router (TOR)_ is a virtual private network with the special property that it encrypts communications between hops, such that any intermediary node cannot determine the origin or destination of a packet. Both Bitcoin and Lightning nodes support operation over TOR, which enables you to operate a node without revealing your IP address or location. Hence, it provides a high level of privacy to your network traffic. An added benefit of running TOR is that because it operates as a VPN, it resolves the problem of port forwarding from your Internet router. Incoming connections are received over the TOR tunnel, and your node can be found through an ad-hoc generated _onion address_ instead of an IP address.
_The Onion Router (Tor)_ is a virtual private network with the special property that it encrypts communications between hops, such that any intermediary node cannot determine the origin or destination of a packet. Both Bitcoin and Lightning nodes support operation over Tor, which enables you to operate a node without revealing your IP address or location. Hence, it provides a high level of privacy to your network traffic. An added benefit of running Tor is that because it operates as a VPN, it resolves the problem of port forwarding from your Internet router. Incoming connections are received over the Tor tunnel, and your node can be found through an ad-hoc generated _onion address_ instead of an IP address.
Enabling TOR requires two steps: First you must install the TOR router and proxy on your computer. Second, you must enable the use of the TOR proxy in your Bitcoin or Lightning configuration.
Enabling Tor requires two steps: First you must install the Tor router and proxy on your computer. Second, you must enable the use of the Tor proxy in your Bitcoin or Lightning configuration.
To install TOR on a Ubuntu Linux system that uses the +apt+ package manager, run:
To install Tor on a Ubuntu Linux system that uses the +apt+ package manager, run:
----
sudo apt install tor
----
Next, we configure our Lightning node to use TOR for its external connectivity. Here is an example configuration for LND:
Next, we configure our Lightning node to use Tor for its external connectivity. Here is an example configuration for LND:
----
[Tor]
@ -488,9 +495,9 @@ tor.streamisolation=true
listen=localhost
----
This will enable TOR (+tor.active+), establish a v3 onion service (+tor.v3=true+), use a different onion stream for each connection (+tor.streamisolation+), and restrict listening for connections to the local host only, to avoid leaking your IP address (+listen=localhost+).
This will enable Tor (+tor.active+), establish a v3 onion service (+tor.v3=true+), use a different onion stream for each connection (+tor.streamisolation+), and restrict listening for connections to the local host only, to avoid leaking your IP address (+listen=localhost+).
You can check if TOR is correctly installed and working by running a simple one-line command. This command should work on most flavors of Linux:
You can check if Tor is correctly installed and working by running a simple one-line command. This command should work on most flavors of Linux:
----
curl --socks5 localhost:9050 --socks5-hostname localhost:9050 -s https://check.torproject.org/ | cat | grep -m 1 Congratulations | xargs
@ -498,15 +505,15 @@ curl --socks5 localhost:9050 --socks5-hostname localhost:9050 -s https://check.t
If everything is working properly, the response of this command should be +"Congratulations. This browser is configured to use Tor."+.
Due to the nature of TOR, you can't easily use an external service to check if your node is reachable via an onion address. Nonetheless, you should see your TOR onion address in the logs of your Lightning node. It is a long string of letters and numbers followed by the suffix +.onion+. Your node should now be reachable from the Internet, with the added bonus of privacy!
Due to the nature of Tor, you can't easily use an external service to check if your node is reachable via an onion address. Nonetheless, you should see your Tor onion address in the logs of your Lightning node. It is a long string of letters and numbers followed by the suffix +.onion+. Your node should now be reachable from the Internet, with the added bonus of privacy!
===== Manual port forwarding
This is the most complex process and requires quite a bit of technical skill. The details depend on the type of Internet router you have, your service provider settings and policies, and a lot of other context. Try UPNP or TOR first, before you try this much more difficult mechanism.
This is the most complex process and requires quite a bit of technical skill. The details depend on the type of Internet router you have, your service provider settings and policies, and a lot of other context. Try UPNP or Tor first, before you try this much more difficult mechanism.
The basic steps are as follows:
. Find the IP address of the computer your node is on. This is usually dynamically allocated by the Dynamic Host Configuration Protocol (DHCP) and is often somewhere in the 192.168.0.X or 10.0.0.X range.
. Find the IP address of the computer your node is on. This is usually dynamically allocated by the Dynamic Host Configuration Protocol (DHCP) and is often somewhere in the 192.168.x.x or 10.x.x.x range.
. Find the Media Access Control (MAC) address of your node's network interface. This can be found in the Internet settings of that computer.
@ -519,7 +526,7 @@ Once done re-configuring, repeat the port check using one of the websites from t
=== Security of your node
A Lightning node is, by definition, a hot-wallet. That means that the funds (both on-chain and off-chain) controlled by a Lightning node are directly controlled by keys that are loaded in the node's memory or stored on the node's hard disk. If a Lightning node is compromised, it is trivial to create on-chain or off-chain transactions to drain its funds. It is therefore critically important that you protect it from unauthorized access.
A Lightning node is, by definition, a hot wallet. That means that the funds (both on-chain and off-chain) controlled by a Lightning node are directly controlled by keys that are loaded in the node's memory or stored on the node's hard disk. If a Lightning node is compromised, it is trivial to create on-chain or off-chain transactions to drain its funds. It is therefore critically important that you protect it from unauthorized access.
Security is a holistic effort, meaning that you have to secure every layer of a system. As the saying goes: the chain is only as strong as the weakest link. This is an important concept in information security and we will apply it to our node.
@ -538,7 +545,7 @@ To secure your operating system, here are some of the top items to consider:
. Process isolation: Use the operating system features to isolate processes from each other.
. File system permissions: Configure the file system carefully, on the least-privilege principle. Do not make files readable or writable by everyone.
. Strong authentication: Use strong randomly generated passwords or, whenever possible, public-key authentication. E.g. it is safer to use Secure Shell (SSH) with a cryptographic key pair instead of a password.
. Two-factor authentication (2FA): Use two-factor authentication wherever possible, including Universal 2-Factor (U2F) with hardware security keys. This applies to all external services you might be using such as your cloud service provider. You can apply this also to your own set-up such as your own SSH configuration. Use 2FA also for indirect services. For exmaple, say you are using a cloud service. You gave your cloud service provider an email address, so you should also protect your email address with 2FA.
. Two-factor authentication (2FA): Use two-factor authentication wherever possible, including Universal 2-Factor (U2F) with hardware security keys. This applies to all external services you might be using such as your cloud service provider. You can apply this also to your own set-up such as your own SSH configuration. Use 2FA also for indirect services. For example, say you are using a cloud service. You gave your cloud service provider an email address, so you should also protect your email address with 2FA.
. Backup: Make backups of your system, and make sure you protect the backups with encryption too. Perform these backups periodically. At least once test if you can restore your backup and that your backup is complete and accessible. If possible, keep one copy of your backups on a different disk to avoid that a single hard disk failure destroys _both_ your active node as well as your backup copies.
. Vulnerability and exposure management: Use remote scanning to ensure you have minimized the attack surface of your system. Close any unnecessary services or ports.
- Minimize: Install only software and packages that you really need and use. Uninstall packages that you no longer use. It is recommended that you do _not_ use your node computer for non-node activities that you can perform on another of your computers. Especially, if you can, do _not_ use your node computer for browsing, surfing the Internet, or reading your email.
@ -576,11 +583,11 @@ Channel backup mechanisms are still a work-in-progress and a weakness in most Li
==== Static Channel Backups (SCB)
At the time of writing this book, only LND offers a built-in mechanism for static channel backups. Eclair has no backup on the server side, although Eclair mobile does offer optional backup to a Google Drive. C-lightning recently merged the necessary interfaces for a plugin to implement channel backups. Unfortunately, there is no consistent, agreed upon backup mechanism across different node implementations.
At the time of writing this book, only LND offers a built-in mechanism for static channel backups. Eclair has a similar mechanism deployed for server-side deployments, although Eclair mobile does offer optional backup to a Google Drive. C-lightning recently merged the necessary interfaces for a plugin to implement channel backups. Unfortunately, there is no consistent, agreed upon backup mechanism across different node implementations.
File-based backups of the Lightning node databases are at best a partial solution because you run the risk of backing up an inconsistent database state. In addition, you may not reliably catch the latest state commitments. It is much better to have a backup mechanism that is triggered every time there is a state change in a channel, thereby ensuring data consistency.
To set up static channel backups in LND, set the +backupfilepath+ parameter either on the command-line or in the configuration file. LND will then save an SCB file in that directory path. Of course, that's only the first step of the solution. Now, you have to setup a mechanism that monitors this file for changes. Each time the file changes the backup mechanism must copy this file to another, preferably "off-site" disk. Such backup mechanisms are beyond the scope of this book. Nonetheless, any sophisticated backup solution should be able to handle this scenario. Recall, the backup files should be encrypted too.
To set up static channel backups in LND, set the +backupfilepath+ parameter either on the command line or in the configuration file. LND will then save an SCB file in that directory path. Of course, that's only the first step of the solution. Now, you have to setup a mechanism that monitors this file for changes. Each time the file changes the backup mechanism must copy this file to another, preferably "off-site" disk. Such backup mechanisms are beyond the scope of this book. Nonetheless, any sophisticated backup solution should be able to handle this scenario. Recall, the backup files should be encrypted too.
==== Hot wallet risk
@ -606,7 +613,7 @@ Another technique you can use involves running a second Lightning node that is n
The advantage of this technique lies in the fact that the Lightning node that receives payments for your shop will be publicly known. This makes it a target for hackers, as any Lightning node associated with a shop would be assumed to have a large balance. A second node that is not associated with your shop will not easily be identified as a valuable target.
As an additional measure of security, you can make your second node a hidden TOR service so that its IP address is not known. That further reduces the opportunity for attacks and increases your privacy.
As an additional measure of security, you can make your second node a hidden Tor service so that its IP address is not known. That further reduces the opportunity for attacks and increases your privacy.
You will need to set up a script that runs at regular intervals. The purpose of this script is to create an invoice on your hidden node and to pay that invoice from your shop's node, thereby shifting funds over to your hidden node.
@ -614,7 +621,7 @@ Keep in mind that this technique does not move funds into cold storage. Both Lig
===== Submarine swap sweep
Another way to reduce your Lightning hot-wallet balance is to use a technique called a _submarine swap_. Submarine swaps, conceptualized by co-author Olaoluwa Osuntokun and Alex Bosworth, allow the exchange of on-chain bitcoin for Lightning payments and vice versa.
Another way to reduce your Lightning hot-wallet balance is to use a technique called a _submarine swap_. Submarine swaps, conceptualized by co-author Olaoluwa Osuntokun and Alex Bosworth, allow the exchange of on-chain bitcoin for Lightning payments and vice versa. Essentially, submarine swaps are atomic swaps between Lightning off-chain funds and Bitcoin on-chain funds.
A node operator can initiate a submarine swap and send all available channel balances to the other party who will send them as a result on-chain bitcoin in exchange.
@ -622,7 +629,7 @@ In the future, this could be a paid service offered by nodes on the Lightning Ne
The advantage of a submarine swap for sweeping funds is that no channel needs to be closed. That means that we preserve our channels, only re-balancing our channels through this operation. As we send a Lightning payment out, we shift some balance from local to remote on one or more of our channels. Not only does that reduce the balance exposed in our node's hot wallet, it also increases the balance available for future incoming payments.
You could do this by trusting an intermediary to act as a gateway, but this risks your coins being stolen. But in the case of a submarine swap, the operation does not require trust. Submarine swaps are non-custodial _atomic_ operations. That means that the counterparty in your submarine swap cannot steal your funds because the on-chain payment depends on the completion of the off-chain payment and vice-versa. We will discuss submarine swaps in more detail in <<submarine_swaps>>.
You could do this by trusting an intermediary to act as a gateway, but this risks your coins being stolen. But in the case of a submarine swap, the operation does not require trust. Submarine swaps are non-custodial _atomic_ operations. That means that the counterparty in your submarine swap cannot steal your funds because the on-chain payment depends on the completion of the off-chain payment and vice-versa.
===== Submarine swaps with Loop
@ -633,7 +640,7 @@ One example of a submarine swap service is _Loop_ by Lightning Labs, the same co
To use the _Loop_ service you must be running an LND Lightning node.
====
For the purpose of reducing the balance of your Lightning hot wallet, you would use the Loop Out service. To use the Loop service, you need to install some additional software on your node. The Loop software runs alongside your LND node and provides some command-line tools to execute submarine swaps. You can find the Loop software and installation instructions here:
For the purpose of reducing the balance of your Lightning hot wallet, you would use the Loop Out service. To use the Loop service, you need to install some additional software on your node. The Loop software runs alongside your LND node and provides some command line tools to execute submarine swaps. You can find the Loop software and installation instructions here:
https://github.com/lightninglabs/loop
@ -675,7 +682,7 @@ If you have the time and skills you should test some basic fault scenarios on th
- Automatic node restart: What happens when your node or one of your nodes crashes? Simulate this fault by killing the corresponding node processes. If a node crashes, it should automatically restart itself. Test it to make sure the node or nodes really restart automatically on failure without human intervention. If this is not the case, most likely your node is not set up correctly as an operating system service.
- Automatic network reconnection: What happens if your network goes down? What happens when your ISP goes temporarily down? What happens when your ISP assigns a new IP address to your router or your computer? When the network comes back, do the nodes your are running automatically reconnect to the network? Simulate this fault by unplugging and later re-plugging the Ethernet cable from the device hosting your nodes. The nodes should automatically reconnect and continue operation without human intervention.
- Automatic network reconnection: What happens if your network goes down? What happens when your ISP goes temporarily down? What happens when your ISP assigns a new IP address to your router or your computer? When the network comes back, do the nodes you are running automatically reconnect to the network? Simulate this fault by unplugging and later re-plugging the Ethernet cable from the device hosting your nodes. The nodes should automatically reconnect and continue operation without human intervention.
- Configure your log files: All of the above failures should leave textual entries behind in the corresponding log files. Turn up the verbosity of logging if needed. Find these error entries in the log files and use them for monitoring.
@ -691,6 +698,7 @@ https://lightning.watch
Over time, we expect more third-party services to provide specialized Lightning node monitoring payable via micro-payments. Perhaps such services and their APIs will become standardized and will one day be directly supported by Lightning node software.
[[watchtowers]]
==== Watchtowers
_Watchtowers_ are a mechanism for outsourcing the monitoring and penalty resolution of Lightning protocol violations.
@ -709,14 +717,14 @@ watchtower.active=1
watchtower.towerdir=/path_to_watchtower_data_directory
----
You can use LND's watchtower client by activating it in the configuration and then using the command-line to connect it to a watchtower server. The configuration is:
You can use LND's watchtower client by activating it in the configuration and then using the command line to connect it to a watchtower server. The configuration is:
----
[wtclient]
wtclient.active=1
----
LND's command-line client +lncli+ shows the following options for managing the watchtower client:
LND's command line client +lncli+ shows the following options for managing the watchtower client:
----
$ lncli wtclient
@ -766,6 +774,7 @@ One way to find well connected nodes is to open a channel to a popular merchant
Another way to find well-connected nodes is to use a Lightning Explorer (see <<ln_explorer>>) such as +1ml.com+ and browse the list of nodes sorted by channel capacity and number of channels. Don't go for the biggest nodes as that encourages centralization. Go for a node in the middle of the list so that you can help them grow. Another factor to consider might be the time span a node has been in operation. Nodes established for more than a year are likely to be more reputable and less risky than nodes that started operation a week ago.
[[autopilot]]
===== Autopilot
The task of opening channels can be partially automated with the use of an _autopilot_, which is software that opens channels automatically based on some heuristic rules. Autopilot software is still relatively new and it doesn't always select the best channel partners for you. Especially in the beginning, it might be better to open channels manually.
@ -807,10 +816,22 @@ As is common, the amounts in the configuration file are enumerated in satoshi.
Currently channels below 1 mBTC are not very useful and we do not recommend you open channels that are too small and below this amount.
With the wider adoption of multipath payments, smaller channels are less of a burden. But for the time being, this is our recommendation.
The +c-lightning+ plugin works very differently in comparison to the +lnd+ autopilot.
The +c-lightning+ plugin which was orignally written by Rene Pickhardt works very differently in comparison to the +lnd+ autopilot.
First, it differs in the algorithms used to make the recommendations. We will not cover this here. Secondly, it differs in its user interface.
You will need to download the _autopilot plugin_ from the +c-lightning+ plugin repository at https://github.com/lightningd/plugins/tree/master/autopilot and activate it.
We have already explained how to activate plugins in +c-lightning+.
[NOTE]
====
In order to activate a plugin in +c-lightning+, place it into the +~/.lightning/plugins+ directory, ensure that it's executable (e.g. +chmod +x ~/.lightning/plugins/autopilot.py+), then restart +lightningd+.
Alternatively, if you don't want a plugin to automatically activate when you start +lightningd+ you can place it in a different directory and manually activate it with the +plugin+ argument to +lightningd+:
----
lightningd --plugin=~/lightning-plugins/autopilot.py
----
====
The autopilot in +c-lightning+ is controlled via 3 configuration values which can be set in the config file or as command line arguments when you start +lightningd+.
----
@ -883,6 +904,7 @@ Some examples:
* Your channel partner is online, but is not responding to requests to initiate a mutual close.
* Your channel partner is online and your nodes are negotiating a mutual close, but they become stuck and cannot reach a resolution.
[[channel_rebalancing]]
==== Re-balancing channels
In the course of transacting and routing payments on Lightning, the combination of inbound and outbound capacities can become unbalanced.
@ -891,15 +913,15 @@ For example, if one of your channel partners is frequently routing payments thro
There are many ways to re-balance channels, each with different advantages and disadvantages. One way is to use a _submarine swap_ (e.g. +Loop-Out+) as described previously in this chapter. Another way to re-balance is to simply wait for routed payments that flow in the opposite direction. If your node is well connected, when a specific route becomes exhausted in one direction, the same route becomes available in the opposite direction. Other nodes may "discover" that route in the opposite direction and start using it as part of their payment path, thereby re-balancing the funds again.
A third way to re-balance channels is to purposefully create a _circular route_ that sends a payment from your node back to your node, via the Lightning Network. By sending a payment out on a channel with large local capacity and arranging the path so that it returns to your node on a channel with large remote capacity, both of those channels will become more balanced. An example of a circular route re-balancing strategy can be seen in <<circular-rebalancing>>.
A third way to re-balance channels is to purposefully create a _circular route_ that sends a payment from your node back to your node, via the Lightning Network. By sending a payment out on a channel with large local capacity and arranging the path so that it returns to your node on a channel with large remote capacity, both of those channels will become more balanced. An example of a circular route re-balancing strategy can be seen in <<circular_rebalancing>>.
[[circular-rebalancing]]
[[circular_rebalancing]]
.Circular route re-balancing
image::images/circular-rebalancing.png[]
Circular re-balancing is supported by most Lightning node implementations and can be done on the command-line or via one of the web management interfaces such as _Ride the Lightning (RTL)_ (see <<rtl>>).
Circular re-balancing is supported by most Lightning node implementations and can be done on the command line or via one of the web management interfaces such as _Ride the Lightning (RTL)_ (see <<rtl>>).
Channel rebalancing is a complex issue that is the subject of active research and covered in more detail in <<rebalancing_channels>>.
Channel rebalancing is a complex issue that is the subject of active research and covered in more detail in <<channel_rebalancing>>.
=== Routing fees
@ -937,14 +959,14 @@ You can also use the routing fee settings to re-balance channels. If most of you
=== Node management
Managing your Lightning node on the command-line is obviously not easy. It gives you the full flexibility of the node's API and the ability to write your own custom scripts to satisfy your personal requirements. But if you don't want to deal with the complexity of the command line and only need some basic node management capabilities, you should consider installing a web-based user interface that makes node management easier.
Managing your Lightning node on the command line is obviously not easy. It gives you the full flexibility of the node's API and the ability to write your own custom scripts to satisfy your personal requirements. But if you don't want to deal with the complexity of the command line and only need some basic node management capabilities, you should consider installing a web-based user interface that makes node management easier.
There are a number of competing projects that offer web-based Lightning node management. Some of the most popular ones are described below.
[[rtl]]
==== Ride The Lightning (RTL)
_RTL_ is a graphical web user interface to help users manage Lightning node operations for the three main Lightning node implementations (LND, c-lightning, and Eclair). RTL is an open source project developed by Suheb, Shahana Farooqui, and many other contributors. You can find the RTL software here:
https://github.com/Ride-The-Lightning/RTL
@ -960,9 +982,9 @@ Lightning Labs, the makers of LND, provide a web-based graphical user interface
https://github.com/lightninglabs/lndmon
=== Thunderhub
==== ThunderHub
A very aesthetically pleasing web-based graphical user interface similar to RTL but exclusive to LND. It can be used to make payments, rebalance channels and manage the node through a variety of features. Find +Thunderhub+ here:
A very aesthetically pleasing web-based graphical user interface similar to RTL but exclusive to LND. It can be used to make payments, rebalance channels and manage the node through a variety of features. Find +ThunderHub+ here:
https://thunderhub.io

@ -1,6 +1,6 @@
== Lightning Network Architecture
In the first part of this book we introduced the main concepts of the Lightning Network, worked through a comprehensive example of routing a payment and set up the tools we can use to explore further. In the second part of the book we will explore the Lightning Network in a lot more technical detail, dissecting each of the building blocks.
In the first part of this book we introduced the main concepts of the Lightning Network, worked through a comprehensive example of routing a payment and setting up the tools we can use to explore further. In the second part of the book we will explore the Lightning Network in a lot more technical detail, dissecting each of the building blocks.
In this section we will outline the components of the Lightning Network in more detail and provide a "big picture" perspective to guide you through the following chapters.
@ -25,3 +25,31 @@ Peer-2-Peer (P2P) Layer:: This layer is primary protocol layer for communication
Routing Layer:: This layer contains the protocols used to route payments between nodes, end-to-end and atomically. This layer contains the "core" functionality of the Lightning Network: routed payments.
Payment Layer:: The highest layer of the network, which presents a reliable payment interface to applications.
=== Lightning in Detail
Over the next 10 chapters, we will diseect the protocol suite and examine each component of the Lightning Network in detail.
We spent quite some time trying to decide the best order of presenting this detail. It's not an easy choice as there is so much interdependence between different components: as you start explaining one, you find that it pulls in quite a few of the other componenents. Instead of a top-down or bottom-up approach, we ended up choosing a more meandering path that starts with the most fundamental building blocks that are unique to the Lightning Network - Payment Channels - and moves outwards from there. But since that path is not obvious, we will use the Lightning Protocol Suite shown in <<lightning_network_protocol_suite>> as a map. In each chapter will focus on one or more related components, and you will see them highlighted in the protocol suite. Kind of like a map marker saying "You are here!".
Here's what we will cover:
<<payment_channels>>:: In this chapter we will look at how payment channels work, in significantly more depth than we saw in the earlier parts of the book. We will look at the structure and Bitcoin Script of the funding and commitment transactions and the process used by nodes to negotiate each step in the protocol.
<<routing_htlcs>>:: Next, we will put together several payment channels in a network and route a payment from one end to the other. In that process we will dive into the Hash Time-Locked Contract smart contract and the Bitcoin Script that we use to construct it.
<<channel_operation>>:: Putting together the concepts of a simple payment channel and a routed payment using HTLCs, we will now look at how HTLCs are part of each channel's commitment transaction. We will also look at the protocol for adding, settling, failing and removing HTLCs from the commitments.
<<onion_routing>>:: Next, we will look at how the HTLC information is propagated across the network inside the onion routing protocol. We will look at the mechanism for layered encryption and decryption that gives the Lightning Network some of its privacy characteristics.
<<gossip>>:: In this chapter we will look at how Lightning nodes find each other and learn about published channels, in order to construct a channel graph that they can use to find paths across the network.
<<path_finding>>:: Next, we will see how the information from the gossip protocol is used by each node to build a "map" of the entire network, which it can use to find paths from one point to another to route payments. We'll also look at the exiting innovations in path finding such as multi-part payments.
<<payment_requests>>:: A key part of the Lightning Network are payment requests, also known as Lighting Invoices. In this chapter we dissect the structure and encoding of an invoice.
<<wire_protocol>>:: Underpinning the Lightning Network is the Peer-to-Peer protocol that nodes use to exchange messages about the network and about their channels. In this chapter we look at how those messages are constructed and the extension capabilities built into messages with feature bits and TLV encoding.
<<encrypted_transport>>:: Moving down to the lower-level part of the network, we will look at the underlying encrypted transport system that ensures the secrecy and integrity of all communications between nodes.
Let's dive in!

@ -106,7 +106,7 @@ So the full identifier for Rene's node would be:
[TIP]
====
The alias of Rene's node is +ln.rene-pickhardt.de+ however this name exists just for better readability every node operator can announce an alias at free will and actually there is no mechanism that prevents node operators to select an alias that is already being used. Thus in order to refer to a node one must use the +NodeID@Address:Port+ schema.
The alias of Rene's node is +ln.rene-pickhardt.de+ however this name exists just for better readability. Every node operator can announce whatever alias they want, and there is no mechanism that prevents node operators from selecting an alias that is already being used. Thus in order to refer to a node one must use the +NodeID@Address:Port+ schema.
====
The identifier above is often encoded in a QR code, making it easier for users to scan, if they want to connect their own node to the specific node identified by that address.
@ -157,7 +157,7 @@ Second, Alice constructs the funding and refund transactions (as we will see lat
The name of the +funding_signed+ message can be a bit confusing. This message does not contain a signature for the funding transaction but it rather contains Bob's signature for the refund transaction that allows Alice to claim her bitcoin back from the multisig.
====
Once the transaction has sufficient confirmations (as defined my the `minimum_depth` field in the `accept_channel` message), Alice and Bob exchange a +funding_locked+ messages and the channel enters normal operating mode.
Once the transaction has sufficient confirmations (as defined by the `minimum_depth` field in the `accept_channel` message), Alice and Bob exchange +funding_locked+ messages and the channel enters normal operating mode.
===== The open_channel message
@ -261,7 +261,7 @@ Alice's node constructs a multisignature script as shown in <<A_B_multisig>> bel
2 <Alice_funding_pubkey> <Bob_funding_pubkey> 2 CHECKMULTISIG
----
Note that in practice, the funding keys are deterministically _sorted_ (using lexicographical order of the serialized compressed form of the public keys) before being placed in the witness script (. By agreeing to this sorted order ahead of time, we ensure both parties will construct an identical funding transaction output, which is signed by the commitment transaction signature exchanged.
Note that in practice, the funding keys are deterministically _sorted_ (using lexicographical order of the serialized compressed form of the public keys) before being placed in the witness script. By agreeing to this sorted order ahead of time, we ensure both parties will construct an identical funding transaction output, which is signed by the commitment transaction signature exchanged.
This script is encoded as a Pay-to-Witness-Script-Hash Bitcoin address, that looks something like this:
@ -281,7 +281,7 @@ Alice *does not broadcast* this transaction, because doing so would put her 140,
.Dual-funded payment channels
****
In the current implementation of Lightning, channels are funded only by the node initiating the channel (Alice in our example). Dual-funded channels have been proposed, but not yet implemented. In a dual-funded channel, both Alice and Bob would contribute inputs to the funding transaction. Dual-funded channels require a slightly more complicated message flow and cryptographic protocol, so they have not been implemented yet but are planned for a future update to the Lightning BOLTS.
In the current implementation of Lightning, channels are funded only by the node initiating the channel (Alice in our example). Dual-funded channels have been proposed, but not yet implemented. In a dual-funded channel, both Alice and Bob would contribute inputs to the funding transaction. Dual-funded channels require a slightly more complicated message flow and cryptographic protocol, so they have not been implemented yet but are planned for a future update to the Lightning BOLTs. The C-Lightning implementation includes an experimental version of a variant on dual funded channels.
****
==== Holding signed transactions without broadcasting
@ -325,11 +325,11 @@ This means that Alice can create a chained transaction by referencing an output
==== Solving malleability (Segregated Witness)
Alice has to depend on the transaction ID of the funding transaction being known before confirmation. But before the introduction of Segregated Witness (a.k.a SegWit) in August 2017, this was not sufficient to protect Alice. Because of the way transactions were constructed with the signatures (witnesses) included in the transaction ID, it was possible for a third party (e.g. Bob) to broadcast an alternative version of a transaction with a malleated (modified) transaction ID. This is known as _Transaction Malleability_ and made it impossible to implement payment channels securely.
Alice has to depend on the transaction ID of the funding transaction being known before confirmation. But before the introduction of Segregated Witness (a.k.a SegWit) in August 2017, this was not sufficient to protect Alice. Because of the way transactions were constructed with the signatures (witnesses) included in the transaction ID, it was possible for a third party (e.g. Bob) to broadcast an alternative version of a transaction with a malleated (modified) transaction ID. This is known as _Transaction Malleability_ and made it difficult to implement indefinite lifetime payment channels securely.
If Bob could modify Alice's funding transaction before it was confirmed and produce a replica that had a different transaction ID, Bob could make Alice's refund transaction invalid and hijack her bitcoin. Alice would be at Bob's mercy to get a signature to release her funds and could easily be blackmailed. Bob couldn't steal the funds, but he could prevent Alice from getting them back.
The introduction of SegWit made unconfirmed transaction IDs immutable, meaning that Alice could be sure that the transaction ID of the funding transaction would not change. As a result, Alice can be confident that if she gets Bob's signature on the refund transaction, she has a way to recover her money. She now has a way to implement the Bitcoin equivalent of a "prenup" before locking her funds into the multisig.
The introduction of SegWit made unconfirmed transaction IDs immutable from the PoV of 3rd parties, meaning that Alice could be sure that the transaction ID of the funding transaction would not change. As a result, Alice can be confident that if she gets Bob's signature on the refund transaction, she has a way to recover her money. She now has a way to implement the Bitcoin equivalent of a "prenup" before locking her funds into the multisig.
[TIP]
====
@ -435,13 +435,13 @@ It is indeed! In fact, we rely on Bitcoin's ability to *prevent* a double spend
As long as Alice and Bob hold these transactions and don't broadcast them, the funding output is unspent. But if a commitment transaction is broadcast and confirmed, it will spend the funding output. If Alice or Bob attempt to broadcast more than one commitment transaction, only one of them will be confirmed and the others will be rejected as attempted (and failed) double-spends.
If more than one commitment transaction are broadcast, there are many factors that will determine which one gets confirmed first: the amount of fees included, the speed of propagation of these competing transactions, network topology, etc. Essentially it becomes a race without a predictable outcome. That doesn't sound very secure, it sounds like someone could cheat.
If more than one commitment transaction are broadcast, there are many factors that will determine which one gets confirmed first: the amount of fees included, the speed of propagation of these competing transactions, network topology, etc. Essentially it becomes a race without a predictable outcome. That doesn't sound very secure. It sounds like someone could cheat.
==== Cheating with old commitment transactions
Let's look more carefully at the commitment transactions in <<competing_commitments_1>>. All four commitment transactions are signed and valid. But only the last one accurately reflects the most recent channel balances. In this particular scenario, Alice has an opportunity to cheat, by broadcasting an older commitment and getting it confirmed on the Bitcoin blockchain. Let's say Alice transmits Commitment #0 and gets it confirmed: she will effectively close the channel and take all 140,000 satoshis herself. In fact, in this particular example any commitment but #3 improves Alice's position and allows her to "cancel" at least part of the payments reflected in the channel.
In the next section we will see how the Lightning Network resolves this problem - preventing older commitment transactions from being used by the channel partners by a mechanism of revocation and penalties. There are other ways to prevent the transmission of older commitment transactions but they require an upgrade to Bitcoin called _input rebinding_. We discuss this in more detail in <<eltoo>>.
In the next section we will see how the Lightning Network resolves this problem - preventing older commitment transactions from being used by the channel partners by a mechanism of revocation and penalties. There are other ways to prevent the transmission of older commitment transactions, such as _eltoo channels_ but they require an upgrade to Bitcoin called _input rebinding_.
==== Revoking old commitment transactions
@ -535,7 +535,26 @@ OP_ENDIF
OP_CHECKSIG
----
This is a conditional script (see <<conditional_scripts>>), which means the output can be spent if _either_ of the two conditions is met. The first clause allows the output to be spent by anyone who can sign for +<revocationpubkey>+. The second clause is timelocked by +<to_self_delay>+ blocks and can only be spent after that many blocks by anyone who can sign for +<local_delayedpubkey>+. In our example, we had set the +<to_self_delay>+ timelock to 432 blocks, but this is a configurable delay that is negotiated by the two channel partners. The +to_self_delay+ timelock duration is usually chose in proportion to the channel capacity, meaning that larger capacity channels (more funds), have longer +to_self_delay+ timelocks to protect the parties.
This is a conditional script (see <<conditional_scripts>>), which means the output can be spent if _either_ of the two conditions is met. The first clause allows the output to be spent by anyone who can sign for +<revocationpubkey>+. The second clause is timelocked by +<to_self_delay>+ blocks and can only be spent after that many blocks by anyone who can sign for +<local_delayedpubkey>+. In our example, we had set the +<to_self_delay>+ timelock to 432 blocks, but this is a configurable delay that is negotiated by the two channel partners. The +to_self_delay+ timelock duration is usually chosen in proportion to the channel capacity, meaning that larger capacity channels (more funds), have longer +to_self_delay+ timelocks to protect the parties.
The first clause allows the output to be spent by anyone who can sign for +<revocationpubkey>+. A critical requirement to the security of this script is that the remote party *cannot* unilaterally sign with the `revocationpubkey`. To see why this is important, consider the scenario where the remote party breaches a previously revoked commitment, if they can sign with this key, then they can simply take the revocation clause _themselves_ and steal all the funds in the channel. Instead, we derive the `revocationpubkey` for _each_ state based on information from _both_ the self (local) and remote party. A clever use of symmetric and asymmetric cryptography is used to allow both sides to compute the `revocationpubkey` public key, but only the honest self party to compute the private key given their secret information.
[TIP]
====
As shown above, each side sends a `revocation_basepoint` during the initial channel negotiation messages as well as a `first_per_commitment_point`. The `revocation_basepoint` is static for the lifetime of the channel, while each new channel state will be based off a new `first_per_commitment_point`.
Given this information, the `revocationpubkey` for each channel state is derived via the following series of Elliptic Curve and hashing operations: `revocationpubkey = revocation_basepoint * sha256(revocation_basepoint || per_commitment_point) + per_commitment_point * sha256(per_commitment_point || revocation_basepoint)`.
Due to the commutative property of the Abelian groups that Elliptic Curves are defined over, once the `per_commitment_secret` (the private key for the `per_commitment_point`) is revealed by the remote party, self can derive the private key for the `revocationpubkey` with the following operation: `per_commitment_secret = (revocationbase_priv * sha256(revocationpubkey || per_commitment_point)) + (per_commitment_secret * sha256(per_commitment_point || revocation_basepoint)) mod N`.
To see why this works in practice, notice that we can _re order_ (commute) and expand the public key computation of the original formula for `revocation_basepoint`:
```
revocation_priv = G*(revocationbase_priv * sha256(revocation_basepoint || per_commitment_point) + G*(per_commitment_secret * sha256(per_commitment_point || revocation_basepoint))
= G*(revocationbase_priv + sha256(revocation_basepoint || per_commitment_point) + per_commitment_point * sha256(per_commitment_point || revocation_basepoint))
```
In other words, the `revocationbase_priv` can only be derived (and used to sign for the `revocationpubkey` by the party that knows _both_ the `revocationbase_priv` _and_ the `per_commitment_secret`. This little trick is what makes the public-key based revocation system used in the Lightning Network secure.
====
[TIP]
====
@ -617,7 +636,8 @@ Once Alice has received the +revoke_and_ack+ from Bob she can be sure that Bob c
In practice, both Alice and Bob have to monitor for "cheating". They are monitoring the Bitcoin blockchain for any commitment transactions related to any of the channels they are operating. If they see a commitment transaction confirmed on-chain they will check to see if it is the most recent commitment. If it is an "old" commitment, they must immediately construct and broadcast a penalty transaction. The penalty transaction spends *both* the +to_local+ and +to_remote+ outputs, closing the channel and sending both balances to the "cheated" channel partner.
In order to more easily allow both sides to keep track of the commitment numbers of the passed revoke commitments, each commitment actually _encodes_ the number of the commitment within the lock time and sequence fields in a transition. Within the protocol, this special encoding are referred to as "state hints". Assuming a party knows the current commitment number, they're able to use the state hints to easily recognize if a broadcasted commitment was a revoked one, and if so, which commitment number was breached, as that number is used to easily look up which revocation secret should be used in the revocation secret tree (shachain).
[[revocation_secret_derivation]]
In order to more easily allow both sides to keep track of the commitment numbers of the passed revoke commitments, each commitment actually _encodes_ the number of the commitment within the lock time and sequence fields in a transition. Within the protocol, this special encoding is referred to as "state hints". Assuming a party knows the current commitment number, they're able to use the state hints to easily recognize if a broadcasted commitment was a revoked one, and if so, which commitment number was breached, as that number is used to easily look up which revocation secret should be used in the revocation secret tree (shachain).
Rather than encode the state hint in plain sight, an _obfuscated_ state hint is used in its place. This obfuscation is achieved by first XOR'ing the current commitment number with a set of random bytes generated deterministically using the funding public keys of both sides of the channel. A total of 6 bytes across the lock time and sequence (24 bits of the locktime and 24 bits of the sequence) are used to encode the state hint within the commitment transaction, so 6 random bytes are needed to use for XOR'ing. To obtain these 6 bytes, both sides obtain the SHA-256 hash of the initiator's funding key concatenated to the responder's funding key. Before encoding the current commitment height, the integer is XOR'd with this state hint obfuscater, and then encoded in the lower 24 bits of the locktime, and the upper 64 bits of the sequence.

@ -1,4 +1,6 @@
[[routing_on_a_network_of_payment_channels]]
[[routing]]
[[routing_htlcs]]
== Routing on a Network of Payment channels
In this chapter we will finally unpack how payment channels can be connected to form a _network of payment channels_ via a process called _routing_. Specifically, we will look at the first part of the routing layer, the Atomic & Trustless Multihop Payment protocol. This is highlighted by a double outline in the protocol suite, shown in <<LN_protocol_routing_highlight>>:
@ -51,7 +53,7 @@ Let's return to Alice who, in previous chapters, purchased a coffee from Bob wit
Now Alice is watching a live stream from Dina, the gamer, and wants to send Dina a tip of 50,000 satoshis via the Lightning Network. But Alice has no direct channel with Dina. What can Alice do?
Alice could open a direct channel with Dina, however that would require liquidity and on-chain fees which could be more than the value of the tip itself. Instead, Alice can use her existing open channels to send a tip to Dina _without_ the need to open a channel directly with Dina. This is possible, as long as there exists some path of channels from Alice to Dina with sufficient capacity to route the tip.
As you can see in <<routing_network>>, Alice has an open channel with Bob, the coffee shop owner. Bob, in turn, has an open channel with the software developer Chan who helps him with the point of sale system he uses in his coffee shop. Chan is also the owner of a large software company which develops the game that Dina plays, and they already have an open channel which Dina uses to pay for the game's license and in-game items.
[[routing_network]]
@ -200,7 +202,7 @@ With a chain of contracts like this in place, Bob and Chan could not run away wi
However, one issue still remains.
If Dina refused to release her secret pre-image, then Chan, Bob, and Alice would all have their coins stuck in escrow but wouldn't be reimbursed.
And similarly if anyone else along the chain failed to pass on the secret, the same thing would happen.
So while no one can steal money from Alice everyone still have their money stuck in escrow permanently.
So while no one can steal money from Alice, everyone would still have their money stuck in escrow permanently.
Luckily, this can be resolved by adding a deadline to the contract.
@ -267,21 +269,21 @@ Atomicity:: The payment is fully executed, or it fails and everyone is refunded.
Multihop:: The security of the system extends end-to-end for payments routed through multiple payment channels, just as it is for a payment between the two ends of a single payment channel.
An optional, additional property, is the ability to split payments into multiple parts while maintaining atomicity for the entire payment. These are called _Multi-Part Payments (MPP)_ and are explored further in <<multipart_payments>>.
An optional, additional property, is the ability to split payments into multiple parts while maintaining atomicity for the entire payment. These are called _Multi-Part Payments (MPP)_ and are explored further in <<mpp>>.
==== Implementing Atomic Trustless Multihop Payments
Bitcoin Script is flexible enough that there are dozens of ways to implement a fairness protocol that has the properties of atomicity, trustless operation and multihop security. Choosing a specific implementation is dependent on certain tradeoffs between privacy, efficiency and complexity.
The fairness protocol for routing used in the Lightning Network today is called a Hash Time-Locked Contract (HTLC). HTLCs use a hash pre-image as the secret that unlocks a payment, as we saw in the gold coin example in this chapter. The recipient of a payment generates a random secret number and calculates its hash. The hash becomes the condition of payment and once the secret is revealed, all the participants can redeem their incoming payments. HTLCs offer atomicity, trustless operation and multihop security. While HTLCs are efficient and very simple, they involve a small compromise of privacy (see <<htlc_privacy_compromise>>).
The fairness protocol for routing used in the Lightning Network today is called a Hash Time-Locked Contract (HTLC). HTLCs use a hash pre-image as the secret that unlocks a payment, as we saw in the gold coin example in this chapter. The recipient of a payment generates a random secret number and calculates its hash. The hash becomes the condition of payment and once the secret is revealed, all the participants can redeem their incoming payments. HTLCs offer atomicity, trustless operation and multihop security.
Another proposed mechanism for implementing routing is a _Point Time-Locked Contract (PTLC)_. PTLCs also achieve atomicity, trustless operation and multihop security, but do so with increased efficiency and better privacy. Efficient implementation of PTLCs depends on a new digital signature algorithm called _Schnorr signatures_, which is expected to active in Bitcoin in 2021.
Another proposed mechanism for implementing routing is a _Point Time-Locked Contract (PTLC)_. PTLCs also achieve atomicity, trustless operation and multihop security, but do so with increased efficiency and better privacy. Efficient implementation of PTLCs depends on a new digital signature algorithm called _Schnorr signatures_, which is expected to be activated in Bitcoin in 2021.
=== Revisiting our example
Let's revisit our example from the first part of this chapter. Alice wants to "tip" Dina, with a Lightning payment. Let's say Alice wants to send Dina 50,000 satoshis as a tip.
For Alice to pay Dina, Alice will need Dina's node to generate a Lightning invoice. We will discuss this in more detail in <<bolt11_invoices>>. For now, let's assume that Dina has a website that can produce a Lightning invoice for tips.
For Alice to pay Dina, Alice will need Dina's node to generate a Lightning invoice. We will discuss this in more detail in <<invoices>>. For now, let's assume that Dina has a website that can produce a Lightning invoice for tips.
[TIP]
====
@ -312,6 +314,7 @@ The mere fact that any transaction can be taken on-chain at any time is precisel
In all the examples that follow, we will assume that any of these transactions can be made on-chain at any time. The participants will choose to keep them off-chain, but there is no difference in the functionality of the system other than the higher fees and delay imposed by on-chain mining of the transactions. The example works the same if all the transactions are on-chain or off-chain.
[[htlcs]]
=== Hash Time Locked Contracts (HTLCs)
In this section we explain how Hash Time Locked Contracts (HTLCs) work.
@ -409,9 +412,9 @@ The unlocking script combined with the locking script would produce:
The Bitcoin Script engine would evaluate this script as follows:
1. +R+ is pushed to the stack
1. The OP_SHA256 operator takes the value +R+ off the stack and hashes it, pushing the result H~R~ to the stack
1. +H+ is pushed to the stack
1. The OP_EQUAL operator compares +H+ and H~R~. If they are equal, the result is +TRUE+, the script is complete and the payment is verified.
2. The OP_SHA256 operator takes the value +R+ off the stack and hashes it, pushing the result H~R~ to the stack
3. +H+ is pushed to the stack
4. The OP_EQUAL operator compares +H+ and H~R~. If they are equal, the result is +TRUE+, the script is complete and the payment is verified.
==== Extending HTLCs from Alice to Dina
@ -502,12 +505,12 @@ The unlocking and locking script are combined and evaluated by the scripting eng
----
1. +<Bob's Sig>+ is pushed on to the stack
1. +R+ is pushed on to the stack
1. OP_SHA256 pops and hashes +R+ from the top of the stack and pushes H~R~ on to the stack
1. +H+ is pushed on to the stack
1. OP_EQUALVERIFY pops H and H~R~ and compares them. If they are not the same, execution halts. Otherwise, we continue without output to the stack
1. +<Bob's Pub> key is pushed to the stack
1. OP_CHECKSIG pops +<Bob's Sig>+ and +<Bob's Pub>+ and verifies the signature. The result (TRUE/FALSE) is pushed to the stack.
2. +R+ is pushed on to the stack
3. OP_SHA256 pops and hashes +R+ from the top of the stack and pushes H~R~ on to the stack
4. +H+ is pushed on to the stack
5. OP_EQUALVERIFY pops H and H~R~ and compares them. If they are not the same, execution halts. Otherwise, we continue without output to the stack
6. +<Bob's Pub>+ key is pushed to the stack
7. OP_CHECKSIG pops +<Bob's Sig>+ and +<Bob's Pub>+ and verifies the signature. The result (TRUE/FALSE) is pushed to the stack.
As you can see, this is slightly more complicated, but now we have fixed the HTLC and made sure only the intended recipient can spend it.

@ -43,8 +43,8 @@ Alice and Bob start with a payment channel that has 70,000 satoshi balance on ea
As we saw in <<payment_channels>> this means that Alice and Bob have negotiated and each hold commitment transactions. These commitment transactions are asymmetric, delayed and revocable, and look like the example in <<alice_bob_commitment_txs_1>> below:
[[alice_bob_commitment_txs_1]]
.Alice and Bob's initial commitment transactions:
image:images/alice_bob_commitment_txs_1.png[]
.Alice and Bob's initial commitment transactions
image::images/alice_bob_commitment_txs_1.png["Alice and Bob's initial commitment transactions"]
==== Adding an HTLC
@ -55,10 +55,11 @@ To add the HTLC, Alice starts the flow we saw in <<HTLC_commitment_message_flow>
[[update_add_htlc]]
==== The +update_add_htlc+ message
Alice sends the `update_add_HTLC` Lightning message to Bob. This message is defined in https://github.com/lightningnetwork/lightning-rfc/blob/master/02-peer-protocol.md#adding-an-htlc-update_add_htlc[BOLT #2 - Peer Protocol - update_add_HTLC], and is shown in <<update_add_HTLC_message_fields>> below:
Alice sends the `update_add_HTLC` Lightning message to Bob. This message is defined in https://github.com/lightningnetwork/lightning-rfc/blob/master/02-peer-protocol.md#adding-an-htlc-update_add_htlc[BOLT #2 - Peer Protocol - update_add_HTLC], and is shown below:
[[update_add_HTLC_message_fields]]
.The update_add_HTLC message
====
----
[channel_id:channel_id]
[u64:id]
@ -67,6 +68,7 @@ Alice sends the `update_add_HTLC` Lightning message to Bob. This message is defi
[u32:cltv_expiry]
[1366*byte:onion_routing_packet]
----
====
+channel_id+:: This is the channel that Alice has with Bob that she wants to add the HTLC. Remember that Alice and Bob may have multiple channels with each other.
@ -91,34 +93,34 @@ The received information is enough for Bob to create a new commitment transactio
We've already seen the basic structure of an HTLC in <<routing>>. The complete script of an offered HTLC is defined in https://github.com/lightningnetwork/lightning-rfc/blob/master/03-transactions.md#offered-htlc-outputs[BOLT #3 - Transactions - Offered HTLC output] and is shown in <<offered_htlc_output_script>> below:
[source,linenum]
[[offered_htlc_output_script]]
.Offered HTLC output script:
====
----
# Revocation
# Revocation <1>
OP_DUP OP_HASH160 <RIPEMD160(SHA256(revocationpubkey))> OP_EQUAL
OP_IF
OP_CHECKSIG
OP_ELSE
<remote_HTLCpubkey> OP_SWAP OP_SIZE 32 OP_EQUAL
OP_IF
# Redemption
# Redemption <2>
OP_HASH160 <RIPEMD160(payment_hash)> OP_EQUALVERIFY
2 OP_SWAP <local_HTLCpubkey> 2 OP_CHECKMULTISIG
OP_ELSE
# Refund
# Refund <3>
OP_DROP <cltv_expiry> OP_CHECKLOCKTIMEVERIFY OP_DROP
OP_CHECKSIG
OP_ENDIF
OP_ENDIF
----
<1> The first clause of the OP_IF conditional is redeemable by Alice with a revocation key. If this commitment is later revoked, Alice will have a revocation key to claim this output in a penalty transaction, taking the whole channel balance.
<2> The second clause is redeemable by the pre-image (payment secret or in our example Dina's secret) if it is revealed. This allows Bob to claim this output if he has the secret from Dina, meaning he has successfully delivered the payment to Dina.
<3> The third and final clause is a refund of the HTLC to Alice, if the HTLC expires without reaching Dina. It is timelocked with the expiration +cltv_expiry+. This ensures that Alice's balance is not "stuck" in an HTLC that can't be routed to Dina.
====
There are three ways to claim this output. Try to read the script and see if you can figure it out (remember, it is a stack-based language so things appear "backwards"). In the order they appear in the script, these are:
revocation:: The first clause of the OP_IF conditional is redeemable by Alice with a revocation key. If this commitment is later revoked, Alice will have a revocation key to claim this output in a penalty transaction, taking the whole channel balance.
redemption:: The second clause is redeemable by the pre-image (payment secret or in our example Dina's secret) if it is revealed. This allows Bob to claim this output if he has the secret from Dina, meaning he has successfully delivered the payment to Dina.
refund:: The third and final clause is a refund of the HTLC to Alice, if the HTLC expires without reaching Dina. It is timelocked with the expiration +cltv_expiry+. This ensures that Alice's balance is not "stuck" in an HTLC that can't be routed to Dina.
There are three ways to claim this output. Try to read the script and see if you can figure it out (remember, it is a stack-based language so things appear "backwards").
==== New commitment with HTLC output
@ -134,14 +136,16 @@ Shortly after sending the +update_add_htlc+ message, she will commit to the new
Alice sends +commitment_signed+ to Bob, with the signature for the new commitment and for the HTLC within. We saw the +commitment_signed+ message in <<payment_channels>>, but now we can understand the rest of the fields. As a reminder, it is shown in <<commitment_signed_message>> below:
[[commitment_signed_message]]
[[ops_commitment_signed_message]]
.The commitment_signed message
====
----
[channel_id:channel_id]
[signature:signature]
[u16:num_htlcs]
[num_htlcs*signature:htlc_signature]
----
====
The fields +num_htlcs+ and +htlc_signature+ now make more sense:
@ -151,7 +155,7 @@ The fields +num_htlcs+ and +htlc_signature+ now make more sense:
Alice can send these signatures without hesitation: she can always get a refund if the HTLC expires without being routed to Dina.
Now, Bob has a new signed commitment transaction, as show in <<signed_commitment_3b>> below:
Now, Bob has a new signed commitment transaction, as shown in <<signed_commitment_3b>> below:
[[signed_commitment_3b]]
.Bob has a new signed commitment
@ -163,11 +167,13 @@ Now that Bob has a new signed commitment, he needs to acknowledge it and revoke
[[revoke_and_ack_message_2]]
.The +revoke_and_ack+ message
====
----
[channel_id:channel_id]
[32*byte:per_commitment_secret]
[point:next_per_commitment_point]
----
====
Bob sends the +per_commitment_secret+ that allows Alice to construct a revocation key to build a penalty transaction spending Bob's old commitment. Once Bob has sent this, he cannot ever publish "Commitment #2" without risking a penalty transaction and losing all his money. So, the old commitment is effectively revoked.
@ -215,11 +221,11 @@ image::images/revoked_commitment_2a.png[Alice has revoked the old commitment]
=== Multiple HTLCs
At any point in time, Alice and Bob may have dozens or even hundreds of HTLCs across a single channel. Each HTLC would be a offered and added to the commitment transaction as an additional output. A commitment transaction would therefore always have 2 outputs for the channel partner balances and any number of HTLC outputs, one per HTLC.
At any point in time, Alice and Bob may have dozens or even hundreds of HTLCs across a single channel. Each HTLC is offered and added to the commitment transaction as an additional output. A commitment transaction therefore always has 2 outputs for the channel partner balances and any number of HTLC outputs, one per HTLC.
As we saw in the +commitment_signed+ message, there is an array for HTLC signatures, meaning that multiple HTLCs can be committed to at the same time.
As we saw in the +commitment_signed+ message, there is an array for HTLC signatures so that multiple HTLC commitments can be transmitted at the same time.
The current maximum number of HTLCs allowed on a channel is 483 HTLCs, to account for the maximum Bitcoin transaction size and ensure that the commitment transactions would continue to be valid Bitcoin transaction.
The current maximum number of HTLCs allowed on a channel is 483 HTLCs to account for the maximum Bitcoin transaction size and ensure that the commitment transactions continue to be valid Bitcoin transactions.
As we will see in the next section, the maximum is only for _pending_ HTLCs, since once an HTLC is fulfilled (or fails due to timeout/error), it is removed from the commitment transaction.
@ -227,7 +233,7 @@ As we will see in the next section, the maximum is only for _pending_ HTLCs, sin
Now Bob and Alice both have a new commitment transaction with an additional HTLC output and we have achieved a major step towards updating a payment channel.
The new Balance of Alice and Bob does not reflect yet that Alice has successfully send 50,200 satoshis to Bob.
The new balance of Alice and Bob does not reflect yet that Alice has successfully sent 50,200 satoshis to Bob.
However the HTLCs are now set up in a way that secure settlement in exchange for the proof of payment will be possible.
@ -265,7 +271,7 @@ H = RIPEMD160( SHA256 (R) )
If the result +H+ matches the payment hash in the HTLC, Chan can do a little dance of celebration. This long-awaited secret can be used to redeem the HTLC, and will be passed back along the chain of payment channels all the way to Alice, resolving every HTLC that was part of this payment to Dina.
Let's go back to Alice and Bob's channel and watch them unwind the HTLC. To get there, let's assume Dina sent the +update_fulfill_htlc+ to Chan, Chan sent +update_fulfill_htlc+ to Bob and Bob sent ++update_fulfill_htlc+. The payment pre-image has propagated all the way back to Alice.
Let's go back to Alice and Bob's channel and watch them unwind the HTLC. To get there, let's assume Dina sent the +update_fulfill_htlc+ to Chan, Chan sent +update_fulfill_htlc+ to Bob and Bob sent +update_fulfill_htlc+ to Alice. The payment pre-image has propagated all the way back to Alice.
==== Bob settles the HTLC with Alice
@ -326,7 +332,7 @@ At this point, you will easily understand why HTLCs are used for both "remote" a
* Alice orders a coffee from Bob's shop page.
* Bob's shop sends an invoice with a payment hash.
* Alice constructs and HTLC from that payment hash.
* Alice constructs an HTLC from that payment hash.
* Alice offers the HTLC to Bob with +update_add_htlc+.
* Alice and Bob exchange commitments and revocations adding the HTLC to their commitment transactions.
* Bob sends +update_fulfill_htlc+ to Alice with the payment pre-image.

@ -25,7 +25,7 @@ Let's say Alice wants to send a secret letter to Dina, indirectly via some inter
==== Selecting a path
The Lightning Network uses _source routing_, which means that the payment path is selected and specified by the sender, and only the sender. In this example, our Alice's secret letter to Dina will be the equivalent of a payment. To make sure the letter reaches Dina, Alice will create a path from her to Dina, using Bob and Chan as intermediaries.
The Lightning Network uses _source routing_, which means that the payment path is selected and specified by the sender, and only the sender. In this example, Alice's secret letter to Dina will be the equivalent of a payment. To make sure the letter reaches Dina, Alice will create a path from her to Dina, using Bob and Chan as intermediaries.
[TIP]
====
@ -35,6 +35,7 @@ There may be many paths that make it possible for Alice to reach Dina. We will e
As a reminder, the path selected by Alice is shown in <<alice_dina_path>>, below:
[[alice_dina_path]]
.Path: Alice to Bob to Chan to Dina
image::images/alice_dina_path.png["Alice to Bob to Chan to Dina"]
Let's see how Alice can use this path without revealing information to intermediaries Bob and Chan.
@ -110,13 +111,13 @@ From <<routing>> we know that Alice will send a 50,000 satoshi payment to Dina v
.Payment path with HTLCs from Alice to Dina
image::images/alice-dina-htlc.png[Payment path with HTLCs from Alice to Dina]
As we see in <<gossip>>, Alice is able to construct this path to Dina because Lightning nodes announce their channels to the entire Lightning Network using the _Lightning Gossip Protocol_. After the initial channel announcement, Bob and Chan each sent out an additional "channel update" message with their routing fee and timelock expectations for payment routing.
As we will see in <<gossip>>, Alice is able to construct this path to Dina because Lightning nodes announce their channels to the entire Lightning Network using the _Lightning Gossip Protocol_. After the initial channel announcement, Bob and Chan each sent out an additional "channel update" message with their routing fee and timelock expectations for payment routing.
From the announcements and updates, Alice knows the following information about the channels between Bob, Chan and Dina:
* A +short_channel_id+ (short channel ID) for each channel, that Alice can use to reference the channel, when constructing the path
* An +cltv_expiry_delta+ (timelock delta) which Alice can add to the expiry time for each HTLC
* A +cltv_expiry_delta+ (timelock delta) which Alice can add to the expiry time for each HTLC
* A +fee_base_msat+ and +fee_proportional_millionths+ which Alice can use to calculate the total routing fee expected by that node for relay on that channel.
@ -132,21 +133,26 @@ Alice already knows her own channel to Bob, and therefore doesn't need this info
==== Alice constructs the payloads
There are two possible formats that Alice can use for the information communicated to each hop: A legacy fixed-length format called the _hop data_ and a more flexible Type-Length-Value (TLV) based format called the _hop payload_. The TLV message format is explained in more detail in <<tlv>>. It offers flexibility by allowing fields to be added to the protocol at will. Both formats are specified in https://github.com/lightningnetwork/lightning-rfc/blob/master/04-onion-routing.md#packet-structure[BOLT #4 - Onion Routing - Packet Structure]
There are two possible formats that Alice can use for the information communicated to each hop: A legacy fixed-length format called the _hop data_ and a more flexible Type-Length-Value (TLV) based format called the _hop payload_. The TLV message format is explained in more detail in <<tlv>>. It offers flexibility by allowing fields to be added to the protocol at will.
[NOTE]
====
Both formats are specified in https://github.com/lightningnetwork/lightning-rfc/blob/master/04-onion-routing.md#packet-structure[BOLT #4 - Onion Routing - Packet Structure.]
====
Alice will start building the hop data from the end of the path backwards: Dina, Chan, Bob.
===== Final node payload for Dina
Alice first builds the payload that will be delivered to Dina. Dina will not be constructing an "outgoing HTLC", because Dina is the final node and payment recipient. For this reason, the payload for Dina is different that all the others (uses all zeros for the `short_channel_id`), but only Dina will know this since it will be encrypted in the innermost layer of the onion. Essentially, this is the "secret letter to Dina" we saw in our physical envelope example.
Alice first builds the payload that will be delivered to Dina. Dina will not be constructing an "outgoing HTLC", because Dina is the final node and payment recipient. For this reason, the payload for Dina is different than all the others (uses all zeros for the `short_channel_id`), but only Dina will know this since it will be encrypted in the innermost layer of the onion. Essentially, this is the "secret letter to Dina" we saw in our physical envelope example.
The hop payload for Dina must match the information in the invoice generated by Dina for Alice and will contain (at least) the following fields in Type-Lenth-Value (TLV) format:
The hop payload for Dina must match the information in the invoice generated by Dina for Alice and will contain (at least) the following fields in Type-Length-Value (TLV) format:
amt_to_forward:: The amount of this payment in milli-satoshis. If this is only one part of a multi-part payment, the amount is less than the total. Otherwise, this is a single full payment and it is equal to the invoice amount and +total_msat+ value.
outgoing_cltv_value:: The payment expiry timelock set to the value +min_final_cltv_expiry+ in the invoice.
payment_secret:: A special 256-bit secret value from the invoice, allowing Dina to recognize this incoming payment, and also prevents a class of probing that previously made 0-value invoices insecure. Probing by intermediate nodes is mitigated, as this value is encrypted to _only_ the recipient, meaning they can't reconstruct a final packet that "looks" legitimate.
payment_secret:: A special 256-bit secret value from the invoice, allowing Dina to recognize this incoming payment. This also prevents a class of probing that previously made 0-value invoices insecure. Probing by intermediate nodes is mitigated as this value is encrypted to _only_ the recipient, meaning they can't reconstruct a final packet that "looks" legitimate.
total_msat:: The total amount matching the invoice. This may be omitted if there is only one part, in which case it is assumed to match +amt_to_forward+ and must equal the invoice amount.
@ -222,7 +228,7 @@ image::images/onion_hop_payloads.png[Hop payloads for all the hops]
Alice must now generate several keys that will be used to encrypt the various layers in the onion.
Remember the goals of onion routing, that Alice can achieve with these keys:
With these keys, Alice can achieve a high degree of privacy and integrity:
* Alice can encrypt each layer of the onion so that only the intended recipient can read it.
* Every intermediary can check that the message is not modified.
@ -232,7 +238,7 @@ Remember the goals of onion routing, that Alice can achieve with these keys:
[WARNING]
====
Like a chopped onion, the following technical details may bring tears to your eyes. Feel free to skip to the next section if you get confused. Come back to this and read BOLT #4 if you want to learn more.
Like a chopped onion, the following technical details may bring tears to your eyes. Feel free to skip to the next section if you get confused. Come back to this and read https://github.com/lightningnetwork/lightning-rfc/blob/master/04-onion-routing.md#packet-construction[BOLT #4 - Onion Routing - Packet Construction], if you want to learn more.
====
@ -278,58 +284,80 @@ One important detail that seems almost magical is the ability for Alice to creat
// To editor: Maybe put this in an appendix instead of a sidebar?
[[ecdh]]
[[ecdh_explained]]
.Elliptic Curve Diffie-Hellman (ECDH) explained
****
Assume Alice's private key is +a+ and Bob's private key is +b+. Using the Elliptic Curve, they multiply each private key by the generator point +G+ to produce their public keys +A+ and +B+ respectively:
Assume Alice's private key is +a+ and Bob's private key is +b+. Using the Elliptic Curve, Alice and Bob each multiply their private key by the generator point +G+ to produce their public keys +A+ and +B+ respectively:
A = aG
B = bG
Now Alice and Bob can create a shared secret +ss+, a value that they can both calculate independently without exchanging any information, such that
Now Alice and Bob can use _Elliptic Curve Diffie-Hellman Key Exchange_ to create a shared secret +ss+, a value that they can both calculate independently without exchanging any information
The shared secret +ss+ is calculated by each by multiplying their own private key with the *other's* public key, such that:
ss = aB = bA
But why would these two multiplications result in the same value +ss+?
Follow along, as we demonstrate the math that proves this is possible:
ss
= aB
calculated by Alice who knows both +a+ and +B+
calculated by Alice who knows both +a+ (her private key) and +B+ (Bob's public key)
= a(bG)
because we know
because we know that B = bG, we substitute
= (ab)G
because of associativity
because of associativity, we can move the parentheses
= (ba)G
because the curve is an abelian group
because xy = yx (the curve is an abelian group)
= b(aG)
because of associativity
because of associativity, we can move the parentheses
= bA
can be calculated by Bob who knows +b+ and +A+
because A = aG, we can substitute
The result bA can be calculated independently by Bob who knows +b+ (his private key) and +A+ (Alice's public key).
We have therefore shown that
ss = aB = bA
ss = aB (Alice can calculate this)
ss = bA (Bob can calculate this)
Alice can multiple her private key with Bob's public key to calculate +ss+
Thus, they can each independently calculate +ss+ which they can use as a shared key to symmetrically encrypt secrets between the two of them without communicating the shared secret.
Bob can multiply his private key with Alice's public key to calculate +ss+
****
Thus, they will both get the same result which they can use as a shared key to symmetrically encrypt secrets between the two of them without communicating the shared secret.
A unique trait of Sphinx as a mix-net packet format is that rather than include a distinct session key for each hop in the route, which would increase the size of the mix-net packet dramatically, clever _blinding_ scheme is used deterministically randomize the session key at each hop.
In practice, this little trick allows us to keep the onion packet as compact as possible while still retaining the desired security properties.
The session key for hop `i` is derived using the node public key, and derived shared secret of hop `i-1`:
```
session_key_i = session_key_{i-1} * SHA256(node_pubkey_{i-1} || shared_secret_{i-1})
```
In other words, we take the session key of the prior hop, and multiply it by a value derived from the public key and derived shared secret for that hop.
As EC multiplication can be performed on a public key without knowledge of the private key, each hop is able to re-randomize the session key for the next hop in a deterministic fashion.
The creator of the onion packet knows all the shared secrets (as they're encrypted the packet uniquely for each hop), and thus are able to derive all the blinding factors.
This knowledge allows them to derive all the session keys used up front during packet generation.
Note that the very first hop uses the original session key generated, as this key is used to kick off the session key blinding by each subsequent hop.
****
[[wrapping_the_onion]]
=== Wrapping the onion layers
@ -368,11 +396,10 @@ image::images/onion_packet.png[]
* 1300 bytes: The actual _onion payload_ containing the instructions for each hop
* 32 bytes: An HMAC integrity checksum
A unique trait of Sphinx as a mix-net packet format is that rather than include a distinct session key for each hop in the route, which would increase the size of the mix-net packet dramatically, instead a clever _blinding_ scheme is used deterministically randomize the session key at each hop.
A unique trait of Sphinx as a mix-net packet format is that rather than include a distinct session key for each hop in the route, which would increase the size of the mix-net packet dramatically, instead a clever _blinding_ scheme is used to deterministically randomize the session key at each hop.
In practice, this little trick allows us to keep the onion packet as compact as possible while still retaining the desired security properties.
==== Wrapping the onion (outlined)
Here is the process of wrapping the onion, outlined below. Come back to this list, as we explore each step with our real-world example.
@ -381,25 +408,27 @@ For each hop the sender (Alice) repeats the same process:
1. Alice generates the per-hop shared secret and the rho, mu, and pad keys
1. Alice generates 1300 bytes of filler and fills the 1300-byte onion payload field with this filler.
2. Alice generates 1300 bytes of filler and fills the 1300-byte onion payload field with this filler.
1. Alice calculates the HMAC for the hop payload (zeros for the final hop).
3. Alice calculates the HMAC for the hop payload (zeros for the final hop).
1. Alice calculates the length of the hop payload + HMAC + space to store the length itself
4. Alice calculates the length of the hop payload + HMAC + space to store the length itself
1. Alice _right shifts_ the onion payload by the calculated space needed to fit the hop payload. The rightmost "filler" data is discarded, making enough space on the left for the payload.
5. Alice _right shifts_ the onion payload by the calculated space needed to fit the hop payload. The rightmost "filler" data is discarded, making enough space on the left for the payload.
1. Alice inserts the length + hop payload + HMAC at the front of the payload field in the space made from shifting the filler.
6. Alice inserts the length + hop payload + HMAC at the front of the payload field in the space made from shifting the filler.
1. Alice uses the _rho_ key to generate a 1300 byte one-time-pad.
7. Alice uses the _rho_ key to generate a 1300 byte one-time-pad.
1. Alice obfuscates the entire onion payload by XOR-ing with the bytes generated from rho.
8. Alice obfuscates the entire onion payload by XOR-ing with the bytes generated from rho.
1. Alice calculates the HMAC of the onion payload, using the mu key.
9. Alice calculates the HMAC of the onion payload, using the mu key.
1. Alice adds the session public key (so that the hop can calculate the shared secret)
10. Alice adds the session public key (so that the hop can calculate the shared secret)
1. Alice adds the version number.
11. Alice adds the version number.
12. Deterministically re-blinds the session key using a value derived by hashing the shared secret and prior hop's public key.
Next, Alice repeats the process. The new keys are calculated, the onion payload is shifted (dropping more junk), the new hop payload is added to the front and the whole onion payload encrypted with the rho byte-stream for the next hop.
@ -479,14 +508,14 @@ If a secret key is ever used again, then the node can detect it, and reject the
The nature of HTLCs in the Lightning Network allows us to further strengthen the replay protection by adding an additional _economic_ incentive.
Remember that the payment hash of an HTLC can only ever safely be used (for a complete payment) once.
If a payment hash is used again, and traverses a node that has already seen the payment secret fo that hash, then they can simply pull the funds, and collect the entire payment amount without forwarding!
If a payment hash is used again, and traverses a node that has already seen the payment secret for that hash, then they can simply pull the funds, and collect the entire payment amount without forwarding!
We can use this fact to strengthen the replay protection by requiring that the _payment hash_ is included in our HMAC computation as the associated data.
With this added step, attempting to replay an onion packet also requires the sender to commit to using the _same_ payment hash.
As a result, on top of the normal replay protection, an attacker also stands to lose the entire amount of the HTLC replayed as well.
One consideration with the ever-increasing set of session keys stored for replay protection is: are nodes able to reclaim this space?
In the context of the Lightning Network, the answer is: yes!
Once again, due to the uniquer attributes of the HTLC construct, we can make a further improvement over the base Sphinx protocol.
Once again, due to the unique attributes of the HTLC construct, we can make a further improvement over the base Sphinx protocol.
Given that HTLCs are _time locked_ contracts based on the absolute block height, once an HTLC has expired, then the contract is effectively permanently closed.
As a result, nodes can use this CLTV expiration height as an indicator to know when it's safe to garbage collect an entry in the anti-replay log.
@ -500,6 +529,12 @@ image::images/chan_onion_wrapping.png[]
Alice starts with the 1300 onion payload created for Dina. The first 65 (or less) bytes of this are Dina's payload obfuscated and the rest is filler. Alice must be careful not to overwrite Dina's payload.
Next, Alice needs to locate the ephemeral public key (that was generated at the very start for each hop) that will be prepended to the routing packet at this hop.
Remember that rather than include a unique ephemeral public key (that the sender and intermediate node use in an ECDH operation to arrive a shared secret), Sphinx uses a single ephemeral public key that is deterministically randomized at each hop.
When processing the packet, Dina will use her shared secret and public key to derive the blinding value (`b_dina`) and use that to re-randomize the ephemeral public key, in an identical operation to what Alice performs during initial packet construction.
Alice adds an inner HMAC checksum to Chan's payload and inserts it at the "front" (left side) of the onion payload, shifting the existing payload to the right by an equal amount.
Remember that there are effectively _two_ HMACs used in the scheme: the outer and the inner HMAC.
In this case, Chan's _inner_ HMAC is actually Dina's _outer_ HMAC.
@ -521,6 +556,7 @@ image::images/bob_onion_wrapping.png[]
Start with the onion payload (obfuscated) containing Chan's and Dina's hop payloads.
Obtain the session key for this hop dervied from the blinding factor generated by the prior hop.
Include the prior hop's outer HMAC as this hop's inner HMAC.
Insert Bob's hop payload at the beginning and shift everything else over to the right, dropping a Bob-hop-payload-size chunk from the end (it was filler anyway).
@ -531,9 +567,15 @@ Calculate the outer HMAC and stick it on the end of Bob's hop payload.
==== The final onion packet
The final onion payload is read to send to Bob. Alice doesn't need to add any more hop payloads.
The final onion payload is ready to be sent to Bob. Alice doesn't need to add any more hop payloads.
Alice calculates an HMAC for the onion payload, to cryptographically secure it with a checksum that Bob can verify.
Alice adds a 33-byte public session key that will be used by each hop to generate a shared-secret and the rho, mu, and pad keys.
Alice calculates an HMAC for the onion payload, to cryptographically secure it with a checksum that Bob can verify. Alice adds a 33-byte public session key that will be used by each hop to generate a shared-secret and the rho, mu, and pad keys. Finally Alice puts the onion version number (+0+ currently) in the front. This allows for future upgrades of the onion packet format.
Finally Alice puts the onion version number (+0+ currently) in the front.
This allows for future upgrades of the onion packet format.
The result can be seen in <<onion_packet_2>> below:
@ -547,7 +589,7 @@ In this section we will look at how the onion packet is forwarded and how HTLCs
==== The update_add_htlc message
Onion packets are sent as part of the +update_add_htlc+ message. If you recall from <<update_add_htlc>>, in <<channel_operations>>, we saw the contents of the +update_add_htlc+ message were as follows:
Onion packets are sent as part of the +update_add_htlc+ message. If you recall from <<update_add_htlc>>, in <<channel_operation>>, we saw the contents of the +update_add_htlc+ message were as follows:
----
[channel_id:channel_id]
@ -578,13 +620,13 @@ onion_routing_packet:: The final onion packet Alice constructed with all the hop
==== Bob checks the onion
As we saw in <<channel_operations>>, Bob will add the HTLC to the commitment transactions and update the state of the channel with Alice.
As we saw in <<channel_operation>>, Bob will add the HTLC to the commitment transactions and update the state of the channel with Alice.
Bob will unwrap the onion he received from Alice as follows:
1. Bob takes the session key from the onion packet and derives the Alice-Bob shared secret.
1. Bob generates the +mu+ key from the shared secret and uses it to verify the onion packet HMAC checksum.
2. Bob generates the +mu+ key from the shared secret and uses it to verify the onion packet HMAC checksum.
Now that Bob has generated the shared key and verified the HMAC, he can start unwrapping the 1300 byte onion payload inside the onion packet. The goal is for Bob to retrieve his own hop payload and then forward the remaining onion to the next hop.
@ -621,7 +663,7 @@ At the same time, applying the +rho+ byte stream to the 1300 zeroes that were ad
.Bob de-obfuscates the onion, obfuscates the filler
image::images/bob_deobfuscates.png[Bob de-obfuscates the onion, obfuscates the filler]
==== Bob extracts the outer HAMC for the next hop
==== Bob extracts the outer HMAC for the next hop
Remember that an inner HMAC is included for each hop, then will then become the outer HMAC for the _next_ hop.
In this case, Bob extracts the inner HMAC (he's already verified the integrity of the encrypted packet w/ the outer HMAC), and puts it aside as he'll append it to the deobfuscated packet to allow Chan to verify the HMAC of her encrypted packet.
@ -638,18 +680,23 @@ Now Bob can keep the first half 1300 bytes, and discard the extended (filler) 13
Bob now has a 1300 byte onion packet to send to the next hop. It is almost identical to the onion payload that Alice had created for Chan, except that the last 65 or so bytes of filler was put there by Bob and will be different.
No one can tell the difference between filler put there by Alice and filler put there by Bob. Filler is filler! It's all random bytes anyway.
No one can tell the difference between filler put there by Alice and filler put there by Bob. Filler is filler! It's all random bytes anyway. Note that if Bob (or one of Bob's other aliases) is present in the route in two disctinct locations, then they can tell the difference as the base protocol always uses the same payment hash across the entire route. Atomic Multipath Payments (AMP), and Point Time Locked Contrats (PTLCs) eliminate the correlation vector by randomizing the payment idenitifer across each route/hop.
==== Bob constructs the new onion packet
Bob now copies the onion payload into the onion packet, appends the outer HMAC for chan, re-randomizes the session key with the Elliptic Curve multiplication operation, and appends a fresh version byte.
Bob now copies the onion payload into the onion packet, appends the outer HMAC for chan, re-randomizes the session key (the same way Alice the sender does) with the Elliptic Curve multiplication operation, and appends a fresh version byte.
////
TODO
In order to re-randomize the session key, bob first computes the blinding factor for his hop, using his node public key and the shared secret he derived:
```
b_bob = SHA256(P_bob || shared_secret_bob)
```
Clarify how the HMAC and session key are computed for this onion packet
With this generated, Bob now re-randomizes the session key by performing an EC multiplication using his session key and the blinding factor:
```
session_key_chan = session_key_bob * b_bob
```
////
The `session_key_chan` public key will then be appended to the front of the onion packet for processing by Chan.
==== Bob verifies the HTLC details
@ -685,25 +732,27 @@ Chan repeats the exact same process as Bob:
1. Chan receives the +update_add_htlc+ and processes the HTLC request, adding it to commitment transactions.
1. Chan generates the Alice-Chan shared key and the +mu+ subkey
2. Chan generates the Alice-Chan shared key and the +mu+ subkey
3. Chan verifies the onion packet HMAC, then extracts the 1300 onion payload
1. Chan verifies the onion packet HMAC, then extracts the 1300 onion payload
4. Chan extends the onion payload by 1300 extra bytes, filling it with zeroes.
1. Chan extends the onion payload by 1300 extra bytes, filling it with zeroes.
5. Chan uses the +rho+ key to produce 2600 bytes.
1. Chan uses the +rho+ key to produce 2600 bytes.
6. Chan uses the generated byte stream to XOR and de-obfuscate the onion payload. Simultaneously the XOR operation obfuscates the extra 1300 zeroes, turning them into filler
1. Chan uses the generated byte stream to XOR and de-obfuscate the onion payload. Simultaneously the XOR operation obfuscates the extra 1300 zeroes, turning them into filler
7. Chan extracts the inner HMAC in the payload, which will become the outer HAMC for Dina.
1. Chan extracts the inner HMAC in the payload, which will become the outer HAMC for Dina.
8. Chan removes his hop payload and left-shifts the onion payload by the same amount. Some of the filler generated in the 1300 extended bytes move into the first-half 1300 bytes becoming part of the onion payload.
1. Chan removes his hop payload and left-shifts the onion payload by the same amount. Some of the filler generated in the 1300 extended bytes move into the first-half 1300 bytes becoming part of the onion payload.
9. Chan constructs the onion packet for Dina with this onion payload.
1. Chan constructs the onion packet for Dina with this onion payload.
10. Chan builds an +update_add_htlc+ message for Dina and inserts the onion packet into it.
1. Chan builds an +update_add_htlc+ message for Dina and inserts the onion packet into it.
11. Chan sends the +update_add_htlc+ to Dina
1. Chan sends the +update_add_htlc+ to Dina
12. Chan re-randomizes the session key as Bob did in the prior hop for Dina.
==== Dina receives the final payload
@ -749,7 +798,7 @@ Finally the return node sends the return packet to the hop from which it receive
Each hop receiving an error, will generate an +ammag+ key and obfuscate the return packet again using an XOR operation with the byte-stream from +ammag+.
Eventually, the sender (origin node) receives a return packet. It will then generate +ammag+ and +um+ keys for each hop and XOR de-bfuscate the return error iteratively until it reveals the return packet.
Eventually, the sender (origin node) receives a return packet. It will then generate +ammag+ and +um+ keys for each hop and XOR de-obfuscate the return error iteratively until it reveals the return packet.
==== Failure Messages
@ -782,3 +831,5 @@ One proposed solution to this problem is called "stuckless payments", and it dep
=== Conclusion
The Lightning Network's onion routing protocol is adapted from the Sphinx Protocol to better serve the needs of a payment network. As such, it offers a huge improvement in privacy and counter-surveillance compared to the public and transparent Bitcoin blockchain.
In <<path_finding>> we will see how the combination of source routing and onion routing is used by Alice to find a good path and route the payment to Dina. To find a path, Alice first needs to learn about the network topology, which is the topic of the next section <<gossip>>.

@ -1,7 +1,7 @@
[[gossip]]
== Gossip and the channel graph
In this chapter we will describe the Lightning Network's _Gossip Protocol_ and how it is used by nodes to construct and maintain a _Channel Graph_.
In this chapter we will describe the Lightning Network's _Gossip Protocol_ and how it is used by nodes to construct and maintain a _Channel Graph_. We will also review the _DNS Bootstrap_ mechanism used to find peers to "gossip" with.
The gossip protocol and routing information section is highlighted by a double outline spanning the "Routing Layer" and "Peer 2 Peer Layer" of <<LN_protocol_gossip_highlight>>:
@ -15,7 +15,7 @@ Thus, the sender has to be able to map the Lightning Network, by constructing a
The channel graph is the interconnected set of publicly advertised channels, and the nodes that these channels interlink.
As channels are backed by a funding transaction that is happening on-chain, one might falsely believe that Lightning Nodes could just extract the existing channels from the Bitcoin Blockchain.
However this only possible to a certain extent.
However this is only possible to a certain extent.
The funding transactions are Pay-to-Witness-Script-Hash (P2WSH) addresses and the nature of the script (a 2-of-2 multisig) will only be revealed once the funding transaction output is spent.
Even if the nature of the script was known it's important to remember that not all 2-of-2 multisig scripts correspond to payment channels.
@ -56,7 +56,7 @@ Let's revisit some of the terminology that we have used throughout the book, spe
| payment | message
|===
As the Lightning Network is a peer-to-peer network, some initial bootstrapping is required in order for peers to discover each other. Within this chapter we'll follow the story of a new peer connecting to the network for the first time, and examine each step in the bootstrapping process from initial peer discovery, to channel graph syncing and validation.
As the Lightning Network is a peer-to-peer network, some initial bootstrapping is required in order for peers to discover each other. Within this chapter we'll follow the story of a new peer connecting to the network for the first time, and examine each step in the bootstrapping process from initial peer discovery to channel graph syncing and validation.
As an initial step, our new node needs to somehow _discover_ at least _one_ peer that is already connected to the network and has a full channel graph (as we'll see later, there's no canonical version of the channel graph). Using one of many initial bootstrapping protocols to find that first peer, after a connection is established, our new
peer now needs to _download_ and _validate_ the channel graph. Once the channel graph has been fully validated, our new peer is ready to start opening channels and sending payments on the network.
@ -75,11 +75,11 @@ In this section, we'll begin to follow a new Lightning node that wishes to join
. Begin the process of ongoing maintenance of the channel graph itself
==== P2P Boostrapping
==== P2P Bootstrapping
Before doing any thing else, our new node first needs to discover a set of peers who are already part of the network. We call this process initial peer bootstrapping, and it's something that every peer to peer network needs to implement properly in order to ensure a robust, healthy network.
Bootstrapping new peers to existing peer to peer networks is a very well studied problem with several known solutions, each with their own distinct trade offs. The simplest solution to this problem is simply to package a set of _hard coded_ bootstrap peers into the packaged p2p node software. This is simple in that each new node has a list of bootstrap peersin the software they're running, but rather fragile given that if the set of bootstrap peers goes offline, then no new nodes will be able to join the network. Due to this fragility, this
Bootstrapping new peers to existing peer to peer networks is a very well studied problem with several known solutions, each with their own distinct trade offs. The simplest solution to this problem is simply to package a set of _hard coded_ bootstrap peers into the packaged p2p node software. This is simple in that each new node has a list of bootstrap peers in the software they're running, but rather fragile given that if the set of bootstrap peers goes offline, then no new nodes will be able to join the network. Due to this fragility, this
option is usually used as a fallback in case none of the other p2p bootstrapping mechanisms work properly.
Rather than hard coding the set of bootstrap peers within the software/binary itself, we can instead allow peers to dynamically obtain a fresh/new set of bootstrap peers they can use to join the network. We'll call this process _initial peer discovery_. Typically we'll leverage
@ -89,27 +89,26 @@ existing Internet protocols to maintain and distribute a set of bootstrapping pe
* Internet Relay Chat (IRC)
* Hyper-Text Transfer Protocol (HTTP)
Similar to the Bitcoin protocol, the primary initial peer discovery mechanism used in the Lightning Network happens via DNS. As initial peer discovery is a critical and universal task for the network, the process has been _standardized_ in https://github.com/lightningnetwork/lightning-rfc/blob/master/10-dns-bootstrap.md[BOLT #10 - DNS Bootstrap]
Similar to the Bitcoin protocol, the primary initial peer discovery mechanism used in the Lightning Network happens via DNS. As initial peer discovery is a critical and universal task for the network, the process has been _standardized_ in https://github.com/lightningnetwork/lightning-rfc/blob/master/10-dns-bootstrap.md[BOLT #10 - DNS Bootstrap].
==== DNS Bootstrapping
The BOLT 10 document describes a standardized way of implementing peer
The https://github.com/lightningnetwork/lightning-rfc/blob/master/10-dns-bootstrap.md[BOLT #10] document describes a standardized way of implementing peer
discovery using the Domain Name System (DNS). Lightning's flavor of DNS based bootstrapping uses up to 3 distinct record types:
* +SRV+ records for discovering a set of _node public keys_.
* +A+ records for mapping a node's public key to its current +IPv4+ address.
* +AAA+ records for mapping a node's public key to its current +IPv6+ address (if one exists).
* +AAA+ records for mapping a node's public key to its current +IPv6+ address.
Those somewhat familiar with the DNS protocol may already be familiar with the +A+ and +AAA+ record types, but not the +SRV+ type. The +SRV+ record type is used by protocols built on top of DNS, to determine the
_location_ for a specified service. In our context, the service in question is a given Lightning node, and the location its IP address. We need to use this additional record type as unlike nodes within the Bitcoin protocol, we need both a public key _and_ an IP address in order to connect to a node. As we see in <<wire_protocol>> the transport encryption protocol used in LN requires knowledge of the public key of a node before connecting, so as to implement identity hiding for nodes in the network.
Those somewhat familiar with the DNS protocol may already be familiar with the +A+ (name to IPv4 address) and +AAA+ (name to IPv6 address) record types, but not the +SRV+ type. The +SRV+ record type is used by protocols built on top of DNS, to determine the _location_ for a specified service. In our context, the service in question is a given Lightning node, and the location its IP address. We need to use this additional record type as unlike nodes within the Bitcoin protocol, we need both a public key _and_ an IP address in order to connect to a node. As we see in <<wire_protocol>> the transport encryption protocol used in LN requires knowledge of the public key of a node before connecting, so as to implement identity hiding for nodes in the network.
===== A new peer's bootstrapping workflow
Before diving into the specifics of BOLT 10, we'll first outline the high level flow of a new node that wishes to use BOLT 10 to join the network.
Before diving into the specifics of https://github.com/lightningnetwork/lightning-rfc/blob/master/10-dns-bootstrap.md[BOLT #10], we'll first outline the high level flow of a new node that wishes to use BOLT #10 to join the network.
First, a node needs to identify a single, or set of DNS servers that understand BOLT 10 so they can be used for p2p bootstrapping.
First, a node needs to identify a single, or set of DNS servers that understand BOLT #10 so they can be used for p2p bootstrapping.
While BOLT 10 uses lseed.bitcoinstats.com as the seed server, there exists no "official" set of DNS seeds for this purpose, but each of the major implementations maintain their own DNS seed, and cross query each other's seeds for redundancy purposes. In <<dns_seeds>> you'll see a list non-exhaustive list of some popular DNS seed servers.
While BOLT #10 uses lseed.bitcoinstats.com as the seed server, there exists no "official" set of DNS seeds for this purpose, but each of the major implementations maintain their own DNS seed, and cross query each other's seeds for redundancy purposes. In <<dns_seeds>> you'll see a list non-exhaustive list of some popular DNS seed servers.
[[dns_seeds]]
.Table of known lightning dns seed servers
@ -124,9 +123,9 @@ While BOLT 10 uses lseed.bitcoinstats.com as the seed server, there exists no "o
DNS seeds exist for both Bitcoin's mainnet and testnet. For the sake
of our example, we'll assume the existence of a valid BOLT 10 DNS seed at +nodes.lightning.directory+.
of our example, we'll assume the existence of a valid BOLT #10 DNS seed at +nodes.lightning.directory+.
Next, our new node will issue an +SRV+ query to obtain a set of _candidate bootstrap peers_. The response to our query will be a series of _bech32_ encoded public keys. As DNS is a text based protocol, we can't send raw binary data, so an encoding scheme is required. BOLT 10 specifies a bech32 encoding due to its use in the wider Bitcoin ecosystem. The number of encoded public keys returned depends on the server returning the query, as well as all the resolvers that stand between the client and the authoritative server.
Next, our new node will issue an +SRV+ query to obtain a set of _candidate bootstrap peers_. The response to our query will be a series of _bech32_ encoded public keys. As DNS is a text based protocol, we can't send raw binary data, so an encoding scheme is required. BOLT #10 specifies a bech32 encoding due to its use in the wider Bitcoin ecosystem. The number of encoded public keys returned depends on the server returning the query, as well as all the resolvers that stand between the client and the authoritative server.
Using the widely available +dig+ command-line tool, we can query the _testnet_ version of the DNS seed mentioned above with the following command:
@ -136,6 +135,7 @@ $ dig @8.8.8.8 test.nodes.lightning.directory SRV
We use the +@+ argument to force resolution via Google's nameserver (with IP address 8.8.8.8) as they do not filter large SRV query responses. At the end of the command, we specify that we only want +SRV+ records to be returned. A sample response looks something like:
====
----
$ dig @8.8.8.8 test.nodes.lightning.directory SRV
@ -146,25 +146,27 @@ $ dig @8.8.8.8 test.nodes.lightning.directory SRV
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 43610
;; flags: qr rd ra; QUERY: 1, ANSWER: 25, AUTHORITY: 0, ADDITIONAL: 1
;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 512
;; QUESTION SECTION:
;test.nodes.lightning.directory. IN SRV
;; ANSWER SECTION:
test.nodes.lightning.directory. 59 IN SRV 10 10 9735 ln1qfkxfad87fxx7lcwr4hvsalj8vhkwta539nuy4zlyf7hqcmrjh40xx5frs7.test.nodes.lightning.directory.
test.nodes.lightning.directory. 59 IN SRV 10 10 9735 <1>
ln1qfkxfad87fxx7lcwr4hvsalj8vhkwta539nuy4zlyf7hqcmrjh40xx5frs7.test.nodes.lightning.directory. <2>
test.nodes.lightning.directory. 59 IN SRV 10 10 15735 ln1qtgsl3efj8verd4z27k44xu0a59kncvsarxatahm334exgnuvwhnz8dkhx8.test.nodes.lightning.directory.
<SNIP>
[...]
;; Query time: 89 msec
;; SERVER: 8.8.8.8#53(8.8.8.8)
;; WHEN: Thu Dec 31 16:41:07 PST 2020
----
<1> TCP port number where LN node can be reached.
<2> Node public key (ID) encoded as a virtual domain name.
====
We've truncated the response for brevity and show only two of the returned responses. Starting from the right-most column, we have a candidate "virtual" domain name for a target node, then to the left we have the _TCP port_ that this node can be reached using. The first response uses the standard TCP port for LN: +9735+. The second response uses a custom port which is permitted by the protocol.
We've truncated the response for brevity and show only two of the returned responses. The responses contain a "virtual" domain name for a target node, then to the left we have the _TCP port_ where this node can be reached. The first response uses the standard TCP port for LN: +9735+. The second response uses a custom port which is permitted by the protocol.
Next, we'll attempt to obtain the other piece of information we need to connect to a node: its IP address. Before we can query for this however, we'll first _decode_ the returned sub-domain which is the bech32 encoding of the public key:
Next, we'll attempt to obtain the other piece of information we need to connect to a node: its IP address. Before we can query for this however, we'll first _decode_ the bech32 encoding of the public key from the virtual domain name:
----
ln1qfkxfad87fxx7lcwr4hvsalj8vhkwta539nuy4zlyf7hqcmrjh40xx5frs7
@ -178,6 +180,8 @@ Decoding this bech32 string we obtain the following valid
----
Now that we have the raw public key, we'll now ask the DNS server to _resolve_ the virtual host given so we can obtain the IP information (+A+ record) for the node:
====
----
$ dig ln1qfkxfad87fxx7lcwr4hvsalj8vhkwta539nuy4zlyf7hqcmrjh40xx5frs7.test.nodes.lightning.directory A
@ -193,18 +197,20 @@ $ dig ln1qfkxfad87fxx7lcwr4hvsalj8vhkwta539nuy4zlyf7hqcmrjh40xx5frs7.test.nodes.
;ln1qfkxfad87fxx7lcwr4hvsalj8vhkwta539nuy4zlyf7hqcmrjh40xx5frs7.test.nodes.lightning.directory. IN A
;; ANSWER SECTION:
ln1qfkxfad87fxx7lcwr4hvsalj8vhkwta539nuy4zlyf7hqcmrjh40xx5frs7.test.nodes.lightning.directory. 60 IN A X.X.X.X
ln1qfkxfad87fxx7lcwr4hvsalj8vhkwta539nuy4zlyf7hqcmrjh40xx5frs7.test.nodes.lightning.directory. 60 IN A X.X.X.X <1>
;; Query time: 83 msec
;; SERVER: 2600:1700:6971:6dd0::1#53(2600:1700:6971:6dd0::1)
;; WHEN: Thu Dec 31 16:59:22 PST 2020
;; MSG SIZE rcvd: 138
----
<1> The DNS server returns an IP Address X.X.X.X. We've replaced it with X's in the text here so as to avoid presenting a real IP address.
====
In the above command, we've queried the server so we can obtain an +IPv4+ (+A+ record) address for our target node (replaced by X.X.X.X in the example above). Now that we have both the raw public key, IP address, and TCP port, we can connect to the node transport protocol at:
+026c64f5a7f24c6f7f0e1d6ec877f23b2f672fb48967c2545f227d70636395eaf3@X.X.X.X:9735+
Querying for the current +A+ record for a given node can also be used to look up the _latest_ set of addresses for a given node. Such queries can be used to more quickly (compared to waiting on gossip as we'll cover later) sync the latest addressing information for a node.
Querying the current DNS +A+ record for a given node can also be used to look up the _latest_ set of addresses. Such queries can be used to more quickly sync the latest addressing information for a node, compared to waiting for address updates on the gossip network (see <<node_announcement>>).
At this point in our journey, our new Lightning node has found its first
peer and established its first connection! Now we can begin the second phase of new peer bootstrapping: channel graph synchronization and validation.
@ -213,16 +219,15 @@ First, we'll explore more of the intricacies of BOLT 10 itself to take a deeper
==== SRV Query Options
The BOLT 10 standard is highly extensible due to its usage of nested
The https://github.com/lightningnetwork/lightning-rfc/blob/master/10-dns-bootstrap.md[BOLT #10] standard is highly extensible due to its usage of nested
sub-domains as a communication layer for additional query options. The
bootstrapping protocol allows clients to further specify the _type_ of nodes they're attempting to query for vs the default of receiving a random subset of nodes in the query responses.
The query option sub-domain scheme uses a series of key-value pairs where the key itself is a _single letter_ and the remaining set of text is the value itself. The following query types exist in the current version of the BOLT 10 standards document:
The query option sub-domain scheme uses a series of key-value pairs where the key itself is a _single letter_ and the remaining set of text is the value itself. The following query types exist in the current version of the https://github.com/lightningnetwork/lightning-rfc/blob/master/10-dns-bootstrap.md[BOLT #10] standards document:
* +r+: The "realm" byte which is used to determine which chain or realm queries should be returned for. As is, the only value for this key is +0+ which denotes "Bitcoin".
* +a+: Allows clients to filter out returned nodes based on the _types_ of addresses they advertise. As an example, this can be used to only obtain nodes that advertise a valid IPv6 address.
* The value that follows this type is based on a bitfled that _indexes_ into the set of specified address _type_ which are defined in BOLT 7. The default value for this field is +6+, which which represents both IPv4 and IPv6 (bits 1 and 2 are set)
* +a+: Allows clients to filter out returned nodes based on the _types_ of addresses they advertise. As an example, this can be used to only obtain nodes that advertise a valid IPv6 address. The value that follows this type is based on a bitfled that _indexes_ into the set of specified address _type_ which are defined in https://github.com/lightningnetwork/lightning-rfc/blob/master/07-routing-gossip.md[BOLT #7]. The default value for this field is +6+, which which represents both IPv4 and IPv6 (bits 1 and 2 are set)
* +l+: A valid node public key serialized in compressed format. This allows a client to query for a specified node rather than receiving a set of random nodes.
@ -249,20 +254,24 @@ dig @8.8.8.8 r0.a6.nodes.lightning.directory SRV
=== The channel graph
Now that our new node is able to use the DNS boostrapping protocol to connect to their very first peer, it can start to sync the channel graph! However, before we sync the channel graph, we'll need to learn exactly _what_ we mean by the channel graph. In this section we'll explore the precise _structure_ of the channel graph and examine the unique aspects of the channel graph compared to the typical abstract "graph" data structure which is well known/used in the field of computer science.
Now that our new node is able to use the DNS bootstrapping protocol to connect to their very first peer, it can start to sync the channel graph! However, before we sync the channel graph, we'll need to learn exactly _what_ we mean by the channel graph. In this section we'll explore the precise _structure_ of the channel graph and examine the unique aspects of the channel graph compared to the typical abstract "graph" data structure which is well known/used in the field of computer science.
==== A directed graph
A graph in computer science is a special data structure composed of vertices (typically referred to as nodes) and edges (also known as links). Two nodes may be connected by one or more edges. The channel graph is also _directed_ given that a payment is able to flow in either direction over a given edge (a channel). As we're concerned with _routing payments_, in our model a node with no edges (no payment channels) isn't considered to be a part of the graph as it isn't useful.
A graph in computer science is a special data structure composed of vertices (typically referred to as nodes) and edges (also known as links). Two nodes may be connected by one or more edges. The channel graph is also _directed_ given that a payment is able to flow in either direction over a given edge (a channel). An example of a _directed graph_ is shown below:
[[directed_graph]]
.A directed graph (Source: Wikimedia Commons)
image::images/directed_graph.png["A directed graph"]
In the context of the Lightning Network, our vertices are the Lightning nodes themselves, with our edges being the payment channels connecting these nodes.
In the context of the Lightning Network, our vertices are the Lightning nodes themselves, with our edges being the payment channels connecting these nodes. As we're concerned with _routing payments_, in our model a node with no edges (no payment channels) isn't considered to be a part of the graph as it isn't useful.
As channels themselves are UTXOs (funded 2-of-2 multisig addresses), we can view the channel graph as a special subset of the Bitcoin UTXO set, on top of which we can add some additional information (the nodes, etc) to arrive at the final overlay structure which is the channel graph. This anchoring of fundamental components of the channel graph in the
base Bitcoin blockchain means that it's impossible to _fake_ a valid channel graph, which has useful properties when it comes to spam prevention as we'll see later.
=== Gossip protocol messages
The channel graph information is propagated across the Lightning P2P Network as three messages, which are described in BOLT 7:
The channel graph information is propagated across the Lightning P2P Network as three messages, which are described in https://github.com/lightningnetwork/lightning-rfc/blob/master/07-routing-gossip.md[BOLT #7]:
* +node_announcement+: The vertex in our graph which communicates the public key of a node, as well as how to reach the node over the internet and some additional metadata describing the set of _features_ the node supports.
@ -275,6 +284,7 @@ themselves _authenticated_ allowing a 3rd party to ensure that the owner of a ch
With the high level structure of the channel graph laid out, we'll now dive down into the precise structure of each of the three messages used to gossip the channel graph. We'll also explain how one can also _verify_ each message and component of the channel graph.
[[node_announcement]]
==== The node_announcement message
First, we have the +node_announcement+ message, which serves two primary
@ -295,7 +305,7 @@ the following fields:
* +signature+: A valid ECDSA signature that covers the serialized digest of all fields listed below. This signature must correspond to the public key of the advertised node.
* +features+: A bit vector that describes the set of protocol features that this node understands. We'll cover this field in more detail in <<features>> on the extensibility of the Lightning protocol. At a high level, this field carries a set of bits that represent the features a node understands. As an example, a node may signal that it understands the latest channel type.
* +features+: A bit vector that describes the set of protocol features that this node understands. We'll cover this field in more detail in <<feature_bits>> on the extensibility of the Lightning protocol. At a high level, this field carries a set of bits that represent the features a node understands. As an example, a node may signal that it understands the latest channel type.
* +timestamp+: A UNIX "epoch" encoded timestamp. This allows clients to enforce a partial ordering over the updates to a node's announcement.
@ -315,7 +325,7 @@ Validating an incoming +node_announcement+ is straight forward. The following as
* With this constraint, we enforce a forced level of "freshness".
* If no +node_announcement+ exists for the given node, then an existing +channel_announcement+ that refernces the given node (more on that later) MUST already exist in one's local channel graph.
* If no +node_announcement+ exists for the given node, then an existing +channel_announcement+ that references the given node (more on that later) MUST already exist in one's local channel graph.
* The included +signature+ MUST be a valid ECDSA signature verified using the included +node_id+ public key and the double-sha256 digest of the raw message encoding (minus the signature and frame header) as the message.
@ -337,15 +347,16 @@ Due to the existence of unadvertised channels, the _true_ size of the channel gr
===== Locating a channel on the Bitcoin blockchain
As mentioned earlier, the channel graph is authenticated due to its usage of public key cryptography, as well as the Bitcoin blockchain as a spam prevention system. In order to have a node accept a new +channel_announcement+, the advertisement must _prove_ that the channel actually exists in the Bitcoin blockchain. This proof system adds an upfront cost to adding a new entry to the channel graph (the on-chain fees on must pay to create the UTXO of the channel). As a result, we mitigate spam and ensure that a dishonest node on the network can't fill up the memory of an honest node at no cost with bogus channels.
As mentioned earlier, the channel graph is authenticated due to its usage of public key cryptography, as well as the Bitcoin blockchain as a spam prevention system. In order to have a node accept a new +channel_announcement+, the advertisement must _prove_ that the channel actually exists in the Bitcoin blockchain. This proof system adds an upfront cost to adding a new entry to the channel graph (the on-chain fees one must pay to create the UTXO of the channel). As a result, we mitigate spam and ensure that a dishonest node on the network can't fill up the memory of an honest node at no cost with bogus channels.
Given that we need to construct a proof of the existence of a channel, a
natural question that arises is: how do we "point to" or reference a given channel for the verifier? Given that a payment channel is anchored in a UTXO, an initial thought might be to first attempt to just advertise the full outpoint (+txid:index+) of the channel. Given the outpoint is globally unique and confirmed in the chain, this sounds like a good idea, however it has a drawback: the verifier must maintain a full copy of the UTXO set in order to verify channels. This works fine for Bitcoin full-nodes, but clients which rely on lightweight verification don't typically maintain a full UTXO set. As we want
to ensure we can support mobile nodes in the Lightning Network, we're forced to find another solution.
natural question that arises is: how do we "point to" or reference a given channel for the verifier? Given that a payment channel is anchored in a Unspent Transaction Output (see <<utxo>>), an initial thought might be to first attempt to advertise the full outpoint (+txid:index+) of the channel. Given the outpoint is globally unique and confirmed in the chain, this sounds like a good idea, however it has a drawback: the verifier must maintain a full copy of the UTXO set in order to verify channels. This works fine for Bitcoin full-nodes, but clients which rely on lightweight verification don't typically maintain a full UTXO set. As we want to ensure we can support mobile nodes in the Lightning Network, we're forced to find another solution.
What if rather than referencing a channel by its UTXO, we reference it based onits "location" in the chain? In order to do this, we'll need a scheme that allows us to "index" into a given block, then a transaction within that block, and finally a specific output created by that transaction. Such an identifier is described in BOLT 7 and is referred to as a _short channel ID_, or +scid+.
What if rather than referencing a channel by its UTXO, we reference it based on its "location" in the chain? In order to do this, we'll need a scheme that allows us to reference a given block, then a transaction within that block, and finally a specific output created by that transaction. Such an identifier is described in https://github.com/lightningnetwork/lightning-rfc/blob/master/07-routing-gossip.md[BOLT #7] and is referred to as a _short channel ID_, or +scid+.
The +scid+ is used both in +channel_announcement+ (and +channel_update+) as well as within the onion encrypted routing packet included within HTLCs as we learned <<onion_routing>>.
[[short_channel_id]]
[[scid]]
===== The Short Channel ID
Based on the information above, we have three pieces of information we need to encode in order to uniquely reference a given channel. As we want a compact representation, we'll attempt to encode the information into a _single_ integer. Our integer format of choice is an unsigned 64-bit integer, comprised of 8 bytes.
@ -355,7 +366,7 @@ bytes to encode the transaction index _within_ a block. This is more than enough
Our final +scid+ format resembles:
----
block_height (3 bytes) || transaction_index (3 bytes) || output_index (2 byes)
block_height (3 bytes) || transaction_index (3 bytes) || output_index (2 bytes)
----
Using bit packing techniques, we first encode the most significant 3 bytes as the block height, the next 3 bytes as the transaction index, and the least significant 2 bytes as the output index of that creates the channel UTXO.
@ -375,7 +386,7 @@ A channel_announcement primarily communicates two things:
When describing the proof, we'll typically refer to node +1+ and node +2+. Out of the two nodes that a channel connects, the "first" node is the node that has a "lower" public key encoding when we compare the public key of the two nodes in compressed format hex-encoded in lexicographical order. Correspondingly, in addition to a node public key on the network, each node should also control a public key within the Bitcoin blockchain.
Similar to the +node_announcement+ message, all included signatures of the +channel_announcement+ message should be signed/verified against the raw encoding of the message (minus the header) that follows _after_ the final signature (as it isn't possible for a digital signature to sign itself..).
Similar to the +node_announcement+ message, all included signatures of the +channel_announcement+ message should be signed/verified against the raw encoding of the message (minus the header) that follows _after_ the final signature (as it isn't possible for a digital signature to sign itself).
With that said, a +channel_announcement+ message has the following fields:
@ -386,7 +397,7 @@ With that said, a +channel_announcement+ message has the following fields:
* +bitcoin_signature_1+: The signature of the multisig key (in the funding output) of the first node over the message digest.
* +bitcoin_signature_2+: The signature of the multi-sig key (in the funding output) of the second node over the message digest.
* +bitcoin_signature_2+: The signature of the multisig key (in the funding output) of the second node over the message digest.
* +features+: A feature bit vector that describes the set of protocol level features supported by this channel.
@ -400,7 +411,7 @@ With that said, a +channel_announcement+ message has the following fields:
* +bitcoin_key_1+: The raw multisig key for the channel funding output for the first node in the network.
* +bitcoin_key_2+: The raw multi-sig key for the channel funding output for the second node in the network.
* +bitcoin_key_2+: The raw multisig key for the channel funding output for the second node in the network.
===== Channel announcement validation
@ -410,11 +421,11 @@ Armed with the information in the +channel_announcement+, any Lightning node (ev
First, the verifier will use the short channel ID to find which Bitcoin block contains the channel funding output. With the block height information, the verifier can request only that specific block from a Bitcoin node. The block can then be linked back to the genesis block by following the block header chain backwards (verifying the proof-of-work), confirming that this is in fact a block belonging to the Bitcoin blockchain.
Next, the verifier uses the transaction index number to identify the transaction ID of the transaction containing the payment channel. The block retrieved previously will contain an indexed list of transaction IDs.
Next, the verifier uses the transaction index number to identify the transaction ID of the transaction containing the payment channel. Most modern Bitcoin libraries will allow indexing into the transaction of a block based on the index of the transaction within the greater block.
Next, the verifier requests the raw transaction from a Bitcoin node, by reference to the transaction ID. The verifier will validate the transaction (checking that it is properly signed and produces the same transaction ID when hashed).
Next, uses a Bitcoin library (in the verifier's language) to extract the relevant transaction according to its index within the block. The verifier will validate the transaction (checking that it is properly signed and produces the same transaction ID when hashed).
Next, the verifier will extract the Pay-to-Witness-Script-Hash output referenced by the output index number of the short channel ID. This is the address of the channel funding output.
Next, the verifier will extract the Pay-to-Witness-Script-Hash output referenced by the output index number of the short channel ID. This is the address of the channel funding output. Additionally, the verified will ensure that the size of the allegd channel matches the value of the output produced at the specified output index.
Finally, the verifier will reconstruct the multisig script from +bitcoin_key_1+ and +bitcoin_key_2+ and confirm that it produces the same address as in the output.
@ -422,7 +433,7 @@ The verifier has now independently verified that the payment channel in the anno
==== The channel_update message
The third and final message used in the gossip protocol is the +channel_update+ message. Two of these are generated for each payment channel, one by each channel partner, announcing their routing fees, timelock expectations and capabilities.
The third and final message used in the gossip protocol is the +channel_update+ message. Two of these are generated for each payment channel (one by each channel partner) announcing their routing fees, timelock expectations and capabilities.
The +channel_update+ message also contains a timestamp, allowing a node to update its routing fees and other expectations and capabilities by sending a new +channel_update+ message with a higher (later) timestamp that supersedes any older updates.
@ -431,7 +442,7 @@ The +channel_update+ message contains the following fields:
* signature: A digital signature matching the node's public key, to authenticate the source and integrity of the channel update
* chain_hash: The hash of the genesis block of the chain contianing the channel
* chain_hash: The hash of the genesis block of the chain containing the channel
* short_channel_id: The short channel ID to identify the channel

@ -1,7 +1,9 @@
[[path_finding]]
== Path Finding and Payment Delivery
Payment delivery on the Lightning Network depends on finding a path from the sender to the recipient, a process called _path finding_.
Payment delivery on the Lightning Network depends on finding a path from the sender to the recipient, a process called _path finding_. Since the routing is done by the sender, the sender must find a suitable path to reach the destination. This path is then encoded in an onion, as we saw in <<onion_routing>>.
In this chapter we will examine the problem of path finding, understand how uncertainty about channel balances complicates this problem and look at how a typical path finding implementation attempts to solve it.
=== Path finding in the Lightning protocol suite
@ -9,9 +11,9 @@ Path finding, path selection, multi-path payments (MPP) and the payment attempt
These components are highlighted by a double outline in the protocol suite, shown in <<LN_protocol_pathfinding_highlight>>:
[[LN_protocol_routing_highlight]]
[[LN_protocol_pathfinding_highlight]]
.The Lightning Network Protocol Suite
image::images/LN_protocol_routing_highlight.png["The Lightning Network Protocol Suite"]
image::images/LN_protocol_pathfinding_highlight.png["The Lightning Network Protocol Suite"]
==== Where is the BOLT?
@ -23,9 +25,10 @@ That's because path finding isn't an activity that requires any form of coordina
The term path finding may be somewhat misleading, because it implies a search for _a single path_ connecting two nodes. In the beginning, when the Lightning Network was small and not well interconnected, the problem was indeed about finding a way to join payment channels to reach the recipient.
But, as the Lightning Network has grown explosively, the path finding problem's nature has shifted. In mid-2021, as we finish this book, the Lightning Network consists of 20,000 nodes connected by at least 55,000 public channels with an aggregate capacity of almost 2,000 BTC. A node has on average 8.8 channels, while the top 10 most connected nodes have between 400 and 2000 channels _each_. A visualization of just a small subset of the Lightning Network channel graph (as of July 2021) is shown in <<lngraph>>:
But, as the Lightning Network has grown explosively, the path finding problem's nature has shifted. In mid-2021, as we finish this book, the Lightning Network consists of 20,000 nodes connected by at least 55,000 public channels with an aggregate capacity of almost 2,000 BTC. A node has on average 8.8 channels, while the top 10 most connected nodes have between 400 and 2000 channels _each_. A visualization of just a small subset of the Lightning Network channel graph is shown in <<lngraph>>:
[[lngraph]]
.A visualization of part of the Lightning Network as of July 2021
image::images/LNGraphJuly2021.png[]
[NOTE]
@ -52,7 +55,7 @@ All of these criteria may be desirable to some extent and selecting paths that a
Path finding in the Lightning Network falls under a general category of _graph theory_ in mathematics and the more specific category of _graph traversal_ in computer science.
A network such as the Lightning Network can be represented as a mathematical construct called a _graph_, where _nodes_ are connected to each other by _edges_ (equivalent to the payment channels). The Lightning Network forms a _directed graph_ because the nodes are linked _asymmetrically_, since the channel balance is split between the two channel partners and the payment liquidity is different in each direction. A directed graph with numerical capacity constrains on its edges is called a _flow network_, a mathematical construct used to optimize transportation and other similar networks. Flow networks can be used as a framework when solutions need to achieve a specific flow while minimizing cost, known as the Minimum Cost Flow Problem (MCFP)_.
A network such as the Lightning Network can be represented as a mathematical construct called a _graph_, where _nodes_ are connected to each other by _edges_ (equivalent to the payment channels). The Lightning Network forms a _directed graph_ because the nodes are linked _asymmetrically_, since the channel balance is split between the two channel partners and the payment liquidity is different in each direction. A directed graph with numerical capacity constrains on its edges is called a _flow network_, a mathematical construct used to optimize transportation and other similar networks. Flow networks can be used as a framework when solutions need to achieve a specific flow while minimizing cost, known as the Minimum Cost Flow Problem (MCFP).
==== Capacity, balance, liquidity
@ -98,7 +101,7 @@ Our channel liquidity uncertainty range is the range between the minimum and max
Finding a path through a graph is a problem modern computers can solve rather efficiently.
Developers mainly choose breadth-first search if the edges are all of equal weight.
In cases where the edges are not of equal weight, an algorithm based on Dijkstra Algorithm is used, such as A* ("a-star") or
In cases where the edges are not of equal weight, an algorithm based on Dijkstra Algorithm is used, such as https://en.wikipedia.org/wiki/A*_search_algorithm[A* ("A-star")].
In our case the weights of the edges can represent the routing fees.
Only edges with a capacity larger than the amount to be sent will be included in the search.
In this basic form, path finding in the Lightning network is very simple and straight forward.
@ -122,15 +125,13 @@ However, the user might suspect that probing is taking place if the payment is n
While "blind probing" is not optimal and leaves ample room for improvement, it should be noted that even this simplistic strategy works surprisingly well for smaller payments and well-connected nodes.
Most Lightning node and wallet implementation improve on this approach, by ordering/weighting the list of candidate paths. Some implementations order the candidate paths by cost (fees), or some combination of cost/capacity.
Most Lightning node and wallet implementations improve on this approach, by ordering/weighting the list of candidate paths. Some implementations order the candidate paths by cost (fees), or some combination of cost/capacity.
=== Path finding and payment delivery process
Path finding and payment delivery involves several steps, which we list below. Different implementations may use different algorithms and strategies, but the basic steps are likely to be very similar:
* Create a _channel graph_ from announcements and updates, containing the capacity of each channel.
* Filter the graph ignoring any channels with insufficient capacity for the amount we want to send.
* Create a _channel graph_ from announcements and updates, containing the capacity of each channel and filter the graph ignoring any channels with insufficient capacity for the amount we want to send.
* Find paths connecting the sender to the recipient.
@ -150,7 +151,7 @@ These three activities can be repeated in a _payment round_ if we use the failur
In the next sections we will look at each of these steps in more detail, as well as more advanced payment strategies.
==== Channel graph construction
=== Channel graph construction
In <<gossip>> we covered the three main messages that nodes "gossip": +node_announcement+, +channel_announcement+, and +channel_update+. These three messages allow any node to gradually construct a "map" of the Lightning Network in the form of a _channel graph_. Each of these messages provides a critical piece of information for the channel graph:
@ -160,11 +161,11 @@ channel_announcement:: This contains the capacity and channel ID of a public (an
channel_update:: This contains a node's fee and timelock (CLTV) expectations for routing an outgoing (from that node's perspective) payment over a specified channel.
In terms of a mathematical graph, the node_announcement is the information needed to create the nodes or _vertices_ of the graph. The channel_announcement allows us to create the _edges_ of the graph representing the payment channels. Since each direction of the payment channel has its own balance, we create a directed graph. The channel_update allows us to incorporate fees and timelocks to set the _cost_ or _weight_ of the graph edges.
In terms of a mathematical graph, the +node_announcement+ is the information needed to create the nodes or _vertices_ of the graph. The +channel_announcement+ allows us to create the _edges_ of the graph representing the payment channels. Since each direction of the payment channel has its own balance, we create a directed graph. The +channel_update+ allows us to incorporate fees and timelocks to set the _cost_ or _weight_ of the graph edges.
Depending on the algorithm we will use for path finding, we may establish a number of different cost functions for the edges of the graph.
For now, let's ignore the cost function and simply establish a channel graph showing nodes and channels, using the node_announcement and channel_announcement messages.
For now, let's ignore the cost function and simply establish a channel graph showing nodes and channels, using the +node_announcement+ and +channel_announcement+ messages.
In this chapter we will see how Selena attempts to find a path to pay Rashid 1,000,000 (1m) satoshis. To start, Selena is constructing a channel graph using the information from the Lightning Network gossip to discover nodes and channels. Selena will then explore her channel graph to find a path to send a payment to Rashid.
@ -184,7 +185,7 @@ The map territory relation is best illustrated in "Sylvie and Bruno Concluded",
What does this mean for the Lightning Network? LN is the territory, and a channel graph is a map of that territory:
While we could imagine a theoretical (Platonic ideal) channel graph that represents the complete, up-to-date map of the Lightning Network, such a map is simply the Lightning Nwtwork itself. Each node has its own channel graph which is constructed from announcements and is necessarily incomplete, incorrect, and out-of-date!
While we could imagine a theoretical (Platonic ideal) channel graph that represents the complete, up-to-date map of the Lightning Network, such a map is simply the Lightning Network itself. Each node has its own channel graph which is constructed from announcements and is necessarily incomplete, incorrect, and out-of-date!
The map can never completely and accurately describe the territory.
****
@ -279,7 +280,7 @@ The fee and timelock information are very important not just as path selection m
It is also important to note that a channel must have liquidity that is sufficient not only for the payment amount but also for the cumulative fees of all the subsequent hops. Even though Selena's channel to Xavier (S-->X) has enough liquidity for a 1m satoshi payment, it *does not* have enough liquidity once we consider fees. We need to know fees because only paths that have sufficient liquidity for *both payment and all fees* will be considered.
==== Finding candidate paths
=== Finding candidate paths
Finding a suitable path through a directed graph like this is a well-studied computer science problem (known broadly as the "Shortest Path problem"), which can be solved by a variety of algorithms depending on the desired optimization and resource constraints.
@ -302,7 +303,7 @@ But, as we saw previously, the channel +S->X+ does not have enough liquidity for
With two possible paths, Selena is ready to attempt delivery!
==== Payment delivery (Trial-and-error loop)
=== Payment delivery (Trial-and-error loop)
Selena's node starts the trial-and-error loop, by constructing the HTLCs, building the onion and attempting delivery of the payment. For each attempt, there are three possible outcomes:
@ -314,7 +315,7 @@ If the payment fails, then it can be re-tried via a different path by updating t
We'll look at what happens if the payment is "stuck" in <<stuck_payments>>. The important detail is that a stuck payment is the worst outcome because we cannot retry with another HTLC as both (the stuck one and the retry one) might go through eventually and cause a double payment.
===== First attempt (path #1)
==== First attempt (path #1)
Selena attempts the first path (S->A->B->R). She constructs the onion and sends it, but receives a failure code from Bob's node. Bob reports back a +temporary channel failure+ with a +channel_update+ identifying the channel B->R as the one that can't deliver. This attempt is shown in <<path_1_fail>>:
@ -326,7 +327,7 @@ image::images/path_1_fail.png[]
From this failure code, Selena will deduce that Bob doesn't have enough liquidity to deliver the payment to Rashid on that channel. Importantly, this failure narrows the uncertainty of the liquidity of that channel! Previously, Selena's node assumed that the liquidity on Bob's side of the channel was somewhere in the range (0, 4m). Now, she can assume that the liquidity is in the range (0, 999999). Similarly, Selena can now assume that the liquidity of that channel on Rashid's side is in the range (1m, 4m), instead of (0, 4m). Selena has learned a lot from this failure.
===== Second attempt (path #4)
==== Second attempt (path #4)
Now Selena attempts the fourth candidate path (S->A->B->X->Y->R). This is a longer path and will incur more fees, but it's now the best option for delivery of the payment.

@ -0,0 +1,417 @@
[[wire_protocol]]
== Wire Protocol: Framing & Extensibility
In this chapter, we dive into the wire protocol of the Lightning network,
and also cover all the various extensibility levers that have been built into
the protocol. By the end of this chapter, and aspiring reader should be able to
write their very own wire protocol parser for the Lighting Network. In addition
to being able to write a custom wire protocol parser, a reader of this chapter
will gain a deep understanding with respect of the various upgrade mechanisms
that have been built into the protocol.
=== Messaging Layer in the Lightning protocol suite
The messaging layer, which is detailed in this chapter, consists of _Message Framing and Format_, _Type Length Value (TLV)_ encoding, and _Feature Bits_. These components are highlighted by a double outline in the protocol suite, shown in <<LN_protocol_wire_message_highlight>>:
[[LN_protocol_wire_message_highlight]]
.The Lightning Network Protocol Suite
image::images/LN_protocol_wire_message_highlight.png["The Lightning Network Protocol Suite"]
=== Wire Framing
We begin by describing the high level structure of the wire _framing_
within the protocol. When we say framing, we mean the way that the bytes are
packed on the wire to _encode_ a particular protocol message. Without knowledge
of the framing system used in the protocol, a string of bytes on the wire would
resemble a series of random bytes as no structure has been imposed. By applying
proper framing to decode these bytes on the wire, we'll be able to extract
structure and finally parse this structure into protocol messages within our
higher-level language.
It's important to note that as the Lightning Network is an _end to end
encrypted_ protocol, and the wire framing is itself encapsulated within an
_encrypted_ message transport layer. As we see in <<encrypted_message_transport>> the Lighting
Network uses a custom variant of the Noise protocol to handle
transport encryption. Within this chapter, whenever we give an example of wire
framing, we assume the encryption layer has already been stripped away (when
decoding), or that we haven't yet encrypted the set of bytes before we send
them on the wire (encoding).
==== High-Level Wire Framing
With that said, we're ready to describe the high-level schema used to
encode messages on the wire:
* Messages on the wire begin with a _2 byte_ type field, followed by a
message payload.
* The message payload itself, can be up to 65 KB in size.
* All integers are encoded in big-endian (network order).
* Any bytes that follow after a defined message can be safely ignored.
Yep, that's it. As the protocol relies on an _encapsulating_ transport protocol
encryption layer, we don't need an explicit length for each message type. This
is due to the fact that transport encryption works at the _message_ level, so
by the time we're ready to decode the next message, we already know the total
number of bytes of the message itself. Using 2 bytes for the message type
(encoded in big-endian) means that the protocol can have up to `2^16 - 1` or
`65535` distinct messages. Continuing, as we know all messages _MUST_ be below
65KB, this simplifies our parsing as we can use a _fixed_ sized buffer, and
maintain strong bounds on the total amount of memory required to parse an
incoming wire message.
The final bullet point allows for a degree of _backwards_ compatibility, as new
nodes are able to provide information in the wire messages that older nodes
(which may not understand them can safely ignore). As we see below, this
feature combined with a very flexible wire message extensibility format also
allows the protocol to achieve _forwards_ compatibility as well.
==== Type Encoding
With this high level background provided, we now start at the most primitive
layer: parsing primitive types. In addition to encoding integers, the Lightning
Protocol also allows for encoding of a vast array of types including: variable
length byte slices, elliptic curve public keys, Bitcoin addresses, and
signatures. When we describe the _structure_ of wire messages later in this
chapter, we refer to the high-level type (the abstract type) rather than the
lower level representation of said type. In this section, we peel back this
abstraction layer to ensure our future wire parser is able to properly
encoding/decode any of the higher level types.
In <<message_types>>, we map the name of a given message type to the
high-level routine used to encode/decode the type.
[[message_types]]
.High-level message types
[options="header"]
|===
| High Level Type | Framing | Comment
| `node_alias` | A 32-byte fixed-length byte slice. | When decoding, reject if contents are not a valid UTF-8 string.
| `channel_id` | A 32-byte fixed-length byte slice that maps an outpoint to a 32 byte value. | Given an outpoint, one can convert it to a `channel_id` by taking the txid of the outpoint and XOR'ing it with the index (interpreted as the lower 2 bytes).
| `short_chan_id` | An unsigned 64-bit integer (`uint64`) | Composed of the block height (24 bits), transaction index (24 bits), and output index (16 bits) packed into 8 bytes.
| `milli_satoshi` | An unsigned 64-bit integer (`uint64`) | Represents 1000th of a satoshi.
| `satoshi` | An unsigned 64-bit integer (`uint64`) | The based unit of bitcoin.
| `satoshi` | An unsigned 64-bit integer (`uint64`) | The based unit of bitcoin.
| `pubkey` | An secp256k1 public key encoded in _compressed_ format, occupying 33 bytes. | Occupies a fixed 33-byte length on the wire.
| `sig` | An ECDSA signature of the secp256k1 Elliptic Curve. | Encoded as a _fixed_ 64-byte byte slice, packed as `R \|\| S`
| `uint8` | An 8-bit integer. |
| `uint16` | A 16-bit integer. |
| `uint64` | A 64-bit integer. |
| `[]byte` | A variable length byte slice. | Prefixed with a 16-bit integer denoting the length of the bytes.
| `color_rgb` | RGB color encoding. | Encoded as a series if 8-bit integers.
| `net_addr` | The encoding of a network address. | Encoded with a 1 byte prefix that denotes the type of address, followed by the address body.
|===
In the next section, we describe the structure of each of the wire messages
including the prefix type of the message along with the contents of its message
body.
[[tlv_message_extensions]]
=== Type Length Value (TLV) Message Extensions
Earlier in this chapter we mentioned that messages can be up to 65 KB in size,
and if while parsing a messages, extra bytes are left over, then those bytes
are to be ignored. At an initial glance, this requirement may appear to be
somewhat arbitrary, however this requirement allows for de-coupled de-synchronized evolution of the Lighting
Protocol itself. We discuss this more towards the end of the chapter. But first, we turn our attention to exactly what those "extra bytes" at
the end of a message can be used for.
==== The Protocol Buffer Message Format
The Protocol Buffer (Protobuf) message serialization format started out as an
internal format used at Google, and has blossomed into one of the most popular
message serialization formats used by developers globally. The Protobuf format
describes how a message (usually some sort of data structure related to an API)
is encoded on the wire and decoded on the other end. Several "Protobuf
compilers" exists in dozens of languages which act as a bridge that allows any
language to encode a Protobuf that will be able to decode by a compliant decode
in another language. Such cross language data structure compatibility allows
for a wide range of innovation, because it's possible to transmit structure and even
typed data structures across language and abstraction boundaries.
Protobufs are also known for their flexibility with respect to how they
handle changes in the underlying messages structure. As long as the field
numbering schema is adhered to, then it's possible for a newer write of
Protobufs to include information within a Protobuf that may be unknown to any
older readers. When the old reader encounters the new serialized format, if
there're types/fields that it doesn't understand, then it simply _ignores_
them. This allows old clients and new clients to co-exist, as all clients can
parse some portion of the newer message format.
==== Forwards & Backwards Compatibility
Protobufs are extremely popular amongst developers as they have built in
support for both forwards and backwards compatibility. Most developers are
likely familiar with the concept of backwards computability. In simple terms,
the principles states that any changes to a message format or API should be
done in a manner that doesn't break support for older clients. Within our
Protobuf extensibility examples above, backwards computability is achieved by
ensuring that new additions to the proto format don't break the known portions
of older readers. Forwards computability on the other hand is just as important
for de-synchronized updates however it's less commonly known. For a change to
be forwards compatible, then clients are to simply ignore any information
they don't understand. The soft for mechanism of upgrading the Bitcoin
consensus system can be said to be both forwards and backwards compatible: any
clients that don't update can still use Bitcoin, and if they encounters any
transactions they don't understand, then they simply ignore them as their funds
aren't using those new features.
[[tlv]]
=== Type-Length-Value (TLV) Format
In order to be able to upgrade messages in both a forwards and backwards
compatible manner, in addition to feature bits (more on that later), the LN
utilizes a custom message serialization format plainly called: Type Length
Value, or TLV for short. The format was inspired by the widely used Protobuf
format and borrows many concepts by significantly simplifying the
implementation as well as the software that interacts with message parsing. A
curious reader might ask "why not just use Protobufs"? In response, the
Lighting developers would respond that we're able to have the best of the
extensibility of Protobufs while also having the benefit of a smaller
implementation and thus smaller attack. As of version v3.15.6, the Protobuf
compiler weighs in at over 656,671 lines of code. In comparison LND's
implementation of the TLV message format weighs in at only 2.3k lines of code
(including tests).
With the necessary background presented, we're now ready to describe the TLV
format in detail. A TLV message extension is said to be a stream of
individual TLV records. A single TLV record has three components: the type of
the record, the length of the record, and finally the opaque value of the
record:
* `type`: An integer representing the name of the record being encoded.
* `length`: The length of the record.
* `value`: The opaque value of the record.
Both the `type` and `length` are encoded using a variable sized integer that's inspired by the variable sized integer (varint) used in Bitcoin's p2p protocol, called `BigSize` for short.
==== BigSize Integer Encoding
In its fullest form, a `BigSize`
integer can represent value up to 64-bits. In contrast to Bitcoin's varint
format, the `BigSize` format instead encodes integers using a big-endian byte
ordering.
The `BigSize` varint has the components: the discriminant and the body. In the
context of the `BigSize` integer, the discriminant communicates to the decoder
the size of the variable size integer that follows. Remember that the unique thing about
variable sized integers is that they allow a parser to use fewer bytes to encode
smaller integers than larger ones, saving space. Encoding of a `BigSize`
integer follows one of the four following options:
1. If the value is less than `0xfd` (`253`): Then the discriminant isn't really used, and the encoding is simply the integer itself. This allows us to encode very small integers with no additional overhead.
2. If the value is less than or equal to `0xffff` (`65535`):The discriminant is encoded as `0xfd`, which indicates that the value that follows is larger than `0xfd`, but smaller than `0xffff`). The number is then encoded as a 16-bit integer. Including the discriminant, then we can encode a value that is greater than 253, but less than 65535 using 3 bytes.
3. If the value is less than `0xffffffff` (`4294967295`): The discriminant is encoded as `0xfe`. The body is encoded using 32-bit integer, Including the discriminant, then we can encode a value that's less than `4,294,967,295` using 5 bytes.
4. Otherwise, we just encode the value as a full-size 64-bit integer.
==== TLV encoding constraints
Within the context of a TLV message, record types below `2^16` are said to be _reserved_ for future use. Types beyond this
range are to be used for "custom" message extensions used by higher-level application protocols.
The `value` of a record depends on the `type`. In other words, it can take any form as parsers will attempt to interpret it depending on the context of the type itself.
==== TLV canonical encoding
One issue with the Protobuf format is that encodings of the same message may
output an entirely different set of bytes when encoded by two different
versions of the compiler. Such instances of a non-canonical encoding are not
acceptable within the context of Lighting, as many messages contain a
signature of the message digest. If it's possible for a message to be encoded
in two different ways, then it would be possible to break the authentication of
a signature inadvertently by re-encoding a message using a slightly different
set of bytes on the wire.
In order to ensure that all encoded messages are canonical, the following
constraints are defined when encoding:
* All records within a TLV stream MUST be encoded in order of strictly
increasing type.
* All records must minimally encode the `type` and `length` fields. In other words, the smallest `BigSize` representation for an integer MUST be used at all times.
* Each `type` may only appear once within a given TLV stream.
In addition to these encoding constraints, a series of higher-level
interpretation requirements are also defined based on the _arity_ of a given `type` integer. we dive further into these details towards the end of the
chapter once we describe how the Lighting Protocol is upgraded in practice and
in theory.
[[feature_bits]]
=== Feature Bits & Protocol Extensibility
As the Lighting Network is a decentralized system, no single entity can enforce a
protocol change or modification upon all the users of the system. This
characteristic is also seen in other decentralized networks such as Bitcoin.
However, unlike Bitcoin overwhelming consensus *is not* required to change a
subset of the Lightning Network. Lighting is able to evolve at will without a
strong requirement of coordination, as unlike Bitcoin, there is no global consensus required in the Lightning Network. Due to this fact and the several
upgrade mechanisms embedded in the Lighting Network, only the
participants that wish to use these new Lighting Network features need to
upgrade, and then they are able to interact with each other.
In this section, we explore the various ways that developers and users are
able to design and deploy new features to the Lightning Network. The
designers of the original Lightning Network knew that there were many possible future directions for the network and the underlying protocol. As a result, they made sure to implement several
extensibility mechanisms within the system, which can be used to upgrade it partially or fully in a decoupled, desynchronized, and decentralized
manner.
==== Feature Bits as an Upgrade Discoverability Mechanism
An astute reader may have noticed the various locations that "feature bits" are
included within the Lightning Protocol. A "feature bit" is a bitfield that can
be used to advertise understanding or adherence to a possible network protocol
update. Feature bits are commonly assigned in pairs, meaning that each
potential new feature/upgrade always defines two bits within the bitfield.
One bit signals that the advertised feature is _optional_, meaning that the
node knows about the feature and can use it, but doesn't
consider it required for normal operation. The other bit signals that the
feature is instead *required*, meaning that the node will not continue
operation if a prospective peer doesn't understand that feature.
Using these two bits (optional and required), we can construct a simple
compatibility matrix that nodes/users can consult in order to determine if a peer is compatible with a desired feature:
.Feature Bit Compatibility Matrix
[options="header"]
|===
|Bit Type|Remote Optional|Remote Required|Remote Unknown
|Local Optional|✅|✅|✅
|Local Required|✅|✅|❌
|Local Unknown|✅|❌|❌
|===
From this simplified compatibility matrix, we can see that as long as the other
party knows about our feature bit, then we can interact with them using the
protocol. If the party doesn't even know about what bit we're referring to
*and* they require the feature, then we are incompatible with them. Within the
network, optional features are signaled using an _odd bit number_ while
required feature are signaled using an _even bit number_. As an example, if a peer signals that they known of a feature that uses bit +15+, then we know that
this is an optional feature, and we can interact with them or respond to
their messages even if we don't know about the feature. If
they instead signaled the feature using bit +16+, then we know this is a
required feature, and we can't interact with them unless our node also
understands that feature.
The Lighting developers have come up with an easy to remember phrase that
encodes this matrix: "it's OK to be odd". This simple rule allows for a
rich set of interactions within the protocol, as a simple bitmask operation
between two feature bit vectors allows peers to determine if certain
interactions are compatible with each other or not. In other words, feature
bits are used as an upgrade discoverability mechanism: they easily allow to
peers to understand if they are compatible or not based on the concepts of
optional, required, and unknown feature bits.
Feature bits are found in the: `node_announcement`, `channel_announcement`, and
`init` messages within the protocol. As a result, these three messages can be
used to signal the knowledge and/or understanding of in-flight protocol
updates within the network. The feature bits found in the `node_announcement`
message can allow a peer to determine if their _connections_ are compatible or
not. The feature bits within the `channel_announcement` messages allows a peer
to determine if a given payment type or HTLC can transit through a given peer or
not. The feature bits within the `init` message allow peers to understand if
they can maintain a connection, and also which features are negotiated for the
lifetime of a given connection.
==== TLV for forwards & backwards compatibility
As we learned earlier in the chapter, Type-Length-Value, or TLV records can be
used to extend messages in a forwards and backwards compatible manner.
Overtime, these records have been used to extend existing messages without
breaking the protocol by utilizing the "undefined" area within a message beyond
that set of known bytes.
As an example, the original Lighting Protocol didn't have a concept of the
"largest amount HTLC" that could traverse through a channel as dictated by a routing
policy. Later on, the `max_htlc` field was added to the `channel_update`
message to phase-in this concept over time. Peers that received a
`channel_update` that set such a field but didn't even know the upgrade existed
where unaffected by the change, but have their HTLCs rejected if they are
beyond the limit. Newer peers, on the other hand, are able to parse, verify,
and utilize the new field.
Those familiar with the concept of soft-forks in Bitcoin may now see some
similarities between the two mechanisms. Unlike Bitcoin consensus-level
soft-forks, upgrades to the Lighting Network don't require overwhelming
consensus in order to adopt. Instead, at minimum, only two peers within the
network need to understand a new upgrade in order to start using it. Commonly these two peers may be the recipient and sender of a
payment, or may be the channel partners of a new payment channel.
==== A taxonomy of upgrade mechanisms
Rather than there being a single widely utilized upgrade mechanism within the
network (such as soft-forks for Bitcoin), there exist several possible upgrade mechanisms within the Lighting Network. In this
section, we enumerate these upgrade mechanisms, and
provide a real-world example of their use in the past.
===== Internal Network Upgrades
We start with the upgrade type that requires the most protocol-level
coordination: internal network upgrades. An internal network upgrade is
characterized by one that requires *every single node* within a prospective payment path to understand the new feature. Such an upgrade is similar to any
upgrade within the internet that requires hardware-level upgrades within
the core-relay portion of the upgrade. In the context of LN however, we deal
with pure software, so such upgrades are easier to deploy, yet they still
require much more coordination than any other upgrade mechanism in the
network.
One example of such an upgrade within the network was the introduction of a TLV
encoding for the routing information encoded within the onion
packets. The prior format used a hard-coded fixed-length message
format to communicate information such as the next hop.
As this format was fixed it meant that new protocol-level upgrades weren't possible. The move to the more flexible TLV
format meant that after this upgrade, any sort of feature that
modified the type of information communicated at each hop could be rolled out at will.
It's worth mentioning that the TLV onion upgrade was a sort of "soft" internal
network upgrade, in that if a payment wasn't using any new feature beyond
that new routing information encoding, then a payment could be transmitted
using a mixed set of nodes.
===== End-to-End Upgrades
To contrast the internal network upgrade, in this section we describe the
_end to end_ network upgrade. This upgrade mechanism differs from the internal
network upgrade in that it only requires the "ends" of the payment, the sender
and recipient to upgrade.
This type of upgrade allows
for a wide array of unrestricted innovation within the network. Because of the
onion encrypted nature of payments within the network, those forwarding HTLCs
within the center of the network may not even know that new features are being
utilized.
One example of an end-to-end upgrade within the network was the roll-out of multi-part payments (MPP). MPP is a protocol-level feature that enables a
single payment to be split into multiple parts or paths, to be assembled at the
recipient for settlement. The roll out our MPP was coupled with a new
`node_announcement` level feature bit that indicates that the recipient knows
how to handle partial payments. Assuming a sender and recipient know about each
other (possibly via a BOLT 11 invoice), then they're able to use the new
feature without any further negotiation.
Another example of an end-to-end upgrade are the various types of
"spontaneous" payments deployed within the network. One early type of
spontaneous payments called _keysend_ worked by simply placing the pre-image of a payment within the encrypted onion. Upon receipt, the destination would decrypt the
pre-image, then use that to settle the payment. As the entire packet is end-to-end encrypted, this payment type was safe, since none of the intermediate nodes
are able to fully unwrap the onion to uncover the payment pre-image.
==== Channel Construction Level Updates
The final broad category of updates are those that happen at
the channel construction level, but which don't modify the structure of the HTLC used widely within the network. When we say channel construction, we mean
how the channel is funded or created. As an example, the eltoo channel type
can be rolled out within the network using a new `node_announcement` level
feature bit as well as a `channel_announcement` level feature bit. Only the two
peers on the sides of the channels needs to understand and advertise these new
features. This channel pair can then be used to forward any payment type
granted the channel supports it.
Another is the "anchor outputs" channel format which allows the commitment fee to be
bumped via Bitcoin's Child-Pays-For-Parent (CPFP) fee management mechanism.
=== Conclusion
Lightning's wire protocol is incredibly flexible and allows for rapid innovation and interoperability without strict consensus. It is one of the reasons that the Lightning Network is experiencing much faster development and is attractive to many developers, who might otherwise find Bitcoin's development style too conservative and slow.

@ -1,9 +1,25 @@
[appendix]
[[brontide]]
[[encrypted_message_transport]]
[[encrypted_transport]]
== Lightning's Encrypted Message Transport (Brontide)
In this chapter we will review the Lightning Network's _Encrypted Message Transport_, also known as the _Brontide Protocol_, which allows peers to establish end-to-end encrypted communication, authentication and integrity checking.
In this chapter we will review the Lightning Network's _Encrypted Message
Transport_, also known as the _Brontide Protocol_, which allows peers to
establish end-to-end encrypted communication, authentication, and integrity
checking.
[NOTE]
====
Part of this chapter includes some highly technical detail about the encryption protocol and encryption algorithms used in the Lightning Encrypted Transport. You may decide to skip that section, if you are not interested in those details.
====
=== Encrypted Transport in the Lightning Protocol Suite
The _Encrypted Transport_ component of the Lightning Network and its several components are shown in the left most part of the _Network Connection Layer_ in <<LN_protocol_encrypted_transport_highlight>>:
[[LN_protocol_encrypted_transport_highlight]]
.The Lightning Network Protocol Suite
image::images/LN_protocol_encrypted_transport_highlight.png["The Lightning Network Protocol Suite"]
=== Introduction
@ -17,7 +33,7 @@ level. In this chapter, we'll learn about the encryption protocol used by the
Lightning network in detail. Upon completion of this chapter, the reader will
be familiar with the state of the art in encrypted messaging protocols, as well
as the various properties such a protocol provides to the network. It's worth
mentioning that the core of the encrypted message transport is _agonstic_ to
mentioning that the core of the encrypted message transport is _agnostic_ to
its usage within the context of the Lightning Network. As a result, the
custom encrypted message transport Lightning uses, commonly referred to as
"Brontide" (more on that later) can be dropped into any context that requires
@ -119,7 +135,11 @@ Lightning Network, the flavor of Noise use will be referred to from here on as
"Brontide". A brontide is a low billowing noise, similar to what one would hear
during a thunderstorm when very far away.
==== Noise Protocol Handshakes
=== Lightning Encrypted Transport in detail
In this section we will break down the Lightning Encrypted Transport protocol and delve into the details of the cryptographic algorithms and protocol used to establish encrypted, authenticated and integrity-assured communications between peers. Feel free to skip this section if you find this level of detail daunting.
==== Noise XK: LN's Noise Handshake
The Noise protocol is extremely flexible in that it advertises several
handshakes, each with different security and privacy properties for a would be
@ -152,9 +172,6 @@ Several ephemeral keys are generated throughout the handshake. We use `e` to
refer to a new ephemeral key. ECDH operations between two keys are notated as
the concatenation of two keys. As an example, `ee` represents an ECDH operation
between two ephemeral keys.
=== Brontide: Lightning's P2P Encryption
==== High-Level Overview
Using the notation laid out earlier, we can succinctly describe the `Noise_XK`
@ -169,7 +186,7 @@ as follows:
```
The protocol begins with the "pre-transmission" of the responder's static key
(`rs)` to the initiator. Before executing the handshake, the initiator is to
(`rs`) to the initiator. Before executing the handshake, the initiator is to
generate its own static key (`s`). During each step of the handshake, all
material sent across the wire, as well as the keys sent/used are incrementally
hashed into a "handshake digest", `h`. This digest is never sent across the
@ -201,7 +218,7 @@ variant, the ASCII string is hashed into a digest, which is used to initialize
the starting handshake state. In the context of Brontide, the ASCII string
describing the protocol is: `Noise_XK_secp256k1_ChaChaPoly_SHA256`.
==== Brontide: A Handshake in Three Acts
==== Handshake in Three Acts
The handshake portion of Brontide can be see prated into three distinct "acts".
The entire handshake takes 1.5 round trips between the initiator and responder.
@ -238,33 +255,33 @@ handshake as:
* `ECDH(k, rk)`: performs an Elliptic-Curve Diffie-Hellman operation using
`k`, which is a valid `secp256k1` private key, and `rk`, which is a valid public key
* The returned value is the SHA256 of the compressed format of the
** The returned value is the SHA256 of the compressed format of the
generated point.
* `HKDF(salt,ikm)`: a function defined in `RFC 5869`<sup>[3](#reference-3)</sup>,
evaluated with a zero-length `info` field
* All invocations of `HKDF` implicitly return 64 bytes of
** All invocations of `HKDF` implicitly return 64 bytes of
cryptographic randomness using the extract-and-expand component of the
`HKDF`.
* `encryptWithAD(k, n, ad, plaintext)`: outputs `encrypt(k, n, ad, plaintext)`
* Where `encrypt` is an evaluation of `ChaCha20-Poly1305` (IETF variant)
** Where `encrypt` is an evaluation of `ChaCha20-Poly1305` (IETF variant)
with the passed arguments, with nonce `n` encoded as 32 zero bits,
followed by a *little-endian* 64-bit value. Note: this follows the Noise
Protocol convention, rather than our normal endian.
* `decryptWithAD(k, n, ad, ciphertext)`: outputs `decrypt(k, n, ad, ciphertext)`
* Where `decrypt` is an evaluation of `ChaCha20-Poly1305` (IETF variant)
** Where `decrypt` is an evaluation of `ChaCha20-Poly1305` (IETF variant)
with the passed arguments, with nonce `n` encoded as 32 zero bits,
followed by a *little-endian* 64-bit value.
* `generateKey()`: generates and returns a fresh `secp256k1` keypair
* Where the object returned by `generateKey` has two attributes:
* `.pub`, which returns an abstract object representing the public key
* `.priv`, which represents the private key used to generate the
** Where the object returned by `generateKey` has two attributes:
*** `.pub`, which returns an abstract object representing the public key
*** `.priv`, which represents the private key used to generate the
public key
* Where the object also has a single method:
* `.serializeCompressed()`
** Where the object also has a single method:
*** `.serializeCompressed()`
* `a || b` denotes the concatenation of two byte strings `a` and `b`
@ -529,23 +546,9 @@ creating a decryption oracle.
The structure of packets on the wire resembles the following:
```
+-------------------------------
|2-byte encrypted message length|
+-------------------------------
| 16-byte MAC of the encrypted |
| message length |
+-------------------------------
| |
| |
| encrypted Lightning |
| message |
| |
+-------------------------------
| 16-byte MAC of the |
| Lightning message |
+-------------------------------
```
[[noise_encrypted_packet]]
.Encrypted Packet Structure
image::images/noise_encrypted_packet.png["Encrypted Packet Structure"]
The prefixed message length is encoded as a 2-byte big-endian integer, for a
total maximum packet length of `2 + 16 + 65535 + 16` = `65569` bytes.
@ -606,3 +609,11 @@ Key rotation for a key `k` is performed according to the following steps:
3. Reset the nonce for the key to `n = 0`.
4. `k = k'`
5. `ck = ck'`
=== Conclusion
Lightning's underlying transport encryption, known as _Brontide_, is based on the Noise protocol and offers strong security guarantees of privacy, authenticity and integrity for all communications between Lightning peers.
Unlike Bitcoin where peers often communicate "in the clear" (without encryption), all Lightning communications are encrypted peer-to-peer. In addition to transport encryption (peer-to-peer), in the Lightning Network payments are *also* encrypted into onion packets (hop-to-hop) and payment details are sent out-of-band between the sender and recipient (end-to-end). The combination of all these security mechanisms is cumulative and provides layered defense against de-anonymization, man-in-the-middle attacks and network surveillance.
Of course, no security is perfect and we will see in <<security_and_privacy>> that these properties can be degraded and attacked. However, the Lightning Network significantly improves upon the privacy of Bitcoin.

@ -1,22 +1,28 @@
[appendix]
[[invoices]]
[[lightning_payment_requests]]
[[payment_requests]]
== Lightning Payment Requests
In this chapter we will look at _Lightning Payment Requests_ or as they are more commonly known _Lightning Invoices_.
=== Invoices in the Lightning Protocol Suite
_Payment Requests_, aka _Invoices_ are part of the Payment Layer and are show in the upper left of <<LN_payment_request_highlight>>:
[[LN_payment_request_highlight]]
.The Lightning Network Protocol Suite
image::images/LN_payment_request_highlight.png["The Lightning Network Protocol Suite"]
=== Introduction
As we've learned in prior chapters, minimally two pieces of data are required
As we've learned throughout the book, minimally two pieces of data are required
to complete a Lightning payment: a payment hash, and a destination. As
`SHA-256` is used in the Lightning Network to implement HTLCs, this information
requires 32-bytes in order to communicate. Destinations on the other hand are
simply the `secp256k1` public key of the node that wishes to receive a payment.
The purpose of a payment request in the context of the Lightning Network is to
communicate these two pieces of information from sender to receiver. BOLT 11 is
the name of the document in the set of Lightning Network specifications that
describes a QR-code friendly format for communicating the information required
to complete a payment from receiver to sender. In practice, more than just the
communicate these two pieces of information from sender to receiver. The QR-code friendly format for communicating the information required
to complete a payment from receiver to sender, is described in https://github.com/lightningnetwork/lightning-rfc/blob/master/11-payment-encoding.md[BOLT #11 - Invoice Protocol for Lightning Payments]. In practice, more than just the
payment hash and destination are communicated in a payment request in order to
make the encoding more fully feature.
@ -25,7 +31,7 @@ make the encoding more fully feature.
A commonly asked question when people first encounter a Lightning Payment
request is: why can't a normal static address format be used instead?
In order to answer this question, one must first internalize how Lightning
In order to answer this question, you must first internalize how Lightning
differs from base layer Bitcoin as a payment method. Compared to a Bitcoin
address which may be used to make a potentially unbounded number of payments
(though re-using a Bitcoin address may degrade one's privacy), a Lightning
@ -41,16 +47,13 @@ the payment pre-image is for practical purposes a nonce (number only used
once). If the sender attempts to make another payment using that identical
payment hash, then they risk losing funds, as the payment may not actually be
delivered to the destination. It's safe to assume that after a pre-image has
been reveled, all nodes in the path will keep it around _forever_, then rather
been reveled, all nodes in the path will keep it around forever, then rather
than forward the HTLC in order to collect a routing fee if the payment is
completed, they can simply _settle_ the payment at that instance and gain the
completed, they can simply settle the payment at that instance and gain the
entire payment amount in return. As a result, it's unsafe to ever use a payment
request more than once.
As we'll see later in the book, there exist new variants of the original
Lightning Payment request that allow the sender to -reuse them as many times as
they want. These variants flip the normal payment flow as the sender transmits
a pre-image within the encrypted onion payload to the receiver, who is the only
New variants of the original Lightning Payment request exist that allow the sender to reuse them as many times as they want. These variants flip the normal payment flow as the sender transmits a pre-image within the encrypted onion payload to the receiver, who is the only
one that is able to decrypt it and settle the payment. Alternatively, assuming
a mechanism that allows a sender to typically request a new payment request
from the receiver, then an interactive protocol can be used in order to allow a
@ -63,7 +66,7 @@ information required to complete a payment on the Lightning Network. As
mentioned earlier, the payment hash and destination is the minimum amount of
information required to complete a payment. However in practice, more
information such as time-lock information, payment request expiration, and
possibly an on-chain fallback address are also communicated.
possibly an on-chain fallback address are also communicated. The full specification document is https://github.com/lightningnetwork/lightning-rfc/blob/master/11-payment-encoding.md[BOLT #11 - Invoice Protocol for Lightning Payments]
==== Payment Request Encoding in Practice
@ -124,11 +127,10 @@ A full list of the currently defined multipliers is a follows:
|==============================================
==== Bech32 & the Data Segment
If the "unreadable" portion of looks familiar, then that's because it uses the
very same encoding scheme as segwit compatible Bitcoin addresses use today,
very same encoding scheme as Segwit compatible Bitcoin addresses use today,
namely `bech32`. Describing the `bech32` encoding scheme is outside the scope
of this chapter. In brief, it's a sophisticated way to encode short strings
that has very good error correction as well as detection properties.
@ -144,13 +146,13 @@ timestamp allows the sender to gauge how old the invoice is, and as we'll see
later, allows the receiver to force an invoice to only be valid for a period of
time if they wish.
Similar to the TLV format we learned about in Chapter XXX, the BOLT 11 invoice
Similar to the TLV format we learned about in <<tlv>>, the BOLT 11 invoice
format uses a series of extensible key-value pairs to encode information
needed to satisfy a payment. As key-value pairs are used, it's easy for add
new values in the future if a new payment type or additional
requirement/functionality is introduced.
Finally a signature is included ed that covers the entire invoice signed by the
Finally a signature is included that covers the entire invoice signed by the
destination of the payment. This signature allows the sender to verify that the
payment request was indeed created by the destination of the payment. Unlike
Bitcoin payment request's which aren't signed, this allows us to ensure that a
@ -178,7 +180,7 @@ A full list of all the currently defined tagged fields is as follows:
.BOLT 11 Tagged Invoice Fields
[options="header"]
|==================================================================================================================================================
|===
|Field Tag|Data Length|Usage
|`p`|`52`|The `SHA-256` payment hash.
|`s`|`52`|A `256-bit` secret that increase the end to end privacy of a payment by mitigating probing by intermediate nodes.
@ -190,7 +192,7 @@ A full list of all the currently defined tagged fields is as follows:
|`f`|Variable|A fall back on-chain address to be used to complete the payment if the payment cannot be completed over LN.
|`r`|Variable|One or more entries that allow a receiver to give the sender additional ephemeral edges to complete the payment.
`9`|Variable|A set of 5-bit values that contain the feature bits that are required in order to complete the payment.
|==================================================================================================================================================
|===
The elements contained in the field `r` are commonly referred to as "routing
hints". They allow the receiver to communicate an extra set of edges that may
@ -212,3 +214,7 @@ payment. As an example, if a new payment type is added in the future that isn't
backwards compatible with the original payment type, then the receiver can set
a _required_ feature bit in order to communicate that the payer needs to
underhand that feature in order to complete the payment.
=== Conclusion
As we have seen, invoices are a lot more than just a request for an amount. They contain critical information about _how_ to make the payment, such as "routing hints", the destination node's public key, ephemeral keys to increase security and much more.

@ -20,7 +20,7 @@ Then, they would describe the relevant properties of the system and check whethe
A security model is based on a set of underlying _security assumptions_.
In cryptographic systems, these assumptions are often centered around the mathematical properties of the cryptographic primitives such as ciphers, signatures, and hash functions.
The security assumptions of the Lightning Network are that the ECDSA signatures, SHA-256 hash function, and other cryptographic functions used in the protocol behave within their security definitions.
For example, we assume that it is practically impossible to find a preimage of a hash function.
For example, we assume that it is practically impossible to find a preimage (and second preimage) of a hash function.
This allows the LN to rely on the HTLC mechanism (which uses the preimage of a hash function) for the atomicity of multi-hop payments: nobody except the final recipient can reveal the payment secret and resolve the HTLC.
We also assume a degree of connectivity in the network, namely, that Lightning channels form a connected graph. Therefore, it is possible to find a path from any sender to any receiver. Finally, we assume network messages are propagated within certain timeouts.
@ -110,13 +110,14 @@ Multiple companies have been established to deanonymize users of Bitcoin and oth
At first glance, Lightning provides better privacy than Bitcoin because Lightning payments are not broadcast to the whole network.
While this improves the privacy baseline, other properties of the Lightning protocol may make anonymous payments more challenging.
For instance, larger payments may have fewer routing options.
This may allow an adversary who controls well-capitalized nodes to route most large payments and discover payment amounts and probably other details.
This may allow an adversary who controls well-capitalized nodes to route most large payments and discover payment amounts and probably other details. Over time, as the Lightning Network grows, this may become less of a problem.
Another relevant difference between Lightning and Bitcoin is that Lightning nodes maintain a permanent identity, whereas Bitcoin nodes do not.
A sophisticated Bitcoin user can easily switch nodes used to receive blockchain data and broadcast transactions.
A Lightning user, on the contrary, sends and receives payments through the nodes they have used to open their payment channels.
Moreover, the Lightning protocol assumes that routing nodes announce their IP address in addition to their node ID.
This creates a permanent link between node IDs and IP addresses, which may be dangerous, considering that an IP address is often an intermediary step in anonymity attacks linked to the user's physical location and, in most cases, real-world identity.
It is possible to use Lightning over Tor, but many nodes https://1ml.com/statistics[do not use] this functionality.
It is possible to use Lightning over Tor, but many nodes do not use this functionality, as can be seen from https://1ml.com/statistics[statistics collected from node announcements].
A Lightning user, when sending a payment, has its neighbors in its anonymity set.
Specifically, a routing node only knows the immediately preceding and following nodes.
@ -125,7 +126,7 @@ Therefore, the anonymity set of a node in Lightning roughly equals its neighbors
[[anonymity_set]]
.The anonymity set of Alice and Bob constitutes their neighbors.
image:images/anon-set.png[]
image::images/anon-set.png["The anonymity set of Alice and Bob constitutes their neighbors"]
Similar logic applies to payment receivers.
Many users open only a handful of payment channels, therefore, limiting their anonymity sets.
@ -172,7 +173,7 @@ An off-path adversary tries to assess the sender and the receiver of a payment w
An on-path adversary can leverage any information it might gain by routing the payment of interest.
First, consider the *off-path adversary*.
In the first step of this attack scenario, a potent off-path adversary deduces the individual balances in each payment channel via probing (described in a subsequent section) and forms a network snapshot at time _t1_. For simplicty sake, let's make _t1_ equal 12:05.
In the first step of this attack scenario, a potent off-path adversary deduces the individual balances in each payment channel via probing (described in a subsequent section) and forms a network snapshot at time _t1_. For simplicity's sake, let's make _t1_ equal 12:05.
It then probes the network again at sometime later at time _t2_, which we'll make 12:10. The attacker would then compare the snapshots at 12:10 and 12:05 and use the differences between the two snapshots to infer information about payments that took place by looking at paths that have changed.
In the simplest case, if only one payment occurred between 12:10 and 12:05, the adversary would observe a single path where the balances have changed by the same amounts.
Thus, the adversary learns almost everything about this payment: the sender, the recipient, and the amount.
@ -180,7 +181,7 @@ If multiple payment paths overlap, the adversary needs to apply heuristics to id
Now, we turn our attention to an *on-path adversary*.
Such an adversary might seem convoluted.
However, in June 2020, researchers noted that the single most central node could https://arxiv.org/pdf/2006.12143.pdf[observed] close to 50% of all LN payments, while the four most central nodes https://arxiv.org/pdf/1909.06890.pdf[observe] an average of 72% payments.
However, in June 2020, researchers noted that the single most central node https://arxiv.org/pdf/2006.12143.pdf[observed] close to 50% of all LN payments, while the four most central nodes https://arxiv.org/pdf/1909.06890.pdf[observe] an average of 72% payments.
These findings emphasize the relevance of the on-path attacker model.
Even though intermediaries in a payment path only learn their successor and predecessor, there are several leakages that a malicious or honest-but-curious intermediary might use to infer the sender and the receiver.
@ -240,7 +241,7 @@ Note that in any case, Mallory's estimation becomes twice as precise after just
She can continue probing, choosing the next probing amount such that it divides the current estimation interval in half.
This well-known search technique is called _binary search_.
With binary search, the number of probes is _logarithmic_ in the desired precision.
For example, to obtain Alice's balance in a channel of 1 million satoshis up to a single satoshi, Mallory would only have to perform stem:[\log_2(1000000) \approx 20] probings.
For example, to obtain Alice's balance in a channel of 1 million satoshis up to a single satoshi, Mallory would only have to perform latexmath:[\log_2(1000000) \approx 20] probings.
If one probing takes 3 seconds, one channel can be precisely probed in only about a minute!
Channel probing can be made even more efficient.
@ -273,14 +274,6 @@ First, it is hard for an attacker to target unannounced channels.
Second, nodes that implement just-in-time or JIT routing may be less prone to the attack.
Finally, as multi-part payments make the problem of insufficient capacity less severe, the protocol developers may consider hiding some of the error details without harming efficiency.
References:
* Jordi Herrera-Joancomartí et al. https://eprint.iacr.org/2019/328[On the Difficulty of Hiding the Balance of Lightning Network Channels]
* Nisslmueller et al. https://arxiv.org/abs/2003.00003[Toward Active and Passive Confidentiality Attacks On Cryptocurrency Off-Chain Networks]
* Tikhomirov et al. https://arxiv.org/abs/2004.00333[Probing Channel Balances in the Lightning Network]
* Kappos et al. https://arxiv.org/abs/2003.12470[An Empirical Analysis of Privacy in the Lightning Network]
* https://github.com/LN-Zap/zap-desktop/blob/v0.7.2-beta/services/grpc/router.methods.js[Zap source code with the probing function]
==== Denial of service
When resources are made publicly available, there is a risk that attackers may attempt to make that resource unavailable by executing a denial-of-service attack.
@ -288,7 +281,7 @@ Generally, this is achieved by the attacker bombarding a resource with requests,
The attacks seldom result in the target suffering financial loss aside from the opportunity cost of their service being down and are merely intended to grief the target.
Typical mitigations for denial-of-service attacks require authentication for requests to separate legitimate users from malicious ones or to incur a trivial cost to regular users but will act as a sufficient deterrent to an attacker launching requests at scale.
Anti-denial-of-service measures can be seen everywhere on the internet - websites apply rate limits to ensure that no one user can consume all of their server's attention, film review sites require login authentication to keep angry r/prequelmemes members at bay, and API keys are purchased to allow a limited number of hits.
Anti-denial-of-service measures can be seen everywhere on the internet - websites apply rate limits to ensure that no one user can consume all of their server's attention, film review sites require login authentication to keep angry r/prequelmemes (Reddit group) members at bay, and data services sell API keys to limit the number of queries.
===== DoS in Bitcoin
@ -326,7 +319,7 @@ In the absence of fees for failed payments, the only cost to the attacker is the
==== Commitment jamming
Lightning nodes update their shared state using asymmetric commitment transactions, on which HTLCs are added and removed to facilitate payments.
Each party is limited to a total of https://github.com/lightningnetwork/lightning-rfc/blob/c053ce7afb4cbf88615877a0d5fc7b8dbe2b9ba0/02-peer-protocol.md#the-open_channel-message[483] on the commitment at a time.
Each party is limited to a total of https://github.com/lightningnetwork/lightning-rfc/blob/c053ce7afb4cbf88615877a0d5fc7b8dbe2b9ba0/02-peer-protocol.md#the-open_channel-message[483] HTLCs in the commitment transaction at a time.
A channel jamming attack allows an attacker to render a channel unusable by routing 483 payments through the target channel and holding them until they timeout.
It should be noted that this limit was chosen in the specification to ensure that all the HTLCs can be swept in a https://github.com/lightningnetwork/lightning-rfc/blob/master/05-onchain.md#penalty-transaction-weight-calculation[single justice transaction].
@ -338,11 +331,6 @@ A channel liquidity lockup attack is comparable to a channel jamming attack in t
Rather than locking up slots on the channel commitment, this attack routes large HTLCs through a target channel that consumes all the channel's available bandwidth.
This attack's capital commitment is higher than the commitment jamming attack because the attacking node needs more funds to route failed payments through the target.
References:
* Mizrahi, A., Zohar, A. https://arxiv.org/abs/2002.06564[Congestion Attacks in Payment Channel Networks]
=== Cross-layer deanonymization
Computer networks are often layered.
@ -359,7 +347,7 @@ However, creating and closing payment channels are inherently performed on the B
Consequently, for a complete analysis of LN's privacy provisions, one needs to consider every layer of the technological stack users might interact with.
Specifically, a deanonymizing adversary can and will use off-chain and on-chain data to cluster or link LN nodes to corresponding Bitcoin addresses.
What might be the goals of a deanonymizing attacker in a cross-layer context?
Some of the goals of attackers attemptin to deanonymize LN users, in a cross-layer context:
* Cluster Bitcoin addresses owned by the same user (layer-1). We call these Bitcoin entities.
* Cluster LN nodes owned by the same user (layer-2).
@ -433,15 +421,7 @@ Therefore, many of its properties (privacy, robustness, connectivity, routing ef
In this section, we discuss and analyze the LN from the point of view of network science.
We are particularly interested in understanding the LN channel graph, its robustness, connectivity, and other important characteristics.
==== What is a graph anyway?
A graph is a mathematical model that consists of nodes and edges (connections between nodes).
In the LN, nodes represent LN nodes, and edges represent payment channels between them.
In many cases, just like in the LN, edges can have attributes, for instance, numerical values.
In the case of LN, these attributes can represent a channel's capacity.
We call the degree of a node the number of edges (payment channels) it has.
==== How does the Lightning graph look like in reality?
==== How does the Lightning graph look in reality?
One could have expected that the LN is a random graph, where edges are randomly formed between nodes.
If this was the case, then the LN's degree distribution would follow a Gaussian normal distribution.
In particular, most of the nodes would have approximately the same degree, and we would not expect nodes with extraordinarily large degrees.
@ -494,11 +474,11 @@ However, depending on the utilized attack vector, the adversary may have to prov
The LN is a dynamically changing, permissionless network.
Nodes can freely join or leave the network, they can open and create payment channels anytime they want.
Therefore, a single static snapshot of the LN graph is misleading. We need to consider the temporality and ever-changing nature of the network. For now, the LN graph is growing in terms of the number of nodes and payment channels.
Its effective diameter is also shrinking; that is, nodes become closer to each other, as we can see in <<temporal_ln>>.
Its effective diameter is also shrinking; that is, nodes become closer to each other, as we can see in <<temporal_ln>>:
temporal_ln]]
[[temporal_ln]]
.The steady growth of the LN in terms of nodes, channels and locked capacity.
image:images/ln-over-time.png[]
image::images/ln-over-time.png["The steady growth of the LN in terms of nodes, channels and locked capacity"]
In social networks, triangle closing behavior is common.
Specifically, in a graph where nodes represent people and friendships are represented as edges, it is somewhat expected that triangles will emerge in the graph.
@ -519,11 +499,11 @@ For a precise definition of central point dominance, the reader is referred to h
The larger the central point dominance of a network is, the more centralized the network is.
We can observe that the LN has a greater central point dominance, ie. it is more centralized, than a random graph (Erdős-Rényi graph) or a scale-free graph (Barabási-Albert graph) of equal size.
However, we also note, that over time the central point dominance of the LN gradually decreases as the network grows and densifies, as shown in <<central_point_dominance_ln>>.
However, we also note, that over time the central point dominance of the LN gradually decreases as the network grows and densifies, as shown in <<central_point_dominance_ln>>:
[[central_point_dominance_ln]]
.Central point dominance of the LN, a random graph (ER) and a scale-free graph (BA) of equal size.
image:images/central-point-dominance.png[]
image::images/central-point-dominance.png["Central point dominance of the LN, a random graph (ER) and a scale-free graph (BA) of equal size"]
In general, our understanding of the dynamic nature of the LN channel graph is rather limited.
It is fruitful to analyze how protocol changes like multi-part payments can affect the dynamics of the LN.
@ -543,8 +523,7 @@ Let's look at some of the relevant incentives:
- While we should not base our security assumptions on altruism, to a certain extent, altruistic behavior drives Bitcoin (accepting incoming connections, serving blocks).
- What role does it play in Lightning?
A recent paper has shown that LN nodes are mostly altruistic.
Specifically, the earned routing fees do not compensate for the opportunity costs stemming from liquidity lock-up.
In the early stages of the Lightning Network, many node operators have claimed that the earned routing fees do not compensate for the opportunity costs stemming from liquidity lock-up. This would indicate that operating a node may be driven mostly by altruistic incentives "for the good of the network".
This might change in the future if LN has significantly larger traffic or if a market for routing fees emerge.
On the other hand, if a node wishes to optimize its routing fees, it would minimize the average shortest path lengths to every other node.
Put differently, a profit-seeker node will try to locate itself in the _center_ of the channel graph or close to it.
@ -555,10 +534,32 @@ We're still in the early stages of the Lightning Network.
Many of the concerns listed in this chapter are likely to be addressed as it matures and grows.
In the meantime, there are some measures that you can take to guard your node against malicious users; something as simple as updating the default parameters that your node runs with can go a long way in hardening your node.
==== Private channels
If you primarily intend to use your node for personal sends and receives you may not need to open public channels to the network. By maintaining private channels, you significantly reduce the risk of a denial-of-service attack on your node and may find it easier to utilize your channel bandwidth since the private channels will only be used to receive or send directly to your node.
== Unannounced channels
If you intend to use the Lightning Network to send and receive funds between nodes and wallets you control, and have no interest in routing other users' payments, there is little need to announce your channels to the rest of the network.
You could open a channel between, say, your desktop PC running a full node and your mobile phone running a Lightning Wallet and simply forgo the channel announcement discussed in Chapter 3.
These are sometimes called "private" channels, however it is more correct to refer to them as "unannounced" channels as they are not strictly private.
Unannounced channels will not be known to the rest of the network and won't normally be used to route other users' payments.
They can still be used to route payments if other nodes are made aware of them, for example an invoice could contain routing hints which suggests a path with an unannounced channel.
However, assuming that you've only opened an unannounced channel with yourself, you do gain some measure of privacy.
Since you are not exposing your channel to the network, you lower the risk of a denial-of-service attack on your node.
You can also more easily manage the capacity of this channel, since it will only be used to receive or send directly to your node.
There are also advantages to opening an unannounced channel with a known party that you transact with frequently.
For example, if Alice and Bob frequently play poker for bitcoin, they could open a channel to send their winnings back and forth.
Under normal conditions, this channel will not be used to route payments from other users or collect fees.
And since the channel will not be known to the rest of the network, any payments between Alice and Bob cannot be inferred by tracking changes in the channel's routing capacity.
This confers some privacy to Alice and Bob, however if one of them decides to make other users aware of the channel, such as by including it in the routing hints of an invoice, then this privacy is lost.
It should also be noted that to open an unannounced channel, a public transaction must be made on the Bitcoin blockchain.
Hence it is possible to infer the existence and size of the channel if a malicious party is monitoring the blockchain for channel opening transactions and attempting to match them to channels on the network.
Furthermore, when the channel is closed, the final balance of the channel will be made public once it's committed to the Bitcoin blockchain.
However, since the opening and commitment transactions are pseudonymous it will not be a simple matter to connect it back to Alice or Bob.
In addition, the Taproot update of 2021 makes it difficult to distinguish between channel opening and closing transactions and other specific kinds of Bitcoin transactions.
Hence, while unannouned channels are not completely private, they do provide some privacy benefits when used carefully.
==== Routing considerations
=== Routing considerations
As covered in the <<denial_of_service>> section, nodes that open public channels expose themselves to the risk of a series of attacks on their channels.
While mitigations are being developed on the protocol level, there are many steps that a node can take to protect against denial of service attacks on their public channels.
@ -572,10 +573,6 @@ Some useful guidelines for a custom rate limiter are as follows:
* Shadow channels: nodes that wish to open large channels to a single target can instead open a single public channel to the target and support it with further private channels called [shadow channels](joost on TFTC).
These channels can still be used for routing but are not announced to potential attackers.
References:
* Jager, J. https://anchor.fm/tales-from-the-crypt/episodes/197-Joost-Jager-ekghn6[Tales from the Crypt Episode 197]
==== Accepting channels
At present, Lightning nodes struggle with bootstrapping inbound liquidity. While there are some paid
solutions to acquiring inbound liquidity, like swap services, channel markets, and paid channel opening services from known hubs, many nodes will gladly accept any legitimate looking channel opening request to increase their inbound liquidity.
@ -603,3 +600,23 @@ Some potential strategies are:
=== Conclusion
In summary, privacy and security are nuanced, complex topics and while many researchers and developers are looking for network-wide improvements, it's important for everyone participating in the network to understand what they can do to protect their own privacy and increase security on an individual node level.
=== References and further reading
In this chapter, we used many references from ongoing research on Lightning security. You may find these useful articles and papers listed by topic below:
===== Privacy and probing attacks
* Jordi Herrera-Joancomartí et al. https://eprint.iacr.org/2019/328[On the Difficulty of Hiding the Balance of Lightning Network Channels]
* Nisslmueller et al. https://arxiv.org/abs/2003.00003[Toward Active and Passive Confidentiality Attacks On Cryptocurrency Off-Chain Networks]
* Tikhomirov et al. https://arxiv.org/abs/2004.00333[Probing Channel Balances in the Lightning Network]
* Kappos et al. https://arxiv.org/abs/2003.12470[An Empirical Analysis of Privacy in the Lightning Network]
* https://github.com/LN-Zap/zap-desktop/blob/v0.7.2-beta/services/grpc/router.methods.js[Zap source code with the probing function]
===== Congestion attacks
* Mizrahi, A., Zohar, A. https://arxiv.org/abs/2002.06564[Congestion Attacks in Payment Channel Networks]
===== Routing considerations
* Jager, J. https://anchor.fm/tales-from-the-crypt/episodes/197-Joost-Jager-ekghn6[Tales from the Crypt Episode 197]

@ -0,0 +1,73 @@
[[conclusion_chapter]]
== Conclusion
In just a few years, the Lightning Network has gone from a whitepaper to a rapidly growing global network. As Bitcoin's second layer it has delivered on the promise of fast, inexpensive, and private payments. Additionally, it has started a tsunami of innovation, as it unleashes developers from the constraints of lock-step consensus that exist in Bitcoin development.
Innovation in the Lightning Network is happening in several different levels:
* At Bitcoin's Core protocol, providing use and demand for new Bitcoin Script opcodes, signing algorithms, and optimizations
* At the Lightning protocol level with new features deployed rapidly network-wide.
* At the payment channel level, with new channel constructs and enhancements
* As distinct opt-in features deployed end-to-end by independent implementations that senders and recipients can use if they want.
* With new and exciting Lightning Applications (LApps) build on top of the clients and protocols.
Let's look at how these innovations are changing Lightning now and in the near future.
=== Decentralized and asynchronous innovation
Lightning isn't bound by lock-step consensus, as is the case with Bitcoin. That means that different Lightning clients can implement different features and negotiate their interactions (see <<feature_bits>>). As a result, innovation in the Lightning Network is occurring at a much faster rate than in Bitcoin.
Not only is Lightning advancing rapidly, but it is creating demand for new features in the Bitcoin system. Many recent and planned innovations in Bitcoin are both motivated and justified by their use in the Lightning Network. In fact, the Lightning Network is often mentioned as an example use-case for many of the new features.
==== Bitcoin protocol and Bitcoin Script innovation
The Bitcoin system is, by necessity, a conservative system that has to preserve compatibility with consensus rules to avoid unplanned forks of the blockchain or partitions of the P2P network. As a result, new features require a lot of coordination and testing before they are implemented in "mainnet", the live production system.
Here are some of the current or proposed innovations spurred by Lightning:
Neutrino:: A lightweight client protocol with improved privacy features over the legacy SPV protocol. Neutrino is mostly used by Lightning clients to access the Bitcoin blockchain.
Schnorr signatures:: Introduced as part of the _Taproot_ soft fork, Schnorr signatures will enable flexible Point Time-Locked Contracts (PTLC) for channel construction in Lightning.
Taproot:: Also part of the November 2021 soft-fork that introduces Schnorr signatures, Taproot allows complex scripts to appear as single-payer, single-payee payments, and indistinguishable from the most common type of payment on Bitcoin. This will allow Lightning channel cooperative (mutual) closure transactions to appear indistinguishable from simple payments and increase privacy for LN users.
Input re-binding:: Also known by the names SIGHAS_NOINPUT, or SIGHASH_ANYPREVOUT, this planned upgrade to the Bitcoin Script language is primarily motivated by advanced smart contracts such as the eltoo channel protocol.
Covenants:: Currently in the early stages of research, coventants allow transactions to create outputs that constrain future transactions which spend them. This mechanism could increase security for Lightning channels, by making it possible to enforce address whitelisting in commitment transactions.
==== Lightning protocol innovation
The Lightning P2P protocol is highly extensible and has undergone a lot of change since its inception. The "It's OK to be odd" rule used in feature bits (see <<feature_bits>>) ensure that nodes can negotiate the features they support, enabling multiple independent upgrades to the protocol.
===== TLV extensibility
The Type-Length-Value (see <<tlv>>) mechanism for extending the messaging protocol is extremely powerful and has already enabled the introduction of several new capabilities in Lightning while maintaining both forward and backward compatibility.
==== Payment channel construction
Payment channels are an abstraction that is operated by two channel partners. As long as those two are willing to run new code, they can implement a variety of channel mechanisms simultaneously. In fact, recent research suggests that channels could even be upgraded to a new mechanism dynamically, without closing the old channel and opening a new channel type.
Eltoo:: A proposed channel mechanism that uses input-rebinding to significantly simplify the operation of payment channels and remove the need for the penalty mechanism. It needs a new Bitcoin signature type before it can be implemented
==== Opt-in end-to-end features
Point Time-Locked Contracts (PTLCs):: A different approach to HTLCs, PTLCs can increase privacy, reduce information leaked to intermediary nodes and operate more efficiently than HTLC-based channels.
Large channels:: Large or "Wumbo" channels were introduced in a dynamic way to the network without requiring coordination. Channels that support large payments are advertized as part of the channel announcement messages and can be used in an opt-in manner.
Multi-Part Payments (MPP):: MPP was also introduced in an opt-in manner, but even better only requires the sender and recipient of a payment to be able to do MPP. The rest of the network simply routes HTLCs as if they are single-part payments.
Keysend:: An upgrade introduced independently by Lightning client implementations, it allows the sender to send money in an "unsolicited" and asynchronous way without requiring an invoice first.
HODL invoices:: Payments where the final HTLC is not collected, committing the sender to the payment, but allowing the recipient to delay collection until some other condition is satisfied, or cancel the invoice without collection. This was also implemented independently by different Lightning clients and can be used opt-in.
Onion routed message services:: The onion routing mechanism, and the underlying public key databse of nodes can be used to send data that is unrelated to payments, such as text messages or forum posts. The use of Lightning to enable paid messaging as a solution to spam posts and sybil attacks (spam) is another innovation that was implemented independently of the core protocol.
[[lapps]]
=== Lightning Applications (LApps)
While still in their infancy, we are already seeing the emergence of interesting Lightning Applications. Broadly defined as an application that uses the Lightning Protocol or a Lightning client as a component, LApps are the application layer of Lightning. LApps are being built for simple games, messaging applications, micro-services, payable-APIs, paid dispensers (eg. fuel pumps), derivative trading systems, and much more.
=== Ready, set, go!
The future is looking bright. The Lightning Network is taking Bitcoin to new unexplored markets and applications. Equipped with the knowledge in this book, you can explore this new frontier, or maybe even join as a pioneer and forge a new path.

@ -1,7 +1,12 @@
# Mastering the Lightning Network
[![Build Status](https://travis-ci.com/lnbook/lnbook.svg?branch=develop)](https://travis-ci.com/lnbook/lnbook)
# STATUS: IN PRODUCTION
NO EDITS OR PULL REQUESTS ARE ACCEPTED AT THIS TIME.
The book is currently (Sep 2021) in final production. No changes will be accepted.
<img src="images/cover_thumb.png" width=200 alt="Mastering Lightning Cover">
## About
@ -11,12 +16,6 @@ The book describes the Lightning Network (LN), a Peer-to-Peer protocol running o
The book is suitable for technical readers with an understanding of the fundamentals of Bitcoin and other open blockchains.
## Status
The current status of the book is "IN PRODUCTION": ONLY COPY-EDIT CONTRIBUTIONS ARE ACCEPTED.
See below for status of specific chapters and read the contribution guide to learn how and where to contribute.
### Legend
* :arrows_clockwise: LIVE EDITS - Continuously changing: Submit focused/small Issues and PRs
@ -30,37 +29,35 @@ See below for status of specific chapters and read the contribution guide to lea
|-------|------|:------:|
| PART 1 | PART 1 | PART 1 |
| [Preface and Acknowledgments](preface.asciidoc) | #### | :heavy_check_mark: |
| [Glossary](glossary.asciidoc) | ############## | :arrows_clockwise: |
| [Glossary](glossary.asciidoc) | ############## | :heavy_check_mark: |
| [Introduction](01_introduction.asciidoc) | ########## | :heavy_check_mark: |
| [Getting Started](02_getting_started.asciidoc) | ############# | :heavy_check_mark: |
| [LN Basics (How LN Works)](03_how_ln_works.asciidoc) | ########################### | :heavy_check_mark: |
| [Nodes (LN Clients)](04_node_client.asciidoc) | #################### | :heavy_check_mark: |
| [Operating a Node](05_node_operations.asciidoc) | ############################ | :heavy_check_mark: |
| [Nodes (LN Clients)](04_node_client.asciidoc) | ################## | :heavy_check_mark: |
| [Operating a Node](05_node_operations.asciidoc) | ############################# | :heavy_check_mark: |
| PART 2 | PART 2 | PART2 |
| [Lightning Architecture](06_lightning_architecture.asciidoc) | # | :heavy_check_mark: |
| [Payment Channels in Detail](07_payment_channels.asciidoc) | ################### | :heavy_check_mark: |
| [Payment Channels in Detail](07_payment_channels.asciidoc) | #################### | :heavy_check_mark: |
| [Routing (HTLCs)](08_routing_htlcs.asciidoc) | ################ | :heavy_check_mark: |
| [Channel operation and HTLC settlement](09_channel_operation.asciidoc) | ####### | :heavy_check_mark: |
| [Onion Construction and Routing](10_onion_routing.asciidoc) | ################ | :heavy_check_mark: |
| [Onion Construction and Routing](10_onion_routing.asciidoc) | ################# | :heavy_check_mark: |
| [Channel Graph and Gossip Layer](11_gossip_channel_graph.asciidoc) | ############ | :heavy_check_mark: |
| [Payment Path Finding](12_path_finding.asciidoc) | ############ | :heavy_check_mark: |
| [LN Security and Privacy](13_security_privacy_ln.asciidoc) | ################ | :heavy_check_mark: |
| [Wire Protocol](13_wire_protocol.asciidoc) | ######### | :heavy_check_mark: |
| [Encrypted Message Transport (Brontide)](14_encrypted_transport.asciidoc) | ########## | :heavy_check_mark: |
| [Payment Requests (Invoices)](15_payment_requests.asciidoc) | #### | :heavy_check_mark: |
| [LN Security and Privacy](16_security_privacy_ln.asciidoc) | ################# | :heavy_check_mark: |
| APPENDICES | APPENDICES | APPENDICES |
| [A1 - Bitcoin Fundamentals Review](appendix-bitcoin-fundamentals-review.asciidoc) | ########### | :heavy_check_mark: |
| [A2 - Payment Requests (Invoices)](appendix_payment_requests.asciidoc) | #### | :heavy_check_mark: |
| [A3 - Wire Protocol](appendix_wire_protocol.asciidoc) | ################# | :heavy_check_mark: |
| [A4 - Encrypted Message Transport (Brontide)](appendix_encrypted_transport.asciidoc) | ########## | :heavy_check_mark: |
| [A5 - License Notices](appendix_license_notices.asciidoc) | # | :heavy_check_mark: |
| [A1 - Bitcoin Fundamentals Review](appendix-bitcoin-fundamentals-review.asciidoc) | ############ | :heavy_check_mark: |
| [A2 - Docker Basics](appendix_docker_basics.asciidoc) | ## | :heavy_check_mark: |
| [A3 - Protocol Messages](appendix_protocol_messages.asciidoc) | ######## | :heavy_check_mark: |
| [A4 - License Notices](appendix_license_notices.asciidoc) | # | :heavy_check_mark: |
Total Word Count: 125288
Total Word Count: 126530
Target Word Count: 100,000-120,000
## Contributing
The authors welcome contributions to this book! Read the [Guide to Contributing](CONTRIBUTING.md)
## Source and license
Mastering the Lightning Network is released under the Creative Commons CC-BY-NC-ND license, which allows sharing the source code for personal use only. You may read this book for free. You may not create derivatives (such as PDF copies), or distribute the book commercially. The full terms of the license can be found here:

@ -137,6 +137,7 @@ More information about signature hash types can be found in https://github.com/b
Transactions are data structures that encode the transfer of value between participants in the bitcoin system.
[[utxo]]
==== Inputs and outputs
The fundamental building block of a bitcoin transaction is a transaction output. Transaction outputs are indivisible chunks of bitcoin currency, recorded on the blockchain, and recognized as valid by the entire network. A transaction spends "inputs" and creates "outputs". Transaction inputs are simply references to outputs of previously recorded transactions. This way, each transaction spends the outputs of previous transactions and creates new outputs.
@ -195,7 +196,7 @@ Since transactions are chained, if you pick a transaction at random, you can fol
==== TxID: Transaction identifiers
Every transaction in the Bitcoin system is identified by a unique identifier, called the _transaction ID_ or _TxID_ for short. To produce a unique identifier, we use the SHA-256 cryptographic hash function to produce a hash of the transaction's data. This "fingerprint" serves as a universal identifier. A transaction can be referenced by its transaction ID and once a transaction is recorded on the Bitcoin blockchain, every node in the Bitcoin network knows that this transaction is valid.
Every transaction in the Bitcoin system is identified by a unique identifier (assuming the existence of BIP-0030), called the _transaction ID_ or _TxID_ for short. To produce a unique identifier, we use the SHA-256 cryptographic hash function to produce a hash of the transaction's data. This "fingerprint" serves as a universal identifier. A transaction can be referenced by its transaction ID and once a transaction is recorded on the Bitcoin blockchain, every node in the Bitcoin network knows that this transaction is valid.
For example, a transaction ID might look like this:
@ -267,7 +268,7 @@ _Locking scripts_ are embedded in transaction outputs, setting the conditions th
_Unlocking scripts_ are embedded in transaction inputs, fulfilling the conditions set by the referenced output's locking script. For example, Bob can unlock the output above by providing an unlocking script containing a digital signature.
For validation, the unlocking script and locking script are concatenated and executed. For example, if someone locked a transaction output with the locking script +"3 ADD 5 EQUAL"+, we could spend it with the unlocking script "+2+" in a transaction input. Anyone validating that transaction would concatenate our unlocking script (+2+) and the locking script (+3 ADD 5 EQUAL+) and run the result through the Bitcoin Script execution engine. They would get +TRUE+ and we would be able to spend the output.
Using a simplified model, for validation, the unlocking script and locking script are concatenated and executed (P2SH and Segwit are exceptions). For example, if someone locked a transaction output with the locking script +"3 ADD 5 EQUAL"+, we could spend it with the unlocking script "+2+" in a transaction input. Anyone validating that transaction would concatenate our unlocking script (+2+) and the locking script (+3 ADD 5 EQUAL+) and run the result through the Bitcoin Script execution engine. They would get +TRUE+ and we would be able to spend the output.
Obviously, this simplified example would make a very poor choice for locking an actual Bitcoin output because there is no secret, just basic arithmetic. Anyone could spend the output by providing the answer "2". Most locking scripts therefore require demonstrating knowledge of a secret.
@ -391,7 +392,7 @@ Another important building block that exists in Bitcoin and is used extensively
Bitcoin has two levels of timelocks: transaction-level timelocks and output-level timelocks.
A transaction-level timelock is recorded in the transaction header and prevents the entire transaction from being accepted before the timelock has passed. Transaction-level timelocks are most often used in conjunction with output-level timelocks.
A transaction-level timelock is recorded in the transaction `nLockTime` field of the transaction and prevents the entire transaction from being accepted before the timelock has passed. Transaction-level locktimes are the most commonly used lock time mechanism in Bitcion today.
An output-level timelock is created by a script operator. There are two types of output timelocks: _absolute timelocks_ and _relative timelocks_.

@ -0,0 +1,113 @@
[appendix]
[[appendix_docker]]
== Docker Basic Installation and Use
This book contains a number of examples that run inside docker containers, for standardization across different operating systems.
This section will help you install Docker and familiarize yourself with some of the most commonly used Docker commands, so that you can run the book's example containers.
=== Installing Docker
Before we begin, you should install the Docker container system on your computer. Docker is an open system that is distributed for free as a _Community Edition_ for many different operating systems including Windows, Mac OS and Linux. The Windows and Mac versions are called _Docker Desktop_ and consist of a GUI desktop application and command-line tools. The Linux version is called _Docker Engine_ and is comprised of a server daemon and command-line tools. We will be using the command-line tools, which are identical across all platforms.
Go ahead and install Docker for your operating system by following the instructions to _"Get Docker"_ from the Docker website found here:
https://docs.docker.com/get-docker/
Select your operating system from the list and follow the installation instructions.
[TIP]
====
If you install on Linux, follow the post-installation instructions to ensure you can run Docker as a regular user instead of user _root_. Otherwise, you will need to prefix all +docker+ commands with +sudo+, running them as root like: +sudo docker+.
====
Once you have Docker installed, you can test your installation by running the demo container +hello-world+ like this:
[docker-hello-world]
----
$ docker run hello-world
Hello from Docker!
This message shows that your installation appears to be working correctly.
[...]
----
=== Basic Docker commands
In this chapter, we use Docker quite extensively. We will be using the following Docker commands and arguments:
*Building a container*
----
docker build [-t tag] [directory]
----
...where +tag+ is how we identify the container we are building, and +directory+ is where the container's "context" (folders and files) and definition file (+Dockerfile+) are found.
*Running a container*
----
docker run -it [--network netname] [--name cname] tag
----
...where +netname+ is the name of a Docker network, +cname+ is the name we choose for this container instance and +tag+ is the name tag we gave the container when we built it.
*Executing a command in a container*
----
docker exec cname command
----
...where +cname+ is the name we gave the container in the +run+ command, and +command+ is an executable or script that we want to run inside the container.
*Stopping and starting a container*
In most cases, if we are running a container in an _interactive_ as well as _terminal_ mode, i.e. with the +i+ and +t+ flags (combined as +-it+) set, the container can be stopped by simply pressing +CTRL-C+ or by exiting the shell with +exit+ or +CTRL-D+. If a container does not terminate, you can stop it from another terminal like this:
----
docker stop cname
----
To resume an already existing container use the `start` command, like so:
----
docker start cname
----
*Deleting a container by name*
If you name a container instead of letting Docker name it randomly, you cannot reuse that name until the container is deleted. Docker will return an error like this:
[source,bash]
----
docker: Error response from daemon: Conflict. The container name "/bitcoind" is already in use...
----
To fix this, delete the existing instance of the container:
----
docker rm cname
----
...where +cname+ is the name assigned to the container (+bitcoind+ in the example error message)
*List running containers*
----
docker ps
----
...shows the current running containers and their names
*List docker images*
----
docker image ls
----
...shows the docker images that have been built or downloaded on your computer
=== Conclusion
These basic Docker commands will be enough to get you started and will allow you to run all the examples in this book.

@ -33,3 +33,8 @@ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
++++
=== Lamassu Industries AG
Images of the _Gaia_ Bitcoin ATM (https://lamassu.is/product/gaia) seen in [[bitcoin-atm]] are used with permission of Lamassu Industries AG. The use of these images is not an endorsement of the product or company, but are provided as a visual example of a Bitcoin ATM.

@ -0,0 +1,727 @@
[appendix]
[[wire_protocol_enumeration]]
[[protocol_messages]]
[[messages]]
== Wire Protocol Messages
This appendix lists all the currently defined message types used in the Lightning P2P protocol. Additionally, we show the structure of each message, grouping the messages into logical groupings based on the protocol flows.
[NOTE]
====
Lightning Protocol messages are extensible and their structure may change during network-wide upgrades. For the authoritative information, consult the latest version of the BOLTs found in the https://github.com/lightningnetwork/lightning-rfc[Github - Lightning-RFC] repository.
====
=== Message Types
Currently defined message types are:
[[apdx_message_types]]
.Message Types
[options="header"]
|===
| Type Integer | Message Name | Category
| 16 | `init` | Connection Establishment
| 17 | `error` | Error Communication
| 18 | `ping` | Connection Liveness
| 19 | `pong` | Connection Liveness
| 32 | `open_channel` | Channel Funding
| 33 | `accept_channel` | Channel Funding
| 34 | `funding_created` | Channel Funding
| 35 | `funding_signed` | Channel Funding
| 36 | `funding_locked` | Channel Funding + Channel Operation
| 38 | `shutdown` | Channel Closing
| 39 | `closing_signed` | Channel Closing
| 128 | `update_add_htlc` | Channel Operation
| 130 | `update_fulfill_hltc` | Channel Operation
| 131 | `update_fail_htlc` | Channel Operation
| 132 | `commit_sig` | Channel Operation
| 133 | `revoke_and_ack` | Channel Operation
| 134 | `update_fee` | Channel Operation
| 135 | `update_fail_malformed_htlc` | Channel Operation
| 136 | `channel_reestablish` | Channel Operation
| 256 | `channel_announcement` | Channel Announcement
| 257 | `node_announcement` | Channel Announcement
| 258 | `channel_update` | Channel Announcement
| 259 | `announce_signatures` | Channel Announcement
| 261 | `query_short_chan_ids` | Channel Graph Syncing
| 262 | `reply_short_chan_ids_end` | Channel Graph Syncing
| 263 | `query_channel_range` | Channel Graph Syncing
| 264 | `reply_channel_range` | Channel Graph Syncing
| 265 | `gossip_timestamp_range` | Channel Graph Syncing
|===
In <<message_types>>, the `Category` field allows us to quickly categorize a
message based on its functionality within the protocol itself. At a high level,
we place a message into one of 8 (non exhaustive) buckets including:
* *Connection Establishment*: Sent when a peer to peer connection is first
established. Also used in order to negotiate the set of feature supported
by a new connection.
* *Error Communication*: Used by peer to communicate the occurrence of
protocol level errors to each other.
* *Connection Liveness*: Used by peers to check that a given transport
connection is still live.
* *Channel Funding*: Used by peers to create a new payment channel. This
process is also known as the channel funding process.
* *Channel Operation*: The act of updating a given channel off-chain. This
includes sending and receiving payments, as well as forwarding payments
within the network.
* *Channel Announcement*: The process of announcing a new public channel to
the wider network so it can be used for routing purposes.
* *Channel Graph Syncing*: The process of downloading & verifying the channel
graph.
Notice how messages that belong to the same category typically share an
adjacent _message type_ as well. This is done on purpose in order to group
semantically similar messages together within the specification itself.
=== Message Structure
We now detail each message category in order to define
the precise structure and semantics of all defined messages within the LN
protocol.
==== Connection Establishment Messages
Messages in this category are the very first message sent between peers once
they establish a transport connection. At the time of writing of this chapter,
there exists only a single messages within this category, the `init` message.
The `init` message is sent by _both_ sides of the connection once it has been
first established. No other messages are to be sent before the `init` message
has been sent by both parties.
The structure of the `init` message is defined as follows:
[[apdx_init_message]]
===== The `init` message
* type: *16*
* fields:
** `uint16`: `global_features_len`
** `global_features_len*byte`: `global_features`
** `uint16`: `features_len`
** `features_len*byte`: `features`
** `tlv_stream_tlvs`
Structurally, the `init` message is composed of two variable size bytes slices
that each store a set of _feature bits_. As we see in <<feature_bits>>, feature bits are a
primitive used within the protocol in order to advertise the set of protocol
features a node either understands (optional features), or demands (required
features).
Note that modern node implementations will only use the `features` field, with
items residing within the `global_features` vector for primarily _historical_
purposes (backwards compatibility).
What follows after the core message is a series of T.L.V, or Type Length Value
records which can be used to extend the message in a forwards+backwards
compatible manner in the future. We'll cover what TLV records are and how
they're used later in the chapter.
An `init` message is then examined by a peer in order to determine if the
connection is well defined based on the set of optional and required feature
bits advertised by both sides.
An optional feature means that a peer knows about a feature, but they don't
consider it critical to the operation of a new connection. An example of one
would be something like the ability to understand the semantics of a newly
added field to an existing message.
On the other hand, required feature indicate that if the other peer doesn't
know about the feature, then the connection isn't well defined. An example of
such a feature would be a theoretical new channel type within the protocol: if
your peer doesn't know of this feature, they you don't want to keep the
connection as they're unable to open your new preferred channel type.
==== Error Communication Messages
Messages in this category are used to send connection level errors between two
peers. Another type of error exists in the protocol: an
HTLC forwarding level error. Connection level errors may signal things like
feature bit incompatibility, or the intent to force close (unilaterally
broadcast the latest signed commitment)
The sole message in this category is the `error` message:
[[apdx_error_message]]
===== The `error` message
* type: *17*
* fields:
** `channel_id` : `chan_id`
** `uint16` : `data_len`
** `data_len*byte` : `data`
An `error` message can be sent within the scope of a particular channel by
setting the `channel_id`, to the `channel_id` of the channel under going this
new error state. Alternatively, if the error applies to the connection in
general, then the `channel_id` field should be set to all zeroes. This all zero
`channel_id` is also known as the connection level identifier for an error.
Depending on the nature of the error, sending an `error` message to a peer you
have a channel with may indicate that the channel cannot continue without
manual intervention, so the only option at that point is to force close the
channel by broadcasting the latest commitment state of the channel.
==== Connection Liveness
Messages in this section are used to probe to determine if a connection is
still live or not. As the LN protocol somewhat abstracts over the underlying
transport being used to transmit the messages, a set of protocol level `ping`
and `pong` messages are defined.
[[apdx_ping_message]]
===== The `ping` message
* type: *18*
* fields:
** `uint16` : `num_pong_bytes`
** `uint16` : `ping_body_len`
** `ping_body_len*bytes` : `ping_body`
Next it's companion, the `pong` message.
[[apdx_pong_message]]
===== The `pong` message
* type: *19*
* fields:
** `uint16` : `pong_body_len`
** `ping_body_len*bytes` : `pong_body`
A `ping` message can be sent by either party at any time.
The `ping` message includes a `num_pong_bytes` field that is used to instruct
the receiving node with respect to how large the payload it sends in its `pong`
message is. The `ping` message also includes a `ping_body` opaque set of bytes
which can be safely ignored. It only serves to allow a sender to pad out `ping`
messages they send, which can be useful in attempting to thwart certain
de-anonymization techniques based on packet sizes on the wire.
A `pong` message should be sent in response to a received `ping` message. The
receiver should read a set of `num_pong_bytes` random bytes to send back as the
`pong_body` field. Clever use of these fields/messages may allow a privacy
concious routing node to attempt to thwart certain classes of network
de-anonymization attempts, as they can create a "fake" transcript that
resembles other messages based on the packet sizes set across. Remember that by
default the LN uses an _encrypted_ transport, so a passive network monitor
cannot read the plaintext bytes, thus only has timing and packet sizes to go
off of.
==== Channel Funding
As we go on, we enter into the territory of the core messages that govern the
functionality and semantics of the Lightning Protocol. In this section, we
explore the messages sent during the process of creating a new channel. We'll
only describe the fields used as we leave a in in-depth analysis of the
funding process to <<payment_channels>>.
Messages that are sent during the channel funding flow belong to the following
set of 5 messages: `open_channel`, `accept_channel`, `funding_created`,
`funding_signed`, `funding_locked`.
The detailed protocol flow using these messages is described in <<payment_channels>>.
[[apdx_open_channel_message]]
===== The `open_channel` message
* type: *32*
* fields:
** `chain_hash` : `chain_hash`
** `32*byte` : `temp_chan_id`
** `uint64` : `funding_satoshis`
** `uint64` : `push_msat`
** `uint64` : `dust_limit_satoshis`
** `uint64` : `max_htlc_value_in_flight_msat`
** `uint64` : `channel_reserve_satoshis`
** `uint64` : `htlc_minimum_msat`
** `uint32` : `feerate_per_kw`
** `uint16` : `to_self_delay`
** `uint16` : `max_accepted_htlcs`
** `pubkey` : `funding_pubkey`
** `pubkey` : `revocation_basepoint`
** `pubkey` : `payment_basepoint`
** `pubkey` : `delayed_payment_basepoint`
** `pubkey` : `htlc_basepoint`
** `pubkey` : `first_per_commitment_point`
** `byte` : `channel_flags`
** `tlv_stream` : `tlvs`
This is the first message sent when a node wishes to execute a new funding flow
with another node. This message contains all the necessary information required
for both peers to constructs both the funding transaction as well as the
commitment transaction.
At the time of writing of this chapter, a single TLV record is defined within
the set of optional TLV records that may be appended to the end of a defined
message:
* type: *0*
* data: `upfront_shutdown_script`
The `upfront_shutdown_script` is a variable sized byte slice that MUST be a
valid public key script as accepted by the Bitcoin networks' consensus
algorithm. By providing such an address, the sending party is able to
effectively create a "closed loop" for their channel, as neither side will sign
off an cooperative closure transaction that pays to any other address. In
practice, this address is usually one derived from a cold storage wallet.
The `channel_flags` field is a bitfield of which at the time of writing, only
the _first_ bit has any sort of significance. If this bit is set, then this
denotes that this channel is to be advertised to the public network as a route
bal channel. Otherwise, the channel is considered to be unadvertised, also
commonly referred to as a "private" channel.
The `accept_channel` message is the response to the `open_channel` message:
[[apdx_accept_channel_message]]
===== The `accept_channel` message
* type: *33*
* fields:
** `32*byte` : `temp_chan_id`
** `uint64` : `dust_limit_satoshis`
** `uint64` : `max_htlc_value_in_flight_msat`
** `uint64` : `channel_reserve_satoshis`
** `uint64` : `htlc_minimum_msat`
** `uint32` : `minimum_depth`
** `uint16` : `to_self_delay`
** `uint16` : `max_accepted_htlcs`
** `pubkey` : `funding_pubkey`
** `pubkey` : `revocation_basepoint`
** `pubkey` : `payment_basepoint`
** `pubkey` : `delayed_payment_basepoint`
** `pubkey` : `htlc_basepoint`
** `pubkey` : `first_per_commitment_point`
** `tlv_stream` : `tlvs`
The `accept_channel` message is the second message sent during the funding flow
process. It serves to acknowledge an intent to open a channel with a new remote
peer. The message mostly echoes the set of parameters that the responder wishes
to apply to their version of the commitment transaction. In <<payment_channels>>,
when we go into the funding process in details, we do a deep dive to explore
the implications of the various parameters that can be set when opening a new
channel.
In response, the initiator will send the `funding_created` message.
[[apdx_funding_created_message]]
===== The `funding_created` message
* type: *34*
* fields:
** `32*byte` : `temp_chan_id`
** `32*byte` : `funding_txid`
** `uint16` : `funding_output_index`
** `sig` : `commit_sig`
Once the initiator of a channel receives the `accept_channel` message from the
responder, they they have all the materials they need in order to construct the
commitment transaction, as well as the funding transaction. As channels by
default are single funder (only one side commits funds), only the initiator
needs to construct the funding transaction. As a result, in order to allow the
responder to sign a version of a commitment transaction for the initiator, the
initiator, only needs to send the funding outpoint of the channel.
To conclude the responder sends the `funding_signed` message.
[[apdx_funding_signed_message]]
===== The `funding_signed` message
* type: *34*
* fields:
** `channel_id` : `channel_id`
** `sig` : `signature`
To conclude after the responder receivers the `funding_created` message, they
now own a valid signature of the commitment transaction by the initiator. With
this signature they're able to exit the channel at any time by signing their
half of the multi-sig funding output, and broadcasting the transaction. This is
referred to as a force close. In order to give the initiator the ability to do
so was well, before the channel can be used, the responder then signs the
initiator's commitment transaction as well.
Once this message has been received by the initiator, it's safe for them to
broadcast the funding transaction, as they're now able to exit the channel
agreement unilaterally.
Once the funding transaction has received enough confirmations, the
`funding_locked` is sent.
[[apdx_funding_locked_message]]
===== The `funding_locked` message
* type: *36*
* fields:
** `channel_id` : `channel_id`
** `pubkey` : `next_per_commitment_point`
Once the funding transaction obtains a `minimum_depth` number of confirmations,
then the `funding_locked` message is to be sent by both sides. Only after this
message has been received, and sent can the channel being to be used.
==== Channel Closing
Channel closing is a multi-step process. One node initiates by sending the `shutdown` message. The two channel partners then exchange a series of `channel_closing` messages to negotiate mutually acceptable fees for the closing transaction. The channel funder sends the first `closing_signed` message and the other side can accept by sending a `closing_signed` message with the same fee values.
[[apdx_shutdown_message]]
===== The `shutdown` message
* type: *38*
* fields:
** `channel_id` : `channel_id`
** `u16` : `len`
** `len*byte` : `scriptpubkey`
[[apdx_closing_signed_message]]
===== The `closing_signed` message
* type: *39*
* fields:
** `channel_id` : `channel_id`
** `u64` : `fee_satoshis`
** `signature` : `signature`
==== Channel Operation
In this section, we briefly describe the set of messages used to allow
nodes to operate a channel. By operation, we mean being able to send receive,
and forward payments for a given channel.
In order to send, receive or forward a payment over a channel, an HTLC must
first be added to both commitment transactions that comprise of a channel link.
The `update_add_htlc` message allows either side to add a new HTLC to the
opposite commitment transaction.
[[apdx_update_add_htlc_message]]
===== The `update_add_htlc` message
* type: *128*
* fields:
** `channel_id` : `channel_id`
** `uint64` : `id`
** `uint64` : `amount_msat`
** `sha256` : `payment_hash`
** `uint32` : `cltv_expiry`
** `1366*byte` : `onion_routing_packet`
Sending this message allows one party to initiate either sending a new payment,
or forwarding an existing payment that arrived via in incoming channel. The
message specifies the amount (`amount_msat`) along with the payment hash that
unlocks the payment itself. The set of forwarding instructions of the next hop
are onion encrypted within the `onion_routing_packet` field. In <<onion_routing>>, on
multi-hop HTLC forwarding, we detail the onion routing protocol used in the
Lighting Network in detail.
Note that each HTLC sent uses an auto incrementing ID which is used by any
message which modifies an HTLC (settle or cancel) to reference the HTLC in a
unique manner scoped to the channel.
The `update_fulfill_hltc` allow redemption (receipt) of an active HTLC.
[[apdx_update_fulfill_hltc_message]]
===== The `update_fulfill_hltc` message
* type: *130*
* fields:
** `channel_id` : `channel_id`
** `uint64` : `id`
** `32*byte` : `payment_preimage`
This message is sent by the HTLC receiver to the proposer in order to redeem an
active HTLC. The message references the `id` of the HTLC in question, and also
provides the pre-image (which unlocks the HLTC) as well.
The `update_fail_htlc` is sent to remove an HTLC from a commitment transaction.
[[apdx_update_fail_htlc_message]]
===== The `update_fail_htlc` message
* type: *131*
* fields:
** `channel_id` : `channel_id`
** `uint64` : `id`
** `uint16` : `len`
** `len*byte` : `reason`
The `update_fail_htlc` is the opposite of the `update_fulfill_hltc` message as
it allows the receiver of an HTLC to remove the very same HTLC. This message is
typically sent when an HTLC cannot be properly routed upstream, and needs to be
sent back to the sender in order to unravel the HTLC chain. As we explore in
Chapter XX, the message contains an _encrypted_ failure reason (`reason`) which
may allow the sender to either adjust their payment route, or terminate if the
failure itself is a terminal one.
The `commitment_signed` message is used to stamp the creation of a new commitment transaction
[[apdx_commitment_signed_message]]
===== The `commitment_signed` message
* type: *132*
* fields:
** `channel_id` : `channel_id`
** `sig` : `signature`
** `uint16` : `num_htlcs`
** `num_htlcs*sig` : `htlc_signature`
In addition to sending a signature for the next commitment transaction, the
sender of this message also needs to send a signature for each HTLC that's
present on the commitment transaction. This is due to the existence of the
The `revoke_and_ack` is sent to revoke a dated commitment:
[[apdx_revoke_and_ack_message]]
===== The `revoke_and_ack` message
* type: *133*
* fields:
** `channel_id` : `channel_id`
** `32*byte` : `per_commitment_secret`
** `pubkey` : `next_per_commitment_point`
As the Lightning Network uses a replace-by-revoke commitment transaction, after
receiving a new commitment transaction via the `commit_sig` message, a party
must revoke their past commitment before they're able to receive another one.
While revoking a commitment transaction, the revoker then also provides the
next commitment point that's required to allow the other party to send them a
new commitment state.
The `update_fee` is sent to update the fee on the current commitment
transactions.
[[apdx_update_fee_message]]
===== The `update_fee` message
* type: *134*
* fields:
** `channel_id` : `channel_id`
** `uint32` : `feerate_per_kw`
This message can only be sent by the initiator of the channel they're the ones
that will pay for the commitment fee of the channel as along as it's open.
The `update_fail_malformed_htlc` is sent to remove a corrupted HTLC:
[[apdx_update_fail_malformed_htlc_message]]
===== The `update_fail_malformed_htlc` message
* type: *135*
* fields:
** `channel_id` : `channel_id`
** `uint64` : `id`
** `sha256` : `sha256_of_onion`
** `uint16` : `failure_code`
This message is similar to the `update_fail_htlc` but it's rarely used in
practice. As mentioned above, each HTLC carries an onion encrypted routing
packet that also covers the integrity of portions of the HTLC itself. If a
party receives an onion packet that has somehow been corrupted along the way,
then it won't be able to decrypt the packet. As a result it also can't properly
forward the HTLC, therefore it'll send this message to signify that the HTLC
has been corrupted somewhere along the route back to the sender.
==== Channel Announcement
Messages in this category are used to announce components of the Channel Graph
authenticated data structure to the wider network. The Channel Graph has a
series of unique properties due to the condition that all data added to the
channel graph MUST also be anchored in the base Bitcoin blockchain. As a
result, in order to add a new entry to the channel graph, an agent must be an
on chain transaction fee. This serves as a natural spam de tenace for the
Lightning Network.
The `channel_announcement` is used to announce a new channel to the wider
network.
[[apdx_channel_announcement_message]]
===== The `channel_announcement` message
* type: *256*
* fields:
** `sig` : `node_signature_1`
** `sig` : `node_signature_2`
** `sig` : `bitcoin_signature_1`
** `sig` : `bitcoin_signature_2`
** `uint16` : `len`
** `len*byte` : `features`
** `chain_hash` : `chain_hash`
** `short_channel_id` : `short_channel_id`
** `pubkey` : `node_id_1`
** `pubkey` : `node_id_2`
** `pubkey` : `bitcoin_key_1`
** `pubkey` : `bitcoin_key_2`
The series of signatures and public keys in the message serves to create a
_proof_ that the channel actually exists within the base Bitcoin blockchain. As
we detail in <<scid>>, each channel is uniquely identified by a locator
that encodes it's _location_ within the blockchain. This locator is called this
`short_channel_id` and can fit into a 64-bit integer.
The `node_announcement` allows a node to announce/update it's vertex within the
greater Channel Graph.
[[apdx_node_announcement_message]]
===== The `node_announcement` message
* type: *257*
* fields:
** `sig` : `signature`
** `uint64` : `flen`
** `flen*byte` : `features`
** `uint32` : `timestamp`
** `pubkey` : `node_id`
** `3*byte` : `rgb_color`
** `32*byte` : `alias`
** `uint16` : `addrlen`
** `addrlen*byte` : `addresses`
Note that if a node doesn't have any advertised channel within the Channel
Graph, then this message is ignored in order to ensure that adding an item to
the Channel Graph bares an on-chain cost. In this case, the on-chain cost will
the cost of creating the channel which this node is connected to.
In addition to advertising its feature set, this message also allows a node to
announce/update the set of network `addresses` that it can be reached at.
The `channel_update` message is sent to update the properties and policies of
an active channel edge within the Channel graph.
[[apdx_channel_update_message]]
===== The `channel_update` message
* type: *258*
* fields:
** `signature` : `signature`
** `chain_hash` : `chain_hash`
** `short_channel_id` : `short_channel_id`
** `uint32` : `timestamp`
** `byte` : `message_flags`
** `byte` : `channel_flags`
** `uint16` : `cltv_expiry_delta`
** `uint64` : `htlc_minimum_msat`
** `uint32` : `fee_base_msat`
** `uint32` : `fee_proportional_millionths`
** `uint16` : `htlc_maximum_msat`
In addition to being able to enable/disable a channel this message allows a
node to update it's routing fees as well as other fields that shape the type of
payment that is permitted to flow through this channel.
The `announce_signatures` message is exchange by channel peers in order to
assemble the set of signatures required to produce a `channel_announcement`
message.
[[apdx_announce_signatures_message]]
===== The `announce_signatures` message
* type: *259*
* fields:
** `channel_id` : `channel_id`
** `short_channel_id` : `short_channel_id`
** `sig` : `node_signature`
** `sig` : `bitcoin_signature`
After the `funding_locked` message has been sent, if both sides wish to
advertise their channel to the network, then they'll each send the
`announce_signatures` message which allows both sides to emplace the 4
signatures required to generate a `announce_signatures` message.
==== Channel Graph Syncing
The `query_short_chan_ids` allows a peer to obtain the channel information
related to a series of short channel IDs.
[[apdx_query_short_chan_ids_message]]
===== The `query_short_chan_ids` message
* type: *261*
* fields:
** `chain_hash` : `chain_hash`
** `u16` : `len`
** `len*byte` : `encoded_short_ids`
** `query_short_channel_ids_tlvs` : `tlvs`
As we learn in <<gossip>>, these channel IDs may be a series of channels
that were new to the sender, or were out of date which allows the sender to
obtain the latest set of information for a set of channels.
The `reply_short_chan_ids_end` message is sent after a peer finishes responding
to a prior `query_short_chan_ids` message.
[[apdx_reply_short_chan_ids_end_message]]
===== The `reply_short_chan_ids_end` message
* type: *262*
* fields:
** `chain_hash` : `chain_hash`
** `byte` : `full_information`
This message signals to the receiving party that if they wish to send another
query message, they can now do so.
The `query_channel_range` message allows a node to query for the set of channel
opened within a block range.
[[apdx_query_channel_range_message]]
===== The `query_channel_range` message
* type: *263*
* fields:
** `chain_hash` : `chain_hash`
** `u32` : `first_blocknum`
** `u32` : `number_of_blocks`
** `query_channel_range_tlvs` : `tlvs`
As channels are represented using a short channel ID that encodes the location
of a channel in the chain, a node on the network can use a block height as a
sort of _cursor_ to seek through the chain in order to discover a set of newly
opened channels.
The `reply_channel_range` message is the response to `query_channel_range` and
includes the set of short channel IDs for known channels within that range.
[[apdx_reply_channel_range_message]]
===== The `reply_channel_range` message
* type: *264*
* fields:
** `chain_hash` : `chain_hash`
** `u32` : `first_blocknum`
** `u32` : `number_of_blocks`
** `byte` : `sync_complete`
** `u16` : `len`
** `len*byte` : `encoded_short_ids`
** `reply_channel_range_tlvs` : `tlvs`
As a response to `query_channel_range`, this message sends back the set of
channels that were opened within that range. This process can be repeated with
the requester advancing their cursor further down the chain in order to
continue syncing the Channel Graph.
The `gossip_timestamp_range` message allows a peer to start receiving new
incoming gossip messages on the network.
[[apdx_gossip_timestamp_range_message]]
===== The `gossip_timestamp_range` message
* type: *265*
* fields:
** `chain_hash` : `chain_hash`
** `u32` : `first_timestamp`
** `u32` : `timestamp_range`
Once a peer has synced the channel graph, they can send this message if they
wish to receive real-time updates on changes in the Channel Graph. They can
also set the `first_timestamp` and `timestamp_range` fields if they wish to
receive a backlog of updates they may have missed while they were down.

File diff suppressed because it is too large Load Diff

@ -1,16 +1,126 @@
#!make
#
# Makefile to help with building, pulling and pushing containers
#
# NOTE: You cannot push to the container registry unless you are authorized
# in the lnbook organization (i.e. one of the authors or maintainers)
#
# Targets:
#
# make build # Build all containers
# make pull # Pull all containers from the registry
# make build-bitcoind # Build a specific container
# make clean # remove all images and containers
# make push # push updated images to Docker Hub (authors/maintainers only)
# Latest tested versions of Bitcoin and Lightning clients
# OS base image
OS=ubuntu
OS_VER=focal
# bitcoind version
BITCOIND_VER=0.21.0
# LND version
GO_VER=1.13
LND_VER=v0.13.1-beta
# c-lightning version
CL_VER=0.10.1
# Eclair version
ECLAIR_VER=0.4.2
ECLAIR_COMMIT=52444b0
# Docker registry for lnbook
REGISTRY=docker.com
NAME=lnbook
ORG=lnbook
# List of containers
CONTAINERS=bitcoind lnd eclair c-lightning
all: build-all push-all
.DEFAULT: pull
build-all:
for container in ${CONTAINERS}; do \
docker build -t ${NAME}/$$container $$container -f $$container/Dockerfile; \
done
push-all:
build-bitcoind:
docker build \
--build-arg OS=${OS} \
--build-arg OS_VER=${OS_VER} \
--build-arg BITCOIND_VER=${BITCOIND_VER} \
-t ${ORG}/bitcoind:${BITCOIND_VER} \
bitcoind -f bitcoind/Dockerfile
docker image tag ${ORG}/bitcoind:${BITCOIND_VER} ${ORG}/bitcoind:latest
build-cl: build-bitcoind
docker build \
--build-arg OS=${OS} \
--build-arg OS_VER=${OS_VER} \
--build-arg CL_VER=${CL_VER} \
-t ${ORG}/c-lightning:${CL_VER} \
c-lightning -f c-lightning/Dockerfile
docker image tag ${ORG}/c-lightning:${CL_VER} ${ORG}/c-lightning:latest
build-lnd:
docker build \
--build-arg OS=${OS} \
--build-arg OS_VER=${OS_VER} \
--build-arg LND_VER=${LND_VER} \
--build-arg GO_VER=${GO_VER} \
-t ${ORG}/lnd:${LND_VER}_golang_${GO_VER} \
lnd -f lnd/Dockerfile
docker image tag ${ORG}/lnd:${LND_VER}_golang_${GO_VER} ${ORG}/lnd:latest
build-eclair:
docker build \
--build-arg OS=${OS} \
--build-arg OS_VER=${OS_VER} \
--build-arg ECLAIR_VER=${ECLAIR_VER} \
--build-arg ECLAIR_COMMIT=${ECLAIR_COMMIT} \
-t ${ORG}/eclair:${ECLAIR_VER}-${ECLAIR_COMMIT} \
eclair -f eclair/Dockerfile
docker image tag ${ORG}/eclair:${ECLAIR_VER}-${ECLAIR_COMMIT} ${ORG}/eclair:latest
push-bitcoind: build-bitcoind
docker push ${ORG}/bitcoind:${BITCOIND_VER}
docker push ${ORG}/bitcoind:latest
push-lnd: build-lnd
docker push ${ORG}/lnd:${LND_VER}_golang_${GO_VER}
docker push ${ORG}/lnd:latest
push-cl: build-cl
docker push ${ORG}/c-lightning:${CL_VER}
docker push ${ORG}/c-lightning:latest
push-eclair: build-eclair
docker push ${ORG}/eclair:${ECLAIR_VER}-${ECLAIR_COMMIT}
docker push ${ORG}/eclair:latest
build: build-bitcoind build-lnd build-cl build-eclair
push: push-bitcoind push-lnd push-cl push-eclair
pull:
for container in ${CONTAINERS}; do \
docker push ${NAME}/$$container; \
docker pull ${ORG}/$$container:latest ;\
done
clean:
# Try 'make clean-confirm' if you are sure you want to do this.
# CAUTION: ALL docker containers and images on your computer will be removed.
clean-confirm:
docker rm -f `docker ps -qa`
docker rmi -f `docker image ls -qa`

@ -1,34 +1,47 @@
FROM ubuntu:20.04 AS bitcoind-base
RUN apt update && apt install -yqq \
curl gosu jq bash-completion
ENV BITCOIND_VERSION 0.21.0
# Install binaries for Bitcoin Core
ADD https://bitcoincore.org/bin/bitcoin-core-${BITCOIND_VERSION}/bitcoin-${BITCOIND_VERSION}-x86_64-linux-gnu.tar.gz /usr/local
RUN cd /usr/local/ \
&& tar -zxf bitcoin-${BITCOIND_VERSION}-x86_64-linux-gnu.tar.gz \
&& cd bitcoin-${BITCOIND_VERSION} \
&& install bin/* /usr/local/bin \
&& install include/* /usr/local/include \
&& install -v lib/* /usr/local/lib
ARG OS=ubuntu
ARG OS_VER=focal
FROM ${OS}:${OS_VER} as os-base
# Install dependencies
RUN DEBIAN_FRONTEND=noninteractive \
apt-get update -qq && apt-get install -yqq \
curl unzip jq bash-completion
FROM os-base as bitcoind-install
ARG BITCOIND_VER=0.21.0
# Install Bitcoin Core binaries and libraries
RUN cd /tmp && \
curl -# -sLO https://bitcoincore.org/bin/bitcoin-core-${BITCOIND_VER}/bitcoin-${BITCOIND_VER}-x86_64-linux-gnu.tar.gz && \
tar -zxf bitcoin-${BITCOIND_VER}-x86_64-linux-gnu.tar.gz && \
cd bitcoin-${BITCOIND_VER} && \
install -vD bin/* /usr/bin && \
install -vD lib/* /usr/lib && \
cd /tmp && \
rm bitcoin-${BITCOIND_VER}-x86_64-linux-gnu.tar.gz && \
rm -rf bitcoin-${BITCOIND_VER}
# Install runtime scripts, bash-completion and configuration files
# bash completion for bitcoind and bitcoin-cli
ENV GH_URL https://raw.githubusercontent.com/bitcoin/bitcoin/master/
ENV BC /usr/share/bash-completion/completions/
ADD $GH_URL/contrib/bitcoin-cli.bash-completion $BC/bitcoin-cli
ADD $GH_URL/contrib/bitcoind.bash-completion $BC/bitcoind
ADD $GH_URL/contrib/bitcoin-tx.bash-completion $BC/bitcoin-tx
FROM bitcoind-base AS bitcoind
ADD bitcoind /bitcoind
# Copy bitcoind configuration directory
COPY bitcoind /bitcoind
RUN ln -s /bitcoind /root/.
ADD bashrc /root/.bashrc
ADD bitcoind-entrypoint.sh /usr/local/bin
# Copy support scripts
COPY bashrc /root/.bashrc
COPY bitcoind-entrypoint.sh /usr/local/bin
RUN chmod +x /usr/local/bin/bitcoind-entrypoint.sh
ADD mine.sh /usr/local/bin
COPY mine.sh /usr/local/bin
RUN chmod +x /usr/local/bin/mine.sh
COPY cli /usr/local/bin
RUN chmod +x /usr/local/bin/cli
# bitcoind P2P
EXPOSE 18444/tcp

@ -1,23 +1,36 @@
#!/bin/bash
set -Eeuo pipefail
echo Starting bitcoind...
# Start bitcoind
echo "Starting bitcoind..."
bitcoind -datadir=/bitcoind -daemon
until bitcoin-cli -datadir=/bitcoind getblockchaininfo > /dev/null 2>&1
# Wait for bitcoind startup
echo -n "Waiting for bitcoind to start"
until bitcoin-cli -datadir=/bitcoind -rpcwait getblockchaininfo > /dev/null 2>&1
do
echo -n "."
sleep 1
done
echo bitcoind started
echo
echo "bitcoind started"
# Load private key into wallet
export address=`cat /bitcoind/keys/demo_address.txt`
export privkey=`cat /bitcoind/keys/demo_privkey.txt`
# If restarting the wallet already exists, so don't fail if it does,
# just load the existing wallet:
bitcoin-cli -datadir=/bitcoind createwallet regtest > /dev/null || bitcoin-cli -datadir=/bitcoind loadwallet regtest > /dev/null
bitcoin-cli -datadir=/bitcoind importprivkey $privkey > /dev/null || true
echo "================================================"
echo "Importing demo private key"
echo "Imported demo private key"
echo "Bitcoin address: " ${address}
echo "Private key: " ${privkey}
echo "================================================"
bitcoin-cli -datadir=/bitcoind createwallet regtest
bitcoin-cli -datadir=/bitcoind importprivkey $privkey
# Executing CMD
echo "$@"
exec "$@"

@ -0,0 +1,5 @@
#!/bin/bash
#
# Helper script used as an alias for bitcoin-cli with the necessary arguments
#
/usr/bin/bitcoin-cli -datadir=/bitcoind -regtest $@

@ -2,18 +2,17 @@
set -Eeuo pipefail
export address=`cat /bitcoind/keys/demo_address.txt`
export privkey=`cat /bitcoind/keys/demo_privkey.txt`
echo "================================================"
echo "Bitcoin address: " ${address}
echo "Private key: " ${privkey}
echo "Balance:" `bitcoin-cli -datadir=/bitcoind getbalance`
echo "================================================"
echo "Mining 101 blocks to unlock some bitcoin"
bitcoin-cli -datadir=/bitcoind generatetoaddress 101 $address
echo "Mining 1 block every 10 seconds"
while sleep 10; do \
bitcoin-cli -datadir=/bitcoind generatetoaddress 1 $address; \
echo "Balance:" `bitcoin-cli -datadir=/bitcoind getbalance`; \
echo "Mining 6 blocks every 10 seconds"
while echo "Balance:" `bitcoin-cli -datadir=/bitcoind getbalance`;
do
bitcoin-cli -datadir=/bitcoind generatetoaddress 6 $address; \
sleep 10; \
done
# If loop is interrupted, stop bitcoind

@ -1,32 +1,60 @@
FROM lnbook/bitcoind AS c-lightning-base
# Install software-properties-common to add apt repositories
RUN apt update && apt install -yqq \
software-properties-common
# c-lightning
ENV C_LIGHTNING_VER 0.9.3~20210120202101201901~ubuntu20.04.1
RUN add-apt-repository -u ppa:lightningnetwork/ppa
RUN apt-get install -yqq \
lightningd=${C_LIGHTNING_VER}
ARG OS=ubuntu
ARG OS_VER=focal
FROM ${OS}:${OS_VER} as os-base
# Install dependencies
RUN DEBIAN_FRONTEND=noninteractive \
apt-get update -qq && apt-get install -yqq \
curl unzip jq bash-completion
FROM os-base as cl-install
COPY --from=lnbook/bitcoind:latest /usr/bin/bitcoin-cli /usr/bin
# Set CL_VER ENV from ARG
ARG CL_VER=0.10.1
ENV CL_VER=${CL_VER}
RUN apt-get update -qq && apt-get install -yqq \
gpg xz-utils libpq5 libsodium23 && \
apt-get clean && \
rm -rf /var/lib/apt/lists/*
RUN cd /tmp && \
curl -# -sLO https://github.com/ElementsProject/lightning/releases/download/v${CL_VER}/clightning-v${CL_VER}-Ubuntu-20.04.tar.xz
# Verify developer signatures. The `gpg --verify` command will print a
# couple of warnings about the key not being trusted. That's ok. The
# important part is that it doesn't error and reports "Good
# signature".
ADD devkeys.pem /tmp/devkeys.pem
RUN gpg --import /tmp/devkeys.pem
ADD https://github.com/ElementsProject/lightning/releases/download/v0.10.1/SHA256SUMS /tmp/SHA256SUMS
ADD https://github.com/ElementsProject/lightning/releases/download/v0.10.1/SHA256SUMS.asc /tmp/SHA256SUMS.asc
RUN cd /tmp && \
gpg -q --verify SHA256SUMS.asc SHA256SUMS && \
cat SHA256SUMS && \
sha256sum --ignore-missing -c SHA256SUMS
RUN tar -xvf /tmp/clightning-v${CL_VER}-Ubuntu-20.04.tar.xz -C /
ADD https://raw.githubusercontent.com/ElementsProject/lightning/master/contrib/lightning-cli.bash-completion /usr/share/bash-completion/completions/lightning-cli
FROM c-lightning-base AS c-lightning-run
ADD lightningd /lightningd
COPY lightningd /lightningd
WORKDIR /lightningd
RUN ln -s /lightningd /root/.lightning
ADD bashrc /root/.bashrc
ADD c-lightning-entrypoint.sh /usr/local/bin
COPY bashrc /root/.bashrc
COPY c-lightning-entrypoint.sh /usr/local/bin
RUN chmod +x /usr/local/bin/c-lightning-entrypoint.sh
ADD fund-c-lightning.sh /usr/local/bin
COPY fund-c-lightning.sh /usr/local/bin
RUN chmod +x /usr/local/bin/fund-c-lightning.sh
ADD logtail.sh /usr/local/bin
COPY logtail.sh /usr/local/bin
RUN chmod +x /usr/local/bin/logtail.sh
ADD wait-for-bitcoind.sh /usr/local/bin
COPY wait-for-bitcoind.sh /usr/local/bin
RUN chmod +x /usr/local/bin/wait-for-bitcoind.sh
COPY cli /usr/local/bin
RUN chmod +x /usr/local/bin/cli
EXPOSE 9735 9835
ENTRYPOINT ["/usr/local/bin/c-lightning-entrypoint.sh"]

@ -15,5 +15,4 @@ sleep 2
echo "Funding c-lightning wallet"
source /usr/local/bin/fund-c-lightning.sh
echo "$@"
exec "$@"

@ -0,0 +1,5 @@
#!/bin/bash
#
# Helper script used as an alias for lightning-cli with the necessary arguments
#
/usr/bin/lightning-cli --lightning-dir=/lightningd $@

File diff suppressed because it is too large Load Diff

@ -2,21 +2,16 @@
set -Eeuo pipefail
# Generate a new receiving address for c-lightning wallet
address=$(lightning-cli --lightning-dir=/lightningd --network regtest newaddr | jq .address)
address=$(lightning-cli --lightning-dir=/lightningd --network regtest newaddr | jq '.bech32' -r)
# Ask Bitcoin Core to send 10 BTC to the address, using JSON-RPC call
curl --user regtest:regtest \
-H 'content-type: text/plain;' \
http://bitcoind:18443/ \
--data-binary @- <<EOF
{
"jsonrpc": "1.0",
"id": "c-lightning-container",
"method": "sendtoaddress",
"params": [
${address},
10,
"funding c-lightning"
]
}
EOF
until bitcoin-cli \
--rpcuser=regtest \
--rpcpassword=regtest \
--rpcconnect=bitcoind:18443 \
--regtest \
sendtoaddress ${address} 10 "funding c-lightning"
do
sleep 1;
echo Retrying funding...
done

@ -2,4 +2,5 @@
set -Eeuo pipefail
# Show LND log from beginning and follow
touch /lightningd/lightningd.log
tail -n +1 -f /lightningd/lightningd.log || true

@ -2,14 +2,14 @@
set -Eeuo pipefail
echo Waiting for bitcoind to start...
until bitcoin-cli -rpcconnect=bitcoind -rpcport=18443 -rpcuser=regtest -rpcpassword=regtest getblockchaininfo > /dev/null 2>&1
until curl --silent --user regtest:regtest --data-binary '{"jsonrpc": "1.0", "id": "cl-node", "method": "getblockchaininfo", "params": []}' -H 'content-type: text/plain;' http://bitcoind:18443/ | jq -e ".result.blocks > 0" > /dev/null 2>&1
do
echo -n "."
sleep 1
done
echo Waiting for bitcoind to mine blocks...
until bitcoin-cli -rpcconnect=bitcoind -rpcport=18443 -rpcuser=regtest -rpcpassword=regtest getbalance | jq -e ". > 0" > /dev/null 2>&1
until curl --silent --user regtest:regtest --data-binary '{"jsonrpc": "1.0", "id": "cl-node", "method": "getbalance", "params": ["*", 6]}' -H 'content-type: text/plain;' http://bitcoind:18443/ | jq -e ".result > 0" > /dev/null 2>&1
do
echo -n "."
sleep 1

@ -1,8 +1,7 @@
#!/bin/bash
# a small script to help sanity check the versions of the different node implementations
dockerfiles=$(find . -name 'Dockerfile')
# print location of dockerfiles
echo $dockerfiles
# print variables
awk '/ENV/ && /VER|COMMIT/' $dockerfiles
awk '/ARG/ && /VER|COMMIT/' $dockerfiles

@ -1,20 +1,29 @@
FROM ubuntu:20.04 AS eclair-base
RUN apt update && apt install -yqq \
curl gosu jq bash-completion
RUN apt update && apt install -yqq \
openjdk-11-jdk unzip
COPY --from=lnbook/bitcoind /usr/local/ /usr/local/
ARG OS=ubuntu
ARG OS_VER=focal
FROM ${OS}:${OS_VER} as os-base
# Install dependencies
RUN DEBIAN_FRONTEND=noninteractive \
apt-get update -qq && apt-get install -yqq \
curl unzip jq bash-completion
# Install default Java Runtime Environment
RUN DEBIAN_FRONTEND=noninteractive \
apt-get update -qq && apt-get install -yqq \
default-jre-headless && \
apt-get clean && \
rm -rf /var/lib/apt/lists/*
# Install eclair
ENV ECLAIR_VER 0.4.2
ENV ECLAIR_COMMIT 52444b0
WORKDIR /usr/src
RUN curl -sLO https://github.com/ACINQ/eclair/releases/download/v${ECLAIR_VER}/eclair-node-${ECLAIR_VER}-${ECLAIR_COMMIT}-bin.zip \
&& unzip eclair-node-${ECLAIR_VER}-${ECLAIR_COMMIT}-bin.zip \
&& install eclair-node-${ECLAIR_VER}-${ECLAIR_COMMIT}/bin/eclair-cli /usr/local/bin
ARG ECLAIR_VER=0.4.2
ARG ECLAIR_COMMIT=52444b0
RUN cd /usr/src && \
curl -# -sLO https://github.com/ACINQ/eclair/releases/download/v${ECLAIR_VER}/eclair-node-${ECLAIR_VER}-${ECLAIR_COMMIT}-bin.zip && \
unzip eclair-node-${ECLAIR_VER}-${ECLAIR_COMMIT}-bin.zip && \
install eclair-node-${ECLAIR_VER}-${ECLAIR_COMMIT}/bin/eclair-cli /usr/local/bin && \
rm eclair-node-${ECLAIR_VER}-${ECLAIR_COMMIT}-bin.zip
ADD https://raw.githubusercontent.com/ACINQ/eclair/master/contrib/eclair-cli.bash-completion /usr/share/bash-completion/completions/eclair-cli
@ -29,6 +38,11 @@ ADD logtail.sh /usr/local/bin
RUN chmod +x /usr/local/bin/logtail.sh
ADD wait-for-bitcoind.sh /usr/local/bin
RUN chmod +x /usr/local/bin/wait-for-bitcoind.sh
COPY cli /usr/local/bin
RUN chmod +x /usr/local/bin/cli
ENV ECLAIR_VER=$ECLAIR_VER
ENV ECLAIR_COMMIT=$ECLAIR_COMMIT
EXPOSE 9735
ENTRYPOINT ["/usr/local/bin/eclair-entrypoint.sh"]

@ -0,0 +1,5 @@
#!/bin/bash
#
# Helper script used as an alias for eclair-cli with the necessary arguments
#
/usr/local/bin/eclair-cli -s -j -p eclair $@

@ -18,5 +18,4 @@ echo Eclair node started
sleep 2
# Executing CMD
echo "$@"
exec "$@"

@ -23,11 +23,18 @@ eclair {
zmqblock = "tcp://bitcoind:12005"
zmqtx = "tcp://bitcoind:12006"
}
on-chain-fees {
feerate-tolerance {
ratio-low = 0.000001
ratio-high = 1000000
}
}
node-alias = "eclair"
router {
channel-exclude-duration = 1 seconds
broadcast-interval = 1 seconds
}
}

@ -2,14 +2,14 @@
set -Eeuo pipefail
echo Waiting for bitcoind to start...
until bitcoin-cli -rpcconnect=bitcoind -rpcport=18443 -rpcuser=regtest -rpcpassword=regtest getblockchaininfo > /dev/null 2>&1
until curl --silent --user regtest:regtest --data-binary '{"jsonrpc": "1.0", "id": "eclair-node", "method": "getblockchaininfo", "params": []}' -H 'content-type: text/plain;' http://bitcoind:18443/ | jq -e ".result.blocks > 0" > /dev/null 2>&1
do
echo -n "."
sleep 1
done
echo Waiting for bitcoind to mine blocks...
until bitcoin-cli -rpcconnect=bitcoind -rpcport=18443 -rpcuser=regtest -rpcpassword=regtest getbalance | jq -e ". > 0" > /dev/null 2>&1
until curl --silent --user regtest:regtest --data-binary '{"jsonrpc": "1.0", "id": "eclair-node", "method": "getbalance", "params": ["*", 6]}' -H 'content-type: text/plain;' http://bitcoind:18443/ | jq -e ".result > 0" > /dev/null 2>&1
do
echo -n "."
sleep 1

@ -1,40 +1,59 @@
FROM golang:1.13 as lnd-base
ARG OS=ubuntu
ARG OS_VER=focal
ARG GO_VER=1.13
# Define base images with ARG versions
FROM ${OS}:${OS_VER} as os
FROM golang:${GO_VER} as go
ENV GOPATH /go
WORKDIR $GOPATH/src
# OS image with command-line utilities
FROM os AS os-base
# Install dependencies
RUN DEBIAN_FRONTEND=noninteractive \
apt-get update -qq && apt-get install -yqq \
curl unzip jq bash-completion
# Go image for building LND
FROM go as lnd-build
# LND
ENV LND_VER v0.11.1-beta
RUN go get -d github.com/lightningnetwork/lnd
WORKDIR $GOPATH/src/github.com/lightningnetwork/lnd
RUN git checkout tags/${LND_VER}
RUN make && make install
ENV GO_VER=${GO_VER}
ENV GOPATH=/go
FROM ubuntu:20.04 AS lnd-run
# Build LND
ARG LND_VER=v0.13.1-beta
ENV LND_VER=${LND_VER}
RUN mkdir -p ${GOPATH}/src && \
cd ${GOPATH}/src && \
go get -v -d github.com/lightningnetwork/lnd && \
cd ${GOPATH}/src/github.com/lightningnetwork/lnd && \
git checkout tags/${LND_VER} && \
make clean && make && make install
RUN apt update && apt install -yqq \
curl gosu jq bash-completion
# Runtime image for running LND
FROM os-base as lnd-run
COPY --from=lnd-base /go /go
COPY --from=lnbook/bitcoind /usr/local/ /usr/local/
# Copy only the executables
COPY --from=lnd-build /go/bin /go/bin
RUN cp /go/src/github.com/lightningnetwork/lnd/contrib/lncli.bash-completion \
ADD https://raw.githubusercontent.com/lightningnetwork/lnd/master/contrib/lncli.bash-completion \
/usr/share/bash-completion/completions/lncli
ENV GOPATH /go
ENV PATH $PATH:$GOPATH/bin
ADD lnd /lnd
COPY lnd /lnd
RUN ln -s /lnd /root/.lnd
ADD fund-lnd.sh /usr/local/bin
COPY fund-lnd.sh /usr/local/bin
RUN chmod +x /usr/local/bin/fund-lnd.sh
ADD bashrc /root/.bashrc
ADD lnd-entrypoint.sh /usr/local/bin
COPY bashrc /root/.bashrc
COPY lnd-entrypoint.sh /usr/local/bin
RUN chmod +x /usr/local/bin/lnd-entrypoint.sh
ADD logtail.sh /usr/local/bin
COPY logtail.sh /usr/local/bin
RUN chmod +x /usr/local/bin/logtail.sh
ADD wait-for-bitcoind.sh /usr/local/bin
COPY wait-for-bitcoind.sh /usr/local/bin
RUN chmod +x /usr/local/bin/wait-for-bitcoind.sh
COPY cli /usr/local/bin
RUN chmod +x /usr/local/bin/cli
# LND RPC
EXPOSE 10009/tcp

@ -0,0 +1,5 @@
#!/bin/bash
#
# Helper script used as an alias for lncli with the necessary arguments
#
/go/bin/lncli --lnddir=/lnd -n regtest $@

@ -14,5 +14,4 @@ echo "Startup complete"
echo "Funding lnd wallet"
source /usr/local/bin/fund-lnd.sh
echo "$@"
exec "$@"

@ -2,14 +2,14 @@
set -Eeuo pipefail
echo Waiting for bitcoind to start...
until bitcoin-cli -rpcconnect=bitcoind -rpcport=18443 -rpcuser=regtest -rpcpassword=regtest getblockchaininfo > /dev/null 2>&1
until curl --silent --user regtest:regtest --data-binary '{"jsonrpc": "1.0", "id": "lnd-node", "method": "getblockchaininfo", "params": []}' -H 'content-type: text/plain;' http://bitcoind:18443/ | jq -e ".result.blocks > 0" > /dev/null 2>&1
do
echo -n "."
sleep 1
done
echo Waiting for bitcoind to mine blocks...
until bitcoin-cli -rpcconnect=bitcoind -rpcport=18443 -rpcuser=regtest -rpcpassword=regtest getbalance | jq -e ". > 0" > /dev/null 2>&1
until curl --silent --user regtest:regtest --data-binary '{"jsonrpc": "1.0", "id": "lnd-node", "method": "getbalance", "params": ["*", 6]}' -H 'content-type: text/plain;' http://bitcoind:18443/ | jq -e ".result > 0" > /dev/null 2>&1
do
echo -n "."
sleep 1

@ -0,0 +1,177 @@
#!/bin/bash
#
# Helper functions
#
# run-in-node: Run a command inside a docker container, using the bash shell
function run-in-node () {
docker exec "$1" /bin/bash -c "${@:2}"
}
# wait-for-cmd: Run a command repeatedly until it completes/exits successfuly
function wait-for-cmd () {
until "${@}" > /dev/null 2>&1
do
echo -n "."
sleep 1
done
echo
}
# wait-for-node: Run a command repeatedly until it completes successfully, inside a container
# Combining wait-for-cmd and run-in-node
function wait-for-node () {
wait-for-cmd run-in-node $1 "${@:2}"
}
# Start the demo
echo "Starting Payment Demo"
echo "======================================================"
echo
echo "Waiting for nodes to startup"
echo -n "- Waiting for bitcoind startup..."
wait-for-node bitcoind "cli getblockchaininfo | jq -e \".blocks > 101\""
echo -n "- Waiting for bitcoind mining..."
wait-for-node bitcoind "cli getbalance | jq -e \". > 50\""
echo -n "- Waiting for Alice startup..."
wait-for-node Alice "cli getinfo"
echo -n "- Waiting for Bob startup..."
wait-for-node Bob "cli getinfo"
echo -n "- Waiting for Chan startup..."
wait-for-node Chan "cli getinfo"
echo -n "- Waiting for Dina startup..."
wait-for-node Dina "cli getinfo"
echo "All nodes have started"
echo "======================================================"
echo
echo "Getting node IDs"
alice_address=$(run-in-node Alice "cli getinfo | jq -r .identity_pubkey")
bob_address=$(run-in-node Bob "cli getinfo | jq -r .id")
chan_address=$(run-in-node Chan "cli getinfo| jq -r .nodeId")
dina_address=$(run-in-node Dina "cli getinfo | jq -r .identity_pubkey")
# Show node IDs
echo "- Alice: ${alice_address}"
echo "- Bob: ${bob_address}"
echo "- Chan: ${chan_address}"
echo "- Dina: ${dina_address}"
echo "======================================================"
echo
echo "Waiting for Lightning nodes to sync the blockchain"
echo -n "- Waiting for Alice chain sync..."
wait-for-node Alice "cli getinfo | jq -e \".synced_to_chain == true\""
echo -n "- Waiting for Bob chain sync..."
wait-for-node Bob "cli getinfo | jq -e \".blockheight > 100\""
echo -n "- Waiting for Chan chain sync..."
wait-for-node Chan "cli getinfo | jq -e \".blockHeight > 100\""
echo -n "- Waiting for Dina chain sync..."
wait-for-node Dina "cli getinfo | jq -e \".synced_to_chain == true\""
echo "All nodes synched to chain"
echo "======================================================"
echo
echo "Setting up connections and channels"
echo "- Alice to Bob"
# Connect only if not already connected
run-in-node Alice "cli listpeers | jq -e '.peers[] | select(.pub_key == \"${bob_address}\")' > /dev/null" \
&& {
echo "- Alice already connected to Bob"
} || {
echo "- Open connection from Alice node to Bob's node"
wait-for-node Alice "cli connect ${bob_address}@Bob"
}
# Create channel only if not already created
run-in-node Alice "cli listchannels | jq -e '.channels[] | select(.remote_pubkey == \"${bob_address}\")' > /dev/null" \
&& {
echo "- Alice->Bob channel already exists"
} || {
echo "- Create payment channel Alice->Bob"
wait-for-node Alice "cli openchannel ${bob_address} 1000000"
}
echo "Bob to Chan"
run-in-node Bob "cli listpeers | jq -e '.peers[] | select(.id == \"${chan_address}\")' > /dev/null" \
&& {
echo "- Bob already connected to Chan"
} || {
echo "- Open connection from Bob's node to Chan's node"
wait-for-node Bob "cli connect ${chan_address}@Chan"
}
run-in-node Bob "cli listchannels | jq -e '.channels[] | select(.destination == \"${chan_address}\")' > /dev/null" \
&& {
echo "- Bob->Chan channel already exists"
} || {
echo "- Create payment channel Bob->Chan"
wait-for-node Bob "cli fundchannel ${chan_address} 1000000"
}
echo "Chan to Dina"
run-in-node Chan "cli peers | jq -e '.[] | select(.nodeId == \"${dina_address}\" and .state == \"CONNECTED\")' > /dev/null" \
&& {
echo "- Chan already connected to Dina"
} || {
echo "- Open connection from Chan's node to Dina's node"
wait-for-node Chan "cli connect --uri=${dina_address}@Dina"
}
run-in-node Chan "cli channels | jq -e '.[] | select(.nodeId == \"${dina_address}\" and .state == \"NORMAL\")' > /dev/null" \
&& {
echo "- Chan->Dina channel already exists"
} || {
echo "- Create payment channel Chan->Dina"
wait-for-node Chan "cli open --nodeId=${dina_address} --fundingSatoshis=1000000"
}
echo "All channels created"
echo "======================================================"
echo
echo "Waiting for channels to be confirmed on the blockchain"
echo -n "- Waiting for Alice channel confirmation..."
wait-for-node Alice "cli listchannels | jq -e '.channels[] | select(.remote_pubkey == \"${bob_address}\" and .active == true)'"
echo "- Alice->Bob connected"
echo -n "- Waiting for Bob channel confirmation..."
wait-for-node Bob "cli listchannels | jq -e '.channels[] | select(.destination == \"${chan_address}\" and .active == true)'"
echo "- Bob->Chan connected"
echo -n "- Waiting for Chan channel confirmation..."
wait-for-node Chan "cli channels | jq -e '.[] | select (.nodeId == \"${dina_address}\" and .state == \"NORMAL\")' > /dev/null"
echo "- Chan->Dina connected"
echo "All channels confirmed"
echo "======================================================"
echo -n "Check Alice's route to Dina: "
run-in-node Alice "cli queryroutes --dest \"${dina_address}\" --amt 10000" > /dev/null 2>&1 \
&& {
echo "Alice has a route to Dina"
} || {
echo "Alice doesn't yet have a route to Dina"
echo "Waiting for Alice graph sync. This may take a while..."
wait-for-node Alice "cli describegraph | jq -e '.edges | select(length >= 1)'"
echo "- Alice knows about 1 channel"
wait-for-node Alice "cli describegraph | jq -e '.edges | select(length >= 2)'"
echo "- Alice knows about 2 channels"
wait-for-node Alice "cli describegraph | jq -e '.edges | select(length == 3)'"
echo "- Alice knows about all 3 channels!"
echo "Alice knows about all the channels"
}
echo "======================================================"
echo
echo "Get 10k sats invoice from Dina"
dina_invoice=$(run-in-node Dina "cli addinvoice 10000 | jq -r .payment_request")
echo "- Dina invoice: "
echo ${dina_invoice}
echo "======================================================"
echo
echo "Attempting payment from Alice to Dina"
run-in-node Alice "cli payinvoice --json --force ${dina_invoice} | jq -e '.failure_reason == \"FAILURE_REASON_NONE\"'" > /dev/null && {
echo "Successful payment!"
} ||
{
echo "Payment failed"
}

@ -1,37 +0,0 @@
#!/bin/bash
echo Getting node IDs
alice_address=$(docker-compose exec -T Alice bash -c "lncli -n regtest getinfo | jq -r .identity_pubkey")
bob_address=$(docker-compose exec -T Bob bash -c "lightning-cli getinfo | jq -r .id")
chan_address=$(docker-compose exec -T Chan bash -c "eclair-cli -s -j -p eclair getinfo| jq -r .nodeId")
dina_address=$(docker-compose exec -T Dina bash -c "lncli -n regtest getinfo | jq -r .identity_pubkey")
# Let's tell everyone what we found!
echo Alice: ${alice_address}
echo Bob: ${bob_address}
echo Chan: ${chan_address}
echo Dina: ${dina_address}
echo Setting up channels...
echo Alice to Bob
docker-compose exec -T Alice lncli -n regtest connect ${bob_address}@Bob
docker-compose exec -T Alice lncli -n regtest openchannel ${bob_address} 1000000
echo Bob to Chan
docker-compose exec -T Bob lightning-cli connect ${chan_address}@Chan
docker-compose exec -T Bob lightning-cli fundchannel ${chan_address} 1000000
echo Chan to Dina
docker-compose exec -T Chan eclair-cli -p eclair connect --uri=${dina_address}@Dina
docker-compose exec -T Chan eclair-cli -p eclair open --nodeId=${dina_address} --fundingSatoshis=1000000
echo Get 10k sats invoice from Dina
dina_invoice=$(docker-compose exec -T Dina bash -c "lncli -n regtest addinvoice 10000 | jq -r .payment_request")
echo Dina invoice ${dina_invoice}
echo Wait for channel establishment - 60 seconds for 6 blocks
sleep 60
echo Alice pays Dina 10k sats, routed around the network
docker-compose exec -T Alice lncli -n regtest payinvoice --json --inflight_updates -f ${dina_invoice}

@ -1,65 +1,65 @@
argon2-cffi==20.1.0
async-generator==1.10
attrs==21.2.0
backcall==0.2.0
bleach==3.3.1
cffi==1.14.6
cycler==0.10.0
debugpy==1.4.0
decorator==4.4.2
defusedxml==0.7.1
entrypoints==0.3
graphviz==0.17
ipykernel==6.0.3
ipython==7.25.0
ipython-genutils==0.2.0
ipywidgets==7.6.3
jedi==0.18.0
Jinja2==3.0.1
jsonschema==3.2.0
jupyter==1.0.0
jupyter-client==6.1.12
jupyter-console==6.4.0
jupyter-core==4.7.1
jupyterlab-pygments==0.1.2
jupyterlab-widgets==1.0.0
kiwisolver==1.3.1
MarkupSafe==2.0.1
matplotlib==3.4.2
matplotlib-inline==0.1.2
mistune==0.8.4
nbclient==0.5.3
nbconvert==6.1.0
nbformat==5.1.3
nest-asyncio==1.5.1
networkx==2.5.1
notebook==6.4.0
numpy==1.21.1
packaging==21.0
pandocfilters==1.4.3
parso==0.8.2
pexpect==4.8.0
pickleshare==0.7.5
Pillow==8.3.1
prometheus-client==0.11.0
prompt-toolkit==3.0.19
ptyprocess==0.7.0
pycparser==2.20
Pygments==2.9.0
pyparsing==2.4.7
pyrsistent==0.18.0
python-dateutil==2.8.2
pyzmq==22.1.0
qtconsole==5.1.1
QtPy==1.9.0
scipy==1.7.0
Send2Trash==1.7.1
six==1.16.0
terminado==0.10.1
testpath==0.5.0
tornado==6.1
traitlets==5.0.5
ujson==4.0.2
wcwidth==0.2.5
webencodings==0.5.1
widgetsnbextension==3.5.1
argon2-cffi
async-generator
attrs
backcall
bleach
cffi
cycler
debugpy
decorator
defusedxml
entrypoints
graphviz
ipykernel
ipython
ipython-genutils
ipywidgets
jedi
Jinja2
jsonschema
jupyter
jupyter-client
jupyter-console
jupyter-core
jupyterlab-pygments
jupyterlab-widgets
kiwisolver
MarkupSafe
matplotlib
matplotlib-inline
mistune
nbclient
nbconvert
nbformat
nest-asyncio
networkx
notebook>=6.4.1
numpy
packaging
pandocfilters
parso
pexpect
pickleshare
Pillow
prometheus-client
prompt-toolkit
ptyprocess
pycparser
Pygments
pyparsing
pyrsistent
python-dateutil
pyzmq
qtconsole
QtPy
scipy
Send2Trash
six
terminado
testpath
tornado
traitlets
ujson
wcwidth
webencodings
widgetsnbextension

@ -124,5 +124,5 @@ This is trustless as users do not need to loan or send anyone their Bitcoin. Use
The Lightning Network's principal object is to move payments across a network.
Could it move data other than payments across its network too? It can.
Some projects such as _Whatsat_, _Sphinx Chat_, and _Juggernaut_ are implementing instant messaging chat apps on top of the Ligtning Network.
One can imaging other types of data such as electronic tickets, QR codes, or other forms of tokens flowing across the Lightning Network as well.
One can imagine other types of data such as electronic tickets, QR codes, or other forms of tokens flowing across the Lightning Network as well.
The use cases are limited only by our imagination and reach beyond finance.

@ -1,10 +1,11 @@
* 8go (@8go)
* Aaqil Aziz (@batmanscode)
* Alexander Gnip (@quantumcthulhu)
* Alpha Q. Smith (@alpha_github_id)
* Ben Skee (@benskee)
* Brian L. McMichael (@brianmcmichael)
* Daniel Gockel (@dancodery)
* Dapeng Li (@luislee818)
* Darius E. Parvin (@DariusParvin)
* Doru Muntean (@chriton)
* Eduardo Lima III (@elima-iii)
@ -14,18 +15,22 @@
* François Degros (@fdegros)
* Giovanni Zotta (@GiovanniZotta)
* Gustavo Silva (@GustavoRSSilva)
* Guy Thayakorn (@saguywalker)
* Haoyu Lin (@HAOYUatHZ)
* Hatim Boufnichel (@boufni95)
* Imran Lorgat (@ImranLorgat)
* John Davies (@tigeryant)
* Julien Wendling (@trigger67)
* Jussi Tiira (@juhi24)
* Kory Newton (@korynewton)
* Lawrence Webber (@lwebbz)
* Luigi (@gin)
* Maximilian Karasz (@mknoszlig)
* Omega X. Last (@omega_github_id)
* Owen Gunden (@ogunden)
* Patrick Lemke (@PatrickLemke)
* Paul Wackerow (@wackerow)
* Randy McMillan (@RandyMcMillan)
* René Köhnke (@rene78)
* Ricardo Marques (@RicardoM17)
* Sebastian Falbesoner (@theStack)
@ -34,7 +39,6 @@
* Simone Bovi (@SimoneBovi)
* Srijan Bhushan (@srijanb)
* Taylor Masterson (@tjmasterson)
* Guy Thayakorn (@saguywalker)
* Umar Bolatov (@bolatovumar)
* Warren Wan (@wlwanpan)
* Dapeng Li (@luislee818)
* Zachary Haddenham (@senf42)

@ -31,10 +31,10 @@ Some additional definitions, to be cleaned up and moved into alphabetic order ar
[glossary]
address::
A Bitcoin address looks like +1DSrfJdB2AnWaFNgSbv3MZC2m74996JafV+. It consists of a string of letters and numbers. It's really an encoded base58check version of a public key 160-bit hash. Just as you ask others to send an email to your email address, you would ask others to send you bitcoin to one of your Bitcoin addresses.
A Bitcoin address looks like +1DSrfJdB2AnWaFNgSbv3MZC2m74996JafV+. It consists of a string of letters and numbers. It's really an encoded base58check version of a public key 160-bit hash. After P2SH, the 160-bit hash of a script is encoded, and with segwit the 256-bit hash of a script (or 160-bit key hash) is encoded. Just as you ask others to send an email to your email address, you would ask others to send you bitcoin to one of your Bitcoin addresses.
AMP::
Atomic Multipath Payments was an early suggestion for a multipart payment protocol which did not get implemented but introduced the idea of splitting a single payment into multiple parts and send them along potentially different paths.
Atomic Multipath Payments is an extension to the protocol that allows triggering a spontaneous payment (no invoice required) that splits up a payment into multiple parts and uses additive secret sharing to ensure that the payment can only be pulled once all parts arrive. Additionally, each path of a AMP payment uses a distinct payment hash.
Asymmetric Cryptographic System::
Asymmetric cryptography, or public-key cryptography, is a cryptographic system that uses pairs of keys: public keys which may be disseminated widely, and private keys which are known only to the owner.
@ -79,7 +79,7 @@ blockchain::
The blockchain is an irreversible distributed database storing all Bitcoin transactions.
The irreversibility comes from the fact that each group of transactions, referred to as a block, is validated by solving a proof of work riddle and including the hash of the previous block.
Thus, the data can only be changed by an entity providing more than 51% of the computational power of the Bitcoin network.
Blocks currently have a size limit of 1 MB.
Blocks currently have a size limit of 4 Million weight units.
New blocks have a statistical probability of being produced every ten minutes.
BOLT::
@ -221,6 +221,10 @@ hardware wallet::
hash::
A digital fingerprint of some binary input.
hash-based message authentication code (HMAC)::
An HMAC is a message authentication code method for verifying the integrity and authenticity of a message based on a hash function and a cryptographic key.
It is used in onion routing to ensure the integrity of a packet at each hop, as well as within the Norse protocol variant used for message encryption.
hash function::
A cryptographic hash function is a mathematical algorithm that maps data of arbitrary size to a bit string of a fixed size (a hash) and is designed to be a one-way function, that is, a function which is infeasible to invert.
The only way to recreate the input data from an ideal cryptographic hash function's output is to attempt a brute-force search of possible inputs to see if they produce a match, or use a rainbow table of matched hashes.
@ -293,7 +297,7 @@ Neutrino::
Neutrino is a later alternative to SPV that also verifies whether certain transactions are contained in a block without downloading the entire block. However, it offers a number of improvements over SPV: Neutrino does not transmit any information that would allow a third party to determine users identities, it facilitates the use of non-custodial apps, and it reduces the computational load on full nodes. The trade-off for these improvements is that Neutrino requires more data from the full node than SPV.
node::
See Lightning Network Node
See _Lightning Network Node_
network capacity::
Lightning network capacity is the total amount of bitcoin locked and circulated inside the Lightning Network.
@ -301,7 +305,7 @@ network capacity::
It reflects the usage of the Lightning Network to some extent because we expect that people lock bitcoin into Lightning channels in order to spend it or forward other users' payments.
Hence the higher the amount of bitcoin locked in channels, the higher the expected usage of the Lightning Network.
Note that since only public channel capacity can be observed, the true network capacity is unknown.
See private channel.
See _private channel_.
Noise_XK::
The template of the Noise protocol framework to establish an authenticated and encrypted communication channel between two peers of the Lightning Network.
@ -360,7 +364,7 @@ peer::
In particular, they are connected via an encrypted, authenticated communication over a TCP Socket.
penalty transaction::
See Breach Remedy Transaction.
See _Breach Remedy Transaction_.
private channel::
A channel not announced to the rest of the network.
@ -382,10 +386,10 @@ preimage::
proof of work::
A piece of data that requires significant computation to find.
In Bitcoin, miners must find a numeric solution to the SHA256 algorithm that meets a network-wide target, called the difficulty target.
See _bitcoin mining_
See _bitcoin mining_.
Relative Timelock::
Relative Timelock is a type of timelock which allows an input to specify the earliest time the input can be added to a block. The time is relative and is based on when the output referenced by that input was included in a block. Such a feature is jointly achieved by nSequence field and CheckSequenceVerify opcode, which were introduced by BIP68/112/113.
Relative Timelock is a type of timelock which allows an input to specify the earliest time the input can be added to a block. The time is relative and is based on when the output referenced by that input was included in a block. Such a feature is jointly achieved by nSequence field and CheckSequenceVerify opcode, which was introduced by BIP68/112/113.
Revocable Sequence Maturity Contract::
This contract is used to construct a payment channel between two Bitcoin or Lightning Network users who do not need to trust each other.
@ -440,7 +444,7 @@ secret key (aka private key)::
----
Segregated Witness::
Segregated Witness is an upgrade to the Bitcoin protocol in which signature data is separated from Bitcoin transactions. Segregated Witness was deployed as a soft fork and is a change that technically makes Bitcoins protocol rules more restrictive.
Segregated Witness is an upgrade to the Bitcoin protocol that adds a new witness for signatures and other transaction authorization proofs. This new witness field is exempt from the calculation of a new transaction ID, which solves most classes of 3rd party transaction malleability. Segregated Witness was deployed as a soft fork and is a change that technically makes Bitcoins protocol rules more restrictive.
SHA::
The Secure Hash Algorithm or SHA is a family of cryptographic hash functions published by the National Institute of Standards and Technology (NIST). The Bitcoin protocol currently uses SHA256.
@ -463,8 +467,7 @@ source-based routing::
Source-based routing is fundamentally different to how routing works on the Internet Protocol.
soft fork::
Soft fork, or Soft-Forking Change, is a temporary fork in the blockchain which commonly occurs when miners using non-upgraded nodes don't follow a new consensus rule their nodes dont know about.
Not to be confused with fork, hard fork, software fork or Git fork.
Soft fork, or Soft-Forking Change, is a protocol upgrade that's forwards+backwards compatible so it allows old nodes and new nodes to both continue using the same chain.
SPHINX Mix Format::
A particular technique for Onion Routing used in the Lightning Network and invented by George Danezis and Ian Goldberg in 2009.

Binary file not shown.

After

Width:  |  Height:  |  Size: 267 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 267 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 268 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 35 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 37 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 44 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 176 KiB

After

Width:  |  Height:  |  Size: 176 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 64 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 118 KiB

After

Width:  |  Height:  |  Size: 105 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 56 KiB

@ -0,0 +1,8 @@
[[part_1]]
[part]
== Understanding The Lightning Network
[partintro]
--
An overview of the Lightning Network suitable for anyone interested in understanding the basic concepts and use of the Lightning Network
--

@ -0,0 +1,8 @@
[[part_2]]
[part]
== The Lightning Network in detail
[partintro]
--
A detailed explanation of all the components of the Lightning Network and how they work. This part is highly technical and expects the reader to have some programming and computer science experience.
--

@ -9,7 +9,7 @@ This book is a collaboration between Andreas M. Antonopoulos, Olaoluwa Osuntokun
[[intended_audience_sec]]
=== Intended Audience
((("intended audience")))This book is mostly intended for *TBD*.
((("intended audience")))This book is mostly intended for technical readers with an understanding of the fundamentals of Bitcoin and other open blockchains.
[[conventinons_used_sec]]
=== Conventions Used in This Book

@ -0,0 +1,37 @@
from __future__ import print_function
import glob
import re
markup_files = glob.glob('*.asciidoc')
anchor_re = re.compile("\[\[(.*)\]\]")
ref_re = re.compile(".*\<\<([^\>]*)\>\>.")
refs = []
anchors = []
dup_anchors = []
for markup_file in markup_files:
markup_f = open(markup_file, 'r')
markup_contents = markup_f.read()
markup_f.close()
for line in markup_contents.splitlines():
ref_match = ref_re.match(line)
if ref_match:
if ref_match.group(1) not in refs:
refs.append(ref_match.group(1))
anchor_match = anchor_re.match(line)
if anchor_match:
if anchor_match.group(1) not in anchors:
anchors.append(anchor_match.group(1))
else:
dup_anchors.append(anchor_match.group(1))
print("\nAnchors: ", len(anchors))
print("\nDuplicated Anchors: ", len(dup_anchors))
print(dup_anchors)
print("\nReferences: ", len(refs))
print(refs)
broken_refs = list(set(refs) - set(anchors))
print("\nBroken references: ", len(broken_refs), broken_refs)
missing_refs = list(set(anchors) - set(refs))
print("\nUn-referenced Anchors: ", len(missing_refs), missing_refs)
Loading…
Cancel
Save