少しだけ易しいMastering Bitcoin【第5章】
Bitcoinの技術面を学ぶにはこれしかないと言われているほどの名著Mastering Bitcoin を今更読んだので、自分の中での復習を兼ねて、ところどころ解説付きでまとめを書いていきます。
元の本ではサラッと流されているところもしっかり解説するつもりでお節介に書いたので初学者の人には分かりやすいかもしれません。
日本語版PDFはここで無料公開されているので翻訳者の方々への感謝を常に感じながら読みました。
無料公開版ということもあって誤字脱字もたまにあったりするので、
しっかり製本されたものが読みたいという方はAmazonで買って読むことをお勧めします。
前回はこちら↓
第5章 トランザクション
⑴トランザクションのライフサイクル
第2章「ビットコインの仕組み」でざっくり学んだ内容を復習しつつ、トランザクション生成の一連の流れを見ていきます。
・origination (トランザクションの生成)
秘密鍵の保持者がその秘密鍵による署名によって自身のBitcoinアドレスへの未使用アウトプットトランザクションをunlockして、新しいトランザクションのインプットに入れ、送り先Bitcoinアドレス等のアウトプットを設定してトランザクションを作成します。
・broadcast(トランザクションのBitcoinネットワークへの放出)
作られたトランザクションをブロックチェーンに記録するためにBitcoinネットワークに放出します。
Bitcoinトランザクションは300から400byteのデータで、それを数万ものBitcoinノードのうちどれでもいいので1つに辿り着かせればOKです。この時、必ず2つ以上のBitcoinノードにブロードキャストするので、送信者はBitcoinノードを信用する必要はありません。
※例えば、クレジットカードのトランザクションはセンシティブな情報が含まれているので、暗号化されたネットワークでしかデータの転送ができませんが、Bitcoinのトランザクションは一切の機密情報(秘密鍵や証明書)を含んでいないため、どんなネットワークを通してでも送ることができます。このようにBitcoinはお金をデータの形に変え、誰もトランザクションを作成や実行を阻止できないようにした点で革命的です。
・flooding (トランザクションのBitcoinネットワーク伝搬)
BitcoinネットワークはP2Pネットワークであり、それぞれのBitcoinノードは数個の他のノードに接続されています。
トランザクションを受け取った Bitcoinネットワークのノードは、そのトランザクションが有効なものかどうかを確認し、有効であれば、そのノードが接続している隣接ノードに送られ、それぞれの隣接ノードもまたトランザクションを検証した上で全ての隣接ノードにこのトランザクションを送ります。(同時に自身の未検証トランザクションプールにそのトランザクションを記憶します)
このようにして、全ての接続されたノードがこのトランザクションを受け取るまでBitcoinネットワーク内を伝わっていき、数秒以内に全体に広がります。
全てのノードは有効なトランザクションでなければ、次のノードにそのトランザクションを送らないので、DOS攻撃の心配もありません。
・confirmation(マイニングノードによるトランザクションの承認)
floodingを経て未検証トランザクションプールに貯められたトランザクションを、PoW競争に勝利したマイナーがマイナー手数料などを加味して優先順位をつけてブロックに取り込むことで、トランザクションはブロックチェーンに記録され、その上に十分な数のブロックが積み上がる(ファイナリティを得る)ことで、トランザクションはブロックチェーンの永続的な一部になります。
⑵UTXO, 残高, お釣りトランザクション, マイナー手数料, coinbaseトランザクション
ここで第2章「ビットコインの仕組み」で用いた以下の図[ブロックチェーンの中身外観]についてもう少し詳しく説明していきます。
トランザクション生成の際にInputに入れられるものは、未使用のアウトプットのみでした。
この未使用トランザクションアウトプットをUTXO(unspent transaction output) と言います。
UTXOは、特定の所有者(アウトプットの宛先アドレス)にロックされた分割不可能なbitcoinの固まりです 。
bitcoinはsatoshiという8桁の十進数(1bitcoin = 1億satoshi)を持ち、UTXOは satoshi を単位としてbitcoinの量を持つことができます。
そしてブロックチェーンが持っているのは、ただの一つ一つのトランザクションデータのみでした。
Bitcoinウォレットには「残高」が表示されると思いますが、実際には、Bitcoinアドレスの残高という記録があるわけではなく、あるのは散り散りになっているUTXOだけです。ウォレットはブロックチェーンをスキャンしてユーザに属している全てのUTXOを掻き集め残高を計算し、ユーザーのbitcoin残高として表示しているのです。
(画像でのだいすけくんのBitcoin残高は「47.9bitcoin」ですね!)
画像のTransaction16を見てみましょう。
‘かずくん’は’なべさん’に50bitcoinを送りたいのですが、’かずくん’は98bitcoinのUTXOしか持っていません。
UTXOは分割不可能なので、なべさんに送る分との差額をTransaction16-(2)のように自分自身へのお釣りトランザクションとして作成しなくてはなりません。
この時、16-(2)の自分への送金トランザクションが1bitcoin足りないことに気がついたと思います。
これがマイナーへの手数料となるのです。このようにマイナーへの手数料は自分へのお釣りトランザクションの作成を通して任意に設定することができます。
適切なトランザクション手数料はBitcoinネットワーク内での市場原理に基づいて決まります。
このトランザクション手数料はトランザクションのデータサイズ(KB)に基づいて計算され、いくらの支払いをしたかは関係ありません。
マイナーごとにどのトランザクションを優先的に選ぶかの判断条件は違っており、この判断条件には手数料の大きさが大きく影響しています。手数料が含まれていないトランザクション(上記の画像ではTransaction1890には手数料が含まれていませんね)も状況によってはマイナーに選ばれるかもしれませんが、大抵の場合はトランザクション手数料はマイナーによって処理される優先順位に影響し、十分な手数料をもっているトランザクションがマイニングされている次のブロックに含まれる可能性が高くなり、一方十分な手数料を持っていないか、手数料がないトランザクションはブロックに取り込まれること が遅れてしまいます。([第8章]で詳しく解説します)
実はBitcoin初期には、トランザクション手数料は固定されており、Bitcoinネットワーク全体で一定でした。次第に手数料制限は緩和され、Bitcoinネットワークのキャパシティやトランザクション量に基づく市場の力関係にトラ ンザクション手数料が影響されるようになってきました。
現在(2016年時点)の最小トランザクション手数料はトランザクションのデータサイズ1KBあたり0.0001bitcoin(0.1ミリbitcoin)に固定されており、最近1ミリbitcoinに減らされました。多くのトランザクションは1KBより小さいですが、複数のインプットまたはアウトプットを持っているとデータサイズが大きくなり、より大きな手数料になります。
上記の画像を見て、もう一つとてもおかしな点に気づいた方も多いかと思います。
「一番最初のマイニング仙人へのTransaction1に、インプットがない」ですね。
これは、coinbase トランザクションと呼ばれる特殊なトランザクションです。
coinbase トランザクションは、それぞれのブロックの一番最初のトランザクションであり、このトランザクションはマイニングに"勝った"マイナー(ここではマイニング仙人)によってブロックの一番最初に置かれ、マイニングに対する報酬としてマイナーにbitcoinが支払われるトランザクションとなります。このようにしてマイニングプロセスを通してBitcoinのお金が供給されていきます。
つまり、このTransaction1は何もないところから(Bitcoinシステム自体から)生成されたBitcoinなのでインプットを持たないというわけです。
([第8章]で詳しく解説します)
⑶トランザクションの構造
①トランザクションの全体構造
トランザクションは上の図のような要素を持っています。
インプット(資金源)とアウトプット(資金の送信先)は複数あっても良いので、インプット/アプトプットの数 という要素があります。
最後のLocktimeというのは、ここに指定した時刻までトランザクションが承認されないようにするというものです。
トランザクションをLocktimeをつけて作成することで、Locktimeに達するまではキャンセルが可能になります。
通常のトランザクションでは0に設定し、すぐにBitcoinネットワークを伝搬し、承認されます。
Locktimeを指定したい場合には、
①ブロック高(0より大きく500,000,000未満)を設定してそのブロック高までは承認されないようにする
②500,000,000以上のUNIX timeを設定し、その時刻までは承認されないようにする
という方法があります。
②アウトプットの構造
トランザクションのアウトプットは上の図のような構造を持っています。
Amountは、アウトプット(送金)されるBitcoinの額です。
Locking Scriptとは、「このアウトプットを別のトランザクションのインプットとして使用するにあたって満たさなければいけない条件である"解除条件(encumbrance)" 」です。
多くの場合、locking scriptは特定のBitcoinアドレスにアウトプットをロックします。
この場合は、このトランザクションのアウトプット先Bitcoinアドレスの所持者が、 秘密鍵による署名を含むunlocking scriptを提示することでこのアウトプットのロックを外すことで、新しいトランザクションのインプットに入れられるようになります。
③インプットの構造
トランザクションのインプットは上の図のような構造を持っています。
Transaction Hashは、インプットに入れられるUTXOを暗号化したものです。UTXOへのポインタですね。
トランザクションは複数のアウトプットを持つことができますので、入れられたUTXOのうち、何番目のアウトプットかを指定するのがOutput Indexです。
Mastering Bitcoinには書かれていませんが、このTransaction HashとOutput indexは二つ合わせてOut pointという型を形成し、合わせた36byteがprevious_output呼ばれることもありますので覚えておきましょう。
unlocking scriptは、インプットに入れられたUTXOのlocking scriptを解除して所有権を証明するためのものです。
Sequence Numberは、最初のBitcoinのリリースでは、「lock timeが設定され、その時間まで承認されずにメモリプール内にあるトランザクション」に対して「同じインプットだけれどもより高いSequence Number持つトランザクション」を作ることでconfirm前のトランザクションの置換を行うためのものでした。
しかし、トランザクションの置換により置換後のトランザクションの方が手数料が小さい場合、マイナーが置換後のトランザクションをブロックの対象にするインセンティブが無いため失敗したという経緯があり、現在(2016年)は使われておらず、この値は整数最大値(0xFFFFFFFF) に設定することでBitcoinネットワークから無視されるようになっています。(参考:https://techmedia-think.hatenablog.com/entry/2016/03/28/151533)
⑷トランザクションチェーンとOrphanトランザクション
1つのトランザクションは前のトランザクションアウトプット(親と呼ばれる)を使い、また次のトランザクションのためにアウトプット(子と呼ばれる)を作るのでした。この連鎖をトランザクションチェーンといいます。
稀にですが、このトランザクションのチェーン全体(親トランザクション、子トランザクション、孫トランザクション)がほぼ同時に作られることがあります。 この時、トランザクションチェーンはBitcoinネットワークに放出されますが、もしかするとどこかのノードでは、親トランザクションよりも先に子トランザクションが届いてしまうかもしれません。
この場合、子を最初に見つけたノー ドは、この子が参照している親トランザクションのことはまだ知りません。
このような親がいないトランザクションをorphan(孤児)トランザクションと呼び、orphanトランザクションを「親が来るまで保持しておくプール」をorphanトランザクションプールと言います。
一度親が届くと、親のUTXOを参照しているorphanは全てプールから取り出され、再確認されます。
orphanプールにorphanトランザクションを保持しておく方法を使うことで、親トランザクションの到着が遅れたとしても子トランザクションを放棄することなく、かつ正しい順番でトランザクションのチェーンを構築できるのです。
ただし、それぞれのノードがメモリに保持できるorphanトランザクションの数には制限が設けられています。これは、BitcoinノードからのDOS攻撃を防ぐためです。制限数は、 MAX_ORPHAN_TRANSACTIONS という Bitcoinリファレンスクライアントのソースコード内にあるパラメータで定義されています。もしプールにあるorphanトランザクションの数が MAX_ORPHAN_TRANSACTIONS を越えると、ランダムに選ばれたいくつかのorphanトランザクションがプールから追い出されるようになっています。
⑸トランザクションscriptとScript言語
Bitcoinのトランザクションには「アウトプットにあるlocking script」と「インプットにあるunlocking script」の2つのscriptがあり、これらはScript言語と呼ばれる言語で記述されています。
この節でのポイントは「Bitcoinのトランザクションは、Script言語によって”AからBへの送金”という単純なもの以外にも柔軟に設計可能である」という点です。
①scriptによるトランザクションの検証
Bitcoinノードは伝搬されてきた新規トランザクションを検証する際に、「インプットに入れられたUTXOのlocking script」と「インプットに入れられたunlocking script」を同時に実行して「locking scriptが解除されるか」を確認します。
(新規トランザクションの検証をする際の全ての条件については[第8章]で解説します)
locking scriptには大抵の場合、公開鍵または Bitcoinアドレスが含まれているため、locking scriptのことをscriptPubkeyと呼ぶこともあります。
また、unlocking scriptにも大抵の場合、秘密鍵からウォレットが作り出したデジタル署名を含んでいるので、unlocking scriptのことをscriptSigと呼ぶこともあります。
どちらのscriptも「公開鍵 or Bitcoinアドレス:デジタル署名」という通常の送金で使われる組み合わせ以外にもScript言語を書くことで様々な条件を設定することができることを忘れないでください。
Bitcoinクライアントがトランザクションの有効性を確認する手順を見ていくと、
- 最初にトランザクションのインプットに入れられているUTXOを取得しようとする
- そのUTXOはlocking scriptを解除しなければ取得できないので、このUTXOを使おうとしているトランザクションのインプットに含まれているunlocking scriptを取り出し、(スタック実行エンジンを使って)実行する
- unlocking scriptがエラーなく実行され終えたら、そのメインスタック(実行結果)がコピーされる
- コピーされたunlocking scriptのメインスタックが以下の画像のようにlocking scriptの左側に結合されて実行される
- 実行結果がTrueならば、unlocking scriptがそのUTXOを使用するのに必要なlocking scriptの解除に成功したと言うことであり、トランザクションを有効と判断する
- UTXOに"使用済み"という印 をつけ、使用可能な(未使用)UTXOのセットから削除する
(5の実行結果がもしTrue以外だった場合は、UTXOには何の変化も与えられません。UTXOの条件を正しく満たす有効なトランザクションだけがUTXOに”使用済み”ラベルを貼ることができます。)
のようになります。
②Script言語
BitcoinのScript言語はスタックベース言語と呼ばれ、スタックという「データを積み上げていく」データ構造を使っています。
スタックというデータ構造では、pop(積み上がったデータの一番上からデータを取り除く)、push(積み上がったデータの上にデータを追加する)という操作のみが実行できます。
また、Script言語のコードは左から右に処理されていきます。
Script言語は簡単な関数をいくつか持っており、よく使われるものは以下の通りです。
OP_ADD : スタックから2つの要素をpopして、それらを加算した結果をスタックにpushするOP_EQUAL : スタックから2つの要素をpopして、それらが等しければTrue(数値の1)、等しくなければFalse(数値の0)をスタックにpushする
このScript言語で書かれたunlocking scriptがlocking scriptをどう解除するのかを簡単な例で見ていくと
locking script : 3 OP_ADD 5 OP_EQUAL
は
unlocking script : 2
で解除する(実行結果をTrueにする)ことができます。
文字だけで説明されてもよく分からないと思うので、実際の実行フローのイメージを以下の画像で掴んでください。
画像は、locking script の左側にunlocking script である 2 が結合され、1つの要素ずつ順番に左から実行されて行っている様を表しています。
数値が実行されるとスタックにその数値が積み上がり、それに関数が実行されることで最終的にTrueが残っているのがわかると思います。
このようにトランザクションの検証に使われるScript言語は、実は、意図的にループやif文な どの分岐処理ができないように設計されています。これはこの言語がチューリング不完全ということです。
このようになっている理由は、
- scriptの簡潔さの維持や実行時間を予測できるようにするため
- 無限ループを作ることやBitcoinネットワークを使ったDoS(Denial of Service)攻撃を起こすようなトランザクションに内在する"論理爆弾(logic bomb)"などを作ることができなくするため
です。
トランザクションの有効性検証は、Bitcoinにおいて最も重要な部分なので、ここに脆弱性が生まれないように言語に制限を設けています。
また、Script言語はステートレス(state:状態という意味)です。
つまりそのScriptが実行される前の状態も実行された後の状態も一切保持することはありません。これによってscriptを実行するために必要な全ての情報がscriptの中に含まれていることになり、scriptはどんなシステム上でも同じプロセスで実行できるということになります。scriptはどのようなシステム環境下でも実行でき、有効なトランザクションは全ての人に対して有効なのです。
この結果の予測可能性はBitcoinシステムの本質的な利点となっています。
⑹標準的なトランザクション
これまで見てきたScript言語を使えば色々なScriptを持つトランザクションを作ることができます。
しかし、Bitcoin初期のBitcoinリファレンスクライアントから標準的なトランザクションとして5種類のトランザクションが決められており、この標準的なトランザクション以外のトランザクションを受け入れてくれるマイナーは稀です。
この標準トランザクションは、Bitcoin Coreクライアント(リファレンス実装) のソースコードの中の関数で定義されています。
(このソースコードのisStandard(),isStandardtx辺りですね)
では、この5種類の標準トランザクションについて一つずつ見ていきます。
①Pay-to-Public-Key-Hash(P2PKH)
Public key Hashとは「公開鍵のハッシュ == BitcoinアドレスのBase58 encode前」のことでしたね。(第4章まとめ(2)参照)
ここからも推察できる通り、P2PKHはBitcoinアドレスに支払う場合に使われる形式で、Bitcoinネットワークで大半の場合使われているものです。
Bitcoinアドレスに送金するトランザクションは、アウトプットのlocking scriptがこのP2PKH scriptになっており、このP2PKHでロックされたアウトプットは「公開鍵とその公開鍵に対応したデジタル署名」を提示することで解除(資金の使用)ができます。
P2PKHでは
locking scriptは
OP_DUP OP_HASH160 <送金先Bitcoinアドレスの公開鍵ハッシュを16進数で表したもの> OP_EQUAL OP_CHECKSIG
OP_DUP : DUPはduplicateの略でスタックの一番上要素を複製してスタックにpushする関数です。
OP_HASH160 : HASH160とは「SHA256とRIPEMD160を通すこと」で別名”Double Hash”と呼ばれるものでした。
OP_CHECKSIG : その名の通り デジタル署名が公開鍵とマッチするかを確かめる関数です。
unlocking scriptは
<送金先Bitcoinアドレスに対応するデジタル署名> <送金先Bitcoinアドレスの公開鍵>
になっており、これらを一緒に実行すると以下の画像のように処理されて行きます。
これまで何度も「トランザクションのインプットに入れるUTXOに対して秘密鍵のデジタル署名を使うことでそのUTXOの所有権が証明できる」と書いて来ましたが、ここでやっとデジタル署名が何かについて言及します。
ここで、このP2PKH scriptで作られたlocking scriptを持つUTXOを解除してインプットにいれるために、unlocking scriptに入れられている<sig>・デジタル署名があると思いますが、これは以降見ていくどんな標準トランザクションのunlocking scriptにも必要となっています。
locking scriptを解除するのに必要なこのデジタル署名の署名方法とその検証方法については『ECDSAデジタル署名の仕組み』で解説しています。
「秘密鍵、署名用の一時的な秘密鍵、トランザクションデータ」からデジタル署名が作成され、それが「公開鍵、トランザクションデータ」から検証される仕組みになっていますね。
このデジタル署名がunlocking scriptにあり、locking scriptなどにある公開鍵と一緒に実行されることで、「トランザクション作成者がinputのUTXOの所有者であることの証明」と「トランザクションデータが途中で改竄されていないことの証明」もできるようになっているのです。
②Pay-to-Public-Key
このscript形式は、①P2PKHでのとても短い公開鍵ハッシュではなく、公開鍵そのものをlocking scriptに配置するものです。
Pay-to-Public-Key script形式は、主にcoinbaseトランザクションでよく見られる他、P2PKHが使用できるように更新されていない古いマイニングソフトウェアで使われます。
Pay-to-Public-Keyでは
locking scriptは
<送金先Bitcoinアドレスの公開鍵> OP_CHECKSIG
unlocking scriptは
<送金先Bitcoinアドレスに対応するデジタル署名>
になります。
③マルチシグネチャ
マルチシグネチャscriptは、M-of-Nスキーマとしても知られており、 あらかじめ登録されているN個の公開鍵のうち、それに対応するデジタル署名がM個あれば解除できるというscript形式です。
最もよく使われるのは 2-of-3マルチシグネチャでこの場合は、事前にlocking scriptに書かれている3つの公開鍵のうち、それに対応するデジタル署名のうち2つがunlocking scriptに揃っていればこれらを一緒に実行することによってロックが解除されます。
標準的なマルチシグネチャscriptは、2016年時点ではNの部分(公開鍵)は15個までしか設定できないという制限があったそうですが、現在はgithubを見ると”Support up to x-of-3 multisig txns as standard”と書かれている通り公開鍵は3個までしか標準トランザクションと見なされないようです。
M-of-Nマルチシグネチャscriptでは
locking scriptは
M <公開鍵 1> <公開鍵 2> ... <公開鍵 N> N OP_CHECKMULTISIG
OP_CHECKMULTISIG : 設定されたN個の公開鍵に対応するデジタル署名がM個揃っているかを検証する関数
unlocking scriptは
OP_0 <1のデジタル署名> <2のデジタル署名> …
OP_0 : OP_CHECKMULTISIG は、実行した時に「処理に関係のないスタック上の要素を余分に1つpopしてしまう」というバグを持っており、unlocking scriptの一番最初(つまりスタックの一番下)にOP_0という空の値を入れておく事によってひとつ余分にpopする要素がこのOP_0になり、バグを回避できるため、書かれているものです。
になります。
④データアウトプット(OP_RETURN)
Bitcoinのブロックチェーンの上で、トランザクションはその承認と信頼を築くプロセスを通して正確なタイムスタンプとともに現実的に改ざん不可能なデータとなります。
これはBitcoinの送金だけではなく、データの存在証明(Proof of Existence)に使用することができるなどあらゆる応用可能性を秘めています。
しかし、送金と関係のないトランザクションを作る事には問題があります。
本来、送り先Bitcoinアドレスが入れられる20byteの領域を自由なデータに使ってしまうと、これはもちろん秘密鍵に対応していないため、決して使われないUTXOを生み出してしまうことになるのです。この決して使われないトランザクションはUTXOセットから決して削除されず、永遠にUTXOデータベースのサイズを大きくし続けてしまいます。
この問題の妥協的解決策として OP_RETURN が導入されました。
OP_RETURNは、使用不可ということが明示的アウトプットを作り出すことで、UTXOセットに保持されないようにします。OP_RETURN アウトプットはブロックチェーン上に記録されるため、ディスク容量を消費しブロックチェーンのデータサイズの増大を促してしまいますが、UTXOセットには保存されないため、UTXOメモリプールの肥大化にはならないようになっています。
OP_RETURN scriptでは
明示的に使用不可なトランザクションアウトプットに含まれることになるlocking scriptが
OP_RETURN <data>
となっており、dataは80byteに制限され、多くの場合SHA256(32byte)の出力結果のようなハッシュになっています。
また、そのdataを使っているアプリケーションを示すidがprefixとしてdataの頭に追加されることも多いです。
そしてもちろんunlocking scriptは存在しません。
すなわち、このトランザクションに含まれているBitcoinは永遠に使うことができなくなります。そのため、OP_RETURN アウトプットは通常0bitcoinを持ちます。
⑤Pay-to-Script-Hash (P2SH)
Pay-to-Script-Hash (P2SH) は、複雑なトランザクションscriptを簡潔な形にしたscript形式です。
具体的な例でP2SHを説明して行きます。
かずくんは会社を経営しており、共同創業者にえたろうとなべさんがいます。
そしてこの会社は、誰か1人が資金を持ち逃げするのを防ぐために、全ての顧客から会社への料金支払いを2-of-3マルチシグネチャで管理したいとします。
この時、このマルチシグネチャスキームを使うには、会社への支払いトランザクションのアウトプットにあるlocking script が
2 <かずくんの公開鍵> <えたろうの公開鍵> <なべさんの公開鍵> 3 OP_CHECKMULTISIG
になっていなくてはなりません。
しかし、この支払いトランザクションを作成するのは支払いの送金をする顧客であり、この方法をとるには全ての顧客にこの複雑なscriptについて説明しなくてはなりません。
さらに、それぞれの公開鍵はとても長いため、3人分の公開鍵を含むこのscriptのデータサイズはとても大きくなり、その分トランザクション手数料を大きくしなくてはならなくなります。
また、このようなデータサイズの大きなトランザクションがUTXOセットに保持されるとフルノードのメモリを圧迫してしまい、Bitcoinネットワーク全体にとっても良くありません。
つまり、これらの理由から複雑なscriptの使用が現実的に難しいものになってしまうのです。
これを解決するのがP2SHです。
2 <かずくんの公開鍵> <えたろうの公開鍵> <なべさんの公開鍵> 3 OP_CHECKMULTISIG …スクリプト(A)とする
を複雑なscriptとしたかずくんの会社の例でP2SHの仕組みを見ていくと、
- 1. 複雑なscript(A)をHASH160(SHA256とRIPEMD160を通すこと、別名”Double Hash”)で20byte(160bit)のハッシュにする。
- 2.
OP_HASH160 <1で作ったハッシュ> OP_EQUAL
というlocking scriptでトランザクションをロックする
- 3. この2のUTXOを使用するときは
<かずくんのデジタル署名1> <えたろうのデジタル署名1>
という形のunlocking scriptと、元の複雑なスクリプト(A) (これをredeem script : 埋め合わせるscriptという意味 と言う) を用意する
- 4. まず redeem script + locking scriptが実行され、unlocking scriptの中に与えられたredeemスクリプトがlocking scriptの中のハッシュと同じものか確認される
- 5. 4が確認されたら unlocking script + redeem script が実行され、TRUEが返れば、トランザクションが有効だということになる
となっています。
さらに、Pay-to-Script-HashをBase58 encodeして、Pay-to-Script-Hashアドレスとして通常のBitcoinアドレスと全く同様に使うこともできます。
通常のBitcoinアドレスは、Base58 encodeの際にversion prefixが”0”で、エンコード結果のアドレスは”1”から始まるものになるのに対して、P2SHアドレスはversion prefixとして"5"が使われており、 Base58Checkエンコードしたアドレスは"3"から始まるものになります。
このPay-to-Script-Hashアドレスによって、かずくんの会社は全ての顧客にこのアドレスを送金先として教えるだけで良く、顧客側も複雑なScriptを扱わずに済みます。通常のBitcoinアドレスと同様にマルチシグのような複雑なスキームを使用できるようになるのです。
ただし、以下のような注意点もあるので確認しておいてください。
- P2SHの設計で再帰処理ができないため、P2SH redeem scriptの中にP2SHを置くことはできない。
- OP_RETURN はアウトプットを使用するということができないため、 redeem scriptの中で OP_RETURN を使用することはできない。
- P2SHでは、元の複雑なscript(redeem script)をハッシュ化してトランザクションに入れ込むため、BitcoinネットワークはそのUTXOがunlock される時までredeem scriptを認識することはないため、もし誤ったredeem scriptのハッシュをトランザクションにlocking scriptとして入れ込んでしまっても、エラーが出ることはない。その場合は、そのUTXOを使用するときにredeem scriptを与えてもlocking scriptと一致しないため、永遠にそのUTXOは使用できなくなる。
<追記>
これまで説明してきたScript言語とそれによる様々なトランザクションについては
Yenomさんの解説スライドがめちゃめちゃ分かりやすいので見てみるといいと思います。
<現状の疑問点>
・OP_RETURNトランザクションのデータサイズ上限は80byteって書いてあったけど、普通のlocking, unlocking Scriptにはサイズは可変としか書いてない。
そのサイズに制限ってないの?
<参考文献>
[1]https://qiita.com/tnakagawa/items/5fc1baef42a5db57e1f4
続き↓