2013-05-26 13:48:30 -04:00
// Copyright (c) 2009-2010 Satoshi Nakamoto
2022-12-24 23:49:50 +00:00
// Copyright (c) 2009-2022 The Bitcoin Core developers
2014-12-13 12:09:33 +08:00
// Distributed under the MIT software license, see the accompanying
2013-05-26 13:48:30 -04:00
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
2024-10-10 12:20:34 +02:00
# include <bitcoin-build-config.h> // IWYU pragma: keep
2015-12-09 10:53:12 +00:00
2017-11-10 13:57:53 +13:00
# include <chainparams.h>
# include <clientversion.h>
2023-03-23 12:23:29 +01:00
# include <common/args.h>
2023-02-23 15:56:15 -05:00
# include <common/init.h>
2023-05-08 11:32:13 +02:00
# include <common/system.h>
2022-06-28 13:27:57 +01:00
# include <compat/compat.h>
2017-11-10 13:57:53 +13:00
# include <init.h>
2019-07-10 08:06:57 -04:00
# include <interfaces/chain.h>
2017-12-05 15:57:12 -05:00
# include <interfaces/init.h>
2024-01-15 12:55:31 +01:00
# include <kernel/context.h>
2019-09-17 18:28:03 -04:00
# include <node/context.h>
2022-06-14 10:38:51 +02:00
# include <node/interface_ui.h>
2024-05-07 14:21:35 +01:00
# include <node/warnings.h>
2017-11-10 13:57:53 +13:00
# include <noui.h>
2020-12-01 00:36:36 +01:00
# include <util/check.h>
2023-03-06 17:22:33 +01:00
# include <util/exception.h>
2024-01-15 12:55:31 +01:00
# include <util/signalinterrupt.h>
2019-07-10 08:06:57 -04:00
# include <util/strencodings.h>
2022-04-20 16:17:19 +02:00
# include <util/syserror.h>
2018-06-13 14:50:59 -04:00
# include <util/threadnames.h>
2021-01-25 22:45:54 +01:00
# include <util/tokenpipe.h>
2019-06-17 10:56:52 +03:00
# include <util/translation.h>
2020-12-01 00:36:36 +01:00
# include <any>
2019-06-17 10:56:52 +03:00
# include <functional>
2021-03-15 11:59:05 +08:00
# include <optional>
evhttpd implementation
- *Replace usage of boost::asio with [libevent2](http://libevent.org/)*.
boost::asio is not part of C++11, so unlike other boost there is no
forwards-compatibility reason to stick with it. Together with #4738 (convert
json_spirit to UniValue), this rids Bitcoin Core of the worst offenders with
regard to compile-time slowness.
- *Replace spit-and-duct-tape http server with evhttp*. Front-end http handling
is handled by libevent, a work queue (with configurable depth and parallelism)
is used to handle application requests.
- *Wrap HTTP request in C++ class*; this makes the application code mostly
HTTP-server-neutral
- *Refactor RPC to move all http-specific code to a separate file*.
Theoreticaly this can allow building without HTTP server but with another RPC
backend, e.g. Qt's debug console (currently not implemented) or future RPC
mechanisms people may want to use.
- *HTTP dispatch mechanism*; services (e.g., RPC, REST) register which URL
paths they want to handle.
By using a proven, high-performance asynchronous networking library (also used
by Tor) and HTTP server, problems such as #5674, #5655, #344 should be avoided.
What works? bitcoind, bitcoin-cli, bitcoin-qt. Unit tests and RPC/REST tests
pass. The aim for now is everything but SSL support.
Configuration options:
- `-rpcthreads`: repurposed as "number of work handler threads". Still
defaults to 4.
- `-rpcworkqueue`: maximum depth of work queue. When this is reached, new
requests will return a 500 Internal Error.
- `-rpctimeout`: inactivity time, in seconds, after which to disconnect a
client.
- `-debug=http`: low-level http activity logging
2015-01-23 07:53:17 +01:00
2021-11-12 10:06:00 -05:00
using node : : NodeContext ;
2018-08-13 16:13:29 -04:00
const std : : function < std : : string ( const char * ) > G_TRANSLATION_FUN = nullptr ;
2021-01-25 22:45:54 +01:00
# if HAVE_DECL_FORK
/** Custom implementation of daemon(). This implements the same order of operations as glibc.
* Opens a pipe to the child process to be able to wait for an event to occur .
*
* @ returns 0 if successful , and in child process .
* > 0 if successful , and in parent process .
* - 1 in case of error ( in parent process ) .
*
* In case of success , endpoint will be one end of a pipe from the child to parent process ,
* which can be used with TokenWrite ( in the child ) or TokenRead ( in the parent ) .
*/
int fork_daemon ( bool nochdir , bool noclose , TokenPipeEnd & endpoint )
{
// communication pipe with child process
std : : optional < TokenPipe > umbilical = TokenPipe : : Make ( ) ;
if ( ! umbilical ) {
return - 1 ; // pipe or pipe2 failed.
}
int pid = fork ( ) ;
if ( pid < 0 ) {
return - 1 ; // fork failed.
}
if ( pid ! = 0 ) {
// Parent process gets read end, closes write end.
endpoint = umbilical - > TakeReadEnd ( ) ;
umbilical - > TakeWriteEnd ( ) . Close ( ) ;
int status = endpoint . TokenRead ( ) ;
if ( status ! = 0 ) { // Something went wrong while setting up child process.
endpoint . Close ( ) ;
return - 1 ;
}
return pid ;
}
// Child process gets write end, closes read end.
endpoint = umbilical - > TakeWriteEnd ( ) ;
umbilical - > TakeReadEnd ( ) . Close ( ) ;
# if HAVE_DECL_SETSID
if ( setsid ( ) < 0 ) {
exit ( 1 ) ; // setsid failed.
}
# endif
if ( ! nochdir ) {
if ( chdir ( " / " ) ! = 0 ) {
exit ( 1 ) ; // chdir failed.
}
}
if ( ! noclose ) {
// Open /dev/null, and clone it into STDIN, STDOUT and STDERR to detach
// from terminal.
int fd = open ( " /dev/null " , O_RDWR ) ;
if ( fd > = 0 ) {
bool err = dup2 ( fd , STDIN_FILENO ) < 0 | | dup2 ( fd , STDOUT_FILENO ) < 0 | | dup2 ( fd , STDERR_FILENO ) < 0 ;
// Don't close if fd<=2 to try to handle the case where the program was invoked without any file descriptors open.
if ( fd > 2 ) close ( fd ) ;
if ( err ) {
exit ( 1 ) ; // dup2 failed.
}
} else {
exit ( 1 ) ; // open /dev/null failed.
}
}
endpoint . TokenWrite ( 0 ) ; // Success
return 0 ;
}
# endif
2018-08-23 13:42:31 -04:00
static bool ParseArgs ( NodeContext & node , int argc , char * argv [ ] )
2013-05-26 13:48:30 -04:00
{
2018-08-23 13:42:31 -04:00
ArgsManager & args { * Assert ( node . args ) } ;
2014-11-22 19:56:25 +01:00
// If Qt is used, parameters/bitcoin.conf are parsed in qt/bitcoin.cpp's main()
2018-08-23 13:42:31 -04:00
SetupServerArgs ( args , node . init - > canListenIpc ( ) ) ;
2018-04-28 19:40:51 -04:00
std : : string error ;
2020-08-21 20:38:01 +02:00
if ( ! args . ParseParameters ( argc , argv , error ) ) {
2023-02-23 14:58:49 -05:00
return InitError ( Untranslated ( strprintf ( " Error parsing command line arguments: %s " , error ) ) ) ;
2018-04-28 19:40:51 -04:00
}
2014-11-22 19:56:25 +01:00
2023-06-09 11:05:11 -03:00
if ( auto error = common : : InitConfig ( args ) ) {
return InitError ( error - > message , error - > details ) ;
}
// Error out when loose non-argument tokens are encountered on command line
for ( int i = 1 ; i < argc ; i + + ) {
if ( ! IsSwitchChar ( argv [ i ] [ 0 ] ) ) {
return InitError ( Untranslated ( strprintf ( " Command line contains unexpected token '%s', see bitcoind -h for a list of options. " , argv [ i ] ) ) ) ;
}
}
return true ;
}
static bool ProcessInitCommands ( ArgsManager & args )
{
2014-11-22 19:56:25 +01:00
// Process help and version before taking care about datadir
2024-11-20 22:55:23 +01:00
if ( HelpRequested ( args ) | | args . GetBoolArg ( " -version " , false ) ) {
2024-03-20 22:01:30 +00:00
std : : string strUsage = CLIENT_NAME " daemon version " + FormatFullVersion ( ) + " \n " ;
2014-11-22 19:56:25 +01:00
2024-11-20 22:55:23 +01:00
if ( args . GetBoolArg ( " -version " , false ) ) {
2022-02-21 19:32:59 +00:00
strUsage + = FormatParagraph ( LicenseInfo ( ) ) ;
} else {
2024-03-20 22:01:30 +00:00
strUsage + = " \n "
" The " CLIENT_NAME " daemon (bitcoind) is a headless program that connects to the Bitcoin network to validate and relay transactions and blocks, as well as relaying addresses. \n \n "
" It provides the backbone of the Bitcoin network and its RPC, REST and ZMQ services can provide various transaction, block and address-related services. \n \n "
" There is an optional wallet component which provides transaction services. \n \n "
" It can be used in a headless environment or as part of a server setup. \n "
" \n "
" Usage: bitcoind [options] \n "
2020-11-28 18:43:55 -05:00
" \n " ;
strUsage + = args . GetHelpMessage ( ) ;
2014-11-22 19:56:25 +01:00
}
2019-10-28 13:30:20 +01:00
tfm : : format ( std : : cout , " %s " , strUsage ) ;
2016-11-02 21:59:09 +03:00
return true ;
2014-11-22 19:56:25 +01:00
}
2023-06-09 11:05:11 -03:00
return false ;
}
static bool AppInit ( NodeContext & node )
{
bool fRet = false ;
ArgsManager & args = * Assert ( node . args ) ;
2021-01-25 22:45:54 +01:00
# if HAVE_DECL_FORK
// Communication with parent after daemonizing. This is used for signalling in the following ways:
// - a boolean token is sent when the initialization process (all the Init* functions) have finished to indicate
// that the parent process can quit, and whether it was successful/unsuccessful.
// - an unexpected shutdown of the child process creates an unexpected end of stream at the parent
// end, which is interpreted as failure to start.
TokenPipeEnd daemon_ep ;
# endif
2020-12-01 00:36:36 +01:00
std : : any context { & node } ;
2013-05-26 13:48:30 -04:00
try
{
2016-10-25 11:34:27 +02:00
// -server defaults to true for bitcoind but not for the GUI so do this here
2020-08-21 20:38:01 +02:00
args . SoftSetBoolArg ( " -server " , true ) ;
2016-10-25 11:34:27 +02:00
// Set this early so that parameter interactions go to console
2020-08-21 20:13:40 +02:00
InitLogging ( args ) ;
InitParameterInteraction ( args ) ;
2023-05-20 10:51:17 -03:00
if ( ! AppInitBasicSetup ( args , node . exit_status ) ) {
2016-10-25 11:34:27 +02:00
// InitError will have been called with detailed error, which ends up on console
2017-10-16 21:20:28 +01:00
return false ;
2016-10-25 11:34:27 +02:00
}
2020-08-21 20:13:40 +02:00
if ( ! AppInitParameterInteraction ( args ) ) {
2016-10-25 11:34:27 +02:00
// InitError will have been called with detailed error, which ends up on console
2017-10-16 21:20:28 +01:00
return false ;
2016-10-25 11:34:27 +02:00
}
2022-05-25 14:31:54 -04:00
2024-05-07 14:21:35 +01:00
node . warnings = std : : make_unique < node : : Warnings > ( ) ;
2022-05-25 14:31:54 -04:00
node . kernel = std : : make_unique < kernel : : Context > ( ) ;
2024-01-15 12:55:31 +01:00
node . ecc_context = std : : make_unique < ECC_Context > ( ) ;
2022-05-27 16:47:05 -04:00
if ( ! AppInitSanityChecks ( * node . kernel ) )
2016-10-25 11:34:27 +02:00
{
// InitError will have been called with detailed error, which ends up on console
2017-10-16 21:20:28 +01:00
return false ;
2016-10-25 11:34:27 +02:00
}
2022-05-25 14:31:54 -04:00
2021-01-25 22:45:54 +01:00
if ( args . GetBoolArg ( " -daemon " , DEFAULT_DAEMON ) | | args . GetBoolArg ( " -daemonwait " , DEFAULT_DAEMONWAIT ) ) {
# if HAVE_DECL_FORK
2024-10-26 13:27:25 +01:00
tfm : : format ( std : : cout , CLIENT_NAME " starting \n " ) ;
2013-12-20 11:48:22 +01:00
2013-05-26 13:48:30 -04:00
// Daemonize
2021-01-25 22:45:54 +01:00
switch ( fork_daemon ( 1 , 0 , daemon_ep ) ) { // don't chdir (1), do close FDs (0)
case 0 : // Child: continue.
// If -daemonwait is not enabled, immediately send a success token the parent.
if ( ! args . GetBoolArg ( " -daemonwait " , DEFAULT_DAEMONWAIT ) ) {
daemon_ep . TokenWrite ( 1 ) ;
daemon_ep . Close ( ) ;
}
break ;
case - 1 : // Error happened.
2023-02-23 14:58:49 -05:00
return InitError ( Untranslated ( strprintf ( " fork_daemon() failed : % s " , SysErrorString(errno)))) ;
2021-01-25 22:45:54 +01:00
default : { // Parent: wait and exit.
int token = daemon_ep . TokenRead ( ) ;
if ( token ) { // Success
exit ( EXIT_SUCCESS ) ;
} else { // fRet = false or token read error (premature exit).
2022-09-14 20:11:45 +02:00
tfm : : format ( std : : cerr , " Error during initialization - check debug.log for details \n " ) ;
2021-01-25 22:45:54 +01:00
exit ( EXIT_FAILURE ) ;
}
}
2013-05-26 13:48:30 -04:00
}
2016-06-28 09:35:41 +03:00
# else
2023-02-23 14:58:49 -05:00
return InitError ( Untranslated ( " -daemon is not supported on this operating system " ) ) ;
2021-01-25 22:45:54 +01:00
# endif // HAVE_DECL_FORK
2013-05-26 13:48:30 -04:00
}
2017-07-15 10:46:06 +02:00
// Lock data directory after daemonization
if ( ! AppInitLockDataDirectory ( ) )
{
// If locking the data directory failed, exit immediately
2017-10-16 21:20:28 +01:00
return false ;
2017-07-15 10:46:06 +02:00
}
2021-04-02 13:35:01 -04:00
fRet = AppInitInterfaces ( node ) & & AppInitMain ( node ) ;
2013-05-26 13:48:30 -04:00
}
2014-12-07 13:29:06 +01:00
catch ( const std : : exception & e ) {
2013-05-26 13:48:30 -04:00
PrintExceptionContinue ( & e , " AppInit() " ) ;
} catch ( . . . ) {
2017-08-07 07:36:37 +02:00
PrintExceptionContinue ( nullptr , " AppInit() " ) ;
2013-05-26 13:48:30 -04:00
}
2013-10-06 14:18:55 +02:00
2021-01-25 22:45:54 +01:00
# if HAVE_DECL_FORK
if ( daemon_ep . IsOpen ( ) ) {
// Signal initialization status to parent, then close pipe.
daemon_ep . TokenWrite ( fRet ) ;
daemon_ep . Close ( ) ;
}
# endif
2013-05-26 13:48:30 -04:00
return fRet ;
}
2022-05-30 15:59:43 +01:00
MAIN_FUNCTION
2013-05-26 13:48:30 -04:00
{
2018-08-05 16:38:25 +00:00
# ifdef WIN32
2023-03-23 12:23:29 +01:00
common : : WinCmdLineArgs winArgs ;
2018-08-05 16:38:25 +00:00
std : : tie ( argc , argv ) = winArgs . get ( ) ;
# endif
2017-12-05 15:57:12 -05:00
NodeContext node ;
int exit_status ;
std : : unique_ptr < interfaces : : Init > init = interfaces : : MakeNodeInit ( node , argc , argv , exit_status ) ;
if ( ! init ) {
return exit_status ;
}
2014-05-13 10:15:00 +00:00
SetupEnvironment ( ) ;
2013-05-26 13:48:30 -04:00
// Connect bitcoind signal handlers
noui_connect ( ) ;
2023-06-09 11:05:11 -03:00
util : : ThreadSetInternalName ( " init " ) ;
// Interpret command line arguments
ArgsManager & args = * Assert ( node . args ) ;
2018-08-23 13:42:31 -04:00
if ( ! ParseArgs ( node , argc , argv ) ) return EXIT_FAILURE ;
2023-06-09 11:05:11 -03:00
// Process early info return commands such as -help or -version
if ( ProcessInitCommands ( args ) ) return EXIT_SUCCESS ;
// Start application
2024-09-25 10:45:34 +02:00
if ( ! AppInit ( node ) | | ! Assert ( node . shutdown_signal ) - > wait ( ) ) {
2023-06-09 11:05:11 -03:00
node . exit_status = EXIT_FAILURE ;
}
Interrupt ( node ) ;
Shutdown ( node ) ;
return node . exit_status ;
2013-05-26 13:48:30 -04:00
}