導入

ビットコインは、プログラマブルマネーと呼ばれることもあります。そのデジタル的な性質により、ユーザーは資金の使い方に関する条件を非常に柔軟に設定できます。

ビットコインについて議論するとき、私たちはウォレットとコインについて話します。しかし、財布を鍵、コインを小切手、ブロックチェーンを鍵のかかった金庫の列と考えることもできます。各金庫には細いスロットがあり、誰でも小切手を預けたり、その金庫にどれだけの価値があるのか​​を覗いたりすることができます。ただし、内部にアクセスできるのはキーホルダーのみとなります。

キーホルダーを持っている人が他の人にお金を渡したいときは、ボックスのロックを解除します。彼らは古い小切手を参照する新しい小切手を作成し(その後破棄されます)、受信者が開けることができるボックスにそれをロックします。それを費やすために、新しい受信者はこのプロセスを繰り返します。

この記事では、ビットコイン ネットワーク上のノードによって解釈されるプログラミング言語であるスクリプトについて詳しく見ていきます。スクリプトは、金庫のロック/ロック解除メカニズムを制御するものです。


ビットコインはどのように機能するのでしょうか?

上記のアナロジーで考えると、すべてのトランザクションには 2 つの部分、つまり (ボックスのロックを解除する) キーとロックという 2 つの部分があると言えます。鍵を使用して、送りたい小切手が入っているボックスを開け、別の鍵を備えた新しいボックスに新しい小切手を追加します。新しいボックスから使用するには、別のキーが必要です。

十分シンプルです。システム内のロックの種類を少し変えることもできます。場合によっては、複数の鍵の提供を必要とする金庫もあれば、秘密を知っていることを証明する必要がある金庫もあるかもしれません。人々が設定できる条件はたくさんあります。

私たちのキーは scriptSig と呼ばれるものです。ロックは scriptPubKey です。これらのコンポーネントをもう少し詳しく見てみると、実際にはデータのビットとコードのブロックで構成されていることがわかります。これらを組み合わせると、小さなプログラムが作成されます。

トランザクションを行うと、その組み合わせがネットワークにブロードキャストされます。それを受信した各ノードはプログラムをチェックし、トランザクションが有効かどうかを通知します。そうでない場合は破棄されるだけで、ロックされた資金は使用できなくなります。

あなたが保持する小切手 (コイン) は、未使用トランザクション出力 (UTXO) と呼ばれます。この資金は、錠に適合する鍵を提供できる人であれば誰でも使用できます。具体的には、キーは scriptSig で、ロックは scriptPubKey です。

UTXO がウォレット内にある場合、おそらく、この公開鍵の所有権を証明できる人のみがこれらの資金のロックを解除できるという条件が付けられるでしょう。ロックを解除するには、scriptPubKey で指定された公開キーにマップされる秘密キーを使用して、デジタル署名を含む scriptSig を提供します。これは間もなく明らかになるでしょう。


ビットコインスタックを理解する

スクリプトは、スタックベースの言語として知られています。これが意味するのは、私たちが一連の命令を読むとき、それを垂直の列と考えられる場所に配置するということです。たとえば、リスト A、B、C では、A が一番下、C が一番上になるスタックが作成されます。命令で何かをするように指示されると、スタックの最上位から始まる 1 つ以上の要素を操作します。


Elements A, B, and C being added and “popped” from the stack.

要素 A、B、および C が追加され、スタックから「ポップ」されます。


データ (署名、ハッシュ、公開鍵など) と命令 (またはオペコード) を区別できます。指示はデータを削除し、それに対して何かを実行します。以下に、スクリプトがどのようなものになるかを示す非常に簡単な例を示します。

<xyz> <md5 ハッシュ> <d16fb36f0911f878998c136191af705e> <等しいかどうか確認>

赤はデータ、青はオペコードです。左から右に読み取るので、最初に文字列 <xyz> をスタックに置きます。次は <md5 hasher> オペコードです。これはビットコインには存在しませんが、スタックの最上位要素 (<xyz>) を削除し、MD5 アルゴリズムを使用してハッシュするとします。その後、出力がスタックに再度追加されます。ここでの出力は d16fb36f0911f878998c136191af705e になります。

なんと偶然でしょう。次に追加する要素は <d16fb36f0911f878998c136191af705e> なので、スタックには 2 つの同一の要素があります。最後に、<check if equal> は上から 2 つの要素をポップし、それらが等しいかどうかを確認します。等しい場合は、スタックに <1> を追加します。等しくない場合は、<0> を追加します。

指示リストの最後まで来ました。私たちのスクリプトは 2 つの方法で失敗する可能性があります。残りの要素が 0 だった場合、または条件が満たされなかったときに演算子の 1 つが失敗した場合です。この例にはそのような演算子がなく、最終的にゼロ以外の要素 (<1>) になるため、スクリプトは有効でした。これらのルールは、実際のビットコイン取引にも当てはまります。

あれはただのでっちあげの番組だった。では実際のものをいくつか見てみましょう。


公開鍵への支払い (P2PK)

Pay-to-Pubkey (P2PK) は非常に簡単です。これには、資金を特定の公開鍵にロックすることが含まれます。この方法で資金を受け取りたい場合は、ビットコイン アドレスではなく、公開キーを送信者に提供することになります。

2009 年にサトシ・ナカモトとハル・フィニーの間で行われた最初の取引は P2PK 取引でした。この構造はビットコインの初期に頻繁に使用されましたが、現在では Pay-to-Pubkey-Hash (P2PKH) がその構造に大きく取って代わりました。

P2PK トランザクションのロック スクリプトは、<public key> OP_CHECKSIG の形式に従います。十分シンプルです。 OP_CHECKSIG が提供された公開キーと照合して署名をチェックすることは想像できたかもしれません。そのため、scriptSig は単純な <signature> になります。 scriptSig がロックの鍵であることを忘れないでください。


A signature gets added to the stack, followed by a public key. OP_CHECKSIG pops them both and verifies the signature against the public key. If they match, it adds a <1> to the stack. Otherwise, it adds a <0>


これほど簡単なことはありません。署名がスタックに追加され、その後に公開キーが追加されます。 OP_CHECKSIG は両方をポップし、公開鍵に対して署名を検証します。一致する場合、<1> がスタックに追加されます。それ以外の場合は、<0> が追加されます。

次のセクションで詳しく説明する理由により、P2PK は実際にはもう使用されていません。


公開鍵ハッシュへの支払い (P2PKH)

Pay-to-Pubkey-Hash (P2PKH) は現在、最も一般的なタイプのトランザクションです。わざわざ古いソフトウェアをダウンロードしない限り、ウォレットはデフォルトでこれらを実行している可能性があります。

P2PKH の scriptPubKey は次のとおりです。

OP_DUP OP_HASH160 <公開鍵ハッシュ> OP_EQUALVERIFY OP_CHECKSIG

scriptSig を紹介する前に、新しいオペコードが何を行うのかを詳しく見てみましょう。


OP_DUP

OP_DUP は最初の要素をポップし、それを複製します。次に、両方をスタックに戻します。通常、これは元の要素に影響を与えずに複製に対して操作を実行できるようにするために行われます。


OP_HASH160

これにより、最初の要素がポップされ、2 回ハッシュされます。最初のラウンドは SHA-256 アルゴリズムでハッシュされます。 SHA-256 出力は、RIPEMD-160 アルゴリズムでハッシュされます。結果の出力はスタックに再度追加されます。


OP_EQUALVERIFY

OP_EQUALVERIFY は、他の 2 つの演算子 (OP_EQUAL と OP_VERIFY) を組み合わせます。 OP_EQUAL は 2 つの要素をポップし、それらが同一であるかどうかを確認します。存在する場合、スタックに 1 が追加されます。そうでない場合は、0 を追加します。OP_VERIFY は最上位の要素をポップし、それが True (つまり、ゼロ以外) かどうかを確認します。そうでない場合、トランザクションは失敗します。 OP_EQUALVERIFY を組み合わせると、上位 2 つの要素が一致しない場合、トランザクションは失敗します。

今回の scriptSig は次のようになります。

<署名> <公開鍵>

P2PKH 出力のロックを解除するには、署名と対応する公開キーを提供する必要があります。


We’re just adding an extra step to check that the public key matches the hash in the script


上の GIF で何が起こっているかがわかります。P2PK スクリプトとそれほど違いはありません。公開鍵がスクリプト内のハッシュと一致するかどうかを確認するための手順を追加しているだけです。

ただし、注意すべき点があります。P2PKH ロック スクリプトでは、公開鍵は表示されません。表示できるのはハッシュのみです。ブロックチェーン エクスプローラーで、使用されていない P2PKH 出力を見ても、公開鍵を特定することはできません。受信者が資金を送金することを決定したときにのみ、公開鍵が明らかになります。

これにはいくつかの利点があります。 1 つ目は、公開鍵ハッシュは完全な公開鍵よりも単純に渡しやすいということです。サトシはまさにこの理由から 2009 年にこのサービスを立ち上げました。公開鍵ハッシュは、今日ビットコイン アドレスとして知られているものです。

2 番目の利点は、公開キー ハッシュが量子コンピューティングに対する追加のセキュリティ層を提供できることです。私たちの公開鍵は私たちが資金を使うまで分からないため、他の人が秘密鍵を計算することはさらに困難です。これを取得するには、2 ラウンドのハッシュ (RIPEMD-160 と SHA-256) を逆にする必要があります。


➠ 暗号通貨を始めてみませんか?バイナンスでビットコインを買おう!


Pay-to-Script-Hash (P2SH)

Pay-to-Script-Hash (P2SH) は、ビットコインにとって非常に興味深い開発でした。これにより、送信者は資金をスクリプトのハッシュにロックすることができ、スクリプトが実際に何を行うのかを知る必要はありません。次の SHA-256 ハッシュを取得します。

e145fe9ed5c23aa71fdb443de00c7d9b4a69f8a27a2e4fbb1fe1d0dbfb6583f1

資金をロックするためにハッシュの入力を知る必要はありません。ただし、支出者は、ハッシュ化に使用されたスクリプトを提供する必要があり、そのスクリプトの条件を満たす必要があります。

上記のハッシュは次のスクリプトから作成されました。

<2を掛ける> <4> <等しいかどうかを確認>

その scriptPubKey に紐づくコインを使うには、それらのコマンドを提供するだけでは不十分です。完成したスクリプトが True と評価されるような scriptSig も必要です。この例では、これは <2> を掛けて <4> という結果になる要素です。もちろん、scriptSig は <2> だけであることを意味します。

実際には、P2SH 出力の scriptPubKey は次のとおりです。

OP_HASH160 <redeemScript ハッシュ> OP_EQUAL

ここでは新しい演算子はありません。ただし、新しい要素として <redeemScript hash> があります。名前が示すように、これは資金を引き換えるために提供する必要があるスクリプト (redeemScript と呼ばれます) のハッシュです。scriptSig は、redeemScript の内容に応じて変わります。ただし、一般的には、署名と添付された公開キーの組み合わせに続いて (必須の) redeemScript が続きます。

<署名> <公開鍵> <redeemScript>

私たちの評価は、これまでに見てきたスタック実行とは少し異なります。それは 2 つの部分で起こります。 1 つ目は、正しいハッシュを指定したかどうかを単純にチェックするものです。


We’ve reached the end of this mini-program, and the top element is non-zero. That means it’s valid


redeemScript の前の要素には何も加えていないことに注意してください。現時点では使用されていません。このミニプログラムは終わりに達しましたが、先頭の要素はゼロではありません。つまり有効です。

しかし、まだ終わっていません。ネットワーク ノードはこの構造を P2SH として認識するため、実際には scriptSig の要素が別のスタックで待機しています。そこで署名と公開キーが使用されます。

これまで、redeemScript を要素として扱ってきました。しかし今では、それは何でもよい指示として解釈されます。 P2PKH ロック スクリプトの例を見てみましょう。このスクリプトには、<redeemScript> 内の <public key hash> と一致する <signature> と <public key> を指定する必要があります。


Once your redeemScript has been expanded, you can see that we have a situation that looks exactly like a regular P2PKH transaction.


redeemScript が展開されると、通常の P2PKH トランザクションとまったく同じ状況になっていることがわかります。そこからは、通常の場合と同じように実行するだけです。

ここでは P2SH(P2PKH) スクリプトと呼ばれるものをデモンストレーションしましたが、実際にこのようなスクリプトが見つかる可能性はほとんどありません。作成することを妨げるものは何もありませんが、追加のメリットは得られず、最終的にはブロック内のより多くのスペースを占有することになります (したがって、コストも高くなります)。

P2SH は通常、マルチ署名や SegWit 互換のトランザクションなどに便利です。マルチシグトランザクションは複数のキーを必要とする可能性があるため、サイズが非常に大きくなる可能性があります。 Pay-to-Script-Hash を実装する前に、送信者はロック スクリプト内で考えられるすべての公開キーをリストする必要があります。

しかし、P2SH では、支出条件がどれほど複雑であっても関係ありません。 redeemScript のハッシュは常に固定サイズです。したがって、コストは、ロック スクリプトのロックを解除したいユーザーに負担されます。

SegWit 互換性は、P2SH が役立つもう 1 つのケースです (トランザクション構造がどのように異なるかについては、次のセクションで詳しく説明します)。 SegWit はソフト フォークであり、その結果ブロック/トランザクション形式が変更されました。これはオプトインアップグレードであるため、すべてのウォレット ソフトウェアが変更を認識するわけではありません。クライアントが SegWit スクリプト ハッシュを P2SH でラップするかどうかは関係ありません。このタイプのすべてのトランザクションと同様に、ロック解除の redeemScript が何であるかを知る必要はありません。


SegWit トランザクション (P2WPKH および P2WSH)

SegWit のより包括的な概要については、「A Beginner's Guide to Segregated Witness」を参照してください。

SegWit のトランザクション形式を理解するには、もはや scriptSig と scriptPubKey だけが存在するわけではないことを知っておく必要があります。また、証人という新しいフィールドも追加されました。 scriptSig に保持するために使用したデータは監視に移動されるため、scriptSig は空になります。

「bc1」で始まるアドレスを見つけた場合、それらは SegWit ネイティブと呼ばれるものです(P2SH アドレスであるため「3」で始まる単なる SegWit 互換とは対照的です)。


Pay-to-Witness-Pubkey-Hash (P2WPKH)

Pay-to-Witness-Pubkey-Hash (P2WPKH) は、P2PKH の SegWit バージョンです。証人は次のようになります。

<署名> <公開鍵>

これは P2PKH の scriptSig と同じであることがわかります。ここでは、scriptSig は空です。一方、scriptPubKey は次のようになります。

<OP_0> <公開鍵ハッシュ>

それは少し奇妙に見えますね?署名、公開鍵、およびそのハッシュを比較するためのオペコードはどこにありますか?

トランザクションを受信するノードは <public key hash> の長さに基づいてトランザクションをどう処理するかを知っているため、ここでは追加の演算子は示しません。彼らは長さを計算し、古き良き P2PKH トランザクションと同じスタイルで実行する必要があることを理解します。

アップグレードされていないノードは、そのようにトランザクションを解釈する方法を知りませんが、それは問題ではありません。古いルールでは、証人がいないため、ノードは空の scriptSig といくつかのデータを読み取ります。ノードはこれを評価して有効としてマークします。ノードにとっては、誰でも出力を使用できます。これが、SegWit が下位互換性のあるソフトフォークと見なされる理由です。


ペイ・トゥ・ウィットネス・スクリプト・ハッシュ (P2WSH)

Pay-to-Witness-Script Hash (P2WSH) は新しい P2SH です。ここまで読んだ人なら、おそらくこれがどのように見えるか理解できると思いますが、とにかく見ていきましょう。私たちの証人は、通常 scriptSig に入れるものです。たとえば、P2PKH トランザクションをラップする P2WSH では、次のようになります。

<署名1> <公開鍵>

scriptPubKey は次のとおりです。

<OP_0> <スクリプトハッシュ>

同じルールが適用されます。SegWit ノードはスクリプト ハッシュの長さを読み取り、それが P2SH と同様に評価される P2WSH 出力であると判断します。一方、古いノードはそれを誰でも使用できる出力として認識します。


最後に

この記事では、ビットコインの構成要素について少し学びました。それらを簡単に要約しましょう:


スクリプトの種類

説明

公開鍵への支払い (P2PK)

資金を特定の公開鍵にロックします

公開鍵ハッシュへの支払い (P2PKH)

資金を特定の公開鍵ハッシュ (アドレスなど) にロックします。

Pay-to-Script-Hash (P2SH)

受取人が提供できるスクリプトのハッシュに資金をロックします

Pay-to-Witness-Pubkey-Hash (P2WPKH)

P2PK の SegWit バージョン

Pay-to-Witness-Script-Hash (P2WSH)

P2SH の SegWit バージョン


ビットコインを深く掘り下げると、なぜビットコインに大きな可能性があるのか​​がわかります。トランザクションはさまざまなコンポーネントで構成されます。これらの構成要素を操作することで、ユーザーは資金をいつどのように使用できるかに関する条件を非常に柔軟に設定できます。


➠ スクリプトについて質問がありますか?アスクアカデミーへ行きましょう!