LoginSignup
1
1

More than 5 years have passed since last update.

DLCのTransaction

Last updated at Posted at 2018-11-05

はじめに

Discreet Log Contracts(以下、DLC)は、Bitcoinにおける未来予測市場で使う事の出来る技術です。
2017年8月にTadgeによって発表されました、DLCはLightningとほぼ同じ仕組みで動きます。

最近、Lightningが実用化されつつあり、ワークショップなども開催されているようです。
Lightningを理解していれば案外簡単に利用する事が可能であると思います。
ここでは、実際に使用可能なDLCのTransactionについて説明します。
また、実際にregtest環境で演習できるようにしてあります。

簡単な概要

アクターは、大きくユーザ(User)とオラクル(Oracle)が必要です。
ユーザ(User)は、アリス(Alice)とボブ(Bob)とします。
オラクル(Oracle)は、オリビア(Olivia)とします。

これらの、ユーザ同士のマッチングはすでにできているものとします。
(ただし、お互いの素性を知る必要はありません。)

オラクル(Oracle)はメッセージから契約Rポイント(Committed R-point)を計算可能にする為、オラクル自身の公開鍵(楕円曲線の点)と、未来の契約に対するナンス(Nonce、楕円曲線の点)を公開しています。
※:ナンスは、契約毎に異なる必要があります。

アリスとボブは、未来のメッセージに対して契約を行います。
ファンド(Fund Transaction)から、契約実行取引(Contract Execution Transactions , CET)をメッセージ数分作成して、それらの署名をお互いに交換します。
(CETは、アリスとボブとで非対称なTransactionになります。)

未来のメッセージが確定したら、オラクル(Oracle)が確定したメッセージに対して署名値を公開します。
アリスとボブのどちらかが、その署名値を使用して、メッセージに対応した契約実行取引(CET)を送信します。
さらに、契約実行取引(CET)から自身のアドレス(P2WPKH)に送って完了となります。

契約例(DLC Sample)

ここでの例として、オラクルは未来(N日後)の天気について、晴(Fine)か雨(Rain)に署名して公開します。
アリスとボブは、お互い1BTCづつ出しあい、晴(Fine)であればアリスが1.5BTCボブが0.5BTC
雨(Rain)であれば、アリスが0.5BTCボブが1.5BTCとする契約を結ぶ事とします。

オラクル(Oracle)

オラクル(Oracle)は、公開鍵(自身の公開鍵と未来に対する公開鍵の2つ以上)を公開し
未来のメッセージが確定したら、署名値を公開します。
各ユーザは、公開されている公開鍵から各メッセージに対するナンスを計算します。

\begin{align*}
P_o = x_oG & \quad \text{: Oracleの公開鍵} \\
R_n = k_nG & \quad \text{: 未来のナンス} \\
\{ m_{\text{Fine}} , m_{\text{Rain}} \} & \quad \text{: メッセージ}\\
\end{align*}

契約Rポイント(Committed R-point)の求め方

オラクルが公開している情報から、ユーザ(アリスとボブ)が作成し、契約に利用します

\begin{align*}
& R_{\text{Fine}} =R_n + h(R_n\ ||\ m_{\text{Fine}})P_o \\
& R_{\text{Rain}} =R_n + h(R_n\ ||\ m_{\text{Rain}})P_o \\
\end{align*}

署名値の求め方

未来のメッセージが確定したら、以下のどちらかの署名値を計算して公開します。
(晴であれば上、雨であれば下、一方のみ公開)

\begin{align*}
& s_{\text{Fine}} =k_n + h(R_n\ ||\ m_{\text{Fine}})x_o \\
& s_{\text{Rain}} =k_n + h(R_n\ ||\ m_{\text{Rain}})x_o \\
\end{align*}

DLCの手順

アリスとボブの公開鍵を以下とします。

\begin{align*}
P_a = x_aG & \quad \text{: アリスの秘密鍵と公開鍵} \\
P_b = x_bG & \quad \text{: ボブの秘密鍵と公開鍵} \\
\end{align*}

ファンド

アリスとボブはファンドを作成します。
BitcoinのTransactionは以下のとおりです。
このTransactionは、署名値を設定する前にtxidが決定されなければならないので、
Inputsに設定されるUTXOはすべて、Segwitアドレスである必要があります。

Fund_Transaction
Version  0x02000000
Inputs   <Alice's UTXO 1>
         <Alice's UTXO : (option)>
         <Alice's UTXO n (option)>}
         <Bob's UTXO 1>
         <Bob's UTXO : (option)>
         <Bob's UTXO m (option)>
Outputs  <Fund Script (P2WSH)>
         <Alice's change (P2WPKH : option)>
         <Bob's change (P2WPKH : option)>
Locktime 0x00000000

FundのScriptは以下のとおりです。

Fund_Script
OP_2
  <Alice's public key>
  <Bob's public key>
OP_2
OP_CHECKMULTISIG

契約実行取引(Contract Execution Transactions , CET)

アリスとボブは、メッセージ分の署名値を作成しお互いに交換します。
今回の例だと、2つの署名値を交換します。
ここで、オリビアが公開している値から算出した契約Rポイントを使用します。

アリスが署名し、署名値をボブに渡す為のTransaction

メッセージ:晴(アリス⇒ボブ)

Contract_Execution_Transactions
Version  0x02000000
Input    <Fund Output (Fund Transaction : 0)>
Outputs  <CET Script (P2WSH)>                : 0.5 BTC
         <Alice's public key (P2WPKH)>       : 1.5 BTC
Locktime 0x00000000
CET_Script
OP_1
OP_EQUAL
OP_IF
  <Bob's public key> + <R_{Fine}>
OP_ELSE
  144(Delay)
  OP_CHECKSEQUENCEVERIFY
  OP_DROP
  <Alice's public key>
OP_ENDIF
OP_CHECKSIG

メッセージ:雨(アリス⇒ボブ)

Contract_Execution_Transactions
Version  0x02000000
Input    <Fund Output (Fund Transaction : 0)>
Outputs  <CET Script (P2WSH)>                : 1.5 BTC
         <Alice's public key (P2WPKH)>       : 0.5 BTC
Locktime 0x00000000
CET_Script
OP_1
OP_EQUAL
OP_IF
  <Bob's public key> + <R_{Rain}>
OP_ELSE
  144(Delay)
  OP_CHECKSEQUENCEVERIFY
  OP_DROP
  <Alice's public key>
OP_ENDIF
OP_CHECKSIG

ボブが署名し、署名値をボブに渡す為のTransaction

メッセージ:晴(ボブ⇒アリス)

Contract_Execution_Transactions
Version  0x02000000
Input    <Fund Output (Fund Transaction : 0)>
Outputs  <CET Script (P2WSH)>                : 0.5 BTC
         <Bob's public key (P2WPKH)>         : 1.5 BTC
Locktime 0x00000000
CET_Script
OP_1
OP_EQUAL
OP_IF
  <Alice's public key> + <R_{Fine}>
OP_ELSE
  144(Delay)
  OP_CHECKSEQUENCEVERIFY
  OP_DROP
  <Bob's public key>
OP_ENDIF
OP_CHECKSIG

メッセージ:雨(ボブ⇒アリス)

Contract_Execution_Transactions
Version  0x02000000
Input    <Fund Output (Fund Transaction : 0)>
Outputs  <CET Script (P2WSH)>                : 1.5 BTC
         <Bob's public key (P2WPKH)>         : 0.5 BTC
Locktime 0x00000000
CET_Script
OP_1
OP_EQUAL
OP_IF
  <Alice's public key> + <R_{Rain}>
OP_ELSE
  144(Delay)
  OP_CHECKSEQUENCEVERIFY
  OP_DROP
  <Bob's public key>
OP_ENDIF
OP_CHECKSIG

契約実行(Contract Execution)

未来のメッセージが晴(Fine)であったとします。
また、アリスが契約を実行する事とします。
アリスが送信するCETは以下のとおりです。

Contract_Execution_Transactions
Version  0x02000000
Input    <Fund Output (Fund Transaction : 0)>
Outputs  <CET Script (P2WSH)>                : 0.5 BTC
         <Bob's public key (P2WPKH)>         : 1.5 BTC
Locktime 0x00000000
CET_Script
OP_1
OP_EQUAL
OP_IF
  <Alice's public key> + <R_{Fine}>
OP_ELSE
  144(Delay)
  OP_CHECKSEQUENCEVERIFY
  OP_DROP
  <Bob's public key>
OP_ENDIF
OP_CHECKSIG

不正防止用にScriptが組まれているので、遅延(Delay)時間以内(ここでは、144ブロック)に
自身のアドレスに送る必要があります。

Settlement_Transactions
Version  0x02000000
Input    <CET Output (Contract Execution Transactions : 0)>
Outputs  <Alice's public key (P2WPKH)>                      : 1.5-fee BTC
Locktime 0x00000000

合成された公開鍵に対応する、秘密鍵は秘密鍵の和で求めます。
したがって、ここでの秘密鍵は以下となります。

\begin{align*}
x_{a+Fine} = x_a + s_{Fine}
\end{align*}

これによって、計算した署名値(<signature>)を使用してwitnessを設定します。

witnesses
witness[0] <signature>
witness[1] 01
witness[2] <CET Script>

署名値は、合成された秘密鍵を使うので、遅延(Delay)はあまり重要ではありません。
決済取引(Settlement Transactions)が送信するまでの時間が稼げれば良いのです。

演習(Exercise)

Bitcoinをregtestで起動します。

bitcoind -regtest -printtoconsole

Transactionを作成する為に、DLC Transactionをブラウザで開いてください。

はじめてregtestで起動する場合、CSVを有効にする為、432ブロック進めてください。

bitcoin-cli -regtest generate 432

ファンド

ファンドのInputは全てSegwitアドレスである必要がある為、「Preparation」のコマンドを実行してください。
sendtoaddressコマンドにより、txidが2つ出てくるので、voutがどちらか調べます。

bitcoin-cli -regtest getrawtransaction <txid of Alice> 1
bitcoin-cli -regtest getrawtransaction <txid of Bob> 1

txidの順番どおり、Alice、BobのUTXOとなります。
「UTXOs of Alice and Bob」に、txididxを設定します。

「ファンド作成」⇒「契約実行取引の署名交換」⇒「ファンド送信」の流れになります。

「Fund Transaction (with signature)」のhexstringは署名がついていますので確認してみてください。

bitcoin-cli -regtest decoderawtransaction <hexstring>

outputsの0番目にファンドの出力があります。
ファンドを送信します。

bitcoin-cli -regtest sendrawtransaction <hexstring>
bitcoin-cli -regtest generate 1

送信ができたら、txidが出力されます。
※:エラーが出る場合は、UTXOsの設定が間違っている可能性があるのでもう一度確認してみて下さい。

これがブロックに入ったら契約完了となり、Oliviaが署名値を出すまで待つ事になります。
AliceとBobのどちらがCETを送るか、またメッセージは、晴(Fine)と雨(Rain)のどっちであるかを選択します。
CETのhexstringがありますので、確認してみてください。

bitcoin-cli -regtest decoderawtransaction <hexstring>

outputsの0番目が「witness_v0_scripthash」、1番目が「witness_v0_keyhash」となります。
1番目は、相手側のアドレスになっています。
inputsはファンドだけですが、txinwitnessの最後はScriptなので内容を確認してみます。
2-of-2のMultisigである事がわかります。

bitcoin-cli -regtest decodescript <hexstring of script>

CETを送信します。

bitcoin-cli -regtest sendrawtransaction <hexstring>
bitcoin-cli -regtest generate 1

次に、CETから自身のWallet送信します。

bitcoin-cli -regtest decoderawtransaction <hexstring>

outputsの0番目が「witness_v0_keyhash」で、自身側のアドレスになっています。
inputsはCETだけです、txinwitnessの最後はScriptなので内容を確認してみます。
CET Scriptである事がわかります。

bitcoin-cli -regtest decodescript <hexstring of script>

送信します。

bitcoin-cli -regtest sendrawtransaction <hexstring>
bitcoin-cli -regtest generate 1

これで、DLCが完了します。

最後に

基本的なTransactionはこれで終わりですが、実際はOracleと連絡がとれなくなった場合を考慮して、ファンドからお互いに払戻(Refund)トランザクションが必要になります。
払戻トランザクションは、ファンドからお互いに払戻すトランザクションですが、LockTimeをOracleが公表する時間より十分後に設定する必要があります。

1
1
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
1
1