# LNとL2の高速なアトミックスワップおよび条件付き送金のWhitePaper
## 背景
本ネットワークは処理コストの安さやデータの秘匿化だけではなく、Lightning Networkを利用したストレージ・Lightning Network上のBitcoinで手数料を支払いできる点も大きな特徴であり、Bitcoin利用者に対しても利用が容易であるという利点が存在する。
ただし、Lightning Network上の資産しか保有せず、Ethereum上の資産を保有していないユーザーは本ネットワーク上に資産を持ち込む手段がないためDeFiなどの資産の運用やトレードなどを行うことが非常に難しい。
そこで本章ではLightning Networkと本ネットワークとのアトミックスワップによる資産の交換を考える。これによりLightning Network上の資産しか保有していないユーザーであっても本ネットワーク上で資産を持ち、様々なアプリケーションに参加することができる。
その際、IntMax1.0では標準で搭載されているERC20送金機能に加えて、一定の条件下で送金を許可する仕組みである「条件付き送金」を使用することでトラストレスなアトミックスワップを実現する。
## 条件付き送金の仕様
### 条件付き送金の概要
条件付き送金は2つのトランザクションから成り立っており、それぞれ支払いTxと受け取りTxと呼称する。
#### 支払いTx
支払いTxは資金の受け取りに必要な条件を指定し、支払う予定の資産を一時的にロックする。今回指定する条件は
1. 指定したLightning Network側のInvoiceのPreImageを知っていて(すでにLightning Networkでの送金が完了している)、指定したアドレスからの受け取りTxであること。
PreImageはLightning Networkでの支払いの際のルートも知っているため、受け取れるアドレスは予め指定している必要がある。
2. 支払いTxを送ったアドレスと同じ秘密鍵から生成されるアドレスからの受け取りTxであり、かつネットワークのブロック高が指定されたブロック高より大きいこと。
この場合、支払いTxの送信者にトークンが払い戻されるため実質的に送金のキャンセルに該当する。
なおブロック高について条件を設けている理由としてLightning Network上のBTCを受け取った直後にキャンセルすることで相手方がL2上の資金を受け取れないという支払いTx送信者による攻撃を防ぐためである。
#### 受け取りTx
受け取りTxでは支払いTxのTxIdをInputにして上記で指定された条件を満たすTxを発行する。この際、条件を満たしていたら支払いTxでロックされた資金を入手することができる。
この際、OneTimeAddressを刻むSMTには受け取り側だけではなく、支払い側の新たなOneTimeAddressが刻まれる。このOneTimeAddressは支払いTx時に刻まれたOneTimeAddressからだれでも生成できるものであり、このOneTimeAddressが刻まれているかどうかによって支払いTxが消費されているか検証し、二重支払いを防ぐ。
```mermaid
sequenceDiagram
actor S as Sender
participant I as Intmax Network
actor R as Receiver
autonumber
S --> I : Lock Token via Conditional Tx
I --> I : Comsume OneTimeAddress Hash(Sender Pub + nonce)
R --> I : Submit Tx with Sender's Proof
I --> I : Check if Receiver's Tx fullfills Sender's condition
S --> R : Send Sender's Token
I --> S : Send Receipt with OneTimeAddress Hash(Sender Pub + nonce + Suffix)
```
### 支払いTxの技術的仕様
条件付き送金では、まず支払い側が空のアドレスに送金する支払いTxを発行する(この際、資金はLockされる)。
このとき、OneTimeAddressである```Hash(Privkey + nonce)```を消費する。
支払い側は通常のProofにくわえて
$$ Condtions = (Target Block Height, Target OneTimeAddress, PreImage Hash) $$<br />
$$ payerSignature = Sig(Hash(assetID + amount + Conditions), payerPrivkey) $$<br />
$$C_{verifySignedPayment}(txHash, payerOneTimeAddress, Condtions, oldState, newState),\\ (payerPublicKey, payerSignature)) \\ \to \{true,false\}$$<br />
$$zkProve((txHash, payerOneTimeAddress, Conditions, oldState, newState), \\ (payerPublicKey, payerSignature), C_{verifySignedPayment}) \\ \to zkProof_{Payer}$$<br />
となり条件を満たすことを確認する。
**Proofの各種パラメータの説明**
|name|説明|
| :--: | :-- |
|Target Block Height|そのTxが取り込まれる予定,もしくはその次のブロック高|
|Target OneTimeAddress|受取人のOneTimeAddress|
|PreImage Hash|InvoiceのPreImageのハッシュ|
|payerSignature|送金者の署名。条件付き送金の条件と送金内容を署名する|
|assetId|送金対象となるトークンに一意につけられたID|
|$$C_{verifySignedPayment}$$|この回路は <br />1. payerSignatureが正しいことを公開鍵無しで判定する<br />2. このTxが取り込まれた後、Payerの残高がamount分減っていること<br />の2つを判定する|
|newState, oldState|Tx前後のステート。回路で真贋を判定する|
という条件付き支払いの条件や送金の内容についての署名を検証するZkProofを提出する。
### 受け取りTxの技術的仕様
受け取り側は受け取りTxを用意し、このTxは支払いTxをInputにしてTxを実行する。
Inputにした支払いTxのProofの条件が、受け取りTxによって満たされていることが確認されれば、受け取りTxのオーナーに対して支払いが行われる。
このとき、送金Txを送付したPayer側のOneTimeAddressである```Hash(Hash(Payer's Priv key + nonce) + suffix)```を消費する。このOneTimeAddressはnonceは同じであるものの、Lock時とは異なるOneTimeAddressであり、衝突しない。
(そのため、MarketMakerは板を出している間に他のTxを打つことが出来、ユーザビリティの向上に寄与する)
また、次のOneTimeAddressとも衝突しないのでMakerの他Txには影響されない。
このとき受け取りTxが提出するProofは
$$ receiverSignature = Sig(Hash(receiveTxHash + payerOneTimeAddress), receiverPrivkey) $$<br />
$$C_{verifyReceive}((receiveTxhash, receiverOneTimeAddress, receiverSignature, \\ payerEntryAddress, payerFinishAddress, preimage, payerTxData, payerTxHash,\\ oldState, newState, addressSMTRoot, addressSMTSiblings), \\ (receiverPublicKey)) \to \{true,false\}$$<br />
$$zkProve((receiveTxhash, receiverOneTimeAddress, receiverSignature, \\ payerEntryAddress, payerFinishAddress, preimage, payerTxData, payerTxHash,\\ oldState, newState, addressSMTRoot, addressSMTSiblings), (receiverPublicKey), C_{verifyReceive}) \\ \to zkProof_{Receiver}$$<br />
### Proofの各種パラメータの説明
|name|説明|
| :--: | :-- |
|receiverSignature|受け取りTxを提出する際の署名。受け取りたい条件付き送金のoneTimeAddressを含んでいる|
|receiveTxHash|受け取りTxの内容をハッシュしたもの|
|payerEntryAddress|送金Txを作成する際に送金側が使用したOneTimeAddress|
|payerFinishAddress|送金Txを利用後に消費されるOneTimeAddress。PayerEntryAddressから生成可能|
|$$C_{verifyReceive}$$|この回路は<br /> 1. receiverSignatureが正しいことを公開鍵を明かさずに証明する<br /> 2. payerTxDataで指定されたInvoice HashとPreimageが同一であること<br /> 3. payerTxDataで指定されたOneTimeAddress、もしくはそれと同根のアドレスからのTxであること<br />4. payerTxDataとpayerEntryAddressからPayerTxHashが導けること、payerEntryAddressからpayerFinishAddress導けることを証明する<br />4.newStateがoldStateから条件付き送金を達成した状態になっていることを証明する<br />5.payerEntryAddressとpayerTxHashの組がSMTに存在すること<br/>の5点を検証する|
|preimage|InvoiceのPreimage|
|payerEntryAddress|支払いTxで利用されたOneTimeAddress|
|payerFinishAddress|受け取りTxが実行されると消費され、OneTimeAddress SMTに記録されるOneTimeAddress。payerEntryAddressから誰でも導出可能である必要がある|
|payerTxData|送金TxのtxData|
|addressSMTRoot|oneTimeAddressのRoot|
|addressSMTSiblings|計算に必要なsiblings|
また、このときOneTimeAddressのSMTでは以下の2点が証明される
1. 支払いTxを提出したときのOneTimeAddress(payerEntryAddress)は使用されていること
2. 支払いTxの完了OneTimeAddress(payerFinishAddress)が使用されていないこと
### キャンセルTxの技術的仕様
送金キャンセルの場合はキャンセルTxを提出したアドレスが送金Txを提出したアドレスと同じ秘密鍵から生成できることを証明すれば良い。
したがって以下のProofを提出する
$$ cancelSignature = Sig((calcelTxHash+ payerOneTimeAddress), privkey) $$<br />
$$ C_{verifyCancel}((oneTimeAddress, payerTxData, payerTxHash, addressSMTRoot, addressSMTSiblings, oldState, newState, currentBlockHeight), \\(Publickey, nonce)) $$ <br />
$$ zkProve((oneTimeAddress, payerTxData, payerTxHash, addressSMTRoot, addressSMTSiblings, oldState, newState, currentBlockHeight), \\
(publickey, nonce), C_{verifyCancel}) \to zkProof_{Calcel} $$
$$
### Proofの各種パラメータの説明
|name|説明|
| :--: | :-- |
|CancelSignature|キャンセルTxの署名。送金TxのOneTimeAddressを含む|
| Current Block Height|現在のブロック高。|
|$$ C_{verifyCancel}$$|この回路は<br />1. cancelSignatureが正しいことを公開鍵を明かさずに証明する<br />2. 送金TxのCalcelできる送金者のOneTimeAddressと今回のOneTimeAddressが同じ秘密鍵から生成できることを証明する<br />3. 現在のブロック高が支払いTxで指定したブロック高より大きいことを証明する|
## 条件付き送金を利用したLN <=> IntMax間のスワップ
上記の条件付き送金を利用してLightning NetworkとIntmax 1.0ネットワーク間のスワップの仕組みを説明する。
今回はマーケットメイカーがL2上の資産を支払い、LN上のBTCを受け取ることを考える。
1. マーケットメイカーはL2資産のBTC建ての価格を提示し、テイカーはそれに同意する場合自身のアドレスと取引金額を渡す
2. マーケットメイカーはInvoiceを作成してテイカーに渡す
3. 同時にマーケットメイカーは受け取ったアドレスを受取人として指定する支払いTxを生成し、ネットワークに提出する
4. テイカーは取り込まれた支払いTxとInvoiceが正しいことを確認する
5. テイカーはLightning Network支払いを行う
6. マーケットメイカーは受取時にPreimageをテイカーにわたす
7. PreImageを利用して受け取りTxを提出する
8. L2上の資産を受け取る
```mermaid
sequenceDiagram
actor S as Sender
participant I as Intmax Network
actor R as Receiver
autonumber
S --> R : Send L2 Token Price in BTC
R --> S : Send Taker's Address
S --> R : Send Invoice
S --> I : Submit Payment Tx
R --> I : Comfirm Payment Tx
R --> S : Pay BTC by LN
S --> R : Send Preimage
R --> I : Submit Receive Tx with Preimage
I --> R : Transfer L2 Token
```
### スワップの速度に関する懸念
上記のステップ3において受け取りTxをネットワークに提出する際、テイカーはネットワークにトランザクションが取り込まれることを待つ必要がある。IntMaxネットワークがL1チェーンに対してPre commitする間隔を考慮するとこの待ち時間はユーザービリティに大きな悪影響を及ぼす可能性が高い。
とはいえ、マーケットメイカーとオペレーターが結託していて支払いTxが取り込まれない可能性などテイカーが不利益を被る恐れがある。
次節では取引高が少額のときにOperatorに取引成立の責任をもたせることで実質的に0 confirmationでの取引成立を目指す仕組みを説明する。
## 高速化のためのOperator署名
支払いTxをマーケットメイカーが提出する際にOperatorに対して特定のブロック高までに支払いTxをネットワークに取り込むことを確約する署名を提出させる。
$$OPSIG = Signature(\\Hash(Receiver L1 Address, Payment TxHash), \\Operator Privkey)$$
もし、取り込まれていない場合は、手数料支払にも利用されるClaim用のコントラクトにその署名を提出することでOperatorのデポジットを入手することができる。
この仕様のメリットとしては、この署名はL2は全く関与しないことがあげられる。
また、オペレーターが受け取りTxの取り込みを約束するものなので、支払側も安心して次のTxを打つことができる。もちろん受け取り側も支払いTxがネットワークに乗ることを所与として考えられるため、安心して0confできる。
```mermaid
sequenceDiagram
actor S as Sender
actor O as Operator
participant I as Intmax Network
actor R as Receiver
autonumber
S --> R : Send L2 Token Price in BTC
R --> S : Send Taker's Address
S --> O : Send Conditional Payment Tx with Taker's address
O --> R : Send Operator's signature
O --> I : Submit Payment Tx until target block height
S --> R : Send Invoice
R --> I : Comfirm Maker's Tx
R --> S : Pay BTC by LN
S --> R : send Preimage
R --> O : Submit Receive Tx with Preimage
O --> I : Submit Receive Tx
I --> R : Transfer L2 Token
```
###### tags: `Yellow paper`