Difference between revisions of "Bitcoin Core 0.11 (ch 3): Initialization and Startup"
m (→Cache Sizes: archived url https://web.archive.org/web/20160417094316/http://leveldb.googlecode.com/git-history/1.17/doc/index.html)
m (→Initialization steps (init.cpp))
|Line 57:||Line 57:|
| 7 || Load the block chain. ||
| 7 || Load the block chain. ||
Load the blockchain into memory and initialize the UTXO caches.<br>
Load the blockchain into memory and initialize the UTXOcaches.<br>
<u>Calculate cache sizes.</u><br>
<u>Calculate cache sizes.</u><br>
Latest revision as of 12:54, 27 June 2020
This page describes the Bitcoin Core code that manages startup and initialization.
Program entry point
The program's entry point can be found in bitcoind.cpp.
main() is three lines of code:
- SetupEnvironment() (all this does is set the program's locale)
- Connect signal handlers
- AppInit() (this function loops for the life of the program)
AppInit: this is located nearby in bitcoind.cpp:
- Parses the command line
- Opens the data directory
- Reads the config file
- Forks a process (if running as a daemon)
- Passes control to AppInit2(), found in init.cpp.
Initialization steps (init.cpp)
AppInit2() initializes the bitcoin system.
It contains about 800 lines of code, which are broken into 12 steps.
Where each step begins is documented in the code. Init.cpp has a few functions at the top of the file, but for the most part it consists of AppInit2().
The following table summarizes the steps:
|Short Description||Longer Description|
|1||OS-specific setup tasks|| These tasks are not particularly interesting.|
For more info, see the code.
|2||Parameter Interactions|| Certain command-line options require other options to be set in a certain way.|
For example, -zapwallettxes implies a -rescan, thus the code will set the -rescan flag=true if it isn't already.
|3|| Internal flags /
| Sets global variables for certain parameters.|
For the wallet, it sanity-checks transaction fee levels (makes sure your fee is high enough to qualify for relay [error]; but not absurdly high [warning]).
|4||Application init. / RPC Server||
Locks the data directory. (If unable, print error and quit.)
|5||Verify wallet database integrity|| If wallet is enabled, try to open it.|
If the user knows that the wallet has been corrupted (-salvagewallet), try to recover the private keys.
The node registers for certain signals.
|7||Load the block chain.||
Load the blockchain into memory and initialize the UTXO caches.
|8||Load the wallet.||If this is the first time the program has been run, it creates a wallet and gives you an initial key (address).|
|9||Datadir maintenance||If the user is block-pruning, unset NODE_NETWORK and call the pruning function.|
|10||Import blocks||Scan for better chains in the block chain database, that are not yet connected as the active best chain.|
|11|| Start node /
Calls StartNode in net.cpp.
When AppInit2 finishes, control returns to AppInit() in bitcoind.cpp.
There, the code's top-level thread loops indefinitely in a function called WaitForShutdown(). It sleeps for 2 seconds and checks to see if the user pressed ctrl-C. If so, it calls Shutdown() back in init.cpp.
Shutdown() shuts down the RPC server, stops the node, unregisters the signal handlers, etc., and then the program completes.
Step 7 initialized the cache sizes. There are 3 caches contemplated in step 7. Two are LevelDB database caches and the other is the coins cache, whose size is managed by the flushing code in main.cpp.
The user can allocate a total cache size with -dbcache. The user cannot pick and choose how much space to allocate to each specific cache. The default total cache size = 100MB (Max: 4 GB, min: 4 MB).
1) Block index cache
This cache stores uncompressed chunks of the /blocks/index LevelDB data and is managed by LevelDB, as described in the LevelDB documentation.
If the user enables a full transaction index (-txindex=1) it can be up to 1/8 of the total cache size. If -txindex is not enabled then only 2 MiB is needed.
2) UTXO database cache
This is the LevelDB cache for the /chainstate database.
This cache is allocated 25-50% of the remaining cache space, depending on the total cache size.
3) UTXO in-memory cache
This is the coins cache that is managed by the main.cpp code. (see FlushStateToDisk and related functions)
The variable (nCoinsCache) is declared as extern in main.h. In main.cpp, it is hard-coded to 5000 * 300 (in-memory coins are about 300 bytes, so this means 5000 coins), however it should be re-initialized in Step 7.
This cache is given all of the remaining cache space.
This cache is not loaded during initialization, rather it is filled as coins are accessed. (This can be verified by the CCoinsViewCache constructor, which sets cachedCoinsUsage=0.)
The code uses boost::thread_groups to manage the various threads.
It should be noted that although Bitcoin Core is a multi-threaded program, "the reference Satoshi client is largely single-threaded." Comment by Mike Hearn in BIP 31 (2012)
What is meant is that the vast majority of the program's activity takes place in the messaging thread (ThreadMessageHandler - see below.)
Almost all of the threads are part of a single, master thread group that is created on the stack at program startup (see bitcoind.cpp). This thread group is passed to init.cpp which creates a few child threads (including a number of script-checking threads, but these are all part of the master thread group, not a separate group.)
The thread group is passed to net.cpp, which creates the networking threads, including the message-processing thread.
The two other thread groups are task-specific:
- rpc server thread group (see rpcserver.h/cpp)
- miner thread group
Naturally, the node will only create the RPC server thread group if the RPC server is activated, and will only create the miner thread group if it is mining. If both are disabled, then Bitcoin Core only has a single thread group.
The parent thread (meaning the thread in which the program begins operating) delegates almost all of the program's work to child threads. After spawning threads in init.cpp and net.cpp, the parent thread simply listens for a shutdown command, at which time the parent thread needs only to interrupt the threads in its thread group and proceed with shutdown.
The child threads are summarized in this table, listed in the order in which they are created:
|Thread||When / Where Created||Description|
|Script-checking|| Step 4
| This is a set of threads - 4 by default.|
Script-checking (including signature checking) is expensive so is handled in separate threads.
|Scheduler|| Step 4
| Scheduler thread.|
|RPC Threads|| Step 4
|If RPC server enabled, start a group of threads to handle RPC calls.|
|Import|| Step 10
| Imports blocks. Three scenarios:|
1) Reindex (rescan all known blocks from blk???.dat files).
2) Bootstrap (use bootstrap.dat as an alternative to full IBD from the network.)
3) -loadblock (scan a specific blk???.dat file)
If none of those apply, this thread does nothing.
|DNSAddressSeed|| Step 11
| Attempts to build a vector of IP addresses based on the dns seeds, stores the vector and the thread exits.|
In a test in June 2014, this took about 4 seconds and found 158 addresses.
|Plug & Play|| Step 11
| UPNP (Universal Plug & Play) |
Deals with port mapping for UPNP.
|SocketHandler|| Step 11
| This thread services the sockets:|
Waits for I/O on all the relevant sockets with a 50ms timeout.
Processes new incoming connections on listening socket and creates a CNode for the new peer.
Receives and sends data streams.
Sets sockets that have not done anything to a disconnected state.
|OpenAddedConnections|| Step 11
| Initiates outbound connections specified by the user with the –addnode parameter.|
If can't connect, sleeps for 2 minutes each cycle.
|OpenConnections|| Step 11
| Initiates other outbound connections from DNS seeds (if that fails, find nodes based on fixed seeds)|
If can't connect, sleeps for 500 milliseconds each cycle.
|MessageHandler|| Step 11
| This is the program's main thread. |
This thread runs a while(true) loop, receiving and sending messages. (See net.cpp:1049)
The code uses boost::signals2 to call the ProcessMessages and SendMessages functions in main.cpp.
(The code introducing signals is in PR 2154 - see the next-to-last commit in that pull.)
ProcessMessage and SendMessage run in this thread.
So, most of the code in main.cpp runs in this thread.
|Wallet Flusher|| Step 12
|If wallet is enabled, this thread flushes the wallet periodically.|
Bitcoin Core 0.11 (Ch 1): Overview
Bitcoin Core 0.11 (Ch 2): Data Storage
Bitcoin Core 0.11 (Ch 4): P2P Network
Bitcoin Core 0.11 (Ch 5): Initial Block Download
Bitcoin Core 0.11 (Ch 6): The Blockchain