本文へスキップ
buybitcoinsmart

用語集 / トランザクションと手数料

SIGHASH_SINGLE

SIGHASH_SINGLEとは?
SIGHASH_SINGLEは、署名を1つのアウトプットにのみ結び付けるフラグであり、そのアウトプットは、リスト上で署名されるインプットと同じ位置にあるものです。

入力ゼロは出力ゼロと、入力1は出力1と対応し、トランザクション内のそれ以外はすべて署名されないままになります。この設計により、複数の当事者が1つの共有トランザクションの中で各自の受け取りを保証できます。また、ビットコインで最も悪名高い署名のバグを抱えており、レガシー入力には今もこれが含まれています。

仕組み

ダイジェストは、署名対象の入力、トランザクションのバージョン、ロックタイム、そしてちょうど1つの出力、すなわちインデックスがその入力のインデックスと一致する出力を保持します。

そのインデックスより後の出力は、ハッシュ計算の前にコピーから削除されます。それより前の出力はプレースホルダーとして残りますが、中身は空にされ、値はマイナス1、スクリプトは空となり、実際の中身もまた対象に含まれません。他のすべての入力のシーケンス番号は、出力なしフラグの場合と同様にゼロにされます。

そこにバグがあります。元のアルゴリズムでは、署名対象の入力のインデックスが出力の数以上である場合、ハッシュすべき一致する出力が存在しません。コードは失敗する代わりに、固定のダイジェスト、すなわち32バイトの値1を返します。この位置に該当する署名者は全員、同一のダイジェストに対する署名を生成するため、その署名は特定のトランザクションに束縛されず、同じインデックスに入力を用意できる者なら誰でも持ち出して再利用できます。この分岐はBitcoin Coreに今日まで残っています。削除すると、すでにチェーン上にあるコインの有効性が変わってしまうからです。

署名ハッシュアルゴリズムの2度の書き直しは、いずれもこの穴を塞ぎました。BIP143は、一致する出力のないSegWitバージョン0の入力について、ダイジェストの出力部分を32バイトのゼロとし、ダイジェストの残りの部分はその特定の入力に引き続きコミットするため、再利用できるものは何もないと規定しています。BIP341はさらに踏み込みます。Taprootの入力では、出力数を超えるインデックスを持つこの種類の署名は、単に検証に失敗します。

使われる場面

このフラグは署名の末尾に03として現れ、通常の支払いではなく、ほぼ例外なく事前署名済みのオファーの中で見つかります。

そのパターンは、招待として公開された半分のトランザクションです。売り手は「私のこの入力が入り、一致するインデックスの出力が私の提示価格を私に支払う」という文言に署名し、トランザクションの残りを買い手が埋められるよう空白のままにします。売り手の署名は他のすべての入力と出力を無視するため、買い手は自分の資金、自分のお釣り、そしてmempoolが要求するどの水準の手数料でも追加でき、売り手の保証はそのまま維持されます。OrdinalsとRunesのマーケットプレイスはまさにこれに基づいて構築されており、PSBTとして配布されるこの取引は、第三者が間に立たない、真に信頼を必要としない取引のうち、ビットコインが対応する数少ないものの1つです。

このフラグはほぼ常にANYONECANPAYと組み合わせて使われます。単独では依然として入力の完全なリストにコミットしてしまい、他の誰かが完了できるようトランザクションを開いておくという目的が果たせないからです。

SIGHASH_SINGLE vs SIGHASH_ANYONECANPAY

SIGHASH_SINGLEは基本モードであり、SIGHASH_ANYONECANPAYは修飾子であるため、両者は異なる問いに答えます。基本モードは、署名が出力側のどこまでを対象とするかを決めます。すべてか、まったくないか、あるいは一致する1つの出力かです。修飾子は、入力側のどこまでを対象とするかを決めます。すべての入力か、署名対象の1つだけかです。基本モードを1つ選び、そのうえで修飾子を加えるかどうかを別に決めるため、実際の署名のフラグバイトは通常、どちらか一方ではなく両者の合計になります。

混同しやすい用語

よくある質問

SIGHASH_SINGLEのバグとは?

元の署名アルゴリズムでは、一致するアウトプットがないインプットのインデックスは、エラーではなく値1の固定のダイジェストを生成します。そのダイジェストに対する署名はどのトランザクションにも結び付かず、他人が再利用できるため、ウォレットはその位置で決して署名してはなりません。

このバグは今も悪用できますか?

元のアルゴリズムを今も実行するレガシーのインプットでのみ可能です。segwitのインプットはBIP143に従い、代わりにゼロバイトをハッシュし、TaprootのインプットはBIP341の下でそのケースをはっきりと拒否するため、bc1アドレスで保有されるコインは影響を受けません。

関連用語

トランザクションと手数料のその他の用語

このページを英語で読む