Skip to content

Latest commit

 

History

History
317 lines (274 loc) · 11.6 KB

File metadata and controls

317 lines (274 loc) · 11.6 KB

This document is intended for those looking to get started with the Lightning Network Daemon (lnd). This folder uses docker to package lnd and btcd together, making the deployment of both daemons as simple as running a few commands. All configuration between lnd and btcd is handled automatically by the docker-compose.yml file

Prerequisites

Name Version
docker 20.10.13+

Table of content

Create lightning network cluster

This section describes a workflow on simnet, a development/test network that's similar to Bitcoin Core's regtest mode. In simnet mode blocks can be generated at will, as the difficulty is very low. This makes it an ideal environment for testing as one doesn't need to wait tens of minutes for blocks to arrive in order to test channel related functionality. Additionally, it's possible to spin up an arbitrary number of lnd instances within containers to create a mini development cluster. All state is saved between instances using a shared volume.

In the workflow below, we describe the steps required to recreate the following topology, and send a payment from Alice to Bob.

+ ----- +                   + --- +
| Alice | <--- channel ---> | Bob |  <---   Bob and Alice are the lightning network daemons which 
+ ----- +                   + --- +         create channels and interact with each other using the   
    |                          |            Bitcoin network as source of truth. 
    |                          |            
    + - - - -  - + - - - - - - +            
                 |
        + --------------- +
        | Bitcoin network |  <---  In the current scenario for simplicity we create only one  
        + --------------- +        "btcd" node which represents the Bitcoin network, in a 
                                    real situation Alice and Bob will likely be 
                                    connected to different Bitcoin nodes.

General workflow is the following:

  • Create a btcd node running on a private simnet.
  • Create Alice, one of the lnd nodes in our simulation network.
  • Create Bob, the other lnd node in our simulation network.
  • Mine some blocks to send Alice some bitcoins.
  • Open channel between Alice and Bob.
  • Send payment from Alice to Bob.
  • Close the channel between Alice and Bob.
  • Check that on-chain Bob balance was changed.

Important

Prerequisites: This guide assumes you have Docker installed. If not, please follow the official Docker installation guide.

All commands should be executed from the lnd/docker/ directory. Depending on your system's configuration, you may need to prefix docker commands with sudo. For Linux users, we highly recommend following the official Docker documentation to manage Docker as a non-root user, which allows you to run commands without sudo safely

Start btcd, and then create an address for Alice that we'll directly mine bitcoin into.

# Init bitcoin network env variable:
$  export NETWORK="simnet" 

# Create persistent volumes for alice and bob.
$  docker volume create simnet_lnd_alice
$  docker volume create simnet_lnd_bob

# Run the "Alice" container and log into it:
$  docker compose run -d --name alice --volume simnet_lnd_alice:/root/.lnd lnd
$  docker exec -it alice bash

# Generate a new native SegWit (Bech32) address for Alice:
alice $  lncli --network=simnet newaddress p2wkh

# Recreate "btcd" node and set Alice's address as mining address:
$  export MINING_ADDRESS=<alice_address>
$  docker compose up -d btcd

# Generate 400 blocks (we need at least "100 >=" blocks because of coinbase 
# block maturity and "300 ~=" in order to activate segwit):
$  docker exec -it btcd /start-btcctl.sh generate 400

Check Alice balance:

alice $  lncli --network=simnet walletbalance

Connect Bob node to Alice node.

# Run "Bob" node and log into it:
$  docker compose run -d --name bob --volume simnet_lnd_bob:/root/.lnd lnd
$  docker exec -it bob bash

# Get the identity pubkey of "Bob" node:
bob $  lncli --network=simnet getinfo
{
    ----->"identity_pubkey": "0343bc80b914aebf8e50eb0b8e445fc79b9e6e8e5e018fa8c5f85c7d429c117b38",
    "alias": "",
    "num_pending_channels": 0,
    "num_active_channels": 0,
    "num_inactive_channels": 0,
    "num_peers": 0,
    "block_height": 1215,
    "block_hash": "7d0bc86ea4151ed3b5be908ea883d2ac3073263537bcf8ca2dca4bec22e79d50",
    "synced_to_chain": true,
    "testnet": false
    "chains": [
        "bitcoin"
    ]
}

# Get the IP address of "Bob" node:
$  docker inspect bob | grep IPAddress

# Connect "Alice" to the "Bob" node:
alice $  lncli --network=simnet connect <bob_pubkey>@<bob_host>

# Check list of peers on "Alice" side:
alice $  lncli --network=simnet listpeers
{
    "peers": [
        {
            "pub_key": "0343bc80b914aebf8e50eb0b8e445fc79b9e6e8e5e018fa8c5f85c7d429c117b38",
            "address": "172.19.0.4:9735",
            "bytes_sent": "357",
            "bytes_recv": "357",
            "sat_sent": "0",
            "sat_recv": "0",
            "inbound": true,
            "ping_time": "0"
        }
    ]
}

# Check list of peers on "Bob" side:
bob $  lncli --network=simnet listpeers
{
    "peers": [
        {
            "pub_key": "03d0cd35b761f789983f3cfe82c68170cd1c3266b39220c24f7dd72ef4be0883eb",
            "address": "172.19.0.3:51932",
            "bytes_sent": "357",
            "bytes_recv": "357",
            "sat_sent": "0",
            "sat_recv": "0",
            "inbound": false,
            "ping_time": "0"
        }
    ]
}

Create the Alice<->Bob channel.

# Open the channel with "Bob":
alice $  lncli --network=simnet openchannel --node_key=<bob_identity_pubkey> --local_amt=1000000

# Include funding transaction in block thereby opening the channel:
$  docker exec -it btcd /start-btcctl.sh generate 3

# Check that channel with "Bob" was opened:
alice $  lncli --network=simnet listchannels
{
    "channels": [
        {
            "active": true,
            "remote_pubkey": "0343bc80b914aebf8e50eb0b8e445fc79b9e6e8e5e018fa8c5f85c7d429c117b38",
            "channel_point": "3511ae8a52c97d957eaf65f828504e68d0991f0276adff94c6ba91c7f6cd4275:0",
            "chan_id": "1337006139441152",
            "capacity": "1005000",
            "local_balance": "1000000",
            "remote_balance": "0",
            "commit_fee": "8688",
            "commit_weight": "600",
            "fee_per_kw": "12000",
            "unsettled_balance": "0",
            "total_satoshis_sent": "0",
            "total_satoshis_received": "0",
            "num_updates": "0",
             "pending_htlcs": [
            ],
            "csv_delay": 4
        }
    ]
}

Send the payment from Alice to Bob.

# Add invoice on "Bob" side:
bob $  lncli --network=simnet addinvoice --amt=10000
{
        "r_hash": "<your_random_rhash_here>", 
        "pay_req": "<encoded_invoice>", 
}

# Send payment from "Alice" to "Bob":
alice $  lncli --network=simnet sendpayment --pay_req=<encoded_invoice>

# Check "Alice"'s channel balance
alice $  lncli --network=simnet channelbalance

# Check "Bob"'s channel balance
bob $  lncli --network=simnet channelbalance

Now we have open channel in which we sent only one payment, let's imagine that we sent lots of them, and we'd now like to close the channel. Let's do it!

# List the "Alice" channel and retrieve "channel_point" which represents
# the opened channel:
alice $  lncli --network=simnet listchannels
{
    "channels": [
        {
            "active": true,
            "remote_pubkey": "0343bc80b914aebf8e50eb0b8e445fc79b9e6e8e5e018fa8c5f85c7d429c117b38",
       ---->"channel_point": "3511ae8a52c97d957eaf65f828504e68d0991f0276adff94c6ba91c7f6cd4275:0",
            "chan_id": "1337006139441152",
            "capacity": "1005000",
            "local_balance": "990000",
            "remote_balance": "10000",
            "commit_fee": "8688",
            "commit_weight": "724",
            "fee_per_kw": "12000",
            "unsettled_balance": "0",
            "total_satoshis_sent": "10000",
            "total_satoshis_received": "0",
            "num_updates": "2",
            "pending_htlcs": [
            ],
            "csv_delay": 4
        }
    ]
}

# Channel point consists of two numbers separated by a colon. The first one 
# is "funding_txid" and the second one is "output_index":
alice $  lncli --network=simnet closechannel --funding_txid=<funding_txid> --output_index=<output_index>

# Include close transaction in a block thereby closing the channel:
$  docker exec -it btcd /start-btcctl.sh generate 3

# Check "Alice" on-chain balance was credited by her settled amount in the channel:
alice $  lncli --network=simnet walletbalance

# Check "Bob" on-chain balance was credited with the funds he received in the
# channel:
bob $  lncli --network=simnet walletbalance
{
    "total_balance": "10000",
    "confirmed_balance": "10000",
    "unconfirmed_balance": "0"
}

Building standalone docker images

Instructions on how to build standalone docker images (for development or production), outside docker-compose, see the docker docs.

Using bitcoind version

If you are using the bitcoind version of the compose file i.e. docker-compose-bitcoind.yml, follow these additional instructions:

Start Bitcoin Node with bitcoind using Docker Compose

To launch the Bitcoin node using bitcoind in the regtest network using Docker Compose, use the following command:

$  NETWORK="regtest" docker compose -f docker-compose-bitcoind.yml up

Generating RPCAUTH

In bitcoind, the usage of rpcuser and rpcpassword for server-side authentication has been deprecated. To address this, we now use rpcauth instead. You can generate the necessary rpcauth credentials using the rpcauth.py script from the Bitcoin Core repository.

Note: When using any RPC client, such as lnd or bitcoin-cli, It is crucial to either provide a clear text password with username or employ cookie authentication.

Mining in regtest using bitcoin-cli

  1. Log into the lnd container:
$  docker exec -it lnd bash
  1. Generate a new backward compatible nested p2sh address:
lnd$  lncli --network=regtest newaddress np2wkh
  1. Log into the bitcoind container:
$  docker exec -it bitcoind bash
  1. Generate 101 blocks:
# Note: We need at least "100 >=" blocks because of coinbase block maturity.
bitcoind$  bitcoin-cli -chain=regtest -rpcuser=devuser -rpcpassword=devpass generatetoaddress 101 2N1NQzFjCy1NnpAH3cT4h4GoByrAAkiH7zu
  1. Check your lnd wallet balance in regtest network:
lnd$ lncli --network=regtest walletbalance

Note: The address 2N1NQzFjCy1NnpAH3cT4h4GoByrAAkiH7zu is just a random example. Feel free to use an address generated from your lnd wallet to send coins to yourself.

Questions

Irc

  • How to see alice | bob | btcd | lnd | bitcoind logs?
$  docker compose logs <alice|bob|btcd|lnd|bitcoind>