トランザクションに署名する
ビットコイン・トランザクション署名の仕組み - SIGHASHタイプ、署名ダイジェスト、そして所有権を証明するECDSA署名。
0ステップ ·
何を学ぶか
- SIGHASHタイプとは何か、そして何が署名されるかをどう制御するか
- 署名ダイジェストを構築する方法(ハッシュされるデータ)
- ECDSA署名が秘密鍵を明かすことなく所有権を証明する仕組み
署名が必要な理由
インプットはUTXOを参照しますが、誰でもあなたのコインを使うと主張するトランザクションを書けます。署名は、トランザクションがUTXOのロッキング・スクリプトに対応する秘密鍵の保有者によって承認されたことを証明します。
有効な署名がなければ、ノードはトランザクションを拒否します。署名とは、願いを承認に変えるものです。
SIGHASHタイプ
署名前に、署名がトランザクションのどの部分をカバーするかを決めるSIGHASHタイプを選びます。これは署名後に何が変更されうるかを制御します。
| SIGHASHタイプ | 値 | 署名されるもの |
|---|---|---|
| SIGHASH_ALL | 0x01 | すべてのインプットとすべてのアウトプット |
| SIGHASH_NONE | 0x02 | すべてのインプット、アウトプットなし |
| SIGHASH_SINGLE | 0x03 | すべてのインプット、同一インデックスのアウトプットのみ |
| SIGHASH_ANYONECANPAY | 0x80 | 上と組み合わせる; 現在のインプットのみ署名 |
**SIGHASH_ALL (0x01)**は大多数のトランザクションで使われます。意味:「私はこれらのインプットがまさにこれらのアウトプットに使われることを承認します。何も変えないでください。」
SIGHASH_ANYONECANPAY | SIGHASH_ALL (0x81)は、複数の人が共有されたアウトプット・セットにインプットを提供するクラウドファンディング型のトランザクションで使われます。
署名ダイジェスト
署名は生のトランザクションを直接カバーしません。代わりに署名ダイジェスト - 関連トランザクション・データにコミットするハッシュ - を構築します。
レガシー署名(SegWit以前)
レガシー・トランザクションの場合、プロセスは:
- シリアライズされたトランザクションから始める
- 現在のインプットのScriptSigを前のアウトプットのScriptPubKeyに置き換える
- 他のすべてのインプットのScriptSigを空に設定する
- SIGHASHタイプを4バイトのリトル・エンディアン値として付加する
- 結果にダブルSHA256を適用する
digest = SHA256(SHA256(modified_tx || sighash_type))
このプロセスは各インプットについて個別に繰り返されなければなりません。
SegWit署名(BIP143)
BIP143はSegWitインプットのためのより効率的な署名アルゴリズムを導入しました。各インプットに対してトランザクション全体を再シリアライズする代わりに、事前計算されたハッシュを使います:
digest = SHA256(SHA256(
version # 4 bytes
hashPrevouts # SHA256d of all input outpoints
hashSequence # SHA256d of all input sequences
outpoint # This input's txid + vout (36 bytes)
scriptCode # The script being satisfied
value # This input's UTXO value (8 bytes)
sequence # This input's sequence (4 bytes)
hashOutputs # SHA256d of all outputs
locktime # 4 bytes
sighash_type # 4 bytes
))
これはレガシー署名のO(n^2)スケーリング問題を解消します - n個のインプットに署名するのにトランザクション全体のn個のコピーをハッシュする必要がありました。
ECDSA署名
ビットコインはsecp256k1曲線上の**ECDSA(Elliptic Curve Digital Signature Algorithm)**を使います。与えられるもの:
- 秘密鍵
d(256ビット整数) - メッセージ・ハッシュ
z(署名ダイジェスト)
アルゴリズムは署名(r, s)を生成します - 対応する公開鍵を使って誰でも検証できる二つの256ビット整数ですが、dを知らない者は誰も偽造できません。
署名はDERエンコードされ、SIGHASHバイトが付加されます:
30 <total-length>
02 <r-length> <r-value>
02 <s-length> <s-value>
<sighash-byte>
典型的なDERエンコードされた署名は71~73バイトです。
Low-S要件
BIP62とBIP146はs値が曲線の位数の下半分にあることを要求します。ECDSA実装が高いS値を生成する場合、それをorder - sで置き換える必要があります。高いS署名を持つトランザクションは現代のノードによって拒否されます。
トランザクションに組み込む
レガシーインプットの場合、署名と公開鍵はScriptSigに入ります:
<sig-length> <DER-signature + sighash>
<pubkey-length> <compressed-public-key (33 bytes)>
SegWitインプットの場合、ScriptSigは空のままで、データはウィットネス・フィールドに入ります - 次で扱います。
次のステップ
SegWitとウィットネス・データに進み、SegWitトランザクションがウィットネス構造に署名を保存する方法を学びましょう。