BitcoinやモナコインのHTLC<アトミックスワップ可能>

bitcoin＆モナコインでHTLCによるアトミックスワップを行うためのPoCを作成しました。

これにより現在、<b>SymbolやSymbolのコピーチェーン。Ethereumを始めとするEVM互換性のあるチェーンとそれらのERC20,ERC721。さらにBitcoinとBitcoinのコピーチェーンでのアトミックスワップが可能</b>となります。

以下は今回作成したビットコイン系のみのリポジトリ。

https://github.com/0x070696E65/bitcoin-htlc

それ以外は下記、ふぁーさん作成のAtmicPortで使えます。このあとAtomicPortにもビットコイン系が追加されると思います。なお、HTLCのハッシュ関数はHash256（Sha256の二重掛け）です。理由はSymbolのHTLCに対応するため。

https://github.com/ymuichiro/atomic-port

ちなみにEVM互換性のあるチェーンでのHTLCは以下をご覧ください。書きなぐりなので読みにくい。

https://qiita.com/Toshi_ma/items/59938059cee3c2bda0eb

# 使い方
基本的にサンプルは`sample.ts`にあります。
できることは３つ。それぞれBitcoin testnetとMona testnetで利用可能です。もちろん他のビットコインのコピーチェーンや各メインネットも少し触れば対応可能です。

<ul>
<li>トランザクションのロック</li>
<li>引き出し</li>
<li>期間経過後の返金</li>
</ul>

## 準備
```typescript
import * as bitcoin from 'bitcoinjs-lib';
import { btcSwap } from './btcSwap';
import * as ecc from 'tiny-secp256k1';
import ECPairFactory from 'ecpair';

const ECPair = ECPairFactory(ecc);
const aliceWif = "cNaEjitvA19JZxWAFyCFMsm16TvGEmVAW3AkPnVr8E9vgwdZWMGV"
const bobWif = "cQBwuzEBYQrbWKFZZFpgitRpdDDxUrT1nzvhDWhxMmFtWdRnrCSm"
```

### BTCの場合
```typescript
import BitCoin from "./bitcoin"
const network = bitcoin.networks.testnet
const swap = new btcSwap(new BitCoin());
const Alice = ECPair.fromWIF(aliceWif, network);
const Bob = ECPair.fromWIF(bobWif, network);
```

### Monaの場合
```typescript
const coininfo = require('coininfo')
import Mona from "./mona"
const network = coininfo.monacoin.test.toBitcoinJS()
const swap = new btcSwap(new Mona());
const Alice = ECPair.fromWIF(aliceWif, network);
const Bob = ECPair.fromWIF(bobWif, network);
```

## ロック
```typescript
const amount = 5000;
const fee = 1800;
const lockTime = 2;
swap.lock(lockTime, Alice, Bob, amount, fee)
```

ロック送金する金額と手数料をビットコインの場合はSatoshi単位で。Monaの場合は * 100000000(1.1Monaなら110000000)
あとロックする期間をブロック単位で指定するだけ。
コンソールにいくつかの大切な情報が表示されるので控える。（以下にあるものは全部必要）
```
proof: fa86c053566962425bafc51efe57452cdcf3b5766033de95986103376e3*****
secret:19aee0e9f5916cbd2a96e4707ae851b3aecd3a094af1261a10c382fc37a*****
Swap contract (witness script):
aa2019aee0e9f5916cbd2a96e4707ae851b3aecd3a094af1261a10c382fc37ad56b087632103745c9aceb84dcdeddf2c3cdc1edb0b0b5af2f9bf85612d73fa6394758eaee35d67036ae724b17521027efbabf425077cdbceb73f6681c7ebe2ade74a65ea57ebcf0c42364d3822c59068ac
P2WSH swap smart contract address:
tb1qtd8z86gv0e68gdclfrfkuyjk9v6az2m8q2d2fd9zhlv553uqcrqq7x6f47
Transaction hash: 29f8faa916b360e043d4ae5efef824509de945e0147b519fef2f7dde0f967a3d
```

この中ではproofがロック解除（引き出し）に使用するため公開してはいけない。ほかは問題ない。

## 引き出し

引き出しはBobによって行う。
ロック時の情報を使う。Proofは非公開なのでAliceしか知らないのは当然だが、WitnessScriptをおいて置かなければいけないのがちょっとイケてない。これは送信者と受信者の公開鍵とロックするブロック高から算出は可能、つまりロック期間さえ分かれば良いかも。（要検討

```typescript
const txId = "TRANSACTION_HASH"
const contractAddress = "P2WSH_CONTRACT_ADDRESS"
const witnessScript = "SWAP_CONTRACT"
const proof = "PROOF"
const fee = 1700;
swap.withdraw(txId, contractAddress, witnessScript, Bob, proof, fee)
```

## 返金
ロック期間を過ぎた場合に送信者への返金。期間を過ぎていなければエラーになる。

```typescript
const txId = "TRANSACTION_HASH"
const contractAddress = "P2WSH_CONTRACT_ADDRESS"
const witnessScript = "SWAP_CONTRACT"
const fee = 1700;
swap.refund(txId, contractAddress, witnessScript, Alice, fee)
```

# 簡単なコア部コード解説

スマコン（と呼ぶのかも分からないが）部のコードは以下。

```typescript
function swapContractGenerator(receiverPublicKey: Buffer, userRefundPublicKey: Buffer, PAYMENT_HASH: string, timelock: number) {
    return bitcoin.script.fromASM(
        `
        OP_HASH256
        ${PAYMENT_HASH}
        OP_EQUAL
        OP_IF
        ${receiverPublicKey.toString('hex')}
        OP_ELSE
        ${bitcoin.script.number.encode(timelock).toString('hex')}
        OP_CHECKLOCKTIMEVERIFY
        OP_DROP
        ${userRefundPublicKey.toString('hex')}
        OP_ENDIF
        OP_CHECKSIG
        `
        .trim()
        .replace(/\s+/g, ' '),
    );
}
```

※BitCoinScript
https://en.bitcoin.it/wiki/Script

引き出しor返金時にPreImageをInputに加える。PreImageをHash256によりハッシュ化しPAYMENT_HASHを比較。trueなら受取り手の公開鍵をチェックする。

返金の場合は空のPreimageを渡し、falseに向かう。さらにロック期間を超えているか`OP_CHECKLOCKTIMEVERIFY`によって比較する。返金の場合は送金者の公開鍵と比較し返金する。

`OP_CHECKLOCKTIMEVERIFY` に関する詳細は以下

https://github.com/bitcoin/bips/blob/master/bip-0065.mediawiki

https://bitcoinjs-guide.bitcoin-studio.com/bitcoinjs-guide/v5/part-three-pay-to-script-hash/timelocks/readme

※HTLCによる以下アトミックスワップのスマコン箇所参考

https://github.com/bitcoinjs/bitcoinjs-lib/issues/945

https://github.com/hyle-team/atomic_swap_example/blob/main/lib/swap_btc_helper.js#L91

# 記事集
タブ開きすぎて嫌なので主に自分用メモ。（だけど誰かの役に立つかもなので

BitCoin Script
https://en.bitcoin.it/wiki/Script

Submarine Swap - On-chain to Off-chain
https://bitcoinjs-guide.bitcoin-studio.com/bitcoinjs-guide/v5/part-three-pay-to-script-hash/submarine_swaps/swap_on2off_p2wsh.html

CLTV
https://github.com/bitcoinjs/bitcoinjs-lib/blob/master/test/integration/cltv.spec.ts

BIP199 HTLC contract support (for AtomicSwap) #945
https://github.com/bitcoinjs/bitcoinjs-lib/issues/945

Mempool API　reference
https://mempool.space/testnet/docs/api/rest

Mempool Explorer
https://mempool.space/testnet

Alice
https://mempool.space/testnet/address/tb1qq0en3c8cnrh5pu0tvu6dc8665u4yzc0cvv2rwf

OP_CHECKLOCKTIMEVERIFY
https://github.com/bitcoin/bips/blob/master/bip-0065.mediawiki

https://bitcoinjs-guide.bitcoin-studio.com/bitcoinjs-guide/v5/part-three-pay-to-script-hash/timelocks/readme

## Mona

faucet
https://faucet.torifuku-kaiou.tokyo/

wallet
https://testnet-monapalette.komikikaku.com/

Explorer
https://testnet.mpchain.info/

Api reference
https://testnet.mpchain.info/doc

UTXO 取得
https://monaledge.com/article/421
※`search_raw_transactions`ではなく`get_unspent_txouts`があったのでそちらがBetter