Segregated Witnessウォレット開発ガイド
Overview
このドキュメントのほとんどの内容は、BIP141や BIP143、 BIP144、 BIP145などのsegregated witness関連のBIPに記載されています。このドキュメントは、他の関連ドキュメントへの参照点、また何をすべきで何をすべきではないかのチェックリストと考えてください。
基本的なsegregated witnessのサポート
ウォレットはsegwit互換であると認識されるためには、このセクションの全機能を実装しなければなりません。
P2SHへの送信
- segwit互換のウォレットは、pay-to-script-hashと(BIP16)とそのアドレスフォーマット(BIP13)をサポートしなければなりません。
- 支払いを行う際、ウォレットは与えられたP2SHアドレスを
scriptPubKeyに適切に変換し、トランザクションを作成しなければなりません。 - 支払いを受け取る際、ウォレットはP2WPKHスクリプト(後述)をベースにしたP2SHアドレスを作成し、そのようなアドレスへの支払いを認識できる必要があります。
- 単一署名の支払いのみを受け入れるウォレットの場合でも、これは必須要件です。
P2SH-P2WPKHアドレスの作成
- P2SH-P2WPKHは単一署名の(1から始まる)P2PKHアドレスと互換性があります。
- 他のP2SHアドレスと同様にP2SH-P2WPKHアドレスも3から始まるアドレスです。
- P2SH-P2WPKHのUTXOが使用され、その
redeemScriptが公開されるまで、P2SH-P2WPKHアドレスは(非segwitのマルチシグアドレスなどの)非segwitのP2SHアドレスと区別できません。 - P2SH-P2WPKHアドレスは、P2PKHのように支払いを受け取るために1つの公開鍵のみを使用する場合に使われます。
- P2SH-P2WPKHはP2PKHと同じ公開鍵フォーマットを使用しますが、重要な違いは、P2SH-P2WPKHで使用される公開鍵は必ず圧縮公開鍵である必要があります。33バイトで、
0x02もしくは0x03で始まる公開鍵です。非圧縮の公開鍵など他の形式の公開鍵を使用すると、取り返しのつかない資金損失につながる可能性があります。 - P2SH-P2WPKHアドレスを作成するには:
- 公開鍵のSHA256のRIPEMD160(
keyhash)を計算します。keyhashの形式はP2PKHと同じですが、圧縮されていない鍵を誤って使用するのを防ぎ、プライバシー強化のためにもkeyhashの再利用は避けるべきです。 - P2SHの
redeemScriptは常に22バイトです。それはOP_0から始まり、その後にkeyhashがプッシュされます。(例:0x0014{20-byte keyhash}) - 他のP2SHと同様、
scriptPubKeyはOP_HASH160 hash160(redeemScript) OP_EQUALとなり、そのアドレスは3から始まるP2SHアドレスです。
- 公開鍵のSHA256のRIPEMD160(
トランザクションのシリアライゼーション
- segwit互換のウォレットは
nVersion|txins|txouts|nLockTime形式のオリジナルのトランザクションフォーマットをサポートしなければなりません。 - segwit互換のウォレットは
nVersion|marker|flag|txins|txouts|witness|nLockTime形式の新しいシリアライゼーションフォーマットをサポートしなければなりません。nVersionとtxins、txouts、nLockTimeはオリジナルの形式と同じです。markerは必ず0x00です。flagは必ず0x01です。witnessはトランザクションの全witnessデータをシリアライズしたデータです。- 各txinはwitnessフィールドに関連付けられています。その結果、witnessフィールドの数を示すフィールドは無く、暗黙的に
txinsの数がその数を示します。 - 各witnessフィールドは対応する
txinのスタックアイテムの数を示すcompactSizeinteger で始まります。その後に対応するtxinのwitnessスタックアイテムが続きます。 - 各witnessスタックアイテムは、そのスタックアイテムのバイト数を示す
compactSizeintegerで始まります。 txinがwitnessデータと関連付けられていない場合は、対応するwitnessフィールドの値は0x00となり、witnessスタックアイテムの数がゼロであることを示します。
- 各txinはwitnessフィールドに関連付けられています。その結果、witnessフィールドの数を示すフィールドは無く、暗黙的に
- トランザクション内の全ての
txinsがwitnessデータに関連付けられていない場合は、トランザクションはmarkerやflag、witnessが無いオリジナルのトランザクションフォーマットでシリアライズされなければなりません。例えば、トランザクションのtxinsが全てsegwitのUTXOではない場合、そのトランザクションはオリジナルのトランザクションフォーマットでシリアライズされなければなりません。(コインベーストランザクションを除く) - トランザクションのシリアライゼーションの例はBIP143のexampleに記載されています。ウォレットの開発者は実装が新しいトランザクションフォーマットを正しくパースできているかそのexampleでテストすることができます。
Transaction ID
- segwitでは、トランザクションは2つのIDを持ちます。
txidの定義は変わらず、オリジナルのシリアライゼーションフォーマットでダブルSHA256した値です。- 新しく
wtxidが定義され、これはwitnessデータを含む新しいトランザクションフォーマットをダブルSHA256した値になります。 - トランザクションがwitnessデータを持たない場合、
wtxidとtxidは同じ値になります。 txidは引き続きトランザクションのプライマリ識別子として使われます:txin内で前の出力を参照する際に使用されます。- ウォレットやサービスが現在トランザクションを識別するのに
txidを使用している場合、アップグレード後も同様に使い続けることができます。
P2SH-P2WPKHの署名の作成と検証
- 非segwitのUTXOを使用する場合は、署名生成のアルゴリズムは今までと変わりません。
- P2SH-P2WPKHのUTXOを使用する場合:
scriptSigにはredeemScriptしかプッシュしてはいけません。- 対応するwitnessフィールドには署名がプッシュされ、その次に公開鍵がプッシュされなければなりません。
- segwit scriptのための新しい署名生成アルゴリズムがBIP143に定義されています。開発者は注意深くその指示に従い、BIP143のexampleを参考に
sighashを再現できるか確認する必要があります。 - BIP143の署名生成アルゴリズムは、使用される入力のコインの量をカバーしており、軽量ウォレットやハードウェアウォレットの設計のエアギャップを簡素化します。
- P2SH-P2WPKHの場合、
scriptCodeは先頭のバイトを含めて常に26バイトで、0x1976a914{20-byte keyhash}88acとなります。redeemScriptでもscriptPubKeyでもないので注意してください。 - Example
ネットワークサービス(オプション)
- ウォレットがピアツーピアネットワークを介してトランザクションを送受信する場合、ネットワークサービスが必要です。
- Segwit互換ノードは、service bit:
NODE_WITNESS = (1 << 3)を使ってwitnessを提供できることを宣言します。 - witnessデータを持たないトランザクション(=オリジナルフォーマットでシリアライズされたトランザクション)は、
NODE_WITNESSのサポートの有無に関わらず別のノードに送信できます。 - segwitのUTXOを使用するトランザクション(=新しいシリアライゼーションフォーマットでシリアライズされたトランザクション)は、
NODE_WITNESSをサポートしているノードにのみ送信できます。 - segiwtのUTXOを使用しているがwitnessデータが取り除かれたトランザクション(=オリジナルのフォーマットでシリアライズされたトランザクション)が、
NODE_WITNESSをサポートしないノードに送信される可能性があります。ただし、segwitのアクティベート後はそのようなトランザクションは無効となるためブロックにも受け入れられなくなります。 - ネットワークサービスの詳細についてはBIP144に記載されています。
ユーザーのプライバシー
- segwitがアクティベートされて数日は、ネットワーク内に流れるsegwitトランザクション数は限られたものでしょう。
- その間segwitのトランザクションを使用するとBitcoinの追跡が容易になる場合があります。
- デフォルトのお釣りの出力にP2SH-P2WPKHを使用すると、プライバシーに影響を与える可能性があります。
トランザクション手数料の見積もり
- トランザクションサイズに代わって、”virtual size” (
vsize)と呼ばれる新しいメトリックが定義されました。 - トランザクションの
vsizeは、オリジナルシリアライゼーションでシリアライズしたトランザクションデータを3倍し、新しいシリアライゼーションフォーマットでシリアライズしたトランザクションデータをプラスし、その値を4で割って次の整数に切り上げた数値です。例えば新しいシリアライゼーションフォーマットで200バイトのトランザクションで、markerとflagとwitnessを除くと99バイトの場合、vsizeは (99 * 3 + 200) / 4 = 125(切り上げ)となります。 - 非segwitトランザクションの
vsizeは単純にそのトランザクションサイズと同じになります。 - トランザクション手数料は他のトランザクションと
vsizeを比較して見積もられます。(今までのサイズではなく) - 開発者は手数料の見積もりで、4倍の間違いをしないよう気をつける必要があります。
安全なアップグレード
- エンドユーザーはsegwitがネットワーク上で完全にアクティベートされるまで、 P2SH-P2WPKHまたはその他のsegwitアドレスを生成してはいけません。アクティベートの前にP2SH-P2WPKHまたはその他のsegwitアドレスを使用すると、資金を失う可能性があります。
- 同様にお釣り用の出力もアクティベート前にsegwitの出力に送ってはいけません。
- segwitのアクティベーションはBIP9で定義されています。2016年11月15日から2017年11月15日(UTC)までの間、retargetサイクルの2016ブロックのうち1916ブロックがシグナリングされ準備ができた場合、segwitは次のサイクルの後のretargetサイクルでアクティベートされます。
- BIP9のシグナルを判断できないウォレットは、segwitがアクティベートされるまで、segwitのアップグレードバージョンのウォレットをエンドユーザーにリリースすべきではありません。
- 一部のマイナーが新しいルールを正しく実行できない懸念がある場合、アップグレードしたウォレットのリリースは(全てではないにしろ)大半のマイナーが新しいルールに従っていることが確認できるまで延期される可能性があります。ルールに違反している場合、無効な孤立ブロックとして明確に確認できます。
後方互換性
- (1で始まる)P2PKHの支払いの送受信は、引き続きサポートする必要があります。
複雑なスクリプトのサポート
ウォレットが単一署名以外のマルチシグのようなスクリプトタイプをサポートしている場合、以下の要件を満たさなければなりません。
P2SH-P2WSHアドレスの作成
- P2SH-P2WSHアドレスは、P2SHアドレスと互換性があり、任意の複雑なスクリプトを固定サイズのアドレスで表現することができます。
- 他のP2SHやP2SH-P2WPKHアドレスと同様、P2SH-P2WSHアドレスも3から始まります。これらは実際にUTXOを使用し
redeemScriptが公開されるまで区別できません。 - P2SH-P2WSHアドレスを作成するには:
witnessScriptと呼ばれるスクリプトを定義します。witnessScriptのSHA256(scripthash)を計算します。この時ダブルSHA256やRIPEMD160(SHA256)でなく、単体のSHA256であることに注意してください。- P2SHの
redeemScriptは常に34バイトです。OP_0から始まり、その後にscripthashがプッシュされます。(例:0x0020{32-byte scripthash}) - 他のP2SHと同様、
scriptPubKeyはOP_HASH160 hash160(redeemScript) OP_EQUALで、対応するアドレスは3から始まるP2SHアドレスです。
- スクリプトの制限事項
- スクリプトの評価に失敗してはならず、評価後のスタックにはただ1つTRUEとなるスタックアイテムが残っている状態でないといけません。それ以外の場合、評価は失敗します。
- P2SH-P2WSHスクリプト内の公開鍵は圧縮公開鍵でなければならず、それ以外の場合資金が永久に失われる可能性があります。
- OP_IFやOP_NOTIFが使われている場合、その引数は空のvector(false)か
0x01(true)でなければなりません。他の値を使うと資金が永久に失われる可能性があります。 (BIP draft) - OP_CHECKSIGやOP_CHECKMULTISIGがfailを返す場合、全ての署名は空のvectorでなければなりません。それ以外の場合、資金が永久に失われる可能性があります。 (BIP146)
witnessScriptのデフォルトポリシー制限は3600バイトです。witnessScriptを除いて、witnessスタックアイテムは最大100個で、それぞれ最大で80バイトです。これらの制限を超えるトランザクションは中継されずブロックにも入れられません。- スクリプトサイズの10000バイト制限や、201
nOpCountなどの元々のコンセンサスの制約の多くは、そのままP2SH-P2WSHにも適用されます。 - P2SHの520バイトのスクリプトサイズ制限はP2SH-P2WSHには適用されません。これは3600バイトのポリシー制限と10000バイトのコンセンサス制限に置き換えられます。
P2SH-P2WSHの署名の生成と検証
- P2SH-P2WSHを使用するには:
scriptSigには、redeemScriptしかプッシュしてはいけません。- 対応するwitnessフィールドの最後のwitnessアイテムは
witnessScriptでなければなりません。 - 新しいBIP143の署名生成アルゴリズムが適用されます:
- OP_CODESEPARATORを使わない場合、
scriptCodeはwitnessScriptのサイズを示すcompactSizeintegerとそれに続くwitnessScriptになります。例えば、スクリプトがOP_1 (0x51)だとすると、シリアライズしたscriptCodeは(0x0151)になります。 - あまり一般的ではありませんがOP_CODESEPARATORを含むスクリプトについては、BIP143を参照ください。
- OP_CODESEPARATORを使わない場合、
witnessScriptより前のwitnessスタックアイテムはスクリプトを評価する際の入力スタックとして使われます。入力スタックはスクリプトとしては解釈されません。そのため、例えば大きなデータをプッシュするのに0x4c(OP_PUSHDATA1) を使う必要はありません。- 署名の生成とスタック上のシリアライズされた署名が正しいか検証するには、BIP143のexampleを参考にテストしてください。
- Example
高度な設計
最初のsegwitサポートには以下の機能は必要ありません。
Native Pay-to-Witness-Public-Key-Hash (P2WPKH)
- Native P2WPKHは22バイトの
scriptPubKeyです。このscriptPubKeyはOP_0で始まり、その後にkeyhashがプッシュされます。(例:0x0014{20-byte keyhash}) - P2SH-P2WPKHと同様、
keyhashは圧縮公開鍵をRIPEMD160(SHA256)した値です。 - Native P2WPKHを使用する際は、
scriptSigは必ず空で、witnessスタックの形式と署名の生成ルールはP2SH-P2WPKHと同じです(圧縮公開鍵を使用する要件含め)。 - Example
Native Pay-to-Witness-Script-Hash (P2WSH)
- Native P2WSHは34バイトの
scriptPubKeyです。このscriptPubKeyはOP_0から始まり、その後にscripthashがプッシュされます。(例:0x0020{32-byte scripthash}) - P2SH-P2WSHと同様、
scripthashはwitnessScriptをSHA256した値です。 - Native P2WSHを使用する際は、
scriptSigは必ず空で、witnessスタックの形式と署名の生成ルールはP2SH-P2WSHと同じです(圧縮公開鍵を使用する要件含め)。 - Example
Native P2WPKHやP2WSHはどうやって使うのか?
- Native P2WPKHおよびP2WSHのアドレス形式はありません。BIP142は延期され全く違う方法で実装される可能性が高いです。別の試みのBIP173 (Bech32)が2017年6月時点で’Draft’ステータスです。
- P2SH版と比べ、Native版のトランザクションの
vsizeはほとんどの場合小さくなります。そのため手数料はより少額になります。 - Native P2WPKHとP2WSHはBIP70のPayment ProtocolのようにRAW
scriptPubKeyプロトコルを使用します。ただ支払人と受取人のプライバシーに影響する可能性があります(下記参照)。 - Native P2WPKHとP2WSHをデフォルトのお釣り用のアドレスとして使用することはできますが、これにより他の人々が容易にお釣りを識別することができます(下記参照)。
- Native P2WPKHやP2WSHの使用は当初は珍しく、プライバシーの問題を引き起こす可能性があります。
