Bitcoin WednesDay

オランダの歴史のあるBitcoinコミュニティである、Bitcoin Wednesdayが五周年イベントを行いました。プレゼンしませんかと招待が来ましたのでオランダまで行ってプレゼンしてきました。

今回のイベントは、cyperpunk界隈の伝説的人物 Phil Zimmerman, チューリング賞を受賞しているMIT教授Silvio Micali、 Drivechainの発案者 Paul Sztorc、Bitcoin界隈での有名HacktivistであるAmir Taakiが集まるという超豪華イベントでした。

Crypto Steelを使ってみた!

Nayutaの広報、Hitomiです!

今回は、絶対に失くしてはいけないRecovery Seedの保管にCrypto Steelを使ってみました。

この記事は、1. Crypto Steelとは何か2. Crypto Steelの使い方3. Crypto Steel自体の保管方法、という3構成になっています。前回記事(Trezorを使ってみた!前編)で、Rcovery Seedについて書いていますので、気になる方はこちらもチェックしてみてください。

20180522_111354_thumb1

 


1. Crypto Steelとは何か

Crypto Steelとは、Recovery Seedやパスワード、秘密鍵などを保管できるオフライン手段です。イギリスのSWORD社が提供しています。単体でも購入することが出来ますが、Trezorの公式ショップからTrezorとセットで購入することも可能です。

Recovery Seedの保管方法はいくつか考えられるのですが、まずオンラインやコンピュータ上では絶対に保管してはいけません。写真として残しておくのも禁止です。これは、ハッカーからコンピュータ攻撃を受けると、Recovery Seedがハッカーの手に渡り、そのまま仮想通貨を盗み出されてしまう、といったリスクを避けるためです。

また、紙での保存も十分とは言えません。誤って他の紙書類と一緒に捨ててしまったり、火事など災害にあって失くしてしまったり、といったリスクが考えられるからです。

一方、Crypto Steelはその名の通りスチール製なので、火事や水害にあったとしても安全に自分の手元で保管し続けることができます。

Clipboard05

出典:https://cryptosteel.com/

 


2. Crypto Steelの使い方

前回記事では、Recovery Seedはリカバリーシートに記入して保管していました。今回は、そのRecovery SeedをこのCrypto Steelに移します。

20180521_171046

 

1. 箱を開封します。箱の裏側が説明書になっているので、それに従っていきます。

20180522_110930

20180522_110941

 

2. Cryto Steel本体と、アルファベットが刻まれた小さなスチール製のパーツが同封されています。パーツは飛び出る可能性があるので、箱を覆っている透明のフィルムを慎重に開けます。

20180522_111105

20180522_111207

 

3. 本体をスライドして開けます。表に1-12、裏に13-24までが刻まれている板が出てきます。

20180522_111354

 

4. 右端をドライバーで回しながら、指で指している部分を引っ張り出します。

20180522_111437

20180522_111717

5. リカバリーシートを見ながら、1番目の英単語(今回はWineを例にします)のパーツを用意します。

20180522_111619

6. 本体の1番目の列に英単語を入れます。入れにくいので、ドライバーなどを使って押し込んでください。リカバリーシートと同じように順番通りに、正確に、入れていきます。

本体には1単語につき4文字までしか入りませんが、Recovery Seedは4文字目が分かると自動的に1単語に絞られるようになっています。ですので、4文字のみを保管することになります。

20180522_114038

20180522_112136

7. 24単語すべて埋めたら、完成です。リカバリーシートはシュレッダーで細かく刻んで捨てましょう。

 


3. Crypto Steel自体の保管方法

Recovery Seedを保管するために有効なCrypto Steelですが、このCrypto Steel自体をどこに保管するかということを考えなければいけません。金庫など安全な場所に保管しましょう。

また、高額の仮想通貨を持っているならば、XapoCoinbaseが提供する保管サービスなどを利用してもいいかもしれません。

Trezorを使ってみた!後編(2018年6月現在)

Nayutaの広報、Hitomiです!

前編に引き続き、後編ではTrezorの使い方を紹介します。

開封初期設定トランザクション(受信)→端末情報削除&リカバリートランザクション(送信)という構成になっています。

20180521_142027

 


開封

1. 商品が到着します。このとき、DHLに関税と消費税の立替金を支払います。今回は、約3000円かかりました。

20180521_123716

 

2. 中身を取り出したら、まず開封された形跡がないことを確認します。特に、箱を覆っている透明のフィルムが破られていないか、箱の上下に貼られているホログラムがきれいな状態であるか、を確認します。これは、自分の手元に届く前に中身がすり替えられている危険性があるためです。

20180521_123834

20180521_123946

 

3. 開封します。ホログラムを1度剥がすと、元のきれいな状態には戻りません。(写真中央)箱もしっかりと糊付けされているので、力を入れて開けてください。箱の一部が既に開いていたり、すんなり開いてしまった場合は、第三者によって開けられた可能性を疑ったほうがいいかもしれません。

20180521_124353

20180521_125202

20180521_125333

 

