Bitcoin Core 0.11 (ch 3): Initialization and Startup

提供: tezos-wiki
移動先: 案内検索

このページでは、起動と初期化を管理するBitcoin Coreコードについて説明します。

プログラムエントリポイント

プログラムのエントリポイントは bitcoind.cpp にあります。

main()はコードの3行です:

  • SetupEnvironment()(これはプログラムのロケールを設定します)
  • 信号ハンドラを接続する
  • AppInit()(この関数はプログラムの寿命を延ばす)


AppInit:これは bitcoind.cpp の近くにあります。

  • コマンドラインを解析する
  • データディレクトリを開きます。
  • 設定ファイルを読み込みます
  • プロセスをフォークします(デーモンとして実行している場合)
  • コントロールを init.cpp にあるAppInit2()に渡します。


初期化ステップ( init.cpp

AppInit2()はビットコインシステムを初期化します。

これには約800行のコードが含まれており、12段階に分かれています。

各ステップが始まる場所は、コードに文書化されています。 Init.cpp にはファイルの先頭にいくつかの関数がありますが、大部分はAppInit2()で構成されています。

次の表は、手順をまとめたものです。

初期化
ステップ
簡単な説明 詳細
1 OS固有のセットアップタスク これらの作業は特に興味深いものではありません。
詳細は、コードを参照してください。
2 パラメータの相互作用 特定のコマンドラインオプションでは、特定の方法で他のオプションを設定する必要があります。
たとえば、-zapwallettxesは-rescanを意味します。したがって、コードは-rescanフラグ= trueを設定します(まだ存在していない場合)。
3 内部フラグ /
パラメータ健全性チェック
特定のパラメータのグローバル変数を設定します。
財布については、取引料金レベルを正当性をチェックします(あなたの手数料がリレー[エラー]の資格を得るのに十分高いが、不当に高い[警告]ではないことを確認します)。
4 アプリケーション初期化。 / RPCサーバー

データディレクトリをロックします。 (できない場合は、エラーを出力して終了してください。)
スクリプトチェックエンジン用のXスレッドを生成する。 (デフォルト= 0、使用可能なすべてのプロセッサを使用することを意味し、boost :: thread :: hardware_concurrency)。
"ウォームアップ"モードでRPCサーバーを起動します。

5 ウォレット・データベースの整合性の確認 ウォレットが有効になっている場合は、開こうとします。

ウォレットが破損していることがわかっている場合(-salvagewallet)、パスワードの回復を試みます。

6 ネットワーク初期化

ノードは特定の信号を登録する。
ユーザーが特定のネットワーク(ip4、ip6、tor)のピアとのみ対話したいかどうかを確認します。
オニオンルーティング(tor)を使用するかどうかをチェックします。
ユーザーが特定のピアをホワイトリストに登録するかどうかを確認します。
ビットコインポートでリスンしようとします(失敗時に終了します)。
ユーザーが接続をシードする特定のピアを指定した場合は、接続を試みます。

7 ブロックチェーンをロードします。

ブロックチェーンをメモリにロードし、UTXOキャッシュを初期化します。

キャッシュサイズを計算します。
3つの特定のキャッシュに分割された合計キャッシュサイズがあります。
デフォルトの合計キャッシュサイズ= 100MB(最大:4GB、最小:4MB)。
1)ブロックチェーンキャッシュ:合計キャッシュの1/8ですが、2MBを超えてはいけません。
2)UTXOデータベース・キャッシュ:残りのキャッシュ・スペースの25〜50%。 これはLevelDBキャッシュです。
これは、LevelDBデータの圧縮されていないブロックを格納し、LevelDBによって管理されます。the LevelDB documentation.
3)UTXOインメモリキャッシュ:残りのキャッシュスペースの半分。
このキャッシュサイズは、cacheCoinsオブジェクト(CoinsViewCacheの保護されたメンバー)のサイズを定義します。
TODO:このステートメントが正しいことを確認してください...

ブロックチェーンをmapBlockIndexにロードします。
「ブロックチェイン」とは、ブロックツリー全体(アクティブチェーン内のブロックだけでなく、すべての既知のブロック)を意味します。
メモリにロードされるのはブロックに関するメタデータを含むCBlockIndexオブジェクトです。
最後の288ブロック(VerifyDB)を検証します。
注意:プログラムはこの時点までに起動から1秒未満を要します。 このステップには約10〜20秒かかります。

UTXOセット。
UTXOセットはメモリにロードされません。 代わりに、コインがデータベースからアクセスされるときにキャッシュがいっぱいになります。
2015年5月現在、UTXOセット全体をメモリに格納するには約3.6 GBが必要です。
2016年1月現在、ディスク上の圧縮データは約1.2 GBです。

8 ウォレットをロードします。 プログラムが初めて実行された場合は、ウォレットが作成され、最初のキー(アドレス)が与えられます。
9 Datadirのメンテナンス ユーザーがブロックプルーニングを行っている場合は、NODE_NETWORKの設定を解除し、プルーニング機能を呼び出します。
10 インポートブロック 現在有効なチェーンとして接続されていないブロックチェーンデータベースのチェーンをスキャンします。
11 開始ノード /
RPCサーバー

net.cppでStartNodeを呼び出します。
これは、プログラムのメインスレッドであるThreadProcessMessageを含むネットワーキングスレッドグループを起動します(下記参照)。
RPCサーバーを "ウォームアップ"モードから通常モードに移行します。

12 終了


AppInit2が終了すると、 bitcoind.cpp のAppInit()に戻ります。

そこで、コードのトップレベルスレッドは、WaitForShutdown()という関数で無期限にループします。 2秒間スリープ状態になり、ユーザーがctrl-Cを押したかどうかを確認します。 その場合は、 init.cpp でShutdown()を呼び出します。

シャットダウン()は、RPCサーバーをシャットダウンし、ノードを停止し、シグナルハンドラの登録を解除し、プログラムが完了します。

キャッシュサイズ

ステップ7は、キャッシュサイズを初期化した。手順7で考えられる3つのキャッシュがあります.2つはLevelDBデータベースキャッシュであり、もう1つはコインキャッシュであり、そのサイズは main.cpp のフラッシュコードによって管理されます。

ユーザーは、-dbcacheを使用して合計キャッシュ・サイズを割り当てることができます。ユーザーは、特定の各キャッシュに割り当てるスペースを選択して選択することはできません。デフォルトの合計キャッシュサイズ= 100MB(最大:4GB、最小:4MB)。

'1)ブロックインデックスキャッシュ'

このキャッシュには、/ block / index LevelDBデータの圧縮されていないチャンクが保存され、LevelDBのドキュメントに記載されているように、LevelDBによって管理されます。 br>

ユーザーが完全なトランザクションインデックス(-txindex = 1)を有効にした場合、合計キャッシュサイズの1/8までになります。 -txindexが有効でない場合は、2 MiBだけが必要です。


'2)UTXOデータベースキャッシュ'

これは、/ chainstateデータベースのLevelDBキャッシュです。

このキャッシュは、合計キャッシュ・サイズに応じて、残りのキャッシュ・スペースの25〜50%に割り振られます。


'3)UTXOインメモリキャッシュ'

これは main.cpp コードで管理されるコインキャッシュです。 (FlushStateToDiskおよび関連する関数を参照)

変数(nCoinsCache)は、 main.h のexternとして宣言されています。 main.cpp には、5000 * 300にハードコードされています(メモリ内コインは約300バイトなので5000コインを意味します)。しかし、ステップ7で再初期​​化する必要があります。

このキャッシュには残りのキャッシュ領域がすべて与えられます。

このキャッシュは、初期化中にロードされるのではなく、コインがアクセスされるときに満たされます。 (これは、cachedCoinsUsage = 0を設定するCCoinsViewCacheコンストラクタによって検証できます)。

スレッド起動

このコードでは、boost :: thread_groupsを使用してさまざまなスレッドを管理しています。

Bitcoin Coreはマルチスレッドプログラムですが、 "参照Satoshiクライアントは主にシングルスレッドです"ということに注意してください。 BIP 31(2012)のMike Hearnによるコメント

つまり、プログラムの活動の大部分がメッセージングスレッド(ThreadMessageHandler - 以下を参照)で行われるということです。

ほとんどすべてのスレッドは、プログラムの起動時にスタック上に作成される単一のマスタースレッドグループの一部です( bitcoind.cpp を参照)。このスレッドグループはいくつかの子スレッドを生成する init.cpp に渡されます(いくつかのスクリプト検査スレッドを含みますが、これらはすべて別個のグループではなくマスタースレッドグループの一部です)。

スレッドグループは net.cpp に渡され、メッセージ処理スレッドを含むネットワーキングスレッドが作成されます。

2つの他のスレッドグループはタスク固有です。

  • rpcサーバースレッドグループ(<r> rpcserver.h / cpp </u>を参照)
  • minerスレッドグループ

当然のことながら、ノードはRPCサーバーがアクティブになっている場合にのみRPCサーバースレッドグループを作成し、マイナースレッドグループがマイニングの場合にのみ作成します。両方が無効の場合、Bitcoin Coreは単一のスレッドグループしか持たない。

'子スレッド'

親スレッド(プログラムが動作を開始するスレッドを意味する)は、ほとんどすべてのプログラムの作業を子スレッドに委譲します。 init.cpp net.cpp でスレッドを生成した後、親スレッドは単にシャットダウンコマンドを待ちます。スレッドグループを開き、シャットダウンを続行します。

子スレッドは、作成された順にリストされています。

スレッド いつ / どこで作成されました 説明
スクリプトチェック ステップ4
init.cpp
これはスレッドのセットで、デフォルトでは4です。
スクリプトチェック(署名チェックを含む)は高価なので、別のスレッドで処理されます。
スケジューラ ステップ4
init.cpp
スケジューラスレッド。
(TODO: describe)
RPCスレッド ステップ4
rpcserver.cpp
RPCサーバーが有効な場合は、RPC呼び出しを処理するスレッドのグループを開始します。
インポート ステップ10
init.cpp
ブロックをインポートします。 3つのシナリオ:
1)再インデックス(blk ??? datファイルからすべての既知のブロックを再スキャンする)。
2)ブートストラップ(bootstrap.datをネットワークからの完全なIBDの代わりに使用します)。
3)-loadblock(特定のblk ???。datファイルをスキャンする) - これらのどれも適用されない場合、このスレッドは何もしません。
DNSアドレスシード ステップ11
net.cpp
dnsシードに基づいてIPアドレスのベクトルを構築しようとし、ベクトルとスレッドを終了します。
2014年6月のテストでは、これには約4秒かかり、158のアドレスが見つかりました。
プラグ&プレイ ステップ11
net.cpp
UPNP(ユニバーサルプラグ&プレイ)
UPNPのポートマッピングを扱う。
SocketHandler ステップ11
net.cpp
このスレッドはソケットをサービスします:
関連するすべてのソケットのI / Oを50msのタイムアウトで待機します。
リスニングソケットで新しい着信接続を処理し、新しいピアのCNodeを作成します。
データストリームを受信して送信します。
何もしなかったソケットを切断状態に設定します。
OpenAddedConnections ステップ11
net.cpp
-addnodeパラメーターを使用して、ユーザーが指定したアウトバウンド接続を開始します。
接続できない場合、各サイクルで2分間スリープします。
OpenConnections ステップ11
net.cpp
DNSシードから他のアウトバウンド接続を開始する(失敗した場合、固定シードに基づいてノードを見つける)
接続できない場合、各サイクルで500ミリ秒間スリープします。
MessageHandler ステップ11
net.cpp
これがプログラムの主なスレッドです。
このスレッドはwhile(true)ループを実行し、メッセージの送受信を行います。 (参照 net.cpp:1049)
このコードでは、boost :: signals2を使用してmain.cppのProcessMessages関数とSendMessages関数を呼び出します。
(シグナルを導入するコードはPR 2154にあります - そのプルで最後から2番目のコミットを参照してください)。
ProcessMessageとSendMessageはこのスレッドで実行されます。
したがって、 main.cpp のコードのほとんどはこのスレッドで実行されます。
ウォレットフリュッシャー ステップ12
init.cpp
ウォレットが有効な場合、このスレッドは定期的にウォレットをフラッシュします。


関連項目

Core 0.11(Ch 1):概要
Bitcoin Core 0.11(Ch 2):データストレージ
Bitcoin Core 0.11(Ch 4):P2Pネットワーク
Bitcoin Core 0.11(Ch 5):初期ブロックダウンロード
Bitcoin Core 0.11(Ch 6):ブロックチェーン


Category:技術 Category:開発者