BIP16 : P2SH の仕組み

Bitflyerなどの取引所に送金するときに3から始まるアドレスを見たことはありますか? それらはScript Hashアドレスと呼ばれるアドレスです。 このScript HashアドレスはBIIP16で提案されている仕組みなのですが、実際どのような仕組みで動いているのか気になったので調べてみました。

そもそもビットコインのTransactionの仕組みは?

ビットコインでは、Transactionを作ったり使ったりするときにはLock ScriptUnlock Scriptを書きます。 (scriptPubkeyとscriptSigとも呼ばれますがわかりにくいので、これ以降はLock ScriptとUnlock Scriptと呼びます。)

例えば、僕が10BCHを持っているとします。 この10BCHをそのまま置いていると誰かに取られてしまうかもしれないので、僕はこの10BCHに鍵をかけます。それがLock Scriptです。

そして、しばらくして僕がこの10BCHを使いたくなったときに、この鍵を解錠します。そのときに使うのがUnlock Scriptです。

具体的には、[Unlock Script] [Lock Script]の順にコードを実行したときに、実行結果がTrueであればこの10BCHを使うことができます。

実はこのとき、実行結果がTrueになるUnlock Scriptを書けるのであれば、僕以外の人でもこのコインを使うことができます。

スタックマシン

Unlock ScriptLock Scriptはスタックマシンで実行されます。 スタックマシンでは、スタックと呼ばれる領域に値を追加していったり、その領域から値を取り出して演算を行ったりします。 例えば次のようなスクリプトは以下のように実行されます。

2 3 * 4 5 * +

f:id:usatie:20180619200540p:plain

(出典:http://ufcpp.net/study/computer/Compiler.html

ビットコインのTransactionにおいては、このように実行して行った結果、最後にスタックに残る値がTrueであれば、そのコインは使用可能になるということです。

例えば、Lock Script

10 OP_EQUAL

だったとき、Unlock Script

10

であれば、最後にTrueが残ります。

このLock Scriptに対しては、他にも以下のようなUnlock Scriptでも最後にTrueが残るので解錠が可能です。

5 5 OP_ADD

(わからない人はぜひ紙に書いてやって見てください!)

Script Hashの仕組み

Script Hashにおいては、Lock ScriptUnlock Scriptは以下のようになります。

Lock Script :

OP_HASH160 {ハッシュ値X} OP_EQUAL

Unlock Script :

[Script U] {Script Lを文字列にしたもの}

1st Step : Hash160({Script Lを文字列にしたもの}) == {ハッシュ値X}を確認

  1. まず [Script U]がスタックに積まれます
  2. そのあと{Script Lを文字列にしたもの}がスタックに積まれます
  3. OP_HASH160により、{Script Lを文字列にしたもの}が{ハッシュ値H}になります
  4. 3で生成された{ハッシュ値H}と、Lock Scriptの{ハッシュ値X}が等しいことをOP_EQUALで確認します

1st Stepでは {Script Lを文字列にしたもの}をハッシュ化したものが{ハッシュ値X}と等しいことを確認します。 (ちなみに、スタックには依然として[Script U]が積まれたままです。) 確認ができたら2nd Stepに進みます。

2nd Step : 実際のアンロックスクリプトとロックスクリプトを実行

2nd Stepでは、

[Script L]をLock Script

[Script U]をUnlock Script

としてスタックマシンで実行します。 この結果がTrueであれば、このコインは使用可能です。

つまり、{Script Lを文字列にしたもの}から[Script L]を生成したのち、[Script L]を先ほどのスタックに追加して実行します。

まとめ

最初に紹介した簡単なスクリプトの例で言えば、

[Script L] : [10 OP_EQUAL]

[Script U] : [5 5 OP_ADD]

みたいな感じです。 このScript Hashを使うと、どれだけ [Script L]が複雑だったとしても、 送金するときには[Script L]のハッシュ値XさえあればOKという点が嬉しいです。

受け取り側が複雑なマルチシグで受け取りたいときも、送金者はそのマルチシグのロックスクリプトのハッシュ値さえ書いておけば送金できるということで非常に楽です。