4. 同封されているものは、Trezor端末、USBケーブル、説明書、リカバリーシート2枚、シール4枚、ストラップです。

20180521_125609

 


初期設定

1. 要るものは、Trezorセットと自分のコンピュータのみです。Windows(Ver.7 以上) や Mac OS X(Ver.10.11以上)、Linuxといった様々なOSからブラウザで使用可能です。また、USB On-The-Go (aka USB Host)のあるAndroid端末でも使用できるようです。今回は、Chrome(Windows 10)を使っています。

2. https://trezor.io/start/にアクセスし、購入した端末を選択します。今回は、「Trezor One」を選択して進めます。

 

3. 推奨ブラウザのChrome(またはFirefox)で、Trezor Bridge というソフトウェアをダウンロードします。インストールが終わったら、一旦ページを更新します。

 

4. 自動的にこの画面に移るので、USBケーブルを使ってコンピュータにTrezor端末をつなぎます。

 

5. firmwareをインストールします。

 

6. インストールが完了したら、コンピュータ画面に戻り、「Ctrate new」を選択します。このとき、Trezor端末にもインストール完了を伝えるメッセージが表示されます。

20180521_165128

 

7. 禁止事項に目を通します。自分の資産を安全に保管するために重要なことが書いています。例えば、オンラインで秘密鍵を保管しないこと、といった内容です。

Trezor6

8. 24個のRecovery Seedを、付属のリカバリーシートに記録します。Trezor端末にRecovery Seedが表示されるので、必ず順番通りに、正確に、付属の紙にメモしていきます。

※順番を間違ったり、誤った内容を記録してしまうと、二度と取り出せなくる可能性があるのでご注意ください。

例えば、端末に「1st word is: Wine」と表示されたら、シートの1の枠にも「Wine」と記入します。記入を確認したら、端末の「Next」を押して、2番目の記入に進みます。

絶対に全ワードが載ったRecovery Seedをアップロードしないでください。悪意のある第三者に知られると、保有する仮想通貨を、違う端末で復元されてしまうので、すべて失うことを意味します。

20180521_171046

 

9. 1~24まで記入が済んだら、1番目の単語から再確認していくよう求められます。再確認が完了したら、次はTrezor端末に名前を付けます。(漢字も入力可能です)

 

10. 1~9で構成されるPINコードを設定します。Trezor端末に数字がランダムに表示されるので、それを見ながらコンピュータ画面のマス目をクリックします。

セキュリティ上、PINの強度が Strong Enough という表示になるまで、数字を入力するのが理想的です。PINが設定し終わったら、確認のために再入力します。このとき、端末上の数字の配置が変わっているのも確認してみてください。(写真3枚目)

20180521_172032

20180522_100605

 

11. お疲れさまでした。これで初期設定は終了です。


トランザクション(受信)

1. コンピュータ画面の左側にある「アカウント#1」をクリックし、上のバナーにある「受信」を選択します。

16

2. 新しいアドレスが自動的に作られているので、「show full adress」を選択します。この時コンピュータ画面とTrezor端末に受信用アドレスが表示されます。端末の「continue」を押すと、コンピュータ画面にQRコードが表示されるので、アドレスまたはQRコードを送信側の人に伝えます。

Clipboard01

Clipboard02

3. 受信を待っている間、「トランザクション」を選択すると、取引がどのような状態であるかをタイムリーに確認することが出来ます。実際に見てみると、先ほどのトランザクションがUnconfirmed(未確認)の状態であることが確認できました。また、「Details」を選択すると、より詳細の状態を見ることが出来ます。

18

Clipboard19

 

4. Transactionのアドレスを、BlockchainchainFlyerなどのトランザクションが確認できるサイトで検索してみるのも面白いかもしれません。

25

 

5. Unconfirmedの状態が日付と時刻に変わったら、取引完了です。

Clipboard04

Clipboard011


端末情報削除&リカバリー

ここでは、Recovery Seedを使って、端末情報のリカバリー(回復)をテストしてみます。一度テストしておけば、万が一の時にも安心です。テストなので、Trezorウォレットの残高は、失っても大丈夫な約100円の状態で行います。

1. Trezorのアイコンが表示されている場所をクリックし、「advanced」を選択します。ページの一番下にある「端末を消去する」を選択します。

Trezor11

 

2. 全データが消えるという警告を確認した後、Trezor端末で「Do you really want to wipe the device?」という表示が出るので、Confirmを選択します。

12

20180522_101154

 

3. これで端末情報の削除は完了です。一旦、端末を抜きます。

 

4. 続いてリカバリーをします。再度端末を接続すると、この画面が出てくるので、「Recover wallet」を選択します。Trezor端末で「Do you really want to recover the device?」という表示が出るので、Confirmを選択します。

20180522_101827

5. Recovery Seedを入力します。端末上で要求される順番に従って、コンピュータで入力していきます。

20180522_101838

 

6. 全て正しく記入したら、この画面に自動的に移ります。あとは、初期設定で行った手順でPINと端末名を決めます。

15

 

20180523_104853 (1)

7. 元の端末に入っていた残高や取引履歴が元に戻っていることを確認したら、リカバリー終了です。

 


トランザクション(送信)

1. 「送信」を選択します。受信先のウォレットのアドレス、送る額、手数料を記入します。手数料の金額によって、トランザクションが完了する予想時間が変化します。コストと時間のバランスを考えて、手数料を決めます。

22

 

2. PINを入力します。

23

 

3. 送信を待っている間、「トランザクション」を選択すると、取引がどのような状態であるかをタイムリーに確認することが出来ます。実際に見てみると、先ほどのトランザクションがUnconfirmed(未確認)の状態であることが確認できました。

24

Clipboard014

4. Unconfirmedの状態が日付と時刻に変わったら、取引完了です。

Trezorを使ってみた!前編(2018年6月現在)

Nayutaの広報、Hitomiです!

今回は、Trezorというハードウェア型ウォレットを使ってみました。

この記事は、1.Trezorとは何か、2.Trezor(ハードウェア型ウォレット)を選んだ理由、3.ハードウェア型ウォレットに関するセキュリティ情報とCrypto Steelについて、という3構成になっています。Trezorの具体的な使い方については、後編で紹介しています。

TrezorのWebサイトやウォレットアカウントの仕様は、2018年6月上旬のものです。

 


1.Trezorとはなにか

Trezorとは、ハードウェア型ウォレットの製品シリーズ名です。チェコに拠点を構えるSatoshi Labsが提供しています。今回購入したのは、Trezor One(約11,000円)です

New

出典:https://trezor.io/start/

このTrezorと並んで有名なのが、フランスのLedger社が提供しているLedger Nanoシリーズの製品です。

ledger

出典:https://www.ledgerwallet.com/products

そもそも、ハードウォレット型ウォレットは、仮想通貨を自分手元で安全に保管・使用できるという特徴を持っています。この詳細については2.で説明していきます。

Trezorには、絶対に他人にバレてはいけない秘密鍵が入っており、この秘密鍵を使って安全に取引を行います。(もっと厳密にいうと、中の秘密鍵を使ってトランザクションに署名をします。)

Trezorが対応している仮想通貨の種類は段々と増えており、特に2018年の2月末に出荷したTrezor Model Tは約500種類に対応しているようです。なお、EthereumやNEMなどの特定の仮想通貨は、別のインターフェース(EthereumですとMyEtherWalletMyCrypto)と連携させることが必要となります。

 


 

2. Trezor(ハードウェア型ウォレット)を選んだ理由

ウォレットにはいくつかの種類があります。例えば、取引所が運営・管理してくれるウォレットや、サービス業者がそれを担うウェブウォレット、他にもモバイルウォレットやペーパーウォレット、ハードウェア型ウォレットと呼ばれるものです。

今回は、リスクと安全性を考慮して、Trezor(ハードウェア型ウォレット)を選びました。

ウォレットの種類を選ぶ際に気にかけたい事としてまず、「誰が秘密鍵を管理するか」が挙げられます。具体的には、取引所やサービス事業者といった「誰か」に預けるか、それとも、「自分自身で」管理するか、です。

前者の場合、第三者が管理してくれるのは楽ですが、リスクの面からみると、サーバーがハックされたり、その会社が倒産したり、ソフトウェアにバグが残っていたりと、自分たちの手に負えないところで問題が発生する可能性があります。

一方、後者の管理についてはすべて自己責任となります。自分で管理する方法としては、先ほども挙げた、モバイルウォレットやペーパーウォレット、ハードウェア型ウォレットがあります。名前から想像しやすいように、モバイルウォレットはスマートフォン用のアプリ、ペーパーウォレットは紙で出来たウォレットです。これらは、前者のように第三者を信用する必要がない代わりに、どうにかして秘密鍵を自分の手元で保管しなければなりません。

次に気にかけたいことは、紛失してしまった場合の想定です。モバイルウォレットはスマートフォンを紛失すると、ペーパーウォレットは火事などで燃えてしまうと、中に入れていた仮想通貨も一緒に失います。

一方、Trezorは、秘密鍵を自分の手元で管理するだけでなく、端末を紛失したとしても、秘密鍵・残高・取引履歴を新しい端末にリカバリーできるように設計されています。これにはRecovery Seed*というものが使われます。また、Trezorを使う時にはPINコードが必要であり、紛失した端末を他人が不正に使おうとしても、このPINを当てることは不可能に近い設計になっています。これは、PIN入力を間違えれば間違えるほど、次にトライ出来る間隔が指数関数的にどんどん延びていくからです。(例えば19-20回目間の入力では35時間待つ必要があります)

加えて、ハッカーがコンピュータに攻撃を仕掛けてきたとしても、Trezor独自のPINの入力方法により、PINコードが知られることはありません。

このように、リスクと高い安全性を考え、Trezorを選びました。もともと、P2Pマネーの本質は、個人で秘密鍵を管理することです。安易に第三者を信用せずに、自分で自分の資産を管理します。

しかし、安全性というのは確実に保障されるものではありません。お気づきの方もいるかもしれませんが、Trezor自体は盗まれても問題ありませんが、Recovery Seedを盗まれるとOUTです。ですので、Trezorを使うときは、これらをきちんと保管することが非常に重要になってきます。このRecovery Seedの保管については、3.で記載しているので気になる方はチェックしてみてください。

*決定性ウォレットアドレス用のマスター鍵を作るために必要となる乱数列が変換された12 、18 または 24つの英単語のことを指す。乱数列のままだと覚えにくい(記録しにくい)ため開発された。例えばwine、cat、machine。

20180521_171046

 


3.ハードウェア型ウォレットに関するセキュリティ情報とCrypto Steelについて

ハードウェア型ウォレットの安全性の高さを記述したものの、現状としては、必ずしも安全であるとは言い切れません。実際に下に挙げている事例は、ハードウェア型ウォレットの安全性に関係するものです。

2015年 電磁波を照射したり、電圧を上下させたりといったサイドチェーン攻撃を加えることで、Trezorから秘密鍵が盗みだせる可能性がこの時期に指摘された。例えば、オシロスコープを使って、ファームウェア1.3.2の状態のTrezorから秘密鍵が読み取ることが出来てしまう。(この後、Trezor側によって対応済み)

2017年11月 ユーザーのクリップボードがハックされた。宛先アドレスをクリップボードにコピーして貼り付ける際に、マルウェア作成者が所有するアドレスにすり替えられる仕組み。

2018年2月 LedgerウォレットのChromeアプリが起動するPC自体に、マルウェアが侵入する可能性が指摘された。宛先アドレスを生成するコードが改ざんされ、マルウェア作成者のもとへ送金される仕組み。

2018年5月 モバイルウォレットアプリの元開発者がapiキーを不正に所持し、独自で作ったアプリを通して、ユーザーから仮想通貨を盗んだ。

他にも、本来は自分で設定すべきPINがすでに書かれた偽の説明書に従ってしまい、そのまま仮想通貨を盗みとられるという事例や、カンファレンスなどで偽Trezorが無料で配られるといった事例も起こっています。

このような事態に巻き込まれないためにも、自分の手元でしっかりと管理していきます。その第1歩として、紛失してはいけないRecovery Seedを厳重に保管しましょう。次回は、その手段として使用したCrypto Steelのレポートを書いていきます。

20180522_111354

 

 

[LN#023]HTLC (トランザクション)

Lightning Network BOLTの概要について、書いていくシリーズ。

LN#020, LN#021とLightning Network BOLTで使われているHTLCについて書きましたが、読んだ方から「スクリプトのどこでロックしているの?」という質問を受けました。
確かに、スクリプトの内容ばかり書いていて、どう制限がかかっているかについては、OP_CHECKLOCKTIMEVERIFYやOP_CHECKSEQUENCEVERIFYという命令名を書いただけになっていました。

今回は、HTLCとトランザクションについて、実データを例にしながら書いていきます。


regtestで行った例になります。
amountの単位として書いているmsatは msatoshi(ミリsatoshi)です。

  • Aさんが持つamount:300000000 msat
  • Bさんが持つamount : 300000000 msat

ここで、送金を行います。

  • Aさん→Bさん:200000000 msat

送金は、大ざっぱに書くと以下のような通信を行います。

image

送金する額のHTLCをcommitment transactionに追加する工程と、それを反映してcommitment transactionからHTLCを削除する工程です。
commitment transactionの構成が変わるのでそのたびに署名を交換します。

今回は、HTLCの追加に焦点を当てます。


Aさん:送金元(payer)

HTLC追加後の、Aさんが持つcommitment transactionはこうなりました。

ptarmiganが持っているトランザクション出力を使っているため、”bitcoin-cli decoderawtransaction” などとは構成が違うと思いますが、だいたいの雰囲気は伝わるかと思います。

image

HTLCへの送金になるのは、commitment transactionの出力が3つあるうちの真ん中になります。
Aさん=送金元なので、HTLCは「Offered HTLC output」になります。

Offered HTLC outputは、相手への送金を目的としているので、基本的にはBさん宛になるはずです。
Bさん宛=Bさんが署名してどこかに送金する、ということになります。
そのために必要になるのは、送金前に相手からもらったinvoiceに含まれている情報「payment_hash」のハッシュ計算をする前の値である「payment_preimage」という値です。

Aさんの立場からすると、

  • Bさんがpayment_preimageを使ってOffered HTLC outputをどこかに送金すれば、それでよし
  • もしそうしないまま放置するようだったら、送金はなかったものとして、Aさんがどこかに送金する

ということになっています。

この「放置するようだったら」の期限は、commitment transactionを見ても分からず、かといってOffered HTLCのスクリプトを見てもわかりません。
実は、BOLT仕様によって「時間切れになった場合のトランザクション」というものが決められています(2人の署名がいる)。
そして、HTLCを追加した後に署名交換を行いますが、そのときにHTLCの署名も交換するようになっています。

事前に署名をする以上、トランザクションの内容は仕様できっちり決められています。
そのため、Aさんは決められたトランザクション以外をブロックチェーンに展開することができません。

Aさんの時間切れになったときに取り戻すトランザクション(HTLC Timeout Transaction)は、このような形になりました。
(witnessは省略)

image

一番下の、locktimeに値が指定されているところに注目してください。

commitment transactionにもlocktimeは指定しますが、タイプは日時になっていて、それは既に過ぎ去った時間になっているためいつでも展開できますが、Timeout Transactionはブロック高になっています。

そのため、このトランザクションをブロックチェーンに展開するには、現在のブロック高がlocktime以上になるまで待たなくてはなりません(regtestなので、値は小さめになっています)。

Bさんの立場からすると、もしAさんがcommitment transactionをブロックチェーンに展開したとしても、送金をAさんが取り戻すまでにlocktimeまでの余裕があることになります。
その間にpayment_preimageを使って、下図の赤枠の経路を通って取り戻します。

image


Bさん:送金先(payee)

Bさんのcommitment transactionはこうなりました。

image

こちらも、真ん中のoutputがHTLCです。
なお、commitment transactionはBIP69に従ってソートします。

Bさんはお金を受け取る方なので、

  • payment_preimageを使ったトランザクションを期限までに展開する

という動作を行います。

payment_preimageを使って取り戻すトランザクション(HTLC Success Transaction)は、こうなりました。

image

構成はHTLC Timeout Transactionとほぼ同じで、違いはlocktimeの有無になります。
Success Transactionはlocktimeが0なので、payment_preimageを持っていればすぐに展開できます。

Aさんの立場からすると、もしBさんがcommitment transactionを展開したままpayment_preimageを使わずに放置したままになっていても、実はそれほど困りません。
それは、Aさんがpayerだからです。

しかし、Aさんが単に送金を中継している場合、それでは困ります。
Aさんが転送する元になった入金を手に入れるためには、payment_preimageが必要になるからです。

image

放置したままにならないよう、Bさんがcommitment transactionを展開した場合は、payment_preimageを持たなくても一定時間が経過したら取り戻せるようになっています。
それが、下図の赤枠で囲んだ命令です。

image

<cltv_expiry>というのはブロック高で、そのブロック高以上の時間になればその経路が有効になります。
Bさんにとってみれば、その経路をAさんが使う=自分の手に入れられない、ということになり、それまでの間にpayment_preimageを使ってしまおう、と考えることになります。


今回はトランザクションを含めて、Offered/Received HTLCの説明をしました。

今回の話が出てくるのは、HTLCを追加して、そのまま反映されずに残って、チャネルを閉じたくなった場合です。
通常は、HTLCを追加した後、すぐにHTLCを反映するので、commitment transactionにHTLCが残ったままになることはあまりないでしょうが、そういう場合も考慮されているということは知っておいてよいと思います。

[LN#022]送金の転送fee

Lightning Network BOLTの概要について、書いていくシリーズ。

今回は、送金を転送する際のfee計算についてです。


Lightning Network BOLTには、送金を転送するという仕様があります。
だいたいの場合、Lightning Networkで送金をする際には、このような流れになります(図の数字と連番は関係ありません)。

  1. 送金する人(payer)が、送金先の人(payee)からinvoiceの文字列をもらう
  2. payerは、Lightning Networkのノードアプリにinvoiceを伝える
  3. payerのノードアプリが、今まで通知されたchannelの情報を使って、payeeまでのルートを作る
  4. payerは、ルートの最初の人に暗号化されたルート情報と送金額を通知
  5. 受け取った人は、暗号化されたルートから次の送金先と送金額をデコードし、それに従って通知
  6. 手順5を繰り返していき、payeeまでたどり着くと、payeeはinvoiceを解く鍵を送り返す
  7. 鍵を受け取った人はinvoiceを解いて自分への送金を受け取り、送金したルートと逆順に鍵を送っていく

image

中継する人は、経路を使った見返りとして、送金したfeeを受け取ることができます。

feeは、「受け取った送金額」と「次に渡す送金額」の差になります。
たとえばこの図では、中継Aさんがfeeとして10、中継Bさんが20を要求した場合、payeeへ100送りたいならば、payerは130送金します。


手数料はpayerが勝手に決めるわけではなく、各ノードがchannel情報をアナウンスするメッセージの中に入っています。

BOLTメッセージで言えば、channel_updateになります。
feeに関係するパラメータは、この2つです。

image

fee_base_msatは、ベースとなるfeeで、固定です(単位はmsatoshi)。
fee_proportional_millionthsは、100万satoshi=10mBTC辺りのfeeです。

なお、単に相手に送金するだけであればfeeは発生しません。

feeは、経由するチャネルごとにかかるため、経路のチャネルが増えると、feeが多くなっていきます。
しかし、feeはチャネルごとに異なるため、あまり高いfeeを設定しているとpayerがルート計算する際に除外されることでしょう。

2018年2月にTESTNETで値を見たときは、各ノードのデフォルト値はこのようになっていました。
https://github.com/nayutaco/lightning-memo/wiki/%E6%8E%A5%E7%B6%9A%E3%83%86%E3%82%B9%E3%83%88#table

TESTNETなので値が高い低いというのはあまり意味がありません(MAINNETでの値は調べていません)。

パラメータはノードアプリで設定できると思いますので、確認されると面白いでしょう。

[LN#021]HTLC (2)

Lightning Network BOLTの概要について、書いていくシリーズ。

前回の続きで、Lightning Networkで使われているHTLCの説明をしていきます。
なお、今の最新BOLTはcommit: f608c33です。


BOLTでは、2種類のHTLCがあります。

  • Offered HTLC
  • Received HTLC

 

Offered HTLCは送金側、Received HTLCは着金側になります。

今回はBOLTメッセージのシーケンスは関係ありませんが、HTLCの追加と反映はこのような流れになっています。

 

image

 

HTLCはスクリプトで、commitment transactionでは送金先として使われます。
私は、送金するamountを箱に入れて、送金先の人が渡した鍵で封印するようなイメージを描いてます。
送金元が自分のamountの一部を箱に入れ、封をして、送金先に渡してチェックされ、OKだったら封印を解く鍵をもらって、箱から取り出して送金先のamountに追加する、というところです。
封が解かれると、箱は消滅します。

 

実際には、これをスクリプトで行うことになります。


送金する人からすると、以下のような状況が発生すると困ります。

  • 相手がReceived HTLCをもらってない、と言い張る
  • HTLCは渡したが、着金を認めてくれない
  • HTLCは渡して、相手は着金を認めたが、鍵を渡してくれない

 

前回のto_localスクリプトでは、OP_CSV(OP_CHECKSEQUENCEVERIFY)を使うことで、取り戻すまでに時間がかかるようにしていました。
ここでは、OP_CLTV(OP_CHECKLOCKTIMEVERIFY)という命令を使うことで、スクリプトがタイムアウトできるようにします。
送金先の人が一定期間内に鍵を渡さなかった(=スクリプトを解かない)場合、そのHTLCは送金元の人が取り戻すことができる、という条件を付けることで、放置したままになったり、相手との連絡が取れなくなった場合でも取り戻せるようにしているのです。

 

文字で書くと、なるほど、というところですが、これをスクリプトで表さなくてはなりません。
あまり深入りすると説明が終わらなくなるので、ざっと流したいと思います。

 

 

Offered HTLC

BOLTのドキュメントでは”Offered HTLC Outputs”となっていますが、commitment transactionの送金先として説明されているためです。
なお、仕様上のHTLC最大数は483となっています。

 

image

 

これが本体(?)で、to_localスクリプトと同じく、この前にデータを置くことで、OP_IFのルートを変えたり、チェックするデータを変えたりします。

OP_IFを通るのは、<revocationpubkey>などの結果がTRUEだった場合です。
to_localと同様で、「revocation」という単語が入っている場合は、古いcommitment transactionをブロックチェーンに展開した場合の対策になります。
古いcommitment transactionはスクリプト秘密鍵を相手に渡しているので、相手はそのルートを通すことができます(展開した人は通すことができない)。
そうすると、OP_CSVやOP_CLTVなどを通らないルートになるため、即座に相手は取り戻すことができる、というわけです。

 

OP_ELSEのルートが、タイムアウトなどの制限を付けたルートになります。
中のOP_NOTIFルートがタイムアウトして取り戻す場合のルート、OP_ELSEルートが鍵(preimage)を使って解くルートです。

通常、送金をした場合は、着金を確認した人がupdate_fulfill_htlcというメッセージを使ってpreimageを通知します。
preimageをもらった人は、HTLCの鍵であることをチェックして、問題なければHTLCをそのまま反映して、HTLCを消します。

HTLCが残ったままcommitment transactionになるのは、

  • HTLCを追加して、
  • preimageをもらわずに、
  • commitment transactionをブロックチェーンに展開した

という場合だけです(unilateral close: local remote)。

 

commitment transactionが展開されたということは、Lightning Networkのチャネルはクローズされたことになります。
bitcoindのJSON-RPCでgettxoutするとfunding transactionがunspentかどうかチェックできます。
funding transactionがunspentでなくなった=クローズになった、でもあります。

それ以降は、1st Layerでの処理になります。
ブロックチェーンを見て、preimageがあればスクリプトを解くもよいし、タイムアウトまで待って取り戻すもよし、です。
どうしないといけないか、ということについて今のところBOLTでは既定がありません。

 

Received HTLC

説明したかったことはOffered HTLCのところで書いたので、Received HTLCは簡単に済ませます。

 

image

 

相手がOffered HTLCを追加すると、自分はReceived HTLCを追加することになります。

最初のOP_IFがペナルティーのルート。
OP_ELSE以下の、OP_IFがpreimageを持っている場合のルート、OP_ELSEがタイムアウトのルートになります。


Offered HTLCスクリプトも、Received HTLCスクリプトも、終わりがOP_CHECKSIGになっているルートと、OP_CHECKMULTISIGになっているルートがあります。

OP_CHECKSIGは署名が1つで、その署名は自分で作成することができます。
しかし、OP_CHECKMULTISIGは署名が複数必要で、このスクリプトでは2ついるようになっています。

 

複数必要になるのは、以下のルートです。

  • Offered HTLC : タイムアウトして自分に取り戻す
  • Received HTLC : preimageを使って自分に取り戻す

 

相手の署名も必要になりますが、それをどこで取得するかというと、commitment_signedメッセージです。
commitment_signedのhtlc_signatureがその署名になります。

あらかじめ署名ができるということは、送金先も決めておかなくてはなりません。
どこに送金するかというと、to_localスクリプトと同じ形のスクリプトになります。
タイムアウトする場合はHTLC Timeout output、preimageで取り戻す場合はHTLC Success outputと呼びます。

to_localと同じ形のため、そこから取り戻すためにはto_self_delayブロック待たなくてはなりません。


HTLCについては、以上になります。

なるべくゆっくり説明したつもりですが、それでも非常に難解だと思います。
きっちり理解されたい場合は、BOLTの#02, #03, #05あたりを読むことをおすすめします。

[LN#020]HTLC (1)

Lightning Network BOLTの概要について、書いていくシリーズ。

今回は、BOLTで使われているHTLCについて説明します。
以前「[LN#010]送金(4)」でも説明しましたが、もう少しゆっくりやります。


HTLCは、Hashed TimeLock Contractsの略で、BIP112などに説明があります。

BitcoinにはEthereumのようなスマートコントラクトみたいなものは今のところないのですが、IF文は使うことができます。
また、トランザクションのバージョン2からは、OP_CHECKLOCKTIMEVERIFYとOP_CHECKSEQUENCEVERIFYという命令も使うことができます。
(使用できる命令については、wiki/Script参照。)

 

例えば、こちらはregtestで作成したcommitment transactionです。
voutに「to_remote」「Received」「to_local」と書かれていますが、「Received」と「to_local」についてはスクリプト(P2WSH)への送金になっています。

image

 

BOLTでのHTLCは「Offered HTLC」「Received HTLC」になりますが、今回はBitcoinでのスクリプトを中心に説明するため、to_localについて見ていきます。


ここでのto_localスクリプトは、このような構造になっています。

image

 

この構成は、BOLT#3で決められています。

image

 

OP_IF~OP_ELSE~OP_ENDIFという、比較的見慣れた構造になっているのが分かるかと思います。
Bitcoinのスクリプトは、FORTHに似ているといわれています(私はよく知りません)が、私は逆ポーランド記法のようなイメージで考えています。

値(1や0など)をスタックし、次にOP_IFに来ると、直前に積まれているスタックの内容を判断して、OP_IFの方かOP_ELSEの方かの分岐が生じるようになっています。
0が偽で、それ以外は真という扱いです。

最後のOP_CHECKSIGは、スタックから2つ取り出して、1つは署名、1つは公開鍵として署名のverifyを行い、真か偽かをチェックするという命令です。


簡易表記していますが、OP_IFのルートを通す場合は、このようなスタックの動きになります。
左から右に向かって読んでください。
太線の下が動作で、例えば一番左側であれば「”rev-sig”という値をスタックに積んだ」ですし、左から3番目であれば「OP_IFのルートを通る」という意味です。

image

 

OP_IFのルートでは<revocationpubkey>という公開鍵をスタックすることになっているので、その前に<revocationpubkey>の秘密鍵で署名したデータをスタックしておかなくてはなりません(ここでは “rev-sig”と記載)。

そして、OP_IFのルートを通すために”1”をスタックし、あとはスクリプトを順番に処理していきます。


では、OP_ELSEルートを通してみましょう。

この場合は、<local_delayedpubkey>がスタックされるので、前と同様に<local_delayedpubkey>の秘密鍵で署名したデータをスタックしておかなくてはなりません。

しかし、その前にOP_CSV(OP_CHECKSEQUENCEVERIFY)があります。
これは、直前にスタックされている値を取り出し、vinとなるトランザクションがブロックに入ったときのブロック高+スタック値以上のブロック数が経過していない場合はスクリプト自体が偽となる命令になっています。

 

スタックの動きは、こうなります。
OP_DROPは、OP_CSVの結果が真だった場合、スタックしていたto_self_delay値が邪魔になるので、取り除くのに使われています。

 

image

 

そうなると、OP_CSVを経由しない方がすぐに使用できるので、そちらを使いたくなるかもしれません。
しかし、<revocationpubkey>の秘密鍵を使うことになるのは、revoked transaction closeをされた場合、すなわち相手が古いcommitment transactionをブロックチェーンに展開した場合に、ペナルティーとして相手のすべてを取り戻す場合になります。

ブロックチェーンに展開されているので、to_self_delayブロック経過してしまうと、相手がOP_ELSEルートを通るスクリプトを作ることができてしまうので、それまでに取り戻さないといけません。
to_self_delayはChannel Establish時にopen_channel / accept_channelで交換するので、小さすぎず(ペナルティーとして有効になるくらいの期間)、大きすぎず(unilateral closeで自分に取り戻すのに長すぎない期間)であることを確認する必要があります。


今回は、主にto_local scriptの解き方について説明しました。

BOLTでHTLCというと、送金/着金が反映される前、最初のトランザクションでいえば「Received」のようなものを指しますので、次回はそれらについて説明する予定です。

[LN#019]ptarmigan(2018/04/11)

Lightning Network BOLTの概要について、書いていくシリーズ。

今回は趣向を変えて、開発中のLightning Networkノードであるptarmiganの概要を説明します。

image


https://nayutaco.github.io/ptarmigan/

ptarmigan(たーみがん、と発音)は、日本名でいえば「雷鳥」になります。
Lightning Networkなので、雷に由来しています。

GitHubで見るとC++プロジェクトのように見えてしまいますが、実際はC言語です。
これは、単体テストでgtestsを使っていて、テストデータが大量にあるためにそうなってしまいました。

C言語で作っていますが、c-lightningをベースにしているわけではなく、ライブラリを使っている箇所以外はほとんど自作しています。

また、ptarmiganは弊社が作り始めましたが、オープンソースですので、issueを上げてくださったり、Pull Requestしてくださる方を歓迎しています。
日本語でも問題ありません!
(タイトルはなるべく英語で書いてますが、中身はほぼ日本語です)


gitのbranchは development で作業しています。

developmentで、簡単に他ノードとの動作確認したあとでリリースを行っています。
この時点の最新は、2018-04-11です。
https://github.com/nayutaco/ptarmigan/releases/tag/2018-04-11

他のノード(c-lightning / eclair / lnd)の使い方については、別のwikiにメモを作成しています。
https://github.com/nayutaco/lightning-memo/wiki

ptarmiganについてはdocsに書いています。
バージョンやcommit-idは記載当時のものになっていますが、だいたいは現在でも使えるようになっていると思います(動作しなかったら、issueくださると助かります)。


動作環境はUbuntuを想定していますが、Linuxであれば動作するのではないかと思います。
regtestでの動作はWindowsのWSL(Ubuntu)で行っています。

bitcoindの機能を使っていて、スクリプトではbitcoin-cliを呼び出し、ptarmiganのプロセス(ucoind)からはJSON-RPCを呼び出しています。

bitcoindのバージョンは、テスト環境ではv0.16を使っています。
おそらくv0.15でも動作するとは思いますが、今後のことを考えるとv0.16の方が無難かもしれません。
close後の送金アドレスは getnewaddress を使っているので、v0.15ではP2PKH、v0.16ではP2WPKH nested in BIP16 P2SHになります。

ptarmiganは、testnet/regtestでしか使用できません。


開発は、以下を中心に行っています。

  • BOLTを読んで、実装されていないところを追加、修正
  • 他ノードとやりとり
    • 認識が合わない動作があれば、BOLT再読やissueで確認
  • 操作性の向上やログ出力の見直し

BOLTの内容を読んで、それを実装レベルまでどう持っていくのか考えるのに時間がかかります。

まだまだ開発中ですので、ptarmiganに興味を持っていただけるとうれしいです。

[LN#018]announcement

Lightning Network BOLTの概要について、書いていくシリーズ。

今回は、announcementについて書きます。


転送(1)で簡単に紹介しましたが、BOLT#7でannouncement関連のメッセージが定義されています。

  • node_announcement
  • channel_announcement, channel_update

 

node_announcementは、alias名やIPアドレスなど、node自体の情報を展開しています。
相手nodeに接続したい場合は、このnodeからIPアドレスを調べ、接続させることでしょう。

 

1つのchannelには2つのnodeが関係するので、channel自体のannouncementメッセージ(channel_announcement)と、それぞれのnodeが持つchannel情報のannouncementメッセージ(channel_update)があります。
送金を転送するfeeなどは各nodeが主張できるので、通る方向によってfeeが異なる場合もあります。

 

 

このannouncementですが、Lightning Nodeをログ出力する状態にしてコマンドラインから実行するとわかりますが、相手nodeに接続すると、取りあえず大量に送信されてきます。
接続して最初に送信するinitメッセージで、相手nodeが持つchannel関連のannouncement情報を同期させるかどうか選べる(initial_routing_syncフラグ)のですが、だいたいは「同期する」にしているため、相手は持っている情報を送りつけるし、自分も持っている情報を送りつけます。

 

ならば、initial_routing_syncをオフにすればいいじゃないか、と思ってしまいますが、testnetではお金を掛けずにchannelを作ることができるためか、作って放置されるchannelが結構あります。
そういうchannelの情報しか持っていなかった場合、送金の転送をしたくても使用できないルートしか見つけることができなくなってしまうのです。

それを避けるため、取りあえず同期させようとしているのだと思います。

この辺りについては効率が悪いので、BOLTで解決していくのではないかと思われます。