Lightning Network Daemon(Lnd)で遊んでみた ~Docker編~

#はじめに


今回は翻訳ではなくて実際に[Working with LND and Docker](https://dev.lightning.community/guides/docker/)を実際に試してみた様子をレポート。



# Working with LND and Dockerとは
　Dockerのコンテナ上でlndとbtcdを動かすチュートリアル的なもの。
BitcoinのテストネットでLightningの動きを確認できるので、Lightning Networkがよくわからないって人はこれを試して見ると実際の動きが見れるのでより理解しやすくなる。
基本的に書いてある通りにコマンド叩いていれば簡単にサクサク進められるのでまず[本家](https://dev.lightning.community/guides/docker/)を見て見るのをオススメする。


### 環境
 私の環境は以下の通り。

- PC : Macbook Pro
- Docker: 19.03.1
- docker-compose: 1.24.1

githubから[ソースコード](https://github.com/lightningnetwork/lnd)を落として、中のdockerディレクトリに移動したら準備完了

では始めます。

**備考：** ターミナルを３つ使います。どのターミナルでどのコマンドを打てばいいのかわからなくならないようにaliceのターミナルで打つべきコマンドは`alice$`、Bobは`bob$ `、その他は`$`で始まっています。

# ライトニングネットワーククラスタを作る

Bitcoin Coreのregtestモードに似たsimnetを使う。


こんな感んじのトポロジー。
<img width="209" alt="アセット 1@2x-8.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/481488/d803b39f-d339-2e2f-967f-4ed09b71086b.png">

>このチュートリアルではシンプルに1つのBitcoinノードを
Bitcoinネットワークとして扱う。実際の環境では
アリスとボブは異なるBitcoinノードに繋がっている。

**ワークフロー**

- プライベートsimnetで動くbtcdノードを作る。
- シミュレーションネットワークにlndノードとしてのAlice作る
- シミュレーションネットワークにlndノードとしてのBob作る
- Aliceにビットコインを送るためにブロックをマイニングする
- AliceとBobのチャンネルを開設する
- アリスからボブへ送金する
- AliceとBobのチャンネルを閉じる
- オンチェーンでBobのバランスが変わったのを確認する。


以下のコマンドを実行

```
# ビットコインネットワーク環境を初期化
$ export NETWORK="simnet" 
```


```
# アリスのコンテナを実行
$ docker-compose run -d --name alice lnd_btc
$ docker exec -i -t alice bash

```

`bash-5.0#`と表示された。
以降、`alice$`で始まるコマンドはここに打っていく

```
# Aliceのp2shアドレスを生成
alice$ lncli --network=simnet newaddress np2wkh 
```
これを打つとP2SH(Pay To Script Hash)アドレスが表示される。Pay To Script Hashってなんぞって人はググってみるといい。

次は別ターミナルを開いて以下を実行。

```
#  btcdノードをもう一度作りマイニングアドレスとしてアリスのアドレスを設定
$ MINING_ADDRESS=<alice_address> docker-compose up -d btcd
```
`<alice_address>`ってとこにはさっき生成したアリスのp2shアドレスを入れる


```
# ブロックを400生成
$ docker-compose run btcctl generate 400
```

実行するとズラーッとhashgが配列で帰ってくる。
ブロックの成熟に最低100ブロック必要で、さらにsegwitを有効にするために300以上必要らしい。
segwitってなんぞって人もググってみてください。

```
# Segwitがアクティブになってるか確認
$ docker-compose run btcctl getblockchaininfo | grep -A 1 segwit
```

`"status":"active"`と返って来るはず。

Aliceのターミナルに移動してBalanceを確認します

```
alice$ lncli --network=simnet walletbalance
```

 `"total_balance"`、 `"confirmed_balance"`、`"unconfirmed_balance"`が表示される。


ではBobのノードをAliceのノードに繋ぎます。
また新しいターミナルを開いて、

```
$ docker-compose run -d --name bob lnd_btc
$ docker exec -i -t bob bash
```

また、`bash-5.0# `と表示されます。
以降、`bob$`で始まるコマンドはここに打っていく

```
bob$ lncli --network=simnet get-info
```
を打つと

```
{
        "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"
    ]
}
```
こんな感じのが返って来るはずです。

次にボブのIPアドレスを取得します。

```
$ docker inspect bob | grep IPAddress
```

次にアリスのターミナルでBobに接続します。

```
alice$ lncli --network=simnet connect <bob_pubkey>@<bob_host>
```
`<bob_pubkey>`の所には先ほど`getinfo`したBobの`”identity_pubkey”`をいれます。
`<bob_host>`の所にはボブのIPアドレスをいれます。
空の中括弧が返ってきます。

アリスのpeerを確認します。

```
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"
        }
    ]
}
```
みたいなのが返ってきます。

今度はBobのpeerを確認します。

```
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"
        }
    ]
}
```
が返ってきたでしょうか。
お互いにpeerとして設定されたことがわかります。
次にAliceとBobのチャンネルを作ります。

```
alice$ lncli --network=simnet openchannel --node_key=<bob_identity_pubkey> --local_amt=1000000
```
<bob_identity_pubkey>には、Bobの`"identity_pubkey"`をいれます。
"funding_txid"が返ってきます。

funding transactionをブロックに入れてチャンネルを開設します。

```
$ docker-compose run btcctl generate 3
```

Bobとのチャンネルが開設されているか確認します.

```
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
        }
    ]
}
```
が返ってきます。
次にAliceからBobに送金します。
まずはBob側でinvoiceを発行します。

```
bob$ lncli --network=simnet addinvoice --amt=10000
```

```
{
        "r_hash": "<your_random_rhash_here>", 
        "pay_req": "<encoded_invoice>", 
}
```
が返ってきます。

aliceからボブへ送金を行います。

```
alice$ lncli --network=simnet sendpayment --pay_req=<encoded_invoice>
```

`<encoded_invoice>`はinvoice発行時のpay_reqの値を入れます。
入力すると送金の確認がされるので`yes`とうつ。
すると送金が完了します。

では、Aliceのチャンネルのbalanceを確認します。

```
alice$ lncli --network=simnet channelbalance
```

次に、Bobのチャンネルのbalanceを確認します。

```
bob$ lncli --network=simnet channelbalance
```

Aliceのチャンネルポイントの確認をします。

```
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"`の値をよく確認してください。`:`で区切られているのがわかります。`:`の前が`funding_txid`で後ろが`output_index`です。

```
alice$ lncli --network=simnet closechannel --funding_txid=<funding_txid> --output_index=<output_index>
```
<funding_txid>と<output_index>をに先ほどの`funding_txid`と`output_index`を入れ、入力すると`"closing_txid"`が表示されます。
そしてトランザクションを終えます。

```
$ docker-compose run btcctl generate 3
```
チャンネルが閉じられました。

AliceとBobのオンチェーンバランスを確認します。
```
alice$ lncli --network=simnet walletbalance
bob$ lncli --network=simnet walletbalance
```
するとBobの方で、
```
{
    "total_balance": "10000",
    "confirmed_balance": "10000",
    "unconfirmed_balance": "0"
}
```
となっていることが確認できますでしょうか。
Lightning Networkを使った送金に成功したということになります。


## faucetのlightningノードを作る

このセクションではBitcoinを送金できるfaucetノードを作って接続します。
構成は以下の通り。

<img width="343" alt="アセット 2@2x-8.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/481488/d30f0cc6-a86c-c34b-9a05-42c2ba4e5b67.png">


>（１）新しく加えたノードをBobに繋げ、 Alice->Faucet->Bobなmultihop paymentを作る
（２）"Faucet", "Alice", "Bob"はビットコインネットワークを元に相互に結びついたチャンネルを持つLightning Network daemonである。
（３）このシナリオでは"Alice"と"Faucet"は異なるBitcoinノードに結びついたLightning Networkである。もし、"Bob"に"Faucet"をしようとしても、btcdはすでにそれを行ってくれている。

ビットコインネットワークの環境変数を`"testnet"`に変更してbtcdを起動します。

```
$ export NETWORK="testnet"
$ docker-compose up -d "btcd"
```

btcdが同期できたらAliceをFaucetノードに繋ぎます。
Faucetノードのアドレスは[Faucet Lightning Community webpage](https://faucet.lightning.community/)にあります。

Aliceのコンテナを起動。
```
$ docker-compose up -d "alice"; docker exec -i -t "alice" bash
```

Aliceを Faucetノードに接続
```
alice$ lncli --network=simnet connect <faucet_identity_address>@<faucet_host>
```

接続できたらFaucetノードはチャンネルを開設しアリスにいくらかのBitcoinを送金します。

#### 次にすべきことは？
What you may do next?ということで課題が与えられています。

- いくらかfaucetノードに送金してみる。
- faucetにBobのノードを繋いでmultihop paymentを実装して見る(Alice->Faucet->Bob)
- Faucetチャンネルを閉じてオンチェーンbalanceを確認する。



以上で完了となります。
お疲れ様でした！