本文へスキップ
buybitcoinsmart

用語集 / プロトコルとアップグレード

キーパス・スペンド

キーパス・スペンドとは?
キーパス・スペンドは、調整済みの出力鍵に対する1つの署名でTaprootの出力を決済し、ちょうど1つの要素からなるウィットネスを公開して、代替のスクリプトについては何も明らかにしません。

BIP-341で規定されています。

Taprootのアウトプットは、その鍵に対して署名することで、またはコミットされたスクリプトを明かすことで空にすることができ、鍵によるルートが目立たない方のルートです。BIP-341は、そのウィットネスをちょうど1つの要素、デフォルトのsighashの下での64バイトのSchnorr署名に固定しており、これによりインプット全体が230ウェイトユニット、つまり57.5vbytesになります。保有者にとって、共有ボールトと単独の支払いは、オンチェーン上では同じに見えます。

仕組み

鍵パスによる支払いはアウトプット鍵に対して署名しますが、これは誰かが選んだ鍵ではありません。BIP-341はこれをQ = P + int(t)Gとして構築します。ここでPは内部公開鍵であり、tはPとスクリプトツリーのマークルルートとを合わせたタグ付きハッシュです。

したがって署名とは、同じシフトを秘密側に適用することを意味します。参照ルーチンは、内部点のy座標が奇数である場合にまず秘密鍵を反転させます。Taprootのtweakは32バイトのx-only鍵に適用されるためです。その後、曲線の位数を法としてtを加算します。その結果はBIP-340に従って署名され、単独でウィットネススタックに載ります。

検証は、暗号学的な検査である前に、数え上げの検査です。ノードはウィットネスプログラムの32バイトを読み、ウィットネススタックが空であれば直ちに失敗させ、要素が2つ以上あり、かつその最後の要素が0x50で始まる場合には、その要素をannexとして取り除きます。ちょうど1つの要素が残れば、その支払いは鍵パスによる支払いであり、その要素はアウトプット鍵に対してBIP-340署名として検証されなければなりません。この手順のどこにも、スクリプトツリーが過去にコミットされたかどうかをノードに伝えるものはありません。

署名は、値0x00のSIGHASH_DEFAULTが暗黙に指定されている場合には64バイトであり、トランザクション全体を対象とします。別のsighashバイトが付加される場合には65バイトになり、その最後の位置に0x00を持つ65バイトの署名は意図的に拒否されます。これを許すと、マイナーまたは中継する任意のノードが64バイトの署名を65バイトまで水増しでき、wtxidと送信者が意図した手数料率を変えてしまうからです。

署名が対象とするのは、最大で206バイトのメッセージです。トランザクションのバージョンとlocktime、すべてのインプットのoutpoint、金額、直前のscriptPubKey、シーケンス番号のそれぞれのハッシュ、そしてアウトプットにコミットします。

サイズの計算はそこから導かれます。BIP-141の下では、トランザクションの重量はベースサイズ掛ける3に総サイズを足したものであり、仮想サイズはその重量を4で割ったもので、トランザクション全体としては切り上げます。Taprootのインプットは、41ベースバイト(36バイトのoutpoint、空のscriptSigのための1バイトの長さ、4バイトのシーケンス)と、66ウィットネスバイト(スタック数、長さの接頭辞、署名)を占め、41掛ける3足す107、つまり230ウェイトユニットとなり、したがって57.5vbytesとなります。

BIP-341の1つの推奨事項が、ウォレットの作者を戸惑わせます。スクリプトをまったく持たないアウトプットでも、内部鍵そのもののタグ付きハッシュとして計算されるtweakにコミットすべきであり、内部鍵をそのまま公開すべきではありません。仕様はその理由を明記しています。2つの当事者がそれぞれの鍵を共有アウトプット鍵に加算する場合、一方が、自分だけが支払えるスクリプトパスを隠すtweakをこっそり織り込むことができ、他方にはそれに気づく手段がないからです。

ビットコインを購入するときにこれが重要な理由

Taprootの署名メッセージは、ハードウェアウォレットが接続先のコンピュータを信頼せずに手数料を計算できる理由です。

BIP-143、SegWitバージョン0のルールの下では、メッセージは署名するインプットが支払う金額にのみコミットし、それ以上はありませんでした。3つのインプットを持つトランザクションの1つのインプットに署名する機器は、残り2つの金額を渡されなければならず、それを検証できませんでした。これは、侵害されたホストが、画面に表示されたよりはるかに多くの手数料を署名させるために使う隙です。BIP-341は、トランザクションが支払うすべてのインプットの金額と、それらすべての直前のscriptPubKeyにコミットするため、署名者は自らそれらを合計できます。このアップグレードはスクリプトパスによる支払いにも及びますが、当サイトの41件のウォレットレビューに登場する機器の所有者のほとんどが出会うのは鍵パスの方です。

これらのいずれかが当てはまるには、まずウォレットが鍵を導出できなければなりませんが、それらのレビューでは状況は一様ではありません。KeepKeyは2025年2月にファームウェア7.10.0でTaprootのアウトプット対応を追加しました。MetaMask自身の発表は依然としてTaprootを後日の提供予定として挙げているため、ビットコイン対応の他の部分がどうであれ、受け取り用のbc1pアドレスを提供できません。

手数料はインプットごとにわずかな差で鍵パスの方に傾き、それは多くの読者が購入する方向に積み重なります。BIP-143自身のテストベクターにある署名済みのP2WPKHインプットは、71バイトの署名と33バイトの鍵を持ち、スタック数と長さの接頭辞を数えると107ウィットネスバイトとなり、これは271ウェイトユニット、つまり67.75vbytesになります。鍵パスのインプットはそれに対して10.25vbytesを節約するため、30回の少額購入を別々に積み重ね、後でそれらを統合する貯蓄者は、その1つのトランザクションから約307vbytesを削減できます。

プライバシーが実際に何をもたらすのかを明確にしてください。支払いポリシーを隠すことは履歴を隠すことではありません。コインが当サイトがレビューする63社の取引所の1つから来たのであれば、そのプラットフォームはすでにあなたの本人確認書類と出金先アドレスを保有しており、いかなる署名形式もそれには触れません。隠されたままなのは、そのコインが1つの鍵で守られていたのか、弁護士によるリカバリー用の分岐を伴う定足数で守られていたのかという点であり、アドレスを標的にする価値があるのはこの2つ目の事実です。

taproot_sign_keyを順に見る

taproot_sign_keyは、BIP-341がこの正確なウィットネスを生成するために公開している参照ルーチンであり、全体でPythonの9行です。

これはスクリプトツリー、内部秘密鍵、sighashタイプ、そしてBIP-340が要求する補助的なランダム性を受け取ります。スクリプトツリーが空の場合、tweakの入力に空のバイト文字列を設定し、そうでなければその入力はツリーヘルパーが返すマークルルートです。その値で内部秘密鍵をtweakし、sighashに署名し、タイプがゼロでない場合にのみハッシュタイプのバイトを付加し、1つの項目を保持するリストを返します。その項目がウィットネス全体です。

2つの詳細に注意を払う価値があります。空の分岐は、見た目に反してtweakなしの場合ではありません。空のバイト文字列を渡すと、tweakは内部鍵そのもののタグ付きハッシュのまま残り、これはまさに、スクリプトを持たないアウトプットに対して仕様が推奨する支払い不可能なコミットメントだからです。そして、ランダム性の引数はTaprootではなくBIP-340に属します。鍵がtweakされた後、結果は通常のSchnorr署名であり、だからこそ鍵パスによる支払いは、バッチで検証されるために特別な処理を必要としません。

キーパス・スペンドvs P2TR

P2TRはアウトプットの種類であり、鍵パスによる支払いはそれを空にする2つの方法のうちの1つです。コインは、後でどのルートで使われようともP2TRのコインのままです。この区別は、誰かがTaprootアドレスはプライベートだと言うときに重要になります。受け取りに使うと、いずれの場合も32バイトの鍵だけを公開し、それ以外は何も公開しません。一方、人がプライバシーと呼ぶものは、支払いの瞬間に、しかも鍵のルートが取られた場合にのみ現れます。

キーパス・スペンドvs MuSig2

MuSig2は鍵パスによる支払いが必要とする署名を生成する1つの方法であり、その要件ではありません。単一の所有者が単一の鍵で署名する場合、支払うたびに集約プロトコルを一切介さずに鍵パスによる支払いを行います。この2つが混同されるのは、集約が興味深いケースだからです。MuSig2は複数の当事者が1つの鍵と1つの署名に到達できるようにするため、その決済は昼食代を支払う人と同じルートと同じ57.5vbytesを取ります。逆も成り立ち、集約鍵はスクリプトのリーフの中に置くことができ、そこで支払うことは、たまたまMuSig2を使うスクリプトパスによる支払いになります。

混同しやすい用語

よくある質問

鍵パスによる支払いは、そのアウトプットの背後にスクリプトがなかったことを証明するものですか?

いいえ。ノードが見るのは1つの署名であり、スクリプトツリーがコミットされていたかどうかを判別できません。これこそがこの設計の狙いです。BIP-341はさらに進んで、スクリプトがまったくないアウトプットでも鍵を調整することを推奨しています。出力鍵が複数の当事者の鍵を集約したものである場合、そうしないと当事者の1人が隠れたスクリプトパスを紛れ込ませ、そのコインを単独で使用できてしまうからです。

キーパス・スペンドはスクリプトパス・スペンドより手数料が安いですか?

はい、しかも通常は大きな差がつきます。キーパス・スペンドのインプットは64バイトの署名を1つ含み、合計57.5vbyteになります。一方、スクリプトパス・スペンドは、使用したリーフスクリプトに加えて33バイトのコントロールブロックを公開する必要があり、このコントロールブロックはツリーの各階層ごとにさらに32バイトずつ大きくなります。

自分のウォレットがキーパス・スペンドを行っているかどうかは、どうやって確認できますか?

そのウォレットがそもそもTaprootアドレスを導出するかどうかを確認してください。bc1pアドレスが発行され、そこから単一の署名で使用するなら、それがキーパス・スペンドです。対応状況はまだ一様ではありません。KeepKeyは2025年2月のファームウェア7.10.0でTaprootアウトプットを追加しましたが、MetaMaskはTaprootがまだ未対応だとしています。

次に読む

関連用語

プロトコルとアップグレードのその他の用語

このページを英語で読む