chike0905の日記

何者かになりたい

Bitcoind Chainparams調査

Bitcoind Chainparams調査 Bitcoin coreのchainparams.h/.cppを読んでパラメータの意味を調査する。なお本調査では、すべでのコードを精読したわけではなく、呼び出し部分などを参照しながら変数名から推測して執筆しているために、大いに間違っている可能性がある。間違いに気づいたら指摘していただけるとすごく嬉しい。

読んでいるコードは以下

大枠の理解

  • main/test各ネットワークによってそれぞれchainparams.cppでデフォルト値を設定
  • chainparams.hconsensus/params.hを呼んで内包している

consensus/params.hの中身

  • この中のstruct Paramschainparamsから呼んでいる
  • 主に各BIPをアクティベートするためのパラメータと、PoWの設定に関するパラメータ
  • BIP関連大枠としてはソフトフォークの方法として以下の3つがあり、それぞれのアクティベートのためのパラメータが設定されている
    • 各ソフトフォークの方法に関してはこの記事がわかりやすい
    • flag day activation: BIP16
    • IsSuperMajority:BIP34、BIP65、BIP66
    • version bits(BIP9):BIP112、BIP141
      • BIP9に関するパラメータはconsensus/params.h中のstruct BIP9Deploymentで定義されている

パラメータ

params 説明
nSubsidyHalvingInterval int ブロック毎の報酬を半減させるブロック数
BIP16Exception uint256 BIP16が強制的にアクティブになるフラグのブロックハッシュ
BIP34Height int BIP34がアクティブになるブロック高
BIP34Hash uint256 BIP34がアクティブになるブロックハッシュ
BIP65Height int BIP65がアクティブになったブロック高
BIP66Height int BIP66がアクティブになったブロック高
nRuleChangeActivationThreshold unit32_t ソフトフォーク時のアクティベーションするブロックの割合閾値(nMinerConfirmationWindowブロック中の何ブロックの形で指定)
nMinerConfirmationWindow unit32_t アクティベーション時の閾値を定義するためのブロック数(原則としてnPowTargetTimespan / nPowTargetSpacing?)
vDeployments[MAX_VERSION_BITS_DEPLOYMENTS] BIP9Deployment BIP9を利用したソフトフォークパラメータ(struct BIP9Deploymentで定義)
powLimit unit256 PoWのDifficulty最大値
fPowAllowMinDifficultyBlocks bool PoWのDifficultyを最大値と同値を許すかどうか
fPowNoRetargeting bool PoWの難易度調整を行うかどうか
nPowTargetSpacing int64_t PoWの平均成功間隔(秒単位) 
nPowTargetTimespan int64_t PoWの難易度調整を行う間隔(秒単位)
DifficultyAdjustmentInterval int64_t PoWの難易度調整を行う間隔(ブロック単位、nPowTargetTimespan / nPowTargetSpacingから計算して自動設定)
nMinimumChainWork uint256 新規forkチェーン発見時に、最低限満たしているべきPoW難易度
defaultAssumeValid unit256 指定ブロック以前のブロックは正しいとみなすフラグとなるブロックのハッシュ

chainparams.hの中身

  • 中身をみていくと、「チェーンのパラメータ」というより、ノード同士のコミュニケーションであったり、ノード動作/ブートストラップのためのパラメータが主に設定されていた
params 説明
consensus Consensus::Params 上記参照
pchMessageStart CMessageHeader::MessageStartChars 通信時のメッセージヘッダーへ挿入するメッセージPrefix
nDefaultPort int ノードのデフォルト通信ポート
nPruneAfterHeight uint64_t 保存するブロックファイルを圧縮する時の、圧縮せず元データを維持する先頭ブロックからのブロック数
m_assumed_blockchain_size uint64_t 現在の大まかなブロックチェーンデータサイズ(GB単位)
m_assumed_chain_state_size uint64_t 現在のChainStateDBの大まかなサイズ(GB単位)
vSeeds std::vector\<std::string> Seedノードのドメインリスト
base58Prefixes[MAX_BASE58_TYPES] std::vector Base58Checkのencodingを行う際のプレフィックス(それぞれタイプはchainparams.hclass CChainParamsenum Base58Typeで定義)
bech32_hrp std::string bech32におけるHuman Readable Part
strNetworkID std::string ネットワークを識別するID(mainnet/testnetなど)
genesis CBlock Gensisブロック(chainparams.cpp内のCreateGenesisBlock()を用いて生成)
vFixedSeeds std::vector SeedノードのIPv6アドレス(chainparamsseeds.h内で定義)
fDefaultConsistencyChecks bool ノード起動時にBlockIndexやmempoolなどに一貫性があるかのチェックを実施するか(要調査)
fRequireStandard bool スタンダードなTXフォーマットでないTXを扱うかどうか(testnetではtrue)
checkpointData CCheckpointData 検証時にチェックポイントとするブロック高とブロックハッシュのリスト(構造はcheckpoint.hで定義)
chainTxData ChainTxData チェーンの中にあるTXの統計データなど、ノードブートストラップ時のチェーン検証進捗計算のために使われている?(詳細はchainparams.h内のstruct ChainTxDataで定義)
m_fallback_fee_enabled bool WalletでTX作成時にfeeが指定されなかった時に、指定値のfeeを払うようにするかどうか(feeの指定値は起動時に-fallbackfeeパラメータで指定)

感想

  • consensus/params.hの中でソフトフォーク関連のパラメータを定義しているのはなんとなく面白い
    • しかし、ハードコードしている部分が増えるのはノードをブートストラップする時の効率がよくなるのは理解できるが、ソフトウェアとガバナンスの観点からは疑問
  • consensus/params.hの中に半減期の期間の定義があるのはそこで本当にいいのだろうか?と直感的には思った
  • nMinerConfirmationWindowDifficultyAdjustmentIntervalとは別に設定されているのは面白いかもしれない
  • 様々なパラメータが歴史的経緯とともに混沌としていった形跡が見受けられ、一度再設計してみるのも面白いかもしれない
    • BIP関連
  • ノードの運用用のパラメータ(fDefaultConsistencyChecksなど)とノードがコミュニケーションを取るためのパラメータはうまく整理して分離できたりしないだろうか

    • Bitcoinノードの実装と運用、そしてガバナンスに関してコードの観点から疑問を再確認できたので、いい機会だった
  • 最初に読み始めたコードがv0.17ベースのものだったので、すでに削除されたパラメータ(fMineBlocksOnDemand)についても調査していた

    • この辺の歴史的経緯を整理しながらパラメータを整理してドキュメンテーションするのもこのコミュニティには必要なんじゃないだろうかと思ったり