LND Overview and Developer Guide
Mục lục bài viết
Introduction
The LND Overview and Developer Guide aims to provide just enough information
about LND to enable readers to build applications. It starts with a conceptual
review of the Lightning Network, before jumping into the important aspects of
working specifically with LND. If you are already comfortable with how the
Lightning Network works, feel free to skip down to the Components
section. The command line examples are for illustrative purposes only and will
be covered in more depth in the installation guide and
tutorial.
Preliminaries
This overview assumes basic knowledge of Bitcoin mechanics. If terms like “UTXO”
and “locktime” are unfamiliar to you, you should refer to the Bitcoin developer
guide, which serves a similar purpose.
Table of Contents
Lightning Network
The Lightning Network scales blockchains and enables trustless instant payments
by keeping most transactions off-chain and leveraging the security of the
underlying blockchain as an arbitration layer.
This is accomplished primarily through “payment-channels”, wherein two parties
commit funds and pay each other by updating the balance redeemable by either
party in the channel. This process is instant and saves users from having to
wait for block confirmations before they can render goods or services.
Payment channels are trustless, since any attempt to defraud the current
agreed-upon balance in the channel results in the complete forfeiture of funds
by the liable party.
By moving payments off-chain, the cost of opening and closing channels (in the
form of on-chain transaction fees) is ammortized over the volume of payments in
that channel, enabling micropayments and small-value transactions for which the
on-chain transaction fees would otherwise be too expensive to justify.
Furthermore, the Lightning Network scales not with the transaction throughput of
the underlying blockchain, but with modern data processing and latency limits –
payments can be made nearly as quickly as packets can be sent.
Hash Time-Locked Contracts (HTLCs) allow transactions to be sent between parties
who do not have a direct channel by routing them through multiple hops, so anyone
connected to the Lightning Network is part of a single, interconnected global
financial system.
In short, the Lightning Network enables scalable blockchains through a
high-volume of instant transactions not requiring custodial delegation.
Payment Channels
Payment channels are the main workhorse of the Lightning Network. They allow
multiple transactions to be aggregated into just a few on-chain transactions.
In the vast majority of cases, someone only needs to broadcast the first and
last transaction in the channel.
- The Funding Transaction creates the channel. During this stage, funds
are sent into a multisig address controlled by both Alice and Bob, the
counterparties to the channel. This address can be funded as a single-payer
channel or by both Alice and Bob. - The Closing Transaction closes the channel. When broadcast, the multisig
address spends the funds back to Alice and Bob according to their agreed-upon
channel amount.
In the case where either party attempts to defraud the other, a third
transaction, which punishes the attacker, will end up being broadcasted
on-chain. Let’s investigate how this is possible by the way Lightning does
channel updates.
In between the opening and closing transactions broadcast to the blockchain,
Alice and Bob can create a near infinite number of intermediate closing
transactions that gives different amounts to the two parties.
For example, if the initial state of the channel credits both Alice and Bob with
5BTC out of the 10BTC total contained in the multisig address, Alice can make a
1BTC payment to Bob by updating the closing transaction to pay 4BTC/6BTC, where
Alice is credited with 4BTC and Bob with 6BTC. Alice will give the signed
transaction to Bob, which is equivalent to payment, because Bob can broadcast it
at any time to claim his portion of the funds. Similarly, Alice is also able to
broadcast the closing transaction at any time to claim her funds.
To prevent an attack where Alice voids her payment by broadcasting the initial
state of 5BTC/5BTC, there needs to be a way to revoke prior closing
transactions. Payment revocation roughly works like the following.
When Alice broadcasts a closing transaction to the blockchain, she is attesting
to the current state of the chain. But since there may be millions of closing
transactions in a channel, all of which are valid, the blockchain itself can’t
tell if what Alice attested to was indeed the correct state. Therefore, Alice
must wait 3 days after broadcasting the closing transaction before she can
redeem her funds. During this time, Bob is given a chance to reveal a secret
that will allow him to sweep Alice’s funds immediately. Alice can thus revoke
her claim to the money in some state by giving Bob the secret to the closing
transaction. This allows Bob to take all of Alice’s money, but only if Alice
attest to this old state by broadcasting the corresponding closing transaction
to the blockchain.
Channel updates are thus fully trustless. When making an update, both parties
exchange the secrets for the prior state, so that all prior states will have
been revoked except for the current state. Both parties will never broadcast an
old state, because they know the other party can take all their money if they
do so.
Multihop payments
Single channels work well if you have a financial relationship with some entity
where you make payments frequently or in metered amounts. But most payments,
like purchasing an umbrella from a corner store because you lost it again, are
one-off. For Lightning to help Bitcoin scale for general use cases, there needs
to be a way for the whole network to forward payments through channels that
already exist. Furthermore, this process should retain the trustless nature of
individual channels, otherwise it becomes too hard to identify dishonest actors
amongst a large number of hops.
Once you don’t have to trust the intermediaries, you no longer even care who
they are. This allows Lightning nodes to be fully anonymous, which is a huge win
for privacy.
Concretely, Suppose Alice has a channel with Bob, who has a channel with Carol,
who has a channel with Dave: A<->B<->C<->D
. How can Alice pay Dave?
Alice first notifies Dave that she wants to send him some money.
In order for Dave to accept this payment, he must generate a random number R
.
He keeps R
secret, but hashes it and gives the hash H
to Alice.
Alice tells Bob: “I will pay you if you can produce the preimage of H
within 3
days.” In particular, she signs a transaction where for the first three days
after it is broadcast, only Bob can redeem it with knowledge of R, and
afterwards it is redeemable only by Alice. This transaction is called a Hash
Time-Locked Contract (HTLC) and allows Alice to make a conditional promise to
Bob while ensuring that her funds will not be accidentally burned if Bob never
learns what R is. She gives this signed transaction to Bob, but neither of them
broadcast it, because they are expecting to clear it out later.
Bob, knowing that he can pull funds from Alice if he knows R, now has no issue
telling Carol: “I will pay you if you can produce the preimage of H within 2
days.”
Carol does the same, making an HTLC that will pay Dave if Dave can produce R
within 1 day. However, Dave does in fact know R. Because Dave is able to pull
the desired amount from Carol, Dave can consider the payment from Alice
completed. Now, he has no problem telling R to Carol and Bob so that they are
able to collect their funds as well.
Now, everyone can clear out, because they have a guaranteed way to pull their
deserved funds by broadcasting these HTLCs onto Bitcoin’s network (i.e.
on-chain). They would prefer not to do that though, since broadcasting on-chain
is more expensive, and instead settle each of these hops off chain. Alice knows
that Bob can pull funds from her since he has R
, so she tells Bob: “I’ll pay
you, regardless of R
, and in doing so we’ll terminate the HTLC so we can
forget about R.” Bob does the same with Carol, and Carol with Dave.
Now, what if Dave is uncooperative and refuses to give R
to Bob and Carol?
Note that Dave must broadcast the transaction from Carol within 1 day, and in
doing so must reveal R in order to redeem the funds. Bob and Carol can simply
look at the blockchain to determine what R is and settle off-chain as well.
We have shown how to make a payment across the Lightning Network using only
off-chain transactions, without requiring direct channel links or trusting any
intermediaries. As long as there is a path from the payer to the payee, payments
can be routed, just like the Internet.
Network Topology
The expected shape / network topology of the Lightning Network will depend on
behavior implemented in the varying Lightning implementations as well as actual
usage. Users do not have to manually manage their channels, since lnd
has an
‘autopilot’ feature including settings optimizing for both everyday use and fee
revenue. And of course, channels can be opened on demand via the standard
command line, gRPC, and REST interfaces.
Integration guidelines
When integrating lnd
, hot and cold storage must be considered. To maximize
security, we generally want to keep as little as possible in hot wallets, and as
much as possible in cold wallets.
It is possible to construct Lightning channels where the keys are cold, but they
would need to be brought back online to conduct a channel update. Only with hot
wallets can the Lightning Network attain a high volume of transactions.
This is only a surface level introduction to Lightning integration. For a more
illustrative example of how Lightning Network may work in production, check out
the “Integration Components” and “Security Considerations” sections of the
Exchange Integration Document
maintained by Bryan Vu.
Components
Network Layers
The Lightning Network is an overlay network on top of another blockchain. To
avoid confusion it is crucial to differentiate between the following network
layers we encounter when reasoning about lnd
:
- Bitcoin/Litecoin Network: This is the underlying blockchain that
lnd
rests
on top of.lnd
needs a way to communicate with the underlying blockchain in
order to send on-chain payments, create channel open/close transactions, and
watch for events on the blockchain. - P2P Network: This is the peer layer where
lnd
nodes add each other as peers
so they can send messages between one another via an encrypted
connection.
For example, thelncli connect
adds a peer, which are identified by identity
pubkey and IP address. - Payment channel network: This is the layer where nodes are connected by
payment channels. For example, thelncli openchannel
command opens a
channel with a node that was already connected at the peer layer, and the
lncli describegraph
command returns the list of edges and vertices of the
payment channel graph.
Software Components
There are distinct software components we should be aware of when developing on
btcd
orbitcoind
is used bylnd
to interface with the underlying blockchain.lnd
/lncli
: LND stands for Lightning Network Daemon and serves as the
main software component driving the Lightning Network. It manages a database,
connects to peers, opens / closes channels, generates payment invoices, sends,
forwards, and revokes payments, responds to potential breaches, and more.
lncli
opens up a command line interface for drivinglnd
.- Neutrino is an experimental
Bitcoin light client designed to support Lightning mobile clients. This is a
wallet UI usable withlnd
. Neutrino is not required from an application
development standpoint, but can be regarded as the primary way for an
end-user oflnd
to interact with the Bitcoin Network and the applications
built on top of it.
LND Interfaces
There are several ways to drive lnd
.
lncli
is thelnd
command line tool. All commands are executed
instantaneously. A full list of commands can be viewed withlncli --help
.
To see a breakdown of the parameters for a particular command, run
lncli <command> --help
- gRPC is the preferred programmatic way to interact with
lnd
. It includes simple
methods that return a response immediately, as well as response-streaming and
bidrectional streaming methods. Check out the guides for working with gRPC for
Python and Javascript - LND also features a REST proxy someone can use if they are accustomed to
standard RESTful APIs. However, REST does not have full streaming RPC coverage.
All of these LND interfaces are documented in the API
Reference, featuring a description of the
parameters, responses, and code examples for Python, Javascript, and command
line arguments if those exist.
Channel Lifecycle
To better understand the development workflow around Lightning channels, it is
worthwhile to examine step by step the lifecycle of a payment channel. It
contains roughly 4 steps:
- Adding a peer. Before a channel can be opened between two Lightning
nodes, they must first be able to securely communicate with each other. This
is accomplished with theConnectPeer
RPC method orconnect
onlncli
.lncli connect <PUBKEY>@<HOST>:<PORT>
- Initiating Channel Opening. The
OpenChannel
method begins the channel
opening process with a connected peer. Lightning assumes that this is led by
a single party. The opening party can specify a local amount, representing
the funds they would like to commit to the channel, and a “push” amount, the
amount of money that they would like to give to the other side as part of an
initial commitment state. One could imagine that instead of sending a
standard Bitcoin transaction to pay a merchant, they could instead open a
channel with the push amount representing the amount they want to pay, and
optionally add some funds of their own, so that both parties can benefit from
having a channel available for payments in the future.lncli openchannel --node_key
=
<ID_PUBKEY> --local_amt=
<AMOUNT> - Wait for confirmations. To prevent double spending attacks on the channel
opening transaction, users should specify the--block
lncli
command line
argument. So after initializing the channel opening process, it is often
required to mine a few blocks:btcctl generate 6
- Close Channel. If either party in a channel no longer wants to keep it
open, they can close it at any time with theCloseChannel
method.lncli closechannel --funding_txid
=
<funding_txid> --output_index=
<output_index>
Payment Lifecycle
Because Lightning payments are instant, its API tends to be much simpler, since
there is no need to wait for block confirmations before a payment is considered
accepted. It resembles a fairly standard payment flow, but there are a few
additional things to keep in mind.
Payment Requests
Payment requests, often also referred to as Invoices, are a simple, extensible
protocol compatible with QR-codes. It includes a 6-character checksum in case
there is a mistake with copy/paste or manual entry.
Payment requests are composed of two sections:
- Human readable part: Contains a prefix
ln
followed by an optional
amount. - Data part: Contains a UTC Unix timestamp and optionally some tagged
parts, as well as a signature over the human readable and data parts.- Tagged parts include a payment hash, the pubkey of the payee node, a
description of the purpose of payment, an expiration time (default to 1
hour if not specified), and extra routing information. Some tagged parts
are required and others are not.
- Tagged parts include a payment hash, the pubkey of the payee node, a
Because the payment request contains the payment hash, payment requests must
be strictly single use. After an invoice is fulfilled, the hash preimage
becomes publically known. An attacker could save the preimages they’ve seen and
reuse it for another payment that is reusing the invoice. Therefore, failure
to generate new payment requests means that an on-path attacker can steal the
payment en route.
Another detail worth noting is that payees should not accept payments after the
payment request has expired (timestamp
+ expiry
), and payers likewise should
not attempt them. This will affect any web application with lnd
integration,
since if an invoice for a good or service is not fulfilled within the given
timeframe, a new one should be generated.
Other possibly unexpected rules include that the payee should accept up to
twice the amount encoded in the transaction, so that the payer can make payments
harder to track by adding in small variations.
A full specification of the payment request data format, required and optional
parts, and required behavior can be found in BOLT
11.
Payment flow
Let’s now see what an ideal payment flow looks like.
- Create Invoice: The recipient creates an invoice with a specified value,
expiration time, and an optional memo. If there was already an invoice
created for this good and it expired, or a sufficient amount of time has
elapsed, a fresh invoice should be generated.lncli addinvoice --amt
=
6969 --memo=
"A coffee for Roger"
- Check invoice: The payer decodes the invoice to see the destination,
amount and payment hash. This way, they can validate that the invoice was
legitimate, and that they aren’t being defrauded or overcharged. At this
stage, the user should also check that the expiration time of the invoice has
not passedlncli decodepayreq --pay_req
=
<PAY_REQ> - Send payment: The payer sends their payment, possibly routed through the
Lightning Network. Developers can do this through an LND interface and end
users can use the desktop or mobile app.lncli sendpayment --pay_req
=
<PAY_REQ> - Check payment: The recipient checks that their invoice has been
fulfilled. They make a call to theLookupInvoice
command, which returns
this information in thesettled
field.lncli lookupinvoice --rhash
=
<R_HASH>
We have now covered the basic workflow for generating invoices and
sending/receiving payments.
Conclusion
You have completed the conceptual overview of LND and a high level primer on the
components and workflows. To get started on developing, check out the
installation guide and tutorial.