IBC#007: Bitcoin Core initialization — Part 1
I know, it’s been a while since my last article; fiat mining, my sister’s wedding and the organization of a football tournament (where you could pay in sats for the food, btw) took a lot of my time.
However, here I am with a new episode of Inside Bitcoin Code!
In the last episode we finished talking about the AppInit()
function, where the application start-up begins; today and in the next episodes we are going to talk about the Bitcoin Core initialization.
Fasten your seatbelt and let’s go!
AppInitMain()
—
Function signature
Let’s start with the function signature, which can be found in the init.h1 file
bool AppInitMain(node::NodeContext& node, interfaces::BlockAndHeaderTipInfo* tip_info = nullptr);
The function takes as input a NodeContext
structure (see IBC#004) and a BlockAndHeaderTipInfo
, a structure that, as the name suggests, contains information about the block and the header.
In this case, the tip_info
pointer is given a default value (tip_info = nullptr
), which means that when the function is called, the second argument is optional and can be avoided; that’s what actually happens when this function is called in the AppInit()
function, where only the NodeContext
structure is passed as input:
fRet = AppInitInterfaces(node) && AppInitMain(node);
The AppInitMain()
function then returns a bool
value, which underlines if the Bitcoin Core initialization terminated successfully.
AppInitMain()
— Step-by-step
First of all, the command line arguments are recovered from the node information. Assert()
performs a check on the arguments and if 0 is returned, a non-fatal error is signaled in debug mode to the developers. Command line arguments are saved in a constant object of type ArgsManager
.
const ArgsManager& args = *Assert(node.args);
Then the functions asks for the current chain parameters. As before, they are stored in a constant object of type CChainParams
.
const CChainParams& chainparams = Params();
After that, the existence of the -maxuploadtarget
parameter is checked and in case it does not exists an initialization error is returned.
auto opt_max_upload = ParseByteUnits(args.GetArg("-maxuploadtarget", DEFAULT_MAX_UPLOAD_TARGET), ByteUnit::M);
if (!opt_max_upload) {
return InitError(strprintf(_("Unable to parse -maxuploadtarget: '%s'"), args.GetArg("-maxuploadtarget", "")));
}
As can be seen, the check is done on the output of the ParseByteUnits
function, which parses a string and converts it to bytes and returns a variable of type uint64_t
that signals if the string is empty or too big (overflow).
Then, the function tries to create a PID file. This type of file usually reports the process ID of a program. This ID is a unique number is assigned to each process and it is used to identify the process in the operating system. If the file creation fails, FALSE is returned and the whole application is stopped.
if (!CreatePidFile(args)) {
// Detailed error printed inside CreatePidFile().
return false;
}
In the same way as before, the return value of the StartLogging()
function is checked and if the function fails a FALSE value is returned. This function takes as input the command line arguments and checks if the configurations file actually exists; in case it does, the program logs the configurations arguments to the debug.log file, otherwise sends a warning. Moreover, the function returns FALSE if the debug.log file cannot be opened.
if (!init::StartLogging(args)) {
// Detailed error printed inside StartLogging().
return false;
}
Then, a log is written reporting the number of automatic connections allowed and the number of file descriptors available. The syntax %i
allows to write an integer number in a string; in this case, the first %i
gets its value from nMaxConnections
variable, the second one from the nFD
one.
LogPrintf("Using at most %i automatic connections (%i file descriptors available)\n", nMaxConnections, nFD);
Enough for today! The function is quite long and we will face it step-by-step, taking all the time that is needed.
As usual, let me know what you think in the comment section and consider sharing Inside Bitcoin Code to anyone who might be interested. It means the world to me!
Usque in Finem
Tuma