Skip to content

Instantly share code, notes, and snippets.

@azuchi
Last active July 31, 2019 04:55
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save azuchi/1f4aea689877099d5ff720b461a9747d to your computer and use it in GitHub Desktop.
Save azuchi/1f4aea689877099d5ff720b461a9747d to your computer and use it in GitHub Desktop.
トランポリンペイメントの提案の和訳

トランポリンオニオンルーティング

このドキュメントはトランポリンホップの使用を可能にするために、我々が既存のオニオンルーティングに加える追加機能について説明する。

ネットワークが成長するにつれて、ネットワーク全体を最新の状態に保つために、より多くの帯域幅とストレージが必要になる。支払い経路を見つけることは、より多くの計算能力を必要とし、制限のあるデバイスにとってはそれを持続不可能にする。

制限のあるデバイスはネットワークのごく一部のビューを持ち、トランポリンノードを利用して支払いを転送するようにする。この提案は、それでも匿名性を犠牲にしないよう送信者によって作成されたオニオンを使用している(ほとんどの場合、それはより大きな匿名セットを提供するだろう。)。

ネットワーク全体を追跡するノードは、option_trampoline_routingのサポートを広告する必要がある。これらのトランポリンノードには、従来のオニオンルーティングよりも多くの手数料を稼ぐ機会がある。

送信者は、いくつかのトランポリンノードを選択し、対応するトランポリンオニオンTLVを作成する。続いて、最初のトランポリンノード宛のオニオンパケットの最後のper_hopペイロードにそのトランポリンオニオンを埋め込む。トランポリンノード間の経路計算はトランポリンノード辞退に委ねられる。

マーチャントは、送信者が良い最後のトランポリンノードを選択するのを支援するため、自身のインボイスに自身に近いいくつかのトランポリンノードを含めても良い。これはあくまでオプションなので、送信者はこのルーティングヒントを使ってもいいし、使わなくても良い。

興味深い副作用としては、トランポリンルーティングがランデブールーティングとうまく組み合わさっている点だ。単純な新しいTLVタイプとインボイスに含まれるデータが増えたことで、ランデブールーティングはトランポリン具ルーティングの上で簡単に機能し、ここで説明しているのと似た構造になる。

パケット構造

トランポリンオニオン

トランポリンオニオンは以下の構造を持つ、固定サイズのTLVパケット:

  1. タイプ:trampoline_onion_packet
  2. データ:
    • [1 : 0x08] (type)
    • [3 : 0xfde202] (length)
    • [1 : version]
    • [33 : public_key]
    • [672 : tranpoline_hops_data]
    • [32 : hmac]

結果、742バイトの固定サイズのパケットとなり、値はonion_packetとまったく同じ形式でhops_dataがより小さくなる。

trampoline_hops_dataフィールドは、trampoline_hop_payloadのリストで、次のトランポリンホップのアドレス、転送情報およびそれに関連するHMACの難読化データで構成される。またonion_packetの可変サイズのper_hopペイロードと同じフォーマットを使用する。つまり、任意のTVLストリームを含められる:

  1. タイプ:trampoline_hops_data
  2. データ:
    • [n1 : trampoline_hop_payload]
    • [n2 : trampoline_hop_payload]
    • ...
    • filler

trampoline_hop_payloadは、以下の構造のデータ:

  1. タイプ:trampoline_hop_payload
  2. データ:
    • [var_int : length]
    • [length : tlv_stream]
    • [32 : hmac]

tlv_streamには、次のトランポリンホップにルーティングするために必要なデータが含まれている。そのデータをエンコードするために以下の型を使用できる:

  • タイプ:node_id
  • データ:
    • [1 : 0x02] (type)
    • [1 : 0x21] (length)
    • [33 : node_id]
  • タイプ: amount_msat
  • データ:
    • [1 : 0x04] (type)
    • [1 : length]
    • [length : amount_msat_value]
  • タイプ: cltv
  • データ:
    • [1 : 0x06] (type)
    • [1 : length]
    • [length : cltv_value]

使い方

支払いを中継するためにトランポリンノードを使用したいノードは、onion_packetの最後のホップのTLVストリームにtrampoline_onion_packetを使用する:

  1. タイプ:onion_packet
  2. データ:
    • [1 : version]
    • [33 : public_key]
    • [n1 : hop_payload](通常のホップペイロード)
    • [n2 : hop_payload](通常のホップペイロード)
    • ...
    • [n : hop_payload](trampoline_onion_packetを含むホップペイロード)
    • filler
    • [32 : hmac]

最後のhop_payloadの構造は、以下のとおり:

  1. タイプ:hop_payload
  2. データ:
    • [var_int : length]
    • [742 : trampoline_onion_packet]
    • オプションのTLVをここに追加可能
    • [32 : hmac]

非トランポリンノードへの支払い

支払い先の受信者がトランポリンルーティングをサポートしていない場合は、最後のトランポリンノードに最後のホップを標準のオニオン支払いに変換してもらう。

最後のtrampoline_hop_payloadには、以下の構造のrecipient_info TLVパケットが含まれてなければならない:

  1. タイプ:recipient_info
  2. データ:
    • [1 : 0x0a] (type)
    • [1 : 0x01] (length)
    • [1 : 0x00] (option_trampoline_routing)

このデータは、受信者の身元と最後のトランポリンノードに支払われた金額を明らかにすることに注意すること(しかし送信者の身元を明らかにすることはない)。受信者がその身元を隠すためにランデブールーティングを使っている場合、これは回避できる。それ以外の場合、受信者は自身の匿名性を保つためにoption_trampoline_routingをサポートすべきだ(そして、多くの支払いをルーティングしたくない場合は高めのfeeを広告することもできる)。

要件

送信ノードは、

  • trampoline_onion_packetの各ホップがoption_trampoline_routingをサポートしていることを確認しなければならない。
  • 受信者がoption_trampoline_routingをサポートしていない場合、option_trampoline_routing0x00にセットしたTLVをrecipient_infoに含めなければならない。
  • onion_packetと同じ構造で、trampoline_onion_packetを暗号化しなければならない。
  • trampoline_onion_packetonion_packetで異なるsession_keyを使わなければならない。
  • trampoline_hop_payload内で、node_idamount_msatおよびcltv以外のTLVタイプを使ってもいい。
  • trampoline_hop_payloadに追加のTLVタイプを含めることができる。
  • trampoline_onion_packetを最後のホップのonion_packetのペイロードに入れなければならない。

受信ノードはtrampoline_onion_packetを処理する際、

  • option_trampoline_routingをサポートしていない場合、起点ノードへ経路障害を報告しなければならない。
  • trampoline_onion_packetonion_packetとして処理しなければならない。
  • trampoline_onion_packetの中で、未知の偶数のTLVタイプに遭遇したら、起点ノードへ経路障害を報告しなければならない。
  • 次のホップを見つけるのに十分なデータがない場合、起点ノードへ経路障害を報告しなければならない。
  • 次のトランポリンホップへの経路を計算しなければならない:
    • cltv要件を満たす経路が見つからない場合、起点ノードへ経路障害を報告しなければならない。
    • fee要件を満たす経路が見つからない場合、起点ノードへ経路障害を報告しなければならない。
    • 次のトランポリンホップとチャネルを開いている場合、シングルホップの経路を構築するのにそれを使ってもいい。
    • recipient_info TLVのoption_trampoline_routing0x00に設定されていた場合、trampoline_onion_packetonion_packetに変換しなければならない。
    • それ以外では、最後のhop_payloadtrampoline_onion_packetを含めてはならない。
  • エラーハンドリングセクションで指定されているようにエラーを返す。

論拠

この構造はネットワークの不完全なビューを持つノードがトランポリンノードに経路の一部の構造を委任することを可能にする。

起点ノードはトランポリンノードのセットを選択し、最初のトランポリンノードへの経路を知る必要があるだけだ。各トランポリンノードは、次のトランポリンノードへの独自の経路を見つける必要がある。トランポリンノードは前のノード(これはトランポリンノードであってもなくてもいい)だけを知っている。

trampoline_onion_packetはトランポリンノードが使用されるトランポリンノードの数を推測できないように固定サイズになっている。それはonion_packetと同じ構造を使う。

トランポリンノードは、cltvfeeの要件を満たす経路を作成できる限り、自由にホップの数を決めることができる。利用可能な適切なチャネルがある場合、これには次のトランポリンノードへのシングルホップ支払い実行が含まれる。

trampoline_hop_payloadは、node_idamokunt_msatcltvタイプを使って、次のトランポリンノードへの死はリアを作成するためのデータを指定する。これらのタイプを使用するのは必須ではなく、他のエンコードを使ってもいい(例えば、node_idよりもノードアドレスを指定するよりコンパクトな方法が利用可能であればそれを使ってもいい)。

パケットサイズはトランポリンノードに最大8個の中間トランポリンノードと最大10個の中間ノードを許容するよう選択されている。

手数料とCLTV要件

トランポリンルーティングを使って死hらいを送信するには、全てのトランポリンノードが、次のトランポリンノードにルーティングするのに十分なfeescltvを受け取る必要がある。

以下のようなノードとチャネルを考える。

   H1 -- H2    H4
  /        \  /  \
T1          T2    T3
  \        /  \  /
   `---- H3    H5

それぞれ以下のcltv_expiry_deltaを各チャネルの最後に広告する:

  • H1: 10 ブロック
  • H2: 20 ブロック
  • H3: 30 ブロック
  • H4: 40 ブロック
  • H5: 50 ブロック
  • T1: 60 ブロック
  • T2: 70 ブロック
  • T3: 80ブロック

T3は支払いを要求する際に、デフォルトで9のmin_final_cltv_expiryを使用する。

また、各ノードは各チャネルに使用する手数料体系がある。

  • H1: 100 base + 1000 millionths
  • H2: 200 base + 2000 millionths
  • H3: 300 base + 3000 millionths
  • H4: 400 base + 4000 millionths
  • H5: 500 base + 5000 millionths
  • T1: 600 base + 6000 millionths
  • T2: 700 base + 7000 millionths
  • T3: 800 base + 8000 millionths

アリスがランダム化されたcltvの有効期限が42で5000 satoshiの支払いをT3に送信すると仮定する。

T2->T3:

T2はT3まで、H4を経由するケースとH5を経由するケースの2つの経路がある。

H4経由の経路の場合は以下のようになる。

  • H4:
    • amount_msat = 5000000 + 400 + ( 4000 * 5000000 / 1000000 ) = 5020400
    • cltv_expiry = current-block-height + 40 + 42 + 9
    • onion_packet:
      • amt_to_forward = 5000000
      • outgoing_cltv_value = current-block-height + 42 + 9
  • T2
    • amount_msat = 5020400 + 700 + ( 7000 * 5020400 / 1000000 ) = 5056243
    • cltv_expiry = current-block-height + 70 + 40 + 42 + 9
    • onion_packet:
      • amt_to_forward = 5020400
      • outgoing_cltv_value = current-block-height + 40 + 42 + 9

H5経由の経路の場合は以下のようになる。

  • H5:
    • amount_msat = 5000000 + 500 + ( 5000 * 5000000 / 1000000 ) = 5025500
    • cltv_expiry = current-block-height + 50 + 42 + 9
    • onion_packet:
      • amt_to_forward = 5000000
      • outgoing_cltv_value = current-block-height + 42 + 9
  • T2:
    • amount_msat = 5025500 + 700 + ( 7000 * 5025500 / 1000000 ) = 5061379
    • cltv_expiry = current-block-height + 70 + 50 + 42 + 9
    • onion_packet:
      • amt_to_forward = 5025500
      • outgoing_cltv_value = current-block-height + 50 + 42 + 9

T2は、これらいずれかの経路を使ったトランポリン支払いをルーティングするため次の値を広告する。

  • fees: 1200 base + 12500 millionths
  • cltv_expiry_delta: 120 ブロック

T2→T3では、以下のトランポリン値が必要:

  • amount_msat = 5000000 + 1200 + ( 12500 * 5000000 / 1000000 ) = 5063700
  • cltv_expiry = current-block-height + 120 + 42 + 9
  • trampoline_onion_packet:
    • amt_to_forward = 5000000
    • outgoing_cltv_value = current-block-height + 42 + 9

T1->T2:

T1はT2まで、H1,H2を経由するケースとH3を経由するケースの2つの経路がある。

H1からH2を介したルーティングには、以下の値が必要:

  • H2:
    • amount_msat = 5063700 + 200 + ( 2000 * 5063700 / 1000000 ) = 5074028
    • cltv_expiry = current-block-height + 20 + 120 + 42 + 9
    • onion_packet:
      • amt_to_forward = 5063700
      • outgoing_cltv_value = current-block-height + 120 + 42 + 9
  • H1:
    • amount_msat = 5074028 + 100 + ( 1000 * 5074028 / 1000000 ) = 5079203
    • cltv_expiry = current-block-height + 10 + 20 + 120 + 42 + 9
    • onion_packet:
      • amt_to_forward = 5074028
      • outgoing_cltv_value = current-block-height + 20 + 120 + 42 + 9
  • T1:
    • amount_msat = 5079203 + 600 + ( 6000 * 5079203 / 1000000 ) = 5110279
    • cltv_expiry = current-block-height + 60 + 10 + 20 + 120 + 42 + 9
    • onion_packet:
      • amt_to_forward = 5079203
      • outgoing_cltv_value = current-block-height + 10 + 20 + 120 + 42 + 9

H3を介したルーティングには以下の値が必要:

  • H3:
    • amount_msat = 5063700 + 300 + ( 3000 * 5063700 / 1000000 ) = 5079192
    • cltv_expiry = current-block-height + 30 + 120 + 42 + 9
    • onion_packet:
      • amt_to_forward = 5063700
      • outgoing_cltv_value = current-block-height + 120 + 42 + 9
  • T1:
    • amount_msat = 5079192 + 600 + ( 6000 * 5079192 / 1000000 ) = 5110268
    • cltv_expiry = current-block-height + 60 + 30 + 120 + 42 + 9
    • onion_packet:
      • amt_to_forward = 5079192
      • outgoing_cltv_value = current-block-height + 30 + 120 + 42 + 9

T1は、これらいずれかの経路を使ったトランポリン支払いをルーティングするため次の値を広告する。

  • fees: 900 base + 9500 millionths
  • cltv_expiry_delta: 90 ブロック

T1→T2では、以下のトランポリン値が必要:

  • amount_msat = 5063700 + 900 + ( 9500 * 5063700 / 1000000 ) = 5112706
  • cltv_expiry = current-block-height + 90 + 120 + 42 + 9
  • trampoline_onion_packet:
    • amt_to_forward = 5063700
    • outgoing_cltv_value = current-block-height + 120 + 42 + 9

ネットワークプルーニング

TODO:このセクションはまだスペックのフォーマットではない。スペックの取り組みを始める前に、進む道の同意を確認するための全体的な考えのドラフト。

制限のあるデバイス(電話、IoTデバイスなど)で実行されているノードは、自身と近くのチャネルのみ(例えばN半径のヒューリスティックみたいに)を追跡する必要がある。これら近くのチャネルは、最初のトランポリンノードへのv0オニオンルートを構築するのに使われる。

制限ノードはmin_chan_capacityより小さい容量のチャネルを無視するという選択もできる。Nmin_chan_capacityはノードによって設定されネットワークには広告されない。

制限ノードはこれらの要件を満たしていないchannel_announcementを単純に無視する。

制限ノードはトランポリンとして使うため、彼らのネットワークビューの外側にあるノードに関する情報も格納する必要がある。

対照的にトランポリンノードは、支払いを効率的にルーティングできるようにネットワーク・トポロジーの全体像を把握する必要がある。

node_update メッセージ

以下の構造を持つ新しいオプションのnode_updateメッセージを導入する。

  1. タイプ: 261(node_update)
  2. データ:
    • [varint : length]
    • [1 : 0x02] (type)
    • [1 : 0x21] (length)
    • [33 : node_id]
    • [1 : 0x04] (type)
    • [1 : 0x40] (length)
    • [64 : signature]
    • [1 : 0x06] (type)
    • [1 : 0x20] (length)
    • [32 : chain_hash]
    • [1 : 0x08] (type)
    • [1 : 0x1e] (length)
    • [4 : timestamp]
    • [2 : cltv_expiry_delta]
    • [8 : htlc_minimum_msat]
    • [8 : htlc_maximum_msat]
    • [4 : fee_base_msat]
    • [4 : fee_proportional_millionths]

これはchannel_updateメッセージに似た構造を持っているが、チャネルに依存しない。node_updatechannel_updateが中継されるのと同じ方法(staggered broadcast)で中継される必要がある。

トランポリンノードは、インバウンドおよびアウトバウンドキャパシティを持つオープンチャネルを持つノードからnode_updateのみを受け入れて中継する必要がある。

ノードがトランポリンペイメントを中継する意思がない場合、ノードは単純にnode_updateを送信しない。これによりネットワークは、フォーマットを理解しているが送信者もしくは受信者としてのみ使用するノードからトランポリン支払いを中継できるノードを区別できる。

手数料とCLTVの見積もり

トランポリンノードは、他のノードと競合しながら他のトランポリンノードへルーティングできるようにするcltv_expiry_deltafeeを見積もる必要がある。これはトランポリンコストを最小限に抑えるようノードが互いにチャネルを開くよう動機付ける絶好の機会だ。これはノードが競争上の優位性としてスマート手数料見積もりアルゴリズムを実装するための大きな機会でもある。

ノードは非常に保守的で、到達可能な最も遠いノードに対応する最悪のケースのfeecltv_expiry_deltaを広告することがある。

対照的に、ノードは他の全てのトランポリンノードへ到達できないが、ほとんどの場合には上手く行くだろうより低いfeeおよびcltv_expiry_deltaを見つけるためにネットワークの統計分析を適用するかもしれない。そのようなノードは、信頼性を高く持つため、いくつかの支払いは損失を含めてルーティングし、信頼性の評判を高めより多くの支払いを惹きつけることで全体的に利益を出すような選択ができる。

ノードはnode_updateにいくつかの優先ネイバーを含めることができ、これはこれらのノードに安価にルーティングできることを意味する。送信者はその情報を使ってもいいし使わなくてもいい。

トランポリンノードは、経済的実行可能な方法で支払いをルーティングできる場合(例えば次のトランポリンノードと直接もしくは安価な経路がある場合など)、広告している金額よりも低い手数料で支払いを受け入れることができる。

つまり使用しているfee/cltvでまだ適切にルーティングできると思われる場合、支払人は広告された手数料を完全に無視することを選択できる。

手数料の計算に関する詳細例については、手数料とCLTV要件を参照。

ゴシップメッセージのフィルタリング

制限ノードはnode_updateメッセージを監視し、トランポリンとして使用するためそれらのいくつかを保存する必要がある。ノードはトランポリンノードを選択するためのヒューリスティックを自由に選択できる(匿名性のためにある程度のランダム性が望まれる)。

これにより制限ノードのストレージ要件が削減されるが、帯域幅の要件は削減されない。制限ノードは引き続きnode_updateおよびchannel_updateメッセージをリッスンする必要がある(それらのほとんどは無視される)。

ゴシップの再送信の前に適用されるべきゴシップフィルタを導入する。制限ノードは、option_gossip_filtersをサポートするリモートノードにのみ接続する。そしてそのリモートノードとフィルタの調整をする。ゴシップメッセージを受信すると、リモートノードはフィルタを適用し、フィルタに一致するエントリーのみローカルノードに転送する。

※リモートノードはフィルタを完全に無視してローカルノードに全てのゴシップメッセージを転送することを決定できる。その場合、ローカルノードはリモートノードとの全てのチャネルを閉じ、接続を失敗し、より協調的なノードとチャネルを開く。

TODO:アイディアに同意する場合、initフェーズとフィルタの調整要件が必要。

channel_update_filter

ローカルノードは、channel_update_filterをリモードノードに送信できる。リモートノードは、channel_updateを送信する前にこのフィルタを適用する必要がある。これによりローカルノードは、ネットワークのごく一部の最新のビューを維持できる。

フィルタは単純な距離整数だ。リモートノードはリモートノード自体から最大ホップ数だけ離れているノードのchannel_updateのみを転送する必要がある。

このフィルタを計算することは、短い距離については安価だ。リモートノードは評価にコストがかかり過ぎる距離を拒否する必要がある。

TODO: アイディアに同意する場合はメッセージフォーマットの詳細を追加

node_update_filter

ローカルノードはnode_update_filterをリモートノードに送信できる。リモートノードはnode_updateを転送する前に、このフィルタを適用する必要がある。これによりローカルノードはトランポリンノードのリストを定期的に更新し、それらの手数料率とcltvを最新の状態に保つために関係するnode_updateのみを受け取ることができる。

ローカルノードは十分に信頼できるのであればトランポリンノードの同じセットを保持する選択をしてもいい。或いはローカルノードは、匿名性を改善し、新しい支払い経路をテストするためにトランポリンノードのセットを定期的にローテートしてもいい。この決定はユーザー/実装によって設定可能であるべき。

トランポリンノードのセットを頻繁にローテートする簡単なヒューリスティックは、node_idとsha256(local_node_id || latest_block_hash)を比較し、これをNブロックごとに更新することだ。node_update_filterは、これら2つの値の間の距離に基づいている。次に、ローカルノードは広告されている手数料/cltvと信頼性の評判(そのようなデータをを収集できる場合はその履歴データに基づいて)に基づいて、どのトランポリンノードを維持するか選択する。

TODO: アイディアに同意する場合はメッセージフォーマットの詳細を追加

サンプル

トランポリンペイメントをサポートするマーチャント

ボブはトランポリンペイメントをサポートするマーチャントである。ボブは5000 satoshiのインボイスを作成し、そのインボイスにトランポリンルーティングをサポートする近隣の3つ(TB1およびTB2、TB3)を含める。

アリスはトランポリンペイメントでこのインボイスの支払いをしたい。アリスは自分が経路を知っている最初のトランポリンノード(TA1)を選択する。次に別のトランポリンノードTA2(近隣になくてもいい)を選択し、インボイスからトランポリンノードを1つ選択する(TB3)。

トランポリンルートは以下のようになる。

アリス -> TA1 -> TA2 -> TB3 -> ボブ

TA1の最新のnode_updatecltv_expiry_delta = 20およびfee = 3000 msatを広告した。TA2のnode_updateは、cltv_expiry_delta = 15で、fee = 2000 msat。インボイスに記載されているTB3の詳細では、cltv_expiry_delta = 30で、fee = 1000 msatが指定されていた。

※ シンプルにするため、手数料は単一の固定値であるかのように動作する。

アリスは以下のtrampoline_onion_packetを作成する(簡単にするため暗号化は省略)

  • [1:0x08] (type)
  • [3:0xfde202] (length)
  • [1:version]
  • [33:public_key]
  • [76:trampoline_hop_payload] (payload for TA1)
    • [1:0x4b] (length)
    • [1:0x02] (type)
    • [1:0x21] (length)
    • [33:TA2_node_id]
    • [1:0x04] (type)
    • [1:0x03] (length)
    • [3:5003000] (amt_to_forward)
    • [1:0x06] (type)
    • [1:0x01] (length)
    • [1:70] (outgoing_cltv_value)
    • [32:hmac]
  • [76:trampoline_hop_payload] (payload for TA2)
    • [1:0x4b] (length)
    • [1:0x02] (type)
    • [1:0x21] (length)
    • [33:TB3_node_id]
    • [1:0x04] (type)
    • [1:0x03] (length)
    • [3:5001000] (amt_to_forward)
    • [1:0x06] (type)
    • [1:0x01] (length)
    • [1:55] (outgoing_cltv_value)
    • [32:hmac]
  • [76:trampoline_hop_payload] (payload for TB3)
    • [1:0x4b] (length)
    • [1:0x02] (type)
    • [1:0x21] (length)
    • [33:Bob_node_id]
    • [1:0x04] (type)
    • [1:0x03] (length)
    • [3:5000000] (amt_to_forward)
    • [1:0x06] (type)
    • [1:0x01] (length)
    • [1:25] (outgoing_cltv_value)
    • [32:hmac]
  • [76:trampoline_hop_payload] (payload for Bob)
    • [1:0x4b] (length)
    • [1:0x02] (type)
    • [1:0x21] (length)
    • [33:Bob_node_id]
    • [1:0x04] (type)
    • [1:0x03] (length)
    • [3:5000000] (payment_amt)
    • [1:0x06] (type)
    • [1:0x01] (length)
    • [1:25] (final_cltv_expiry)
    • [32:hmac] (0x00...00)
  • [368:filler]
  • [32:hmac]

アリスは自身の近隣のビューからTA1の経路を見つける。

アリス -> H1 -> H2 -> TA1

簡単にするため、全ての中間ノードHiは固定の500 msat 手数料とcltv_expiry_delta=5を広告すると仮定する。

アリスは以下のonion_packetを作成する(簡単にするため暗号化は省略)

  • [1:0x00] (version)
  • [33:public_key]
  • [65:hop_payload] (payload for H1)
    • [1:0x00] (realm)
    • [8:channel_from_H1_to_H2] (short_channel_id)
    • [8:5006500] (amt_to_forward)
    • [4:95] (outgoing_cltv_value)
    • [12:padding]
    • [32:hmac]
  • [65:hop_payload] (payload for H2)
    • [1:0x00] (realm)
    • [8:channel_from_H2_to_TA1] (short_channel_id)
    • [8:5006000] (amt_to_forward)
    • [4:90] (outgoing_cltv_value)
    • [12:padding]
    • [32:hmac]
  • [777:hop_payload] (payload for TA1)
    • [3:0xfde602] (length)
    • [742:trampoline_onion_packet]
    • [32:hmac] (0x00...00)
  • [393:filler]
  • [32:hmac]

H1とH2は他のonion_packetと同じようにonion_packetを転送するが、それがトランポリンルーティング用であることを知らない。

TA1はonion_packetを受け取り、trampoline_onion_packet TLVを見つける。TA1は、trampoline_onion_packetの1つの層を剥がして次のトランポリンホップ(TA2)を発見する。

TA1はTA2への経路を見つける。

TA1 -> H3 -> H4 -> TA2

TA1は以下のonion_packetを作成する(簡単にするため暗号化は省略)

  • [1:0x00] (version)
  • [33:public_key]
  • [65:hop_payload] (payload for H3)
    • [1:0x00] (realm)
    • [8:channel_from_H3_to_H4] (short_channel_id)
    • [8:5003500] (amt_to_forward)
    • [4:75] (outgoing_cltv_value)
    • [12:padding]
    • [32:hmac]
  • [65:hop_payload] (payload for H4)
    • [1:0x00] (realm)
    • [8:channel_from_H4_to_TA2] (short_channel_id)
    • [8:5003000] (amt_to_forward)
    • [4:70] (outgoing_cltv_value)
    • [12:padding]
    • [32:hmac]
  • [777:hop_payload] (payload for TA2)
    • [3:0xfde602] (length)
    • [742:trampoline_onion_packet] (with the TA1 layer peeled)
    • [32:hmac] (0x00...00)
  • [393:filler]
  • [32:hmac]

TA1は事実上2000 msatの手数料を受け取った(受信した3000 msatとTA2にルーティングするために支払われる1000 msat)。

H3とH4は他のonion_packetと同じようにonion_packetを転送し、それがトランポリンルーティング用だとは知らない。

TA2はonion_packetを受け取り、trampoline_onion_packet TLVを見つける。TA2はtrampoline_onion_packetの1つの層をはがして、次のトランポリンホップ(TB3)を発見する。

TA2はTB3とのチャネルを持っているため、以下のonion_packetを作成する(簡単にするため暗号化は省略)

  • [1:0x00] (version)
  • [33:public_key]
  • [777:hop_payload] (payload for TB3)
    • [3:0xfde602] (length)
    • [742:trampoline_onion_packet] (with the TA2 layer peeled)
    • [32:hmac] (0x00...00)
  • [523:filler]
  • [32:hmac]

TA2は事実上2000 msatの手数料を受け取る(2000 msat受信し、TB3へのチャネルを既に持ってるので追加のルーティングコストがかからない)

TB3は、onion_packetを受信し、trampoline_onion_packet TLVを発見する。TB3はtrampoline_onion_packetの1つの層をはがし、次のトランポリンホップ(ボブ)を発見する。TB3はボブが最後の受信者であることを知らない。

TB3はボブへの経路を探す。

TB3 -> H5 -> ボブ

TB3は以下のonion_packetを作成する(簡単にするため暗号化は省略)

  • [1:0x00] (version)
  • [33:public_key]
  • [65:hop_payload] (payload for H5)
    • [1:0x00] (realm)
    • [8:channel_from_H5_to_Bob] (short_channel_id)
    • [8:5000000] (amt_to_forward)
    • [4:25] (outgoing_cltv_value)
    • [12:padding]
    • [32:hmac]
  • [777:hop_payload] (payload for Bob)
    • [3:0xfde602] (length)
    • [742:trampoline_onion_packet] (with the TB3 layer peeled)
    • [32:hmac] (0x00...00)
  • [458:filler]
  • [32:hmac]

TB3は事実上500 msatの手数料を得る(1000 msat受信し、500 msat ボブへの経路に支払う)。

ボブはonion_packetを受信し、trampoline_onion_packet TLVを発見する。ボブはtrampoline_onion_packetの層を1つはがし、自分が受信者であることを発見する(hmacが0x00...00なので)。

有効な支払いルートは以下のとおり:

Alice                 TA1                  TA2 -> TB3         Bob
  |                   ^ |                   ^      |           ^
  |                   | |                   |      |           |
  `---> H1 ---> H2 ---' `---> H3 ---> H4 ---'      `---> H5 ---'

トランポリンサポートのないマーチャント

ボブはトランポリンペイメントをサポートしないマーチャントで、ルーティングのヒントのない5000 satoshiのインボイスを作成する。

アリスはこのインボイスにトランポリンルーティングを使って支払いたい。説明を短くするため、アリスは単一のトランポリンホップTを選択する。

トランポリン経路は、

アリス -> T -> ボブ

Tの最新のnode_updateでは、cltv_expiry_delta=20fee=3000 msatが広告されていた。

簡単にするため、全ての中間ノードHiは固定の500 msat 手数料とcltv_expiry_delta=5を広告すると仮定する。

アリスは以下のtrampoline_onion_packetを作成する(簡単にするため暗号化は省略)

  • [1:0x08] (type)
  • [3:0xfde202] (length)
  • [1:version]
  • [33:public_key]
  • [79:trampoline_hop_payload] (payload for T)
    • [1:0x4e] (length)
    • [1:0x02] (type)
    • [1:0x21] (length)
    • [33:Bob_node_id]
    • [1:0x04] (type)
    • [1:0x03] (length)
    • [3:5000000] (amt_to_forward)
    • [1:0x06] (type)
    • [1:0x01] (length)
    • [1:25] (outoing_cltv_value)
    • [1:0x0a] (type)
    • [1:0x01] (length)
    • [1:0x00] (option_trampoline_routing)
    • [32:hmac] (0x00...00)
  • [593:filler]
  • [32:hmac]

アリスはTへの経路を見つけて、onion_packet内にtrampoline_onion_packetをラップして送信する(前の例を参照)。

Tはtrampoline_onion_packetを受け取り、ボブが支払先で、option_trampoline_routingをサポートしていないことを発見する。

Tはボブへの経路を見つける。

T -> H1 -> H2 -> ボブ

Tは以下のonion_packetを作成する(簡単にするため暗号化は省略)

  • [1:0x00] (version)
  • [33:public_key]
  • [65:hop_payload] (payload for H1)
    • [1:0x00] (realm)
    • [8:channel_from_H1_to_H2] (short_channel_id)
    • [8:5000500] (amt_to_forward)
    • [4:30] (outgoing_cltv_value)
    • [12:padding]
    • [32:hmac]
  • [65:hop_payload] (payload for H2)
    • [1:0x00] (realm)
    • [8:channel_from_H2_to_Bob] (short_channel_id)
    • [8:5000000] (amt_to_forward)
    • [4:25] (outgoing_cltv_value)
    • [12:padding]
    • [32:hmac]
  • [65:hop_payload] (payload for Bob)
    • [1:0x00] (realm)
    • [8:0x0000000000000000] (short_channel_id)
    • [8:5000000] (payment_amt)
    • [4:25] (final_cltv_expiry)
    • [12:padding]
    • [32:hmac] (0x00...00)
  • [1105:filler]
  • [32:hmac]

ボブはonion_packetを受信し、自分が支払いの受信者であることを知る(hmacが0x00...00であるため)。ボブはトランポリンルーティングが使われたことを知ること無く支払いを処理する。

効率的な支払いの経路は

Alice      T                   Bob
  |       ^ |                   ^
  |       | |                   |
  `-------' `---> H1 ---> H2 ---'
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment