Bitcoin Lightning Network Tutorial — How to integrate Lightning to a crypto project
The Chlu team has been working closely with our friends at the MIT Digital Currency Initiative (DCI) for some time. We were honored to be invited recently by the DCI to a two day hackathon at MIT and Fidelity Labs, focused on the latest advancements in Layer 2 technology.
For those who are not aware, Layer 2 technologies focus on scaling blockchains by removing the requirement to immediately “commit” each transaction to Layer 1 blockchains. Blockchains have a fixed block size which, while necessary, constrains how much data they can fit in each block which in turn limits the transaction throughput. Thus we get the much cited ~7 transactions per second that bitcoin’s blockchain can process at peak versus the ~ 45,000 transactions per second that Visa’s network can process at peak. Layer 2 technologies are an effort to address this crucial scaling problem.
The first day of the conference focused on presentations and Q&A from Layer 2 experts. The core of the discussions were around the Lightning Network (LN) which is the Layer 2 technology aimed at scaling bitcoin, but Raiden was also discussed. Research from Lightning Labs was presented by Conner Fromknecht and Elizabeth Stark, from Blockstream by Andrew Poelstra, and from MIT’s DCI by Neha Narula and Tadge Dryja (who described a novel approach to create “invisible smart contracts” using Discreet Log Contracts built on top of LIT). Other Layer 2 innovations were also presented from Sharon Goldberg & Ethan Heilman of CommonWealth Crypto, Sami Makela of TrueBit, Lefteris Karapetsas of Raiden, Evan Schwartz of Interledger and Alex Bosworth of Yalls and submarineswaps.
The second day was a hackathon focused on Layer 2. There were around 8 participating teams, one of which was Chlu. Our project for the hackathon was to investigate how we can provide a proof of payment while using Lightning Network transactions, enabling verified ratings and reviews to support the Chlu protocol.
The rest of this article describes our efforts during the hackathon and concludes with our learnings and future work. Hopefully our write up helps the reader leverage Lightning payments in their crypto projects.
The Hackathon — Approach
Support for Lightning payments as part of the Chlu protocol is complex because transactions are private between the lightning channel participants and only the channel opening transaction and the final channel settlement/closing transaction need to be written to the blockchain. Thus, we don’t have the same proof of payment that we do when directly using blockchains.
We initially investigated building a LN Watchtower as a potential solution, however a discussion with the original Lightning Network paper co-author Tadge Dryja convinced us this was not the right approach. Interestingly, this is because watchtowers implementations need to preserve the privacy of nodes they are helping, which is contrary to what we would want to do, i.e. to know the public key identifiers of the nodes involved in the transaction.
We decided to focus on two things in the 8 hour hackathon: first on integrating Lightning support into our Chlu demo hot wallet, and second, to investigate using LN participant signatures plus Open Timestamps for the LN proof of payment/Chlu protocol.
The following outlines the approach we took to the first task: how to add Lightning payment support to an existing crypto wallet, in our case the Chlu demo hot wallet.
Step 1: Setting up Lightning Nodes
Bitcoind is the Bitcoin Core implementation of the bitcoin blockchain. lnd is the Lightning implementation from Lightning Labs. To make a LN payment a user has to setup a lightning node that in turn talks to bitcoind. Once lnd and bitcoind are setup, a lightning node needs to open a channel to another lightning node. Opening a channel is effectively committing bitcoins into the lightning channel. Below we describe the LN Node infrastructure. We followed the tutorial from the lnd pages to help us with the setup.
Step 1.1 — Create EC2 Instances with LND & Bitcoind
We setup three EC2 nodes each with bitcoind running and synchronised with the bitcoin testnet blockchain, and with lnd installed. Alex Bosworth pointed us to how lnd can run with bitcoind. He posted an excellent gist to help us out. We decided to run three separate LN instances for experimentation however this is essentially not required and the lnd tutorial explains how to set up different lightning nodes on the same host talking to the same bitcoind.
Step 1.2 — Create a Lightning Wallet on each EC2 Instance
We use lnd and lncli to create a new wallets (alice, bob and carol) on the three EC2 instance. You can use lncli create
to create a new wallet for you that is not shared with the local bitcoind
. Once a lightning wallet is created, the public key is used as the identifier for the lightning node.
This was an interesting detail for us to know as in the long run Chlu wants to enable lightning payments for end users without relying on the a dedicated lightning node that is online all the time. This is to avoid user’s private keys being sent to a server running a custodial wallet, and this is a vision that a lot of teams are working towards including the efforts by the Vertcoin team building LitBox.
Step 1.3 — Fund theLightning Wallets
We funded the new wallets using bitcoin test faucet at https://testnet.manu.backend.hamburg/faucet.
Our three nodes are now identifiable from their public key hash. We can see their identity by running lncli getinfo
.
Alice (027bda
)
027bda4485e6be6238df4e14666a721e04aea485d5717ebdd43235a46ce3e16dce@34.196.116.222:9735
Bob (03a488
)
03a488dd9f3e19956c58ee78967b098111fe5e37fa94d57abf3e4018e039c9b0af@52.91.162.42:9735
Carol (03f105
)
03f1055ab2be1da3fe6225f99f1405f54bc2fc8c564f3401b249d97dc4e82efabf@54.90.73.105:9735
Step 1.4 Connect our lightning nodes
We next created a P2P network connection between the nodes.
From Alice’s node we ran lncli connect 03a488..@xxx:yy
to connect to Bob’s lightning node, and then from Bob’s node we run lncli connect 03f105..@xxx:yy
Once the connection is setup we can see that Bob is in Alice’s list of peers by running lncli listpeers
.
Step 1.5 Create Lightning Channels
The next step is to create channels between our nodes. But first we explain what a channel is. A channel is best defined on https://lightning.network/ as:
Two participants create a ledger entry on the blockchain which requires both participants to sign off on any spending of funds. Both parties create transactions which refund the ledger entry to their individual allocation, but do not broadcast them to the blockchain. They can update their individual allocations for the ledger entry by creating many transactions spending from the current ledger entry output. Only the most recent version is valid, which is enforced by blockchain-parsable smart-contract scripting. This entry can be closed out at any time by either party without any trust or custodianship by broadcasting the most recent version to the blockchain.
Create a channel between our lightning nodes
To open a channel we need to keep a few things in mind
- How much capacity we want in the channel? The capacity of the channel determines what is the maximum size of payment that can be made through a channel, and if this channel is routing payments through it, the capacity will influence if the payment can go across the channel.
- The capacity of a channel is not the same in both the directions, in fact, a channel can send up to a certain amount and receive a different amount. The amounts depend on the balance of the channel. Each node maintains a local balance and a remote balance — which tracks the amount of bitcoin committed to the channel by the two parties.
- The screenshot below shows the channel between Bob and Carol. There is the capacity at 1,000,000 and local balance and remote balance are set to 499,819 and 500,000. This is because we created the channel with local amount set to 1,000,000 and pushed 500,000 to the remote balance. The difference went as the fee for publishing the channel creation (funding transaction) to the bitcoin testnet.
Our channel balances at the end of our setup were as follows:
Alice to Bob: 299,819
Bob to Alice: 200,000
Bob to Carol: 499,819
Carol to Bob: 500,000
Step 2 — Making LN Payments
With our channels setup, we are now ready to send payments from Alice to Bob and once that worked, from Alice to Carol — finally getting to that “network” in Lightning Network.
Step 2.1 : Make a Single Hop Payment
To request a payment, a node has to create an “invoice”, which is defined as by lightning protocol as
A simple, extendable QR-code-ready protocol for requesting payments over Lightning.
So to make a payment from Alice to Bob, the following steps need to happen:
- Bob creates an invoice using
lncli addinvoice --amt=100000
to create a payment invoice of 100,000 Satoshi. Note that the invoice does not identify the public key that should make the payment. This allows lightning supporting checkouts to show the invoice as a QR code or a link. - Bob sends the invoice to Alice using any means available — be it a checkout button or a QR code to pay using a lightning enabled wallet.
- Bob pays the invoice by using
lncli sendpayment --pay_req=<INVOICE>
Note that for a direct payment between two lightning nodes, there was no fees, zero, nada, zilch, niente.
After the payment from Alice to Bob our new balances are
Alice to Bob: 299,819
Bob to Alice: 200,000
Bob to Carol: 499,819
Carol to Bob: 500,000
Step 2.2 Making Multi-hop Payments
Now comes the fun part of making payments over the network, with payments routed through intermediaries.
Lightning network routes payments over channels. lnd uses provides an onion routing implementation to preserve privacy of the sending and receiving nodes.
We wanted to try and make a multi-hop payment from Alice to Carol to take the routing sub-system for a drive, and it turned out to be a fun experience because we kept running into the dreaded UnknownNextPeer
error.
We learnt that most likely this is caused by the lack of txindex support in our bitcoind. We restarted our bitcoind with -reindex and -txindex flags. Once transaction indexing had finished we tried making a multi-hop payment by going through the following steps:
- Carol creates an invoice, just as Bob created one in the single-hop payment approach.
lncli addinvoice --amt=10000
- Carol sends the invoice to Alice
- Alices executes sendpayment by running
lncli sendpayment --pay_req=<INVOICE>
At this point we still ran into UnknownNextPeer
issue, so we decided to close all channels that were not created by us and were automatically created by lnd’s autopilot
feature. Once we closed all the channels and tried the multi-hop payment it went through without any problems.
Once back from the hackathon, we reported our experience with the problems while sending a multi-hop payment as an issue on lnd’s repo.
Step 3 — Integrate Lightning with Chlu Wallet
At this point we had multihop LN payments working from the command line between our LN channels on our 3 EC2 instances. However, our first goal of the day was enable Lightning payments from our demo Chlu bitcoin web wallet which also provides an implementation of the Chlu protocol.
Step 3.1 — Run LN-Service on our EC2 LN Node
ln-service is an excellent wrapper around LND written by Alex Bosworth, exposing many of the command line equivalents via a REST api. While not production ready, it was perfect for a quick integration between our EC2 LN Nodes and our Chlu web wallet. We setup ln-service on our lightning node for Alice and given it exposed a REST api, it was trivial to integrate with our Chlu web wallet.
Step 3.2 — Make a payment to another LN wallet
We decided to try to make an LN payment from our Chlu web wallet to another LN web wallet, thus testing a full payment over multiple hops. HTLC.me, also developed by Alex, allows you to simply create a LN web wallet and fund it, which we did. Thus we had our Chlu LN web wallet and our HTLC.me LN web wallet and were ready to go.
With our ln-service setup on our LN node for Alice, and our Chlu wallet changed to make http calls to the service for sending a lightning payment, we then generated an invoice from our htlc.me wallet and were successfully able to send a multi-hop payment to our wallet on htlc.me. This also worked because we had multiple channels open from the ln node running ln-service, these channels were opened by the autopilot
mode.
The following screenshot show our web wallet that uses our reference implementation of the Chlu protocol written in javascript. The first screenshot shows a payment being made using bitcoin blockchain and op_return, while the second one shows the use of LN.
Achievements
- We were able to make direct & multihop payments between ln nodes
- We successfully deployed ln-service that provides an easier API to talk the lnd gRPC.
- We were able to enable lightning payments from our Chlu wallet
Next Steps
While it was great to be able to integrate LN payments into our Chlu web wallet and our first hackathon goal was a resounding success, questions remain about how to really provide consumer wallets in production with this approach. Could spawning docker instances running lnd daemons be a good approach? How can that scale for a wallet provider and what about trustlessness?
For the second goal of enabling proof of payment for lightning payments, discussions with Alex and Tadge pointed to using DIDs signatures and OpenTimeStamp to save the reference to the proof of payments for future verification of reviews. That topic will be the subject of a future article.