ビットコインスクリプト:貨幣のプログラミング言語
ビットコインスクリプトの深層技術ガイド — スタックベースプログラミング言語の動作原理、オペコード、標準スクリプトタイプ(P2PKH、P2SH、P2WPKH、P2TR)、実行トレース、タイムロック、マルチシグ、Tapscriptまで詳細に解説。
存在するすべてのビットコインはプログラムによってロックされている。銀行によってでも、パスワードによってでも、ユーザー名によってでもない — ビットコインスクリプトという言語で書かれた小さく決定論的なプログラムによってロックされている。そのビットコインを使うには、プログラムがTRUEを返すような入力を提供しなければならない。プログラムがFALSEを返すか実行が失敗すれば、ビットコインは使えない。これがビットコインが所有権を強制する根本的なメカニズムだ:身元ではなく、計算を通じて。
ビットコインスクリプトは史上最も重要なプログラミング言語の一つでありながら、驚くほどシンプルだ。ループも、再帰も、浮動小数点演算も、外部状態へのアクセスもない。意図的にチューリング完全ではない。これらの制限はバグではない — ビットコインの1兆ドル以上の価値を可能にする核心的なセキュリティ特性だ。
スタックベース実行モデル
ビットコインスクリプトはForthやPostScriptと類似した哲学を持つスタックベース言語だ。変数も、名前付き関数も、オブジェクトもない。スタック — 後入先出(LIFO)データ構造 — と、データをスタックにプッシュし、ポップし、計算を実行する操作(オペコード)のシーケンスだけが存在する。
簡単なスクリプトを見てみよう:
スクリプト: 2 3 OP_ADD 5 OP_EQUAL
実行トレース:
| ステップ | 操作 | スタック(上→下) | 備考 |
|---|---|---|---|
| 1 | 2 | [2] | 2をプッシュ |
| 2 | 3 | [3, 2] | 3をプッシュ |
| 3 | OP_ADD | [5] | 3と2をポップし、2+3=5をプッシュ |
| 4 | 5 | [5, 5] | 5をプッシュ |
| 5 | OP_EQUAL | [TRUE] | 5と5をポップし、TRUEをプッシュ(等しい) |
スタックの先頭がTRUEなのでスクリプトは成功する。
二部構成スクリプトシステム
ビットコイントランザクションは単一のスクリプトではなく、一緒に実行される2つの相補的なスクリプトを含む:
ScriptPubKey(ロックスクリプト): トランザクション出力に配置され、ビットコインを使うために満たすべき条件を定義する。「パズル」とも呼ばれる。
ScriptSig(アンロックスクリプト): 出力を使うトランザクション入力に配置され、ロックスクリプトを満たすデータを提供する。パズルの「解答」だ。
核心オペコード
スタック操作
- OP_DUP — スタック先頭要素を複製
- OP_DROP — スタック先頭要素を除去
- OP_SWAP — 上位2要素を交換
暗号操作
- OP_HASH160 — SHA-256後にRIPEMD-160を適用(20バイトハッシュ生成)
- OP_CHECKSIG — 公開鍵と署名をポップし、トランザクションに対して署名を検証し、TRUEまたはFALSEをプッシュ
- OP_CHECKMULTISIG — m-of-n署名をトランザクションに対して検証
比較操作
- OP_EQUAL — 2要素をポップし、等しければTRUE、そうでなければFALSEをプッシュ
- OP_EQUALVERIFY — OP_EQUALと同じだがFALSEの場合即座にスクリプトを失敗させる
タイムロック操作
- OP_CHECKLOCKTIMEVERIFY (OP_CLTV) — トランザクションのロックタイムが指定値未満なら失敗
- OP_CHECKSEQUENCEVERIFY (OP_CSV) — 入力のシーケンス番号が指定値未満なら失敗
標準スクリプトタイプ
P2PKH(Pay-to-Public-Key-Hash)
P2PKHはオリジナルの標準スクリプトタイプで、1で始まるアドレスに使われる。
ロックスクリプト(ScriptPubKey):
OP_DUP OP_HASH160 <pubKeyHash> OP_EQUALVERIFY OP_CHECKSIG
アンロックスクリプト(ScriptSig):
<signature> <publicKey>
実行トレース:
| ステップ | 操作 | スタック | 備考 |
|---|---|---|---|
| 1 | <sig> | [sig] | 署名をプッシュ |
| 2 | <pubKey> | [pubKey, sig] | 公開鍵をプッシュ |
| 3 | OP_DUP | [pubKey, pubKey, sig] | 公開鍵を複製 |
| 4 | OP_HASH160 | [hash, pubKey, sig] | 複製された鍵をハッシュ |
| 5 | <pubKeyHash> | [expected, hash, pubKey, sig] | 期待されるハッシュをプッシュ |
| 6 | OP_EQUALVERIFY | [pubKey, sig] | ハッシュの一致を確認 |
| 7 | OP_CHECKSIG | [TRUE] | 公開鍵で署名を検証 |
ロジックはエレガントだ:まずアドレスにハッシュされる公開鍵を知っていることを証明し(3-6)、次に有効な署名を提供して対応する秘密鍵を持っていることを証明する(7)。
なぜ公開鍵をハッシュするのか? 追加のセキュリティ層を提供する。ECDSA(署名アルゴリズム)が破られても、公開鍵を知らない攻撃者は資金を使えない。
P2SH(Pay-to-Script-Hash)
BIP-16(2012年)で導入されたP2SHは、特定の公開鍵ハッシュではなく任意のスクリプトのハッシュにビットコインを送ることを可能にする。実際のスクリプト(「リディームスクリプト」)はビットコインが使われる時にのみ明らかになる。
ロックスクリプト:
OP_HASH160 <scriptHash> OP_EQUAL
P2SHの重要性: 複雑さを送信者から受信者へ移す。P2SH出力を作る送信者は20バイトのハッシュだけが必要で、それが単純な署名要件か、3-of-5マルチシグか、複雑なタイムロックかを知る必要がない。P2SHアドレスは3で始まる。
P2WPKH(Pay-to-Witness-Public-Key-Hash)
P2WPKHはBIP-141(2017年)で導入されたP2PKHのSegWitバージョンだ。署名データ(「ウィットネス」)を従来のScriptSigから分離して別のウィットネス構造に移す。
ロックスクリプト:
OP_0 <20-byte pubKeyHash>
利点:
- トランザクション展性の修正。 レガシートランザクションではScriptSigがトランザクションID計算の一部。SegWitは署名をトランザクションID計算から除外し、この攻撃ベクトルを排除する。ライトニングネットワークに不可欠だった。
- ブロックスペースの効率化。 ウィットネスデータは重み割引を受け、1MBの基本ブロックサイズ制限を維持しながら容量を約2-4MBに拡大する。
P2WPKHアドレスはBech32エンコーディングを使い、bc1qで始まる。
P2TR(Pay-to-Taproot)
BIP-341(2021年11月活性化)で導入されたP2TRは、P2SH以来のビットコインスクリプトの最も重要な進化を表す。シュノア署名(BIP-340)とMAST(Merkleized Abstract Syntax Trees)を使用する。
ロックスクリプト:
OP_1 <32-byte tweaked public key>
2つの支出パス:
鍵パス(通常のケース): 所有者が調整された公開鍵に対するシュノア署名を提供する。ブロックチェーン上では、鍵パス支出は他のいかなる鍵パス支出とも区別できない — 元の設定が単純なシングルキーか、3-of-5マルチシグか、複雑なタイムロック契約かに関わらず。
スクリプトパス(代替手段): 鍵パス支出ができない場合、支出者がMASTツリーから特定のスクリプトを公開して満たす。使用されたスクリプトブランチだけが公開され、他の可能なスクリプトはすべて隠されたままだ。
Taprootが革命的な理由:
均一性によるプライバシー。 鍵パスの場合、すべてのTaproot出力がブロックチェーン上で同一に見える。シングルシグ、マルチシグ、複雑なスマートコントラクトのトランザクションがすべてOP_1 <32-byte key>として表示される。
MASTによる効率性。 実行されたスクリプトパスだけが公開される。
シュノア署名。 鍵集約 — 複数の当事者が公開鍵を単一の集約鍵に結合し、単一の集約署名を生成できる。
P2TRアドレスはBech32mエンコーディングを使い、bc1pで始まる。
タイムロックスクリプト
OP_CHECKLOCKTIMEVERIFY(OP_CLTV)
OP_CLTV(BIP-65)は絶対的タイムロックを強制する — 特定のブロック高やUnixタイムスタンプに達するまでビットコインを使えない。
例:ブロック900,000までロックされた資金
ロックスクリプト:
900000 OP_CHECKLOCKTIMEVERIFY OP_DROP <pubKeyHash> OP_DUP OP_HASH160 OP_EQUALVERIFY OP_CHECKSIG
活用:相続。 アリスが1年のCLTVロックでUTXOを作成する。アリスが1年以内に資金を移動しなければ、相続人が相続人の鍵で請求できる。
OP_CHECKSEQUENCEVERIFY(OP_CSV)
OP_CSV(BIP-112)は相対的タイムロックを強制する — UTXOが確認された後、指定されたブロック数が経過するまでビットコインを使えない。
活用:ライトニングネットワーク。 ペイメントチャネルはOP_CSVを使って「紛争期間」を強制する。
結合タイムロック
OP_IF
<alicePubKey> OP_CHECKSIG
OP_ELSE
144 OP_CHECKSEQUENCEVERIFY OP_DROP
<bobPubKey> OP_CHECKSIG
OP_ENDIF
「アリスは自分の署名で即座に使える、またはボブは144ブロック後に自分の署名で使える」を意味する。このパターンがペイメントチャネルのビルディングブロックだ。
マルチシグスクリプト
レガシーマルチシグ(OP_CHECKMULTISIG)
ロックスクリプト:
OP_2 <pubKey1> <pubKey2> <pubKey3> OP_3 OP_CHECKMULTISIG
アンロックスクリプト:
OP_0 <sig1> <sig2>
OP_0の注意: OP_CHECKMULTISIGの古くからのバグの回避策だ。オペコードが必要以上に1つ多い要素をスタックからポップする。このバグは早期に発見されたが、修正はハードフォークとなるため決して修正できなかった。
Taprootマルチシグ(鍵集約)
Taprootでは、シュノア鍵集約(MuSig2プロトコル)を使って、n人の当事者が個別の公開鍵を単一の集約公開鍵に結合し、単一の集約署名を生成できる。3-of-3のTaprootマルチシグは32バイトの公開鍵と64バイトの署名を生成する — シングルキー支出と同じサイズだ。
Tapscript:ビットコインのプログラマビリティの未来
Tapscript(BIP-342)はTaprootスクリプトパス支出で使われる更新されたスクリプトシステムだ。
OP_CHECKSIGADD。 OP_CHECKMULTISIGをより効率的なメカニズムに置き換え、ダミー要素バグを排除する。
OP_SUCCESSオペコード。 Tapscriptは以前無効化または未定義だったオペコードを無条件に成功するOP_SUCCESSとして再定義する。これはクリーンなアップグレードパスを作る:将来のソフトフォークがOP_CTV、OP_CAT、OP_VAULTのような新機能を追加するためにOP_SUCCESSオペコードを再定義できる。
なぜチューリング不完全性が機能なのか
保証された終了。 すべてのビットコインスクリプトは有限のステップで成功または失敗する。無限ループの可能性がない。
静的分析。 チューリング完全でないため、実行せずにスクリプトが正確に何をするか判断できる。
「ガス」不要。 イーサリアムは無限ループ防止のために「ガス」メカニズムが必要。ビットコインの有限実行はこの複雑さの範疇全体を排除する。
より小さな攻撃表面。 言語がシンプルであるほど、悪用方法は少ない。イーサリアムEVMの複雑さはDAOハック(6000万ドル、2016年)、Parityマルチシグバグ(2億8000万ドル凍結、2017年)など数多くのエクスプロイトを引き起こした。
実際的な意味
ビットコインスクリプトを理解することは学術的なだけでなく、ビットコインを使うすべての人に実際的な意味を持つ:
アドレスタイプの選択。 P2TR(Taproot)アドレスが最高のプライバシーと効率性を提供する。
手数料の見積もり。 トランザクション手数料は使用されるスクリプトタイプによって直接決まるトランザクションの重み(サイズ)に基づく。
セキュリティモデルの認識。 ビットコインが企業のセキュリティチームや政府の法制度ではなく、暗号プログラムによって保護されているという知識は、カストディ、バックアップ、相続についての考え方を根本的に変える。
関連トピックはビットコイントランザクションの読み方、Taproot、SegWitのガイドを参照。