Hashed Time-Locked Contract とは

# 概要

HTLC (Hashed Time-Locked Contract) とは、Block Chain 上に貸金庫のようなものを作成し、

1) 所定の Secret と A の持つ PrivateKey もしくは
2) 所定の日時経過後に B の持つ PrivateKey

のどちらかで、出金を行うことができるようにしたものである。

## 例
使用の例としては、Alice は Bob にとある商品を、0.55 coin で売却する契約をしたとする。

Alice としては、Bob の支払い余力を確認してから、受注処理を行いたいが、Bob は先払いではなく引き換えでの支払いを求めたとする。

Alice は、取引用のキーペアを作成し、その PubkeyHash を Bob に共有し、取引の期限日時 (例えば、2018-05-06 12:00 JST) を Bob と合意する。

Bob も、取引用のキーペアを作成し、またそれとは別に、Secret をランダムに作成して、その Hash を算出する。

Bob は、上記の４つのパラメーター

a) Bob の Secret から作成した Hash
b) Alice の　PubkeyHash
c) 取引の期限日時 (unixtime)
d) Bob の PubkeyHash

から、Contract のスクリプトを作成し、その ScriptHash のアドレスへ 0.55 coin の入金を行う。

Alice は、Bob からのスクリプトをレビューし、Block Chain 上で、該当アドレスへの入金を確認する。

1) 取引に問題がない場合、Bob は商品と引き換えに Secret を Alice へ通知する。Alice は、Secret と Alice の PrivateKey で出金を行い、代金の coin を取得する。

2) 取引が不調に終わった場合、Bob は、取引の期限日時以降に Bob の PrivateKey で払い戻しを行い、coin を回収する。


取引の期限日時は重要で、1) の取引は、期限日時以前に行われなければならない。(そうしないと、Bob が coin を回収してしまうかもしれない。)

Alice としては、取引に余裕を持ちたいので、長い期限を望み、Bob は、資金がロックされる期間を短くしたいので、短い期限を希望するだろう。

# 技術的な実装
では、Bitcoin ライクな暗号通貨システムで、技術的にこのような取引はどのように実現されているのだろうか。

Bitcoin ライクな暗号通貨では、coin の残高管理は、Block Chain 上に、「残高」とそれを引き出すための「問題」のペアの記録で行われている。

coin を引き出すには、その「問題」に対する「解答」を連結することで、新たな「残高」「問題」ペアを生成するとこで行われる。

「問題」に対する「解答」が正当なものかどうかを検証するのは、Forth ライクな言語で記述したプログラムコードである「問題」に対して「解答」に相当する入力データを与えて、「真」という結果が得られるかによって成されている。

もちろん、だれでも「解答」できる「問題」では coin の安全性を維持できないので、基本的に ECDSA キーペアによる署名検証が「問題」として用いられる。

「問題」の作成にはある程度の自由度があるため、工夫次第では、様々な Contract を実現することが可能であり、HTLC は、それらの形態の一つであるといえる。

現行の Bitcoin ライクシステムでは、「問題」を直接な形では記録せず、その Hash 値を求めて、それらを「アドレス」として使用している。


Bitcoin (testnet) で、具体的な取引例を検証してみよう。

## 1) の取引例

Block Chain 上の取引 (トランザクション) は、公開されており、改ざんや消去は実質的に不可能なものである。

testnet 上の coin は、財産的価値を持たないが、技術的な仕様は、mainnet とほぼ同等である。

「アドレス」2NF6SJbtj2VH5vuWxCLuP6D8HJqqs4LcZ1J
https://test-insight.bitpay.com/address/2NF6SJbtj2VH5vuWxCLuP6D8HJqqs4LcZ1J

### scriptPubKey
```
OP_HASH160 efa94de87a3c0f6eb3d1e4a90af0566a77f2f3e7 OP_EQUAL
```

「問題」に相当するスクリプトで、真ん中のハッシュ値 (efa94de87a3c0f6eb3d1e4a90af0566a77f2f3e7) がアドレスを表している。
このタイプの scriptPubKey は、scriptHash と認識され P2SH として、少し特殊な処理が行われる。

### scriptSig
```
3044022069b9d06aeb0fffe874eeec61d09abb71f1b5ef1f990dea177cabab41652c5d480220641a46ab6a507bb95fb4829fb95c835594d14842ef885189e2335d2466949eb3[ALL]
034449f818a0c797e702867a883e8bc22049c74a97fba68d070ae00ef002e5fad7
48a2d91c9b2bf38a0f2de269fb5ec13cae6a794bfdebebfc0b978748ad4831eb
1
63a9141e21aba284d434adc1fe47c50817567c256754ff8876a914431ae17932448f06bb9bde7bc615795531a395556704b06fee5ab17576a9146910d642f754a9c0d53c7ee393fc2756603724ae6888ac
```

「解答」に相当するスクリプトへの入力データで、このデータを与えた結果、「真」と出力されれば、トランザクションが成立する。(もっとも Block Chain には、「偽」となるトランザクションは、リジェクトされるので、記録されない。)
最後の値が、redeemScript であり、このスクリプトが追加処理として実行 (上述の少し特殊な処理) される。このスクリプトのハッシュ値が、アドレスになる。

redeemScript を、

http://chainquery.com/bitcoin-api/decodescript

などで、ディスアセンブルすると、以下のような結果が得られる。

### redeemScriptASM
```
OP_IF
  OP_HASH160 1e21aba284d434adc1fe47c50817567c256754ff OP_EQUALVERIFY OP_DUP OP_HASH160 431ae17932448f06bb9bde7bc615795531a39555
OP_ELSE
  1525575600 OP_CHECKLOCKTIMEVERIFY OP_DROP OP_DUP OP_HASH160 6910d642f754a9c0d53c7ee393fc2756603724ae
OP_ENDIF
OP_EQUALVERIFY OP_CHECKSIG
```

命令語以外に、4つのパラメーターが確認できるが、これが上記で説明した4つのパラメーターに相当する。

さて、入力の後ろから２番目の値が、1 なので OP_IF - OF_ELSE 間の IF 節が処理の対象となる。

前半のパートが、Secret (後ろから3番目の値) の　hash をチェックしている処理で、

```
OP_HASH160 1e21aba284d434adc1fe47c50817567c256754ff OP_EQUALVERIFY
```

後半のパートが、公開鍵の hash チェックと署名の検証処理 (残りの2つの値を使う) に当たる。(署名データの生成には、PrivateKey が必要になる。)

```
OP_DUP OP_HASH160 431ae17932448f06bb9bde7bc615795531a39555
OP_EQUALVERIFY OP_CHECKSIG
```

## 2) の取引例

「アドレス」2N1ScVYdByFBdvmsom8LLEMhXZSxALoZwpJ
https://test-insight.bitpay.com/address/2N1ScVYdByFBdvmsom8LLEMhXZSxALoZwpJ

### scriptPubKey
```
OP_HASH160 59e85e2009ad5f28009b2dba2e53ce6b1a12ba53 OP_EQUAL
```

### scriptSig
```
3045022100d910215a8a5bda6f53f993049913a6905398bcffa4c460295905280bceb833d002203a1efb984e192ffbcfe03b0ae9e3f79a46b8123a500355d233587594d5bdb9c0[ALL]
0339e55ab358d5994a50c1658e5b60c44b638ad13f5b46dcf296d1c73b524a9904
0
63a914e4d6537a296174e57c65718939387970ae868a2e8876a914af2ba9b16fc0feda1ef286769355a2aa5cedc55b6704b06fee5ab17576a9147aea93ab9594656ff4a7eaf3cf391c513a59e4086888ac
```

### redeemScriptASM
```
OP_IF
  OP_HASH160 e4d6537a296174e57c65718939387970ae868a2e OP_EQUALVERIFY OP_DUP OP_HASH160 af2ba9b16fc0feda1ef286769355a2aa5cedc55b
OP_ELSE
  1525575600 OP_CHECKLOCKTIMEVERIFY OP_DROP OP_DUP OP_HASH160 7aea93ab9594656ff4a7eaf3cf391c513a59e408
OP_ENDIF
OP_EQUALVERIFY OP_CHECKSIG
```

こちらでは、後ろから2番目の値が、0 なので OP_ELSE - OP_ENDIF 間の ELSE 節が処理の対象になる。

前半のパートで、処理時刻のチェックを行っている。(1525575600 は unixtime で 2018-05-06T12:00:00+09:00)

```
1525575600 OP_CHECKLOCKTIMEVERIFY OP_DROP
```

同様に、後半のパートが、公開鍵の hash チェックと署名の検証処理 (残りの2つの値を使う) に当たる。

```
OP_DUP OP_HASH160 7aea93ab9594656ff4a7eaf3cf391c513a59e408
OP_EQUALVERIFY OP_CHECKSIG
```