[LN#005]Establish Channel (前半)

相手ノードとのネゴシエーションが終わり、initメッセージの交換が終わると、BOLTメッセージが交換できるようになる。

通常は、ノード間に開設したチャネルを使って送受金を行うため、開設するための「Channel Establish」について説明していく。

まず、ノードのどちらかが出資者(funder)になり、このチャネルでやりとりする総額を決定する。現在のBOLT仕様では、送受金はこの額の範囲内でしか行えない。

送金する場合は送金額を自分に割り当てられた額から減らして相手の割当額に加えるし、着金の場合はその逆になる。
それを繰り返し、チャネルを閉鎖したくなったときに、最後に残った配分をブロックチェーンに展開する。

下の図の青い部分をブロックチェーンではない改装で行うため、2nd Layer技術の一種となっている。
大きなしくみはこれだけである。
ただ、これにdecentralizationやtrustless、秘匿性などを組み合わせていったため、仕様が複雑になっている。

image

Channel Establishは大きく2つに分かれる(BOLTでは前半・後半の呼び名はなく、ここでの説明のために分けている)。

  • funding transaction展開前(前半)
  • funding transaction展開後(後半)

funding transaction“というのは、上の図でいう橙色に当たる。
funderが出資したトランザクションで、その出力先はAさんとBさんのMultiSigになっている。
チャネルの双方が出資し合うように思ってしまうが、BOLT仕様では片方しか出資しない。

このトランザクションをブロックチェーンに展開し、相手が指定したブロック時間だけ経過すると、funding transactionとして有効と見なすことになっている。
今回は、前半だけ解説する。

image

まず、funder(シーケンス図の左)が open_channel メッセージを送信する。
メッセージに問題が無ければ、fundee(シーケンス図の右)が accept_channel メッセージを送信する。

どちらもパラメータが多いが、ここで出資するための情報や条件がほぼ表されている。
主なパラメータを以下に示す(主に、と書いたが、無視できるパラメータは無い)。

MultiSigのための公開鍵 : funding_pubkey
前章に出てきた、鍵生成のためのパラメータ : xxx_basepoint
出資額 : open_channel.funding_satoshis
出資額のうち、相手に渡す額 : open_channel.push_msat
funding transaction展開後、トランザクションが安定したと見なす最短ブロック時間 : accept_channel.minimum_depth

Bitcoinの額は、最小単位がsatoshiである。
しかし、BOLTでの最小単位はmilli-satoshi(msat)で、1000分の1 satoshiである。
ここでは、push_msatがmsatになる。

push_msatは、単に配分として相手に渡すという仕様があるだけで、それを渡すための条件はBOLTで決められていない。
もしpush_msatに値がある状態でチャネルを開設し、そのまま取引をせずにチャネルを閉鎖しても、相手にはpush_msatをsatoshiに変換した額が渡されてしまうので、扱いについては注意が必要である。

accept_channelをチェックして問題が無ければ、 funding_createdメッセージを送信する。
この時点で、チャネルを閉鎖した際、funderとfundeeにいくらずつ配分すべきかのトランザクションを決定することができる。

これはfunding transactionの出力となるトランザクションで、BOLTでは “commitment transaction”と呼ぶ。
以降、commitment transactionでfunderとfundeeの配分を変化させていくことで送受金処理を行っていく。

BOLTではトランザクションの構成を細かく決めることで、トランザクション自体の情報を交換せず、ブロックチェーンに展開する際の署名だけを渡すことが多い(funding transactionが2-of-2 MultiSigのため、その出力であるcommitment transactionを展開するためにはお互いが署名する必要がある)。

ブロックチェーンに見える部分だけの署名関係を簡易図にすると、以下のようになる(txはトランザクションの略)。
commitment transaction(commit_tx)の送金先は、実際はもう少し複雑であるが、基本的にはこうなる。

image

funding_createdメッセージでは、funderが初回のcommitment transactionに署名して、相手に渡す。
また、込みいっていることに、commitment transactionの構成はAさんとBさんで異なる。

これは、funderとfundeeで異なる訳ではなく、トランザクションの項目に”local”と”remote”があり、自分が作るトランザクションの場合は「local=自分」「remote=相手」になり、相手が作るトランザクションの場合は「local=相手」「remote=自分」になるためである。

トランザクションの展開には手数料(fee)も必要になるが、手数料はトランザクションを展開する人の額から差し引くことになっているため、額についてもどちらが展開するかによって変わってくることになる。

それを踏まえて図を修正すると、以下のようになる。

image

そして、funding_createdで送信する署名は、相手が展開するcommitment transactionに対する署名である。

よって、commitment transactionは自分用と相手用の両方を作り、メッセージで送信する場合は相手のcommitment transactionに対しての署名を送信し、メッセージで受信した署名は自分のcommitment transactionでチェックすることになる。

funding_signedを受信して問題が無かった場合、funding_signedメッセージを送信する。
このメッセージも署名を含んでいるが、funding_createdと同様に「相手の持つcommitment transaction」に行った署名になる。

ここまでメッセージを交換すると、funding transactionを展開してから相手が不在になったとしても、自分に取り戻すcommitment transactionを展開することができる状況になったので、funding transactionをブロックチェーンに公開する。

ここまでがEstablish Channelの前半である。

[LN#004]鍵

これからノード間で送金を行うための準備を行う。

送金するためには「チャネル」と呼ぶ関係を作る。
チャネルができた後は、チャネルについた識別子(channel_id)をBOLTメッセージに載せて通信をしていく。
チャネルを開設する処理を「Channel Establishment」と呼んでいる。

https://github.com/lightningnetwork/lightning-rfc/blob/master/02-peer-protocol.md#channel-establishment

Channel Establishのシーケンスを以下に示す。

image

Channel Establishにて、on-chainからoff-chainに制御を移す。
移す際に、FunderとFundeeのMultiSig(2-of-2)に送金を行う。

その2-of-2の鍵や、不正を行わないようBitcoinのトランザクションにスクリプトを作るための鍵などがあり、それらをEstablish中に交換する。
鍵を直接交換するのでは無く、鍵を生成するための情報を交換し、各自で計算することになる。
計算については、以下を参照のこと。
https://github.com/lightningnetwork/lightning-rfc/blob/master/03-transactions.md#keys

また、鍵は固定ではなく、2-of-2トランザクションの出力内容を更新するたびに新しく作り替え、古い鍵情報は廃棄(revoke)する。
送金を行った後で古い出力内容をon-chainに載せられてしまうと、Bitcoinとしてはon-chainに見える送金情報しか確認できないため、結果として行った送金が無かったことになってしまうためである。
ただ、廃棄したことを約束事だけにしてしまわず、トランザクションのスクリプトと、BOLTメッセージのルールを組み合わせることで、古い出力内容をon-chainに展開すると、展開した方が損をする、というしくみになっている。

鍵(公開鍵)は、以下の種類がある(2017/11/27現在)。

  • localkey
  • remotekey
  • local_delayedkey
  • remote_delayedkey
  • local_revocationkey
  • remote_revocationkey
  • local_htlckey
  • remote_htlckey

localとremoteがあり、お互いが作成できるだけの情報を交換する。
これらの鍵を使って、それぞれが2-of-2トランザクションからの出力(commitment transaction)を作成できるようになっている。

このように、鍵については慎重に考えられているが、ここでは、以下を認識しておけば良いだろう。

  • 鍵を直接交換しないで交換した情報から生成する
  • 最初の情報交換は、Channel Establish時に行う
  • 2-of-2トランザクションからの出力内容(commitment transaction)が変わるたびに、鍵を作り直す
  • 古い鍵を使ったcommitment transactionを使うと損する設計になっている
参照

https://github.com/nayutaco/ptarmigan/blob/development/ucoin/src/ln/ln_derkey.c

[LN#003]init

前回、ノード間のネゴシエーションを行った。

ネゴシエーション後、最初に送信するBOLTメッセージは”init”である。

https://github.com/lightningnetwork/lightning-rfc/blob/master/01-messaging.md#the-init-message

image

描画ツールの都合上、initがシーケンスのようにやりとりしているようになってしまったが、実際はどちらが先に送信しても良い。

ただし、initを受信するまでは次のBOLTメッセージを送信することはできない。

initメッセージはglobalとlocalのfeatureをパラメータとして持つ。
featureの内容は、BOLT#9に記載されている。
https://github.com/lightningnetwork/lightning-rfc/blob/master/09-features.md

featureのデータは最短長になるように送信しなくてはならない。
例えば、現時点ではgolbalfeaturesの定義が無いので「0x00」を送信したくなるが、立てるビットがない場合には送信する必要がないため、ここではgflenを0にして、パラメータ自体を送信しないようにする。
あるいは、奇数ビットについては受信側で無視して良いことになっているため、そういうデータなら送信してもよい。

チャネル接続後、ネットワークが切断されて再接続する場合は、initメッセージのあとに”channel_reestablish”を送信する。
再接続については、説明を省略する。
https://github.com/lightningnetwork/lightning-rfc/blob/master/02-peer-protocol.md#message-retransmission

参照

https://github.com/nayutaco/ptarmigan/blob/development/ucoin/src/ln/ln_msg_setupctl.c

[LN#002] Noise Protocol

BOLTは、ノード間でメッセージ交換する。

まず、相手ノードとのネゴシエーションを行い、成功したらその相手とBOLTのメッセージを符号化して通信する。
BOLT#8では、ネゴシエーションの方法と、その後のメッセージ符号化/復号化について説明している。
このBOLT#8だけは、他の章からほぼ独立している。


https://github.com/lightningnetwork/lightning-rfc/blob/master/08-transport.md

ネゴシエーションや符号化の仕方は、Noise Protocolという方式を用いている。
Noise Protocol自体はいくつかパラメータがあり、そのうちBOLTで使用するものだけ#8に記載されている。
シーケンスを以下の図に示す。

 

image

 

ここでは、AがBに対して接続を要求するようになっている。
相手ノードとはIPアドレスなどでTCP接続を行った後、相手をnode_id(Bitcoinの公開鍵と同じ計算で求めた33バイトのデータ)で指定してネゴシエーションを行う。
1.5往復して相手のノードに間違いが無ければ、ネゴシエーションが完了する。


それ以降は、ネゴシエーション時に交換した鍵情報で、BOLTのメッセージを符号化/復号化を行う。
メッセージ構造は、以下に記載されている。

https://github.com/lightningnetwork/lightning-rfc/blob/master/08-transport.md#lightning-message-specification

 

大きく「メッセージ長」と「メッセージ本体」に分かれる。
メッセージ長はChaChaPoly-1305で符号化+MAC付加する(2+16byte)。
メッセージ本体も同様にChaChaPoly-1305で符号化+MAC付加する(メッセージ長+16byte)。
その両者を結合して、1つのメッセージとして相手に送信する。
受信はその逆の動作を行って復号化する。

 

符号化/復号化の鍵はネゴシエーション時のものを使い続けるのではなく、1000回符号化/復号化するたびにrotation処理を行い、鍵を変更する。
1回の送信で2回の符号化を行うため、500回のメッセージ送信でrotation処理を行うことになる。
https://github.com/lightningnetwork/lightning-rfc/blob/master/08-transport.md#lightning-message-key-rotation

 

参照

https://github.com/nayutaco/ptarmigan/blob/development/ucoin/src/ln/ln_enc_auth.c

[LN#001] どこから読むか

現在(2017/11/14)のところ、BOLTは0~11章まである(うち、6章は欠番)。

image

 

このうち、どこから読み始めるのがよいかという質問をされることがあるが、その回答は難しい。


まず、BOLT#0は導入部で用語が多少載っているため、先に目を通すとよいだろう。
テーマソングがあるなど、ふざけたところがあるように見えるかもしれないが、そういった要素はここ以外見当たらない。

 

内容についてはBOLT#1以降になるが、プロトコルの階層順で行くと、BOLT#8を最初に読むのがよいだろう。
BOLT#8は他の章からほぼ独立していて、BOLTでの通信を開始する前のネゴシエーションと、通信を開始してからの符号化処理について書かれている。
他の章は、この章の内容が実現されている前提になっている。
逆に言えば、実装をしないのであれば、BOLT#8はあまり気にしなくてよい。

 

BOLT#1、#2および#7は、P2P通信プロトコルについて記載されている。
BOLT#1,#7で使用するパラメータの一部をBOLT#9で、BOLT#2で使用するパラメータの一部をBOLT#4で詳細に説明している。
BOLT#3は、1st Layer、すなわちBitcoinのブロックチェーンで使用するトランザクションとBOLT#2で交換したメッセージの関係や、スクリプトで使用する鍵の導出について記載されている。
BOLT#5は、トランザクションをon-chain、すなわちBitcoinのブロックチェーンでどのように扱うべきか示している。

 

BOLT#10はノードの情報を得る手段について、BOLT#11は請求書(invoice)についてである。


このように、章単独で読み進められるものではない。
それでもあえてどこからか読み進めるとすれば、BOLT#2がよいか。
内容は分からないにしても、シーケンスが図になっているので、イメージはつかみやすいと思う。

 

ただ、このブログでは、通信を確立するところから順に解説していく。


なお、弊社ではオリジナルノード実装のptarmiganを開発している。
BOLTの標準実装を進めているc-lightningのノードと混在させての送受金テストも動作している(commit id : ebdecebb1a89f7dcd8daa53c57ec58af32f7c40d)。

image

[LN#000] "Basis of Lightning Technology"(BOLT)について

はじめまして、Nayutaのuenoです。

 

BitcoinのLightning Network仕様の1つにBOLTがあります。
これを書いている時点では、まだv1.0になるかならないか、という状況で、変更もしばしば行われています。

弊社ではBOLT実装を行っており、GitHubにて公開しています。
BOLTを読んだだけではわかりづらい箇所が多々ありますが、その内部で何が行われているかを、何回かに分けて解説していきます。

株式会社Nayuta、Wanxiang Global Blockchain Challengeにて3位入賞

2017年9月14日〜16日に上海にて開催中の3rd Global Blockchain Summitにおいて「Wanxiang Global Blockchain Challenge」*1 の入賞者が発表され、株式会社Nayuta(代表取締役:栗元憲一 本社:福岡市中央区)がSmart terminal reference solution部門で3位を受賞しました。

本コンテストは、Wanxiang グループが中国杭州市に計画しているスマートシティでの採用を目指すコンテストで、当スマートシティは5年で2,000億元(約3.2兆円)の投資が計画されています。審査員は、Vitalik Buterin, Jed Mccaleb, Bo shen, Shuo Baiと、ブロックチェーン業界のグローバルリーダーで構成されています。

当社は、SummitのDemo Dayでのプレゼンテーションにおいて、「SmartPlugとそのアプリケーションを支える2nd Layer技術とIoT技術」の提案とこれまでの成果のデモを行い、3位を受賞しました。

今回の受賞を機に、当スマートシティプロジェクトに積極的に関与し、さらなるグローバル市場への展開を推し進めて参ります。

*1 http://www.wxblockchain.com/global/index_en.html

 

[988][267]
[966][266]