6
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

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

Last updated at Posted at 2023-02-01

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

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

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

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

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

使い方

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

  • トランザクションのロック
  • 引き出し
  • 期間経過後の返金

準備

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の場合

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の場合

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);

ロック

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をおいて置かなければいけないのがちょっとイケてない。これは送信者と受信者の公開鍵とロックするブロック高から算出は可能、つまりロック期間さえ分かれば良いかも。(要検討

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)

返金

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

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

簡単なコア部コード解説

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

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 に関する詳細は以下

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

記事集

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

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

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

6
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?