ブロック709,632でのTaprootのアクティベーションの準備に関する発行済みの週刊シリーズのすべてのコピー。

  1. bech32m送信のサポート
  2. Taprootはシングルシグでも価値があるか?
  3. Taproot descriptor
  4. P2WPKHからシングルシグのP2TRへ
  5. なぜ待つ必要があるのか?

bech32m送信のサポート

ニュースレター #154に掲載

11月に予定されているブロック709,632から、 BitcoinユーザーはTaprootアドレスへの支払いを安全に受け取ることができるようになります。 Taprootに対するユーザーの熱意と、ウォレット開発者がTaprootのサポートを実装する必要がある5ヶ月を考えると、 Optechは、ユーザーができるだけ早くTaprootアドレスを生成できるようにする人気ウォレットがいくつか出てくると予想しています。

つまり、ユーザーが提供したアドレスにビットコインを送金するウォレットやサービスは、 ブロック709,632までにTaprootアドレスに送信できるようにする必要があり、 そうしないとユーザーを混乱させ失望させるリスクがあります。 Pay to TapRoot (P2TR)アドレスは、BIP350で定義されているbech32mを使用すます。 これはsegwitのv0 P2WPKHおよびP2WSHアドレスに使用されているBIP173のbech32アルゴリズムと少し異なります。 bech32mは、チェックサム関数でbech32の0x01に代わって、0x2bc830a3を使用します。

この1つの定数を変更することで、bech32mのチェックサムを検証できますが、 既存のP2WPKHおよびP2WSHアドレスについては、元の定数を使用する必要があります。 コードはチェックサムを検証せずにアドレスをデコードし、 v0 segwit (bech32)を使用しているか、v1+ segwit (bech32m)を使用しているかを判断し、 適切なチェックサムを検証する必要があります。 例として、C、C++、JS、Pythonのbech32参照実装を更新したPRを参照ください。 コードが既に参照ライブラリを使用している場合は、リポジトリから最新のコードに更新することができますが、 APIの一部がわずかに変更されていることに注意してください。 BIP350と参照実装は、すべてのbech32m実装が使用すべきtest vectorを提供しています。

Taprootアドレスへの支払いの受け取りは、ブロック709,632まで安全ではありませんが、 支払いの送信によって送信者に問題が発生することはありません。 Bitcoin Coreは、(2019年11月にリリースされた)バージョン0.19以降、 Taprootへの支払いアウトプットを持つトランザクションのリレーや、マイニングをサポートしています。 Optechは、ウォレットやサービスの開発者に対して、Taprootがアクティベートされるまで待つことなく、 今すぐにbech32mのTaprootアドレスへの支払いのサポートを実装することを推奨しています。

Taprootはシングルシグでも価値があるか?

ニュースレター #155に掲載

OptechのTransaction size calculatorを使用すると、 さまざまななタイプのシングルシグ・トランザクションのサイズを比較できます。 予想どおり、P2WPKHのインプットとアウトプットを使用したトランザクションは、 P2PKHのインプットとアウトプットを使用したトランザクションよりもはるかに小さいですが、 意外なことに、P2TRのトランザクションは同等のP2WPKHのトランザクションよりもわずかに大きくなります。

  P2PKH (legacy) P2WPKH (segwit v0) P2TR (taproot/segwit v1)
Output 34 31 43
Input 148 68 57.5
2-in, 2-out tx 374 208.5 211.5

そのため、シングルシグのウォレットがブロック709,632 に備えてTaprootの送信を実装するのは逆効果のように思えるかもしれません。 しかし、よく見てみると、ウォレットのユーザーにとってもネットワーク全体にとっても、 シングルシグにP2TRを使用するのは多くのメリットがあります。

  • 使用料が安い: シングルシグのP2TR UTXOを使用する際のインプットレベルのコストは、 P2WPKH UTXOを使用する際のコストよりも約15%低くなります。 上の表のような単純な分析では、使用者が支払いを要求されているアドレスを選択できないという詳細が隠されています。 つまり、あなたがP2WPKHのままで他のユーザーがP2TRにアップグレードした場合、 あなたの2-in-2-outトランザクションの実際の典型的なサイズは、232.5 vbyteになりますが、 すべてP2TRのトランザクションは211.5 vbyteのままです。

  • プライバシー: アーリーアダプターが新しいスクリプトフォーマットに変更すると一部のプライバシーが失われますが、 Taprootに切り替えたユーザーはすぐにプライバシーが強化されます。 あなたのトランザクションは、新しいLNチャネルや、より効率的なDLC、 安全なマルチシグ、さまざまな賢いウォレットバックアップリカバリー方式、 その他の100の先駆的な開発に取り組んでいる人たちと見分けがつかなくなります。

    P2TRをシングルシグに使用することで、既存のユーザーのプライバシーに影響を与えることなく、 ウォレットをマルチシグやTapscript、LNサポート、またはその他の機能に後でアップグレードすることも可能です。 UTXOがソフトウェアの旧バージョンと新バージョンのどちらで受信されたかは問題になりません。 どちらのUTXOもオンチェーンでは同じように見えます。

  • ハードウェア署名デバイスの利便性の向上: 手数料の過払い攻撃が再発見されてから、 いくつかのハードウェア署名デバイスは、トランザクションで使用される各UTXOに、 そのUTXOを生成したトランザクション全体の重要な部分のコピーを含むメタデータが提供されない限り、 トランザクションへの署名を拒否します。 これにより、ハードウェア署名者が実行しなければならない最悪のケースの処理が大幅に増え、 特に限られたサイズのQRコードを主な通信媒体として使用するハードウェア署名者にとっては問題になります。 Taprootは、手数料の過払い攻撃の原因となる脆弱性を排除し、ハードウェア署名者のパフォーマンスを大幅に向上させます。

  • より予測可能な手数料率: P2PKHおよびP2WPKH UTXOのECDSA署名は、サイズが異なる場合があります(ニュースレター #3参照)。 ウォレットは署名を作成する前にトランザクションの手数料率を選択する必要があるため、 ほとんどのウォレットは、最悪のケースの署名サイズを想定し、 それより小さな署名が生成された場合に手数料率が若干オーバーするのを許容します。 P2TRでは、署名の正確なサイズが事前に分かるため、ウォレットは正確な手数料率を確実に選択することができます。

  • フルノードの支援: Bitcoinシステムの全体的なセキュリティは、かなりの割合のBitcoinユーザーが自身のノードで 承認済みの各トランザクションを検証することに依存しています。 これにはあなたのウォレットが作成するトランザクションの検証も含まれます。 TaprootのSchnorr署名は、効率的なバッチ検証が可能で、 前のブロックをキャッチアップする過程で署名を検証する際にノードが費やす必要のあるCPUサイクル数を約1/2に削減します。 このリストの他のすべてのポイントを拒否したとしても、 フルノードを実行する人々の利益のためにTaprootを使用する準備をご検討ください。

Taproot descriptor

ニュースレター #156に掲載

Output script descriptorは、 ウォレットがアドレスを作成し、そのアドレスに支払われるアウトプットを効率的にスキャンし、 後でそのアドレスから支払うために必要な情報を保存するための汎用的な方法を提供します。 さらに、descriptorは、適度にコンパクトで基本的なチェックサムを含んでいるため、 アドレスの情報をバックアップしたり、異なるウォレット間でコピーしたり、 複数の署名を提供するために協力するウォレット間で共有したりするのに便利です。

descriptorは、現在いくつかのプロジェクトでしか使われていませんが、 descriptorと関連するMiniscriptプロジェクトは、 異なるウォレットやツール間のインターオペラビリティを大幅に向上させる可能性があります。 これは、より多くのユーザーがTaprootの利点を活用して、 マルチシグによるセキュリティとバックアップの使用条件によるリカバリーを向上させるにつれて、 ますます重要になるでしょう。

その前に、Taprootで動作するようにdescriptorを更新する必要があります。 それが最近マージされたBitcoin Core #22051のプルリクエストの主題でした。 単一のdescriptorテンプレートで、P2TRのkeypathによる使用と、 scriptpathによる使用の両方を使用するために必要なすべての情報を提供できるように設計されています。 単純なシングルシグの場合は、以下の記述で十分です:

tr(<key>)

同じ構文をマルチシグや閾値署名にも使用することができます。 例えば、アリスとボブ、キャロルはMuSigを使って鍵を集約し、 tr(<combined_key>)に支払います。

直感的には、tr(<key>)で指定されたkeyはアドレスにエンコードされる鍵にはなりません。 tr() descriptorは、BIP341の安全上の推奨事項に従い、 使用不可能なスクリプトツリーにコミットする内部鍵を使用しています。 これにより、簡易的な鍵集約方式のユーザーに対する攻撃がなくなります (MuSigやMuSig2などのより高度な方式は影響を受けません)。

scriptpathによる使用については、バイナリツリーの内容を指定できる新しい構文が追加されました。 例えば、{ {B,C} , {D,E} }は次のようなツリーを指定します:

Internal key
    / \
   /   \
  / \ / \
  B C D E

ツリーは、前述したdescriptorテンプレートのオプションの2つめのパラメーターとして指定できます。 例えば、アリスがkeypathを介して使用できるようにしたいが、 ボブ、キャロル、ダン、エドモンドが彼女の監査証跡を生成するscriptpathを介して使用できるようにしたい場合 (ただし、サードパーティのチェーン監視用のためのものではない)、アリスは次のdescriptorを使用できます:

tr( <a_key> , { {pk(<b_key>),pk(<c_key>)} , {pk(<d_key>),pk(<e_key>)} )

上記の機能は、Taproot用のdescriptorを使用するために必要なことですが、 PR #22051では、descriptorが期待されるポリシーを完全に記述するために追加できるものがまだいくつか欠けていると指摘しています:

  • keypathの無効化: ユーザーによっては、scriptpathによる使用を強制するために、 keypathの使用を防止したい場合があります。これは現在、 tr()の最初のパラメーターに使用不可能な鍵を使用することで可能ですが、 ウォレットがこの設定をdescriptor自体に保存し、 プライバシーを保護した使用不可能なkeypathを計算させることができると良いでしょう。

  • Tapscriptのマルチシグ: レガシーおよびv0 segwitでは、 multi()およびsortedmulti()descriptorがOP_CHECKMULTISIGopcodeをサポートしています。 Taprootではバッチ検証を可能にするため、スクリプトベースのマルチシグはTapscriptでは少し違った方法で処理されるため、 tr() descriptorでは現在必要なマルチシグopcodeをraw()スクリプトで指定する必要があります。 Tapscript用にmulti()およびsortedmulti()の更新版があると良いでしょう。

  • MuSigベースのマルチシグ: この記事の前半で、 アリスとボブ、キャロルがtr() descriptorを使用するために手動で鍵を集約する説明をしました。 tr(musig(<a_key>, <b_key>, <c_key>))のように指定して、元の鍵情報をすべて保持し、 それを使って協力して署名する際に使用するPSBTフィールドに入力できるようにする関数があると理想的です。

  • タイムロック、ハッシュロック、ポイントロック: LNやDLCCoinswapおよびその他の多くのプロトコルで使用されるこれらの強力な構造は、 今のところraw()関数でしか記述できません。これらのサポートをdescriptorに直接追加することは可能ですが、 代わりにdescriptorの兄弟プロジェクトであるMiniscriptを介してサポートが追加されることになるかもしれません。 Bitcoin CoreへのMiniscriptの統合はまだ進行中のプロジェクトですが、 PSBTやdescriptorのようなツールが既にそうであるように、 その革新性が他のウォレットにも広がることを期待しています。

ウォレットは、Taprootを使い始めるためにdescriptorを実装する必要はありませんが、 実装したウォレットは、後でより高度なTaprootの機能を使用するためのより良い基盤を得ることができます。

P2WPKHからシングルシグのP2TRへ

ニュースレター #157に掲載

既にv0 segwit P2WPKHアウトプットの受け取りと使用をサポートしているウォレットにとって、 シングルシグ用のv1 segwit P2TRへのアップグレードは簡単です。 主な手順は次のとおりです:

  • 新しいBIP32鍵導出パスの使用: BIP32 階層的決定性 (HD)コードを変更する必要はなく、 ユーザーはシードを変更する必要もありません。1 ただし、P2TR公開鍵用の新しい導出パス(BIP86で定義されているような)を使用することを強く推奨します。 そうしないと、ECDSAとSchnorr署名 の両方で同じ鍵を使用した場合に発生する攻撃を受ける可能性があります。

  • ハッシュによる公開鍵の調整: シングルシグでは技術的には必須ではありませんが、 特にすべての鍵がランダムに選択されたBIP32シードから導出されている場合、 BIP341では鍵を使用不可能なscripthashツリーにコミットすることを推奨しています。 これは公開鍵とその鍵のハッシュの曲線の点を加算する楕円曲線の加算操作を使用するという簡単なものです。 この推奨事項に従うことのメリットは、後でスクリプトレスなマルチシグのサポートや、 tr() descriptorのサポートを追加する場合に、同じコードを使用できることです。

  • アドレスの作成と監視: bech32mを使ってアドレスを作成します。 支払いは、scriptPubKey OP_1 <tweaked_pubkey>に送られます。 P2WPKHなどのv0 segwitアドレスのスキャンに使用する方法を使って、 スクリプトに支払いをするトランザクションをスキャンできます。

  • 使用トランザクションの作成: Taprootのすべての非witnessフィールドは、 P2WPKHと同じため、トランザクションのシリアライゼーションの変更について心配する必要はありません。

  • 署名メッセージの作成: これは使用トランザクションのデータに対するコミットメントです。 データのほとんどは、P2WPKHトランザクションに署名するのと同じものですが、 フィールドの順番が変更され、いくつかの追加項目が署名されています。 これを実装するのは、さまざまなデータをハッシュしシリアライズするだけなので、 コードを書くのは簡単です。

  • 署名メッセージのハッシュに署名: Schnorr署名を作成するには、さまざまなな方法があります。 最善の方法は、「独自の暗号を使う」のではなく、信頼できる十分レビューされたライブラリの関数を使用することです。 ただ、何らかの理由によりそれができない場合は、 BIP340は、ECDSA署名を作成するためのプリミティブが利用可能であれば、 簡単に実装できるアルゴリズムを提供します。署名ができたら、 インプットのwitnessデータに入れ、使用トランザクションを送信します。

ブロック709,632でTaprootがアクティベートされる前でも、 testnetやパブリックなデフォルトsignet、 Bitcoin Coreのプライベートなregtestモードを使ってコードをテストできます。 オープンソースのウォレットにTaprootのサポートを追加する場合、 他の開発者があなたのコードから学べるように、 Bitcoin Wikiのtaproot usesページや bech32m adoptionページにその実装のPRへのリンクを追加することをお勧めします。

なぜ待つ必要があるのか?

ニュースレター #158に掲載

これまでの連載では、ウォレットやサービスの開発者に対してTaprootがアクティベートされた時に備えて、 Taprootのアップグレードを今から実装するよう呼びかけてきました。 しかし、サービスやユーザーが損失を被る可能性があるため、 ブロック709,632より前にP2TR用のアドレスを生成しないよう警告しました。

事前にアドレスを生成しない理由は、P2TRスタイルのアウトプットへの支払いは、 ブロック709,632より前では誰でも使用できるためです。 お金は完全に安全ではなくなります。 しかし、そのブロックになると何千ものフルノードがBIP341およびBIP342 (そして関連するBIP340)のルールの適用を開始します。

ブロックチェーンの再編成がないことが保証されているのであれば、 最後のTaproot前のブロック(ブロック709,631)が確認できた時点でP2TRアドレスの生成を始めても安全でしょう。 しかし、ブロックチェーンの再編成については懸念すべき理由があります。 偶然の再編成だけでなく、初期のP2TR支払いからお金を奪うために意図的に作られる再編成もあるためです。

P2TRの支払いを最初に受け取ろうとする大勢の人々を想像してみてください。 ブロック709,631が確認できるとすぐに彼らは単純にいくらかのお金を送信します。2 これらの支払いは、ブロック709,632では安全ですが、 ブロック709,631に代わるブロックを作成したマイナーによって盗まれる可能性があります。 P2TRアウトプットへ送られるお金の価値が十分に大きければ、 1つのブロックではなく2つのブロックをマイニングしようとする方が簡単に利益を得られる可能性があります (詳細はトピックフィー・スナイピングを参照)。

この理由から、再編成のリスクが効果的に解消されたと思われるまでは、 ソフトウェアやサービスでP2TR用のアドレスを生成することはお勧めしません。 アクティベーションから144ブロック(約1日)待つことは、 あなたやあなたのユーザーがTaprootの利点を利用するのを大幅に遅らせることなく、 リスクを最小限に抑えることができる、適度に保守的なマージンだと考えています。

まとめると:

  • 709,631: P2TRスタイルのアウトプットに送信されたお金を誰でも使うことができる最後のブロック
  • 709,632: P2TRアウトプットがBIP341BIP342のルールを満たす場合にのみ使用できる最初のブロック
  • 709,776: ウォレットがユーザーにP2TRアウトプット用のbech32m受信アドレスを提供し始めるのに適したブロック

上記はいずれも、できるだけ早くbech32mアドレスへの支払いを可能にするという、 このシリーズの最初のパートで提供されたアドバイスを変更するものではありません。 安全だと思う前にP2TR用のアドレスを要求した場合、それは彼らのリスクです。

Footnotes

  1. Electrumがsegwit v0にアップグレードされた際、 bech32アドレスで受け取りたい人は誰でも新しいシードを生成する必要がありました。 これは技術的には必要ありませんでしたが、 Electrumの作者は自分たちのカスタムシードの導出方法にいくつかの新しい機能を導入することができました。 その1つがシードのバージョン番号で、シードを使用するスクリプトを指定する機能です。 これにより古いスクリプトを安全に非推奨にできます(例えば、将来リリースされるElectrumのバージョンでは、 従来のP2PKHアドレスへの受信がサポートされなくなる可能性があります)。

    Electrumの開発者がバージョン付きのシードを展開していたのと同時期に、 Bitcoin Coreの開発者は、output script descriptorを使用して、 (他の問題の解決に加えて)スクリプトの非推奨を可能にするという同じ問題を解決し始めました。 次の表は、Electrumのバージョン付きのシードとBitcoin Coreのdescriptorを、 以前両方のウォレットで使用され、 現在も多くの他のウォレットで一般的に使用されているimplicit scripts方式と比較したものです。

    スクリプト管理 初期バックアップ 新しいスクリプトの導入 スキャン(帯域幅/CPUコスト) 非推奨スクリプト
    Implicit scripts (例:BIP44) シードワード 自動(ユーザー操作は不要) サポートされているすべてのスクリプトをスキャン、O(n) サポートされていないスクリプトを使用していることをユーザーに警告する方法はありません
    Explicit scripts(バージョン付きシード) シードワード(バージョンビットを含む) ユーザーは新しいシードのバックアップが必要。 資金は2つの別々のウォレットに分割されるか、ユーザーは旧ウォレットから新しいウォレットに資金を送信する必要があります 単一のスクリプトテンプレートのみをスキャン、O(1) サポートされていないスクリプトに関するユーザーへの警告
    Explicit scripts (descriptor) シードワードとdescriptor ユーザーは新しいdescriptorのバックアップが必要 実際に使用されたスクリプトテンプレートのみをスキャン、O(n); 新しいウォレットの場合はn=1 サポートされていないスクリプトに関するユーザーへの警告

  2. 最初のTaprootブロックでP2TR支払いを受けたいユーザーは、 誰にも教えずにアドレスを生成し、そのアドレス宛にnLockTimeを709,631に設定したトランザクションを作成してください。 このトランザクションは、ブロック709,631を受信するとすぐにブロードキャストできます。 nLockTimeは、そのトランザクションがTaprootのルールが提供される709,632より前のブロックに含まれないことを保証します。 新しいスクリプトタイプやカスタムlocktimeに手を出すのは、 それが何をしているのか分からない場合には危険なので気をつけてください。