Develop with pleasure!

福岡でCloudとかBlockchainとか。

Bitcoinの新しいテストネットワーク「Signet」の仕様を定義したBIP-325

Bitcoin関連のテストを行うのに便利なtestnetだが、ブロックの生成間隔がまばら(30分くらい生成されなかったり、数秒で連続してブロックが生成されたり)だったり、巨大な再編成が起こったりとあまり安定していない。そのためテストになかなか使いづらくなっていた。このような問題を解消するため新しいタイプのテストネットワークがBIP-325として提案された↓

https://github.com/bitcoin/bips/blob/master/bip-0325.mediawiki

Signetでは既存のProof of Workの検証に加えて、ネットワーク起動時に予め設定するチャレンジと呼ばれるscriptPubkeyに対する有効な解答(scriptSig)が提供されるか検証するようになっている。ざっくり言うとPoAタイプのテストネット。

具体的には、ノード起動時に

$ ./bitcoind -signet_blockscript=<scriptPubkey(hexフォーマット)>

のように-signet_blockscriptオプションを使ってチャレンジのscriptPubkeyを指定する。これはP2PKHであってもいいし、k-of-nのマルチシグなどであってもいい。またこのブロックスクリプトによってSignetジェネシスブロックのデータも異なる。詳細はこちら

-signet_blockscriptオプションで起動されたチェーンは、ブロックをマイニングする際に有効なPoWの他、そのブロックのコインベーストランザクションのwitness commitment内にscriptPubkeyに対して有効な解答(scriptSig)を含める必要がある。有効なscriptSigが無い場合無効なブロックと判定される。この時、scriptSig内の署名および署名検証の際に使われるメッセージダイジェストは、ブロックから生成される(詳細は以下BIP参照)。

そのため、-signet_blockscriptに対応する有効な解答が作れるメンバー=対応する秘密鍵を保持し署名を付与できるメンバーしかブロックが作れなくなる。つまり予め決められたこれらのメンバーによりそのsignetのブロックは作られていくことになる。

以下、BIPの内容↓(仕組みの概要は書かれてるけど、Bitcoin Wikiの方がカスタムSignetの立て方など具体的に書いてて参考になるかも。)

概要

複数の独立した参加者が関与する長期的なテストシナリオのため、ブロックの進行に対してProof of Workに加えて署名が使用される新しいタイプのテストネットワークにより、優れた調整と堅牢性を実現する。

動機

Testnetは実際のお金を危険に晒すこと無く新しいことを試すのに最適な場所だが、信頼性が低いことで有名だ。巨大なブロックの再編成や、マイニング中のブロック間に長いギャップが生じたり、また急に連続してブロックが作成されるバーストは、特に長期間に渡ってソフトウェアを実行する複数の独立した参加者が関与するソフトウェアの現実的なテストが実際に実行不可能となることを意味する。

新しいタイプのテストネットワークは、取引所などの組織による結合テストや、eltooやサイドチェーンペグなど次世代のLayer2プロトコルのテストにより適しいてる。目標は完全に信頼できることではなく、むしろ予測可能な非信頼性の量を持つことである。テストネットワークがmainnetと同じように動作する(つまり数千のブロックの再編成などはない)のと同時に、6ブロックの再編成などの予想される稀なイベントをトリガーしやすくする必要がある。Regtestはブロックの作成にコストがかからないため、複数の独立した参加者が関係する長期的シナリオには適していないため、どの参加者もテストネットワークを完全に制御できる。

仕様

新しいタイプのネットワーク「Signet」はチャレンジ(scriptPubkey)と呼ばれる追加のコンセンサスパラメータを受け取る。このチャレンジは単純なpubkey(P2PKHスタイル)、k-of-nのマルチシグもしくはその他の必要なスクリプトにすることができる。

コインベーストランザクションのwitness commitmentは、2つ目のコミットメント(署名/解答)を含むよう拡張される:

1-4 bytes - 以下の (x + 4) byteをプッシュする
4 bytes - Signetヘッダー (0xecc7daa2)
x bytes - 解答 (sigScript)

4バイトのSignetヘッダーで始まらないプッシュ操作は無視される。4バイトのSignetヘッダーを持つ複数のプッシュ操作は、最初のエントリーを除いて無視される。

チャレンジ内に含まれる全ての署名操作はSHA256d(modifiedBlockHash)、つまり以下のデータのダブルSHA256ダイジェストをsighashとして使用する:

サイズ 名前
Int32 4 nVersion
Uint256 32 hashPrevBlock
Uint256 32 modifiedMerkleRoot
Uint32 4 nTime
Uint32 4 nBits

modifiedMerkleRootハッシュは、コインベースのwitness commitmentに上記Signetの拡張が含まれない状態のブロックトランザクションのマークルルートを生成することで取得できる。これは、ブロックのマークルルートがSignet commitment内のマークルルートと異なることを意味する。これは署名されるメッセージ(この場合ブロック)に署名を含めることはできないためだ。署名とは別にブロック生成(マイニング)を簡単にするために、ブロックのnonce値はSignetの署名がコミットしないブロックの他の唯一のコンポーネントだ。Proof of Workを回していくのに、拡張用nonceは使用できない。これはそれを行うと署名が無効になるためだ。代わりに同じ(もしくは更新された)ブロックに再署名することで、Proof of Workの新しい計算スペースが得られる。

上記のコミットメントが見つかった場合、その解答が有効であれば、ブロックは完全に検証されたとみなされる。この検証はwitness commitmentの検証の前後に直接行うのを推奨する(両者の検証で必要なデータはほぼ同じであるため)。

互換性

この仕様は、既存のソフトウェアがすぐにSignetを使用できるという意味で後方互換性がある。

Signet用のネットワークパラメータ(マジックナンバーなど)を追加するだけで、クライアントは変更を加えることなく任意のsignetネットワークに接続して使用できる。ブロックヘッダーには有効なproof of workがあるため、クライアンはブロックが「おそらく」有効であることを簡単に確認できる。

ただし、特定のsignetネットワークでクライアントが受け入れたブロックは誰でもマイニングができる。ただし、これらのブロックには必要な署名が含まれていないため、完全な検証を行うノードはすぐにそのブロックを拒否する。そのため、クライアントはコインベーストランザクション内のブロックの署名を検証するか、信頼できるピアに接続する必要がある。

他のソフトウェアは本番環境で使用しないブロックの署名検証コードを追加する必要はない。これはネットワークが可能な限りmainnetのように動作することが目標である非実稼働のテスト目的に適している。

参照実装

https://github.com/bitcoin/bitcoin/pull/16411