【Bitcoin】Lappsの時代が来た！

#はじめに
　Lightning Network Application略してLappsです。
お金のやり取りの処理を実装するのは何かとめんどくさいけど、Bitcoinなら自由度高くやり取りできんるかもって話。
今回はLappsを作ってみてその過程を記事にしてみます。ちなみに初Lapps。
「SFCにはこんなニッチなことやってるやつもいるんだなー」と流し見していただくだけで十分ありがたいです。
興味持ってくれた人がいるなら是非BCALIへ。



#自己紹介
慶應SFC2年の押川拓夢、RG名 wokashi(をかし) です。
奈良県の高校卒業後、大阪に移り住みふらふらしたり専門行ったりしてたので2年遅れで大学生やってます。
大学入学後はベンチャーで約1年Webエンジニアをやって今は村井研BCALIでBitcoinのLightning Netwrokを主に勉強しています。次のお仕事探し中。



#Lightning Network?

![アセット 2@3x-8.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/481488/cec66863-9ab4-f81a-3552-b59d5e57c13e.png)

今のBitcoinを支払いに使ってる人なんてほとんどいませんよね。
それもそのはず、Bitcoinは今はまだ**メチャクチャ使いずらいです。**

- 送金内容が反映されるまで最大10分待つ必要がある
- 手数料が高くて少額のやりとりができない

と、いうような問題があるためです。
そこで生まれたのがLightning Network。
**個々の支払いを改ざん出来ない形で個別にやり取りし、最終的な支払い結果だけをBitcoinのブロックチェーンに書き込みます。**
詳しくは下の記事に書いています↓

「で、Lightning Networkって何?」: https://qiita.com/ito_wokashi/items/d373c56678a518e393e3

#今回やること
今回は`node.js`でlndのgRPCクライアントを作ってみる。
gRPCでlndが使えたらlndによる送金をアプリケーションに組み込めるようになる。
Lapps製作の第一歩。
~~アリスとボブでinvoice(請求書)を発行して送金を行うとこまでやりたい。~~←失敗


#セットアップ
　まずはBitcoinノードとlightningノードを立ち上げる必要があります。Bitcoinのバックエンド実装には[btcd]()を、lightningは[lnd]()を使うことにします。今回は遊びなのでsimnetというローカルのテストネットを使います。なお、btcdやlndのインストールの手順は下の記事を参考にしてみてください。

「Ubuntuでlndとbtcdの環境を構築してみる」:https://qiita.com/ito_wokashi/items/5cafb65de68a1aa3bc9e

インストールが出来たらターミナルでbtcdを起動します。

```
$ btcd --txindex --simnet --rpcuser=kek --rpcpass=kek
```


次にアリスとボブの作業用ディレクトリを作成します。
別のターミナルを開いて以下のコマンドを入力します。
ここら辺は下の記事でやったのとほぼ同じです。

「Lightning Network Daemon(Lnd)で遊んでみた ~Tutorial編(Stage1)~」: https://qiita.com/ito_wokashi/items/83f1894ee321649296aa

```
$ cd $GOPATH
$ mkdir dev
$ cd dev

$ mkdir alice bob
```

アリスのノードを起動します。

```
$ cd $GOPATH/dev/alice

$ lnd --rpclisten=localhost:10001 --listen=localhost:10011 --restlisten=localhost:8001 --datadir=data --logdir=log --debuglevel=info --bitcoin.simnet --bitcoin.active --bitcoin.node=btcd --btcd.rpcuser=kek --btcd.rpcpass=kek
```

次に、ボブ。

```
$ cd $GOPATH/dev/bob

$ lnd --rpclisten=localhost:10002 --listen=localhost:10012 --restlisten=localhost:8002 --datadir=data --logdir=log --debuglevel=info --bitcoin.simnet --bitcoin.active --bitcoin.node=btcd --btcd.rpcuser=kek --btcd.rpcpass=kek 
```


本来Lappsを作るならチャンネル開設やクローズなどもアプリケーションの機能としてつけるべきですが、今回はあくまで遊びなのでそこらへんはコンソールでやってしまいます。

lndのconfigファイルを作ります。
`lnd.conf`を

- MacOS: /Users/[username]/Library/Application\ Support/Lnd/lnd.conf
- Linux: ~/.lnd/lnd.conf

作り、lightningノードの起動を行います。

```
(アリス)$ lnd --rpclisten=localhost:10001 --listen=localhost:10011 --restlisten=localhost:8001
(ボブ)$ lnd --rpclisten=localhost:10002 --listen=localhost:10012 --restlisten=localhost:8002
```

アリスのwalletを作ります。

```
$ cd $GOPATH/dev/alice
$ lncli --rpcserver=localhost:10001 --macaroonpath=data/chain/bitcoin/simnet/admin.macaroon create
```

今度はボブの。

```
$ cd $GOPATH/dev/bob
$ lncli --rpcserver=localhost:10002 --macaroonpath=data/chain/bitcoin/simnet/admin.macaroon create
```

#Lapps開発開始
ここからは公式のやり方で進めてもなかなかすんなりいかない。
実はgRPCを使わないでWebsocketを使う方法を数日かけて試したのだが、なぜか上手くいかず、Lapps関連は記事が少ないのでどうしようもなかった。
なので最近勉強してはいるもののまだ身についてはいないgRPCを使うことにした。
この辺で俺はクリスマスイブに何をやっているんだと気づき始める。


まずは適当なディレクトリを作り、`npm init`。
grpc周りのパッケージもインストールする。
ついでに`server.js`も作っておきます

```
$ mkdir lapps
$ cd lapps
$ npm init
$ npm install grpc --save
$ touch server.js
```


`lnd/lnrpc/rpc.proto`を使う必要があるため持ってきます。


```
$ curl -o rpc.proto -s https://raw.githubusercontent.com/lightningnetwork/lnd/master/lnrpc/rpc.proto
```

コンパイルするために`googleapis`が必要です。

```
$ git clone https://github.com/googleapis/googleapis.git
```

そしてコンパイル。

```
$  protoc --plugin=protoc-gen-grpc=`which grpc_tools_node_protoc_plugin` --proto_path googleapis:. --js_out=. --grpc_out=. rpc.proto
```

大量のファイルができるはず。
ここからserver.jsを書いていくのですが、私の環境ではこのまま進めると、

```
DeprecationWarning: grpc.load: Use the @grpc/proto-loader module with grpc.loadPackageDefinition instead
```
と表示さ、それ以外の処理を実行してくれなかったので、`@grpc/proto-loader`をインストールし、それを踏まえたコードを書きます。

```server.js
const fs = require('fs');
const grpc = require('grpc');
const protoLoader = require('@grpc/proto-loader');

process.env.GRPC_SSL_CIPHER_SUITES = 'HIGH+ECDSA'

const lndCert = fs.readFileSync(" # tls.certのpathを記述　");
const sslCreds = grpc.credentials.createSsl(lndCert);
const macaroonCreds = grpc.credentials.createFromMetadataGenerator(function(args, callback) {
  const macaroon = fs.readFileSync("# macaroon.adminのpathを記述").toString('hex');
  const metadata = new grpc.Metadata()
  metadata.add('macaroon', macaroon);
  callback(null, metadata);
});

const credentials = grpc.credentials.combineChannelCredentials(sslCreds, macaroonCreds);
const packageDefinition  = protoLoader.loadSync("rpc.proto");
const rpcProto = grpc.loadPackageDefinition(packageDefinition);

const lnrpc = rpcProto.lnrpc;
const lightning = new lnrpc.Lightning('localhost:10001', credentials);
```

だいぶごちゃってますがこれでいけるはず。
試しに`walletbalance`を喋らせます。
最終行に以下を追加

```server.js
let request = {} 
lightning.walletBalance(request, function(err, response) {
  console.log(response);
})
```

ではserverを起動！

```
$ node server.js
{}
```


・・・。
これ以上何をやっても`{}`しか帰ってきませんでした。

ここでタイムアップ。SFC AdventCalenderの担当日になってしまった。
もうちょっと勉強してから再チャレンジします。
また記事にするんでよかったら是非読んでください。