2013-10-11 18:09:59 -03:00
// Copyright (c) 2009-2010 Satoshi Nakamoto
2020-04-16 13:14:08 -04:00
// Copyright (c) 2009-2020 The Bitcoin Core developers
2014-12-13 01:09:33 -03:00
// Distributed under the MIT software license, see the accompanying
2013-10-11 18:09:59 -03:00
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
2015-12-09 07:53:12 -03:00
# if defined(HAVE_CONFIG_H)
2017-11-09 21:57:53 -03:00
# include <config/bitcoin-config.h>
2015-12-09 07:53:12 -03:00
# endif
2017-11-09 21:57:53 -03:00
# include <chainparamsbase.h>
# include <clientversion.h>
2020-04-10 16:34:43 -04:00
# include <optional.h>
2017-11-09 21:57:53 -03:00
# include <rpc/client.h>
2020-05-31 09:41:08 -04:00
# include <rpc/mining.h>
2017-11-09 21:57:53 -03:00
# include <rpc/protocol.h>
2019-06-19 13:39:38 -04:00
# include <rpc/request.h>
2018-10-22 19:51:11 -03:00
# include <util/strencodings.h>
2019-06-17 03:56:52 -04:00
# include <util/system.h>
# include <util/translation.h>
2020-04-02 09:35:10 -03:00
# include <util/url.h>
2013-10-11 18:09:59 -03:00
2019-06-17 03:56:52 -04:00
# include <functional>
2018-04-02 15:31:40 -03:00
# include <memory>
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 03:53:17 -03:00
# include <stdio.h>
2020-05-18 04:14:10 -04:00
# include <string>
2018-08-05 12:38:25 -04:00
# include <tuple>
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 03:53:17 -03:00
# include <event2/buffer.h>
# include <event2/keyvalq_struct.h>
2017-11-09 21:57:53 -03:00
# include <support/events.h>
2013-04-13 02:13:08 -03:00
2015-09-04 11:11:34 -03:00
# include <univalue.h>
2018-07-19 10:48:55 -04:00
# include <compat/stdin.h>
2015-05-18 09:02:18 -03:00
2018-08-13 17:13:29 -03:00
const std : : function < std : : string ( const char * ) > G_TRANSLATION_FUN = nullptr ;
2020-04-02 09:35:10 -03:00
UrlDecodeFn * const URL_DECODE = urlDecode ;
2018-08-13 17:13:29 -03:00
2015-06-27 16:21:41 -03:00
static const char DEFAULT_RPCCONNECT [ ] = " 127.0.0.1 " ;
2015-09-18 10:45:38 -03:00
static const int DEFAULT_HTTP_CLIENT_TIMEOUT = 900 ;
2016-11-22 10:56:29 -03:00
static const bool DEFAULT_NAMED = false ;
2016-11-02 15:59:09 -03:00
static const int CONTINUE_EXECUTION = - 1 ;
2020-08-13 10:16:36 -04:00
static const std : : string ONION { " .onion " } ;
static const size_t ONION_LEN { ONION . size ( ) } ;
2015-09-18 10:45:38 -03:00
2020-05-31 09:41:08 -04:00
/** Default number of blocks to generate for RPC generatetoaddress. */
static const std : : string DEFAULT_NBLOCKS = " 1 " ;
2020-07-19 03:31:51 -04:00
static void SetupCliArgs ( ArgsManager & argsman )
2014-05-26 05:38:44 -04:00
{
2020-07-19 03:31:51 -04:00
SetupHelpOptions ( argsman ) ;
2019-02-06 15:57:52 -03:00
2015-05-21 22:50:01 -03:00
const auto defaultBaseParams = CreateBaseChainParams ( CBaseChainParams : : MAIN ) ;
const auto testnetBaseParams = CreateBaseChainParams ( CBaseChainParams : : TESTNET ) ;
2018-08-20 20:46:34 -03:00
const auto regtestBaseParams = CreateBaseChainParams ( CBaseChainParams : : REGTEST ) ;
2014-05-26 05:38:44 -04:00
2020-07-19 03:47:05 -04:00
argsman . AddArg ( " -version " , " Print version and exit " , ArgsManager : : ALLOW_ANY , OptionsCategory : : OPTIONS ) ;
argsman . AddArg ( " -conf=<file> " , strprintf ( " Specify configuration file. Relative paths will be prefixed by datadir location. (default: %s) " , BITCOIN_CONF_FILENAME ) , ArgsManager : : ALLOW_ANY , OptionsCategory : : OPTIONS ) ;
argsman . AddArg ( " -datadir=<dir> " , " Specify data directory " , ArgsManager : : ALLOW_ANY , OptionsCategory : : OPTIONS ) ;
argsman . AddArg ( " -generate " , strprintf ( " Generate blocks immediately, equivalent to RPC generatenewaddress followed by RPC generatetoaddress. Optional positional integer arguments are number of blocks to generate (default: %s) and maximum iterations to try (default: %s), equivalent to RPC generatetoaddress nblocks and maxtries arguments. Example: bitcoin-cli -generate 4 1000 " , DEFAULT_NBLOCKS , DEFAULT_MAX_TRIES ) , ArgsManager : : ALLOW_ANY , OptionsCategory : : OPTIONS ) ;
argsman . AddArg ( " -getinfo " , " Get general information from the remote server. Note that unlike server-side RPC calls, the results of -getinfo is the result of multiple non-atomic requests. Some entries in the result may represent results from different states (e.g. wallet balance may be as of a different block from the chain state reported) " , ArgsManager : : ALLOW_ANY , OptionsCategory : : OPTIONS ) ;
2020-07-27 02:20:26 -04:00
argsman . AddArg ( " -netinfo " , " Get network peer connection information from the remote server. An optional boolean argument can be passed for a detailed peers listing (default: false). " , ArgsManager : : ALLOW_BOOL , OptionsCategory : : OPTIONS ) ;
2020-07-19 03:31:51 -04:00
SetupChainParamsBaseOptions ( argsman ) ;
2020-07-19 03:47:05 -04:00
argsman . AddArg ( " -named " , strprintf ( " Pass named instead of positional arguments (default: %s) " , DEFAULT_NAMED ) , ArgsManager : : ALLOW_ANY , OptionsCategory : : OPTIONS ) ;
argsman . AddArg ( " -rpcclienttimeout=<n> " , strprintf ( " Timeout in seconds during HTTP requests, or 0 for no timeout. (default: %d) " , DEFAULT_HTTP_CLIENT_TIMEOUT ) , ArgsManager : : ALLOW_ANY , OptionsCategory : : OPTIONS ) ;
argsman . AddArg ( " -rpcconnect=<ip> " , strprintf ( " Send commands to node running on <ip> (default: %s) " , DEFAULT_RPCCONNECT ) , ArgsManager : : ALLOW_ANY , OptionsCategory : : OPTIONS ) ;
argsman . AddArg ( " -rpccookiefile=<loc> " , " Location of the auth cookie. Relative paths will be prefixed by a net-specific datadir location. (default: data dir) " , ArgsManager : : ALLOW_ANY , OptionsCategory : : OPTIONS ) ;
argsman . AddArg ( " -rpcpassword=<pw> " , " Password for JSON-RPC connections " , ArgsManager : : ALLOW_ANY , OptionsCategory : : OPTIONS ) ;
argsman . AddArg ( " -rpcport=<port> " , strprintf ( " Connect to JSON-RPC on <port> (default: %u, testnet: %u, regtest: %u) " , defaultBaseParams - > RPCPort ( ) , testnetBaseParams - > RPCPort ( ) , regtestBaseParams - > RPCPort ( ) ) , ArgsManager : : ALLOW_ANY | ArgsManager : : NETWORK_ONLY , OptionsCategory : : OPTIONS ) ;
argsman . AddArg ( " -rpcuser=<user> " , " Username for JSON-RPC connections " , ArgsManager : : ALLOW_ANY , OptionsCategory : : OPTIONS ) ;
argsman . AddArg ( " -rpcwait " , " Wait for RPC server to start " , ArgsManager : : ALLOW_ANY , OptionsCategory : : OPTIONS ) ;
argsman . AddArg ( " -rpcwallet=<walletname> " , " Send RPC for non-default wallet on RPC server (needs to exactly match corresponding -wallet option passed to bitcoind). This changes the RPC endpoint used, e.g. http://127.0.0.1:8332/wallet/<walletname> " , ArgsManager : : ALLOW_ANY , OptionsCategory : : OPTIONS ) ;
argsman . AddArg ( " -stdin " , " Read extra arguments from standard input, one per line until EOF/Ctrl-D (recommended for sensitive information such as passphrases). When combined with -stdinrpcpass, the first line from standard input is used for the RPC password. " , ArgsManager : : ALLOW_ANY , OptionsCategory : : OPTIONS ) ;
argsman . AddArg ( " -stdinrpcpass " , " Read RPC password from standard input as a single line. When combined with -stdin, the first line from standard input is used for the RPC password. When combined with -stdinwalletpassphrase, -stdinrpcpass consumes the first line, and -stdinwalletpassphrase consumes the second. " , ArgsManager : : ALLOW_ANY , OptionsCategory : : OPTIONS ) ;
argsman . AddArg ( " -stdinwalletpassphrase " , " Read wallet passphrase from standard input as a single line. When combined with -stdin, the first line from standard input is used for the wallet passphrase. " , ArgsManager : : ALLOW_ANY , OptionsCategory : : OPTIONS ) ;
2014-05-26 05:38:44 -04:00
}
2018-06-04 14:55:00 -04:00
/** libevent event log callback */
static void libevent_log_cb ( int severity , const char * msg )
{
# ifndef EVENT_LOG_ERR // EVENT_LOG_ERR was added in 2.0.19; but before then _EVENT_LOG_ERR existed.
# define EVENT_LOG_ERR _EVENT_LOG_ERR
# endif
// Ignore everything other than errors
if ( severity > = EVENT_LOG_ERR ) {
throw std : : runtime_error ( strprintf ( " libevent error: %s " , msg ) ) ;
}
}
2013-10-11 18:09:59 -03:00
//////////////////////////////////////////////////////////////////////////////
//
// Start
//
2014-10-29 14:08:31 -03:00
//
// Exception thrown on connection error. This error is used to determine
// when to wait if -rpcwait is given.
//
class CConnectionFailed : public std : : runtime_error
{
public :
explicit inline CConnectionFailed ( const std : : string & msg ) :
std : : runtime_error ( msg )
{ }
} ;
2016-11-02 15:59:09 -03:00
//
// This function returns either one of EXIT_ codes when it's expected to stop the process or
// CONTINUE_EXECUTION when it's expected to continue further.
//
static int AppInitRPC ( int argc , char * argv [ ] )
2013-10-11 18:09:59 -03:00
{
//
// Parameters
//
2020-07-19 03:31:51 -04:00
SetupCliArgs ( gArgs ) ;
2018-04-28 20:40:51 -03:00
std : : string error ;
if ( ! gArgs . ParseParameters ( argc , argv , error ) ) {
2019-10-28 09:30:20 -03:00
tfm : : format ( std : : cerr , " Error parsing command line arguments: %s \n " , error ) ;
2018-04-28 20:40:51 -03:00
return EXIT_FAILURE ;
}
2018-03-30 17:47:36 -03:00
if ( argc < 2 | | HelpRequested ( gArgs ) | | gArgs . IsArgSet ( " -version " ) ) {
2018-05-08 12:31:21 -03:00
std : : string strUsage = PACKAGE_NAME " RPC client version " + FormatFullVersion ( ) + " \n " ;
2017-08-01 15:17:40 -04:00
if ( ! gArgs . IsArgSet ( " -version " ) ) {
2018-05-08 12:31:21 -03:00
strUsage + = " \n "
" Usage: bitcoin-cli [options] <command> [params] Send command to " PACKAGE_NAME " \n "
" or: bitcoin-cli [options] -named <command> [name=value]... Send command to " PACKAGE_NAME " (with named arguments) \n "
" or: bitcoin-cli [options] help List commands \n "
" or: bitcoin-cli [options] help <command> Get help for a command \n " ;
2018-04-28 17:54:58 -03:00
strUsage + = " \n " + gArgs . GetHelpMessage ( ) ;
2014-11-22 15:56:25 -03:00
}
2019-10-28 09:30:20 -03:00
tfm : : format ( std : : cout , " %s " , strUsage ) ;
2016-11-02 15:59:09 -03:00
if ( argc < 2 ) {
2019-06-13 09:16:10 -04:00
tfm : : format ( std : : cerr , " Error: too few parameters \n " ) ;
2016-11-02 15:59:09 -03:00
return EXIT_FAILURE ;
}
return EXIT_SUCCESS ;
2014-11-22 15:56:25 -03:00
}
2019-07-24 11:54:46 -04:00
if ( ! CheckDataDirOption ( ) ) {
2019-10-28 09:30:20 -03:00
tfm : : format ( std : : cerr , " Error: Specified data directory \" %s \" does not exist. \n " , gArgs . GetArg ( " -datadir " , " " ) ) ;
2016-11-02 15:59:09 -03:00
return EXIT_FAILURE ;
2013-10-11 18:09:59 -03:00
}
2018-04-28 20:40:51 -03:00
if ( ! gArgs . ReadConfigFiles ( error , true ) ) {
2019-10-28 09:30:20 -03:00
tfm : : format ( std : : cerr , " Error reading configuration file: %s \n " , error ) ;
2016-11-02 15:59:09 -03:00
return EXIT_FAILURE ;
2014-04-07 05:10:01 -03:00
}
2016-10-13 17:38:10 -03:00
// Check for -chain, -testnet or -regtest parameter (BaseParams() calls are only valid after this clause)
2015-05-25 04:00:17 -03:00
try {
2018-03-29 02:00:00 -03:00
SelectBaseParams ( gArgs . GetChainName ( ) ) ;
2015-10-27 13:39:42 -03:00
} catch ( const std : : exception & e ) {
2019-06-13 09:16:10 -04:00
tfm : : format ( std : : cerr , " Error: %s \n " , e . what ( ) ) ;
2016-11-02 15:59:09 -03:00
return EXIT_FAILURE ;
2013-11-28 13:28:27 -03:00
}
2016-11-02 15:59:09 -03:00
return CONTINUE_EXECUTION ;
2013-10-11 18:09:59 -03:00
}
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 03:53:17 -03:00
/** Reply structure for request_done to fill in */
struct HTTPReply
2014-05-26 05:38:44 -04:00
{
2016-09-14 10:08:34 -03:00
HTTPReply ( ) : status ( 0 ) , error ( - 1 ) { }
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 03:53:17 -03:00
int status ;
2016-09-14 10:08:34 -03:00
int error ;
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 03:53:17 -03:00
std : : string body ;
} ;
2020-05-18 04:14:10 -04:00
static std : : string http_errorstring ( int code )
2016-09-14 10:08:34 -03:00
{
switch ( code ) {
# if LIBEVENT_VERSION_NUMBER >= 0x02010300
case EVREQ_HTTP_TIMEOUT :
return " timeout reached " ;
case EVREQ_HTTP_EOF :
return " EOF reached " ;
case EVREQ_HTTP_INVALID_HEADER :
return " error while reading header, or invalid header " ;
case EVREQ_HTTP_BUFFER_ERROR :
return " error encountered while reading or writing " ;
case EVREQ_HTTP_REQUEST_CANCEL :
return " request was canceled " ;
case EVREQ_HTTP_DATA_TOO_LONG :
return " response body is larger than allowed " ;
# endif
default :
return " unknown " ;
}
}
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 03:53:17 -03:00
static void http_request_done ( struct evhttp_request * req , void * ctx )
{
HTTPReply * reply = static_cast < HTTPReply * > ( ctx ) ;
2017-08-07 01:36:37 -04:00
if ( req = = nullptr ) {
/* If req is nullptr, it means an error occurred while connecting: the
2016-09-14 10:08:34 -03:00
* error code will have been passed to http_error_cb .
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 03:53:17 -03:00
*/
reply - > status = 0 ;
return ;
}
2014-05-26 05:38:44 -04:00
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 03:53:17 -03:00
reply - > status = evhttp_request_get_response_code ( req ) ;
struct evbuffer * buf = evhttp_request_get_input_buffer ( req ) ;
if ( buf )
{
size_t size = evbuffer_get_length ( buf ) ;
const char * data = ( const char * ) evbuffer_pullup ( buf , size ) ;
if ( data )
reply - > body = std : : string ( data , size ) ;
evbuffer_drain ( buf , size ) ;
}
}
2016-09-14 10:08:34 -03:00
# if LIBEVENT_VERSION_NUMBER >= 0x02010300
static void http_error_cb ( enum evhttp_request_error err , void * ctx )
{
HTTPReply * reply = static_cast < HTTPReply * > ( ctx ) ;
reply - > error = err ;
}
# endif
2016-09-29 11:45:19 -03:00
/** Class that handles the conversion from a command-line to a JSON-RPC request,
* as well as converting back to a JSON object that can be shown as result .
*/
class BaseRequestHandler
{
public :
2017-12-29 12:20:28 -03:00
virtual ~ BaseRequestHandler ( ) { }
2016-09-29 11:45:19 -03:00
virtual UniValue PrepareRequest ( const std : : string & method , const std : : vector < std : : string > & args ) = 0 ;
virtual UniValue ProcessReply ( const UniValue & batch_in ) = 0 ;
} ;
/** Process getinfo requests */
class GetinfoRequestHandler : public BaseRequestHandler
{
public :
const int ID_NETWORKINFO = 0 ;
const int ID_BLOCKCHAININFO = 1 ;
const int ID_WALLETINFO = 2 ;
2020-03-27 19:12:38 -03:00
const int ID_BALANCES = 3 ;
2016-09-29 11:45:19 -03:00
/** Create a simulated `getinfo` request. */
UniValue PrepareRequest ( const std : : string & method , const std : : vector < std : : string > & args ) override
{
2017-11-17 10:11:02 -03:00
if ( ! args . empty ( ) ) {
throw std : : runtime_error ( " -getinfo takes no arguments " ) ;
}
2016-09-29 11:45:19 -03:00
UniValue result ( UniValue : : VARR ) ;
result . push_back ( JSONRPCRequestObj ( " getnetworkinfo " , NullUniValue , ID_NETWORKINFO ) ) ;
result . push_back ( JSONRPCRequestObj ( " getblockchaininfo " , NullUniValue , ID_BLOCKCHAININFO ) ) ;
result . push_back ( JSONRPCRequestObj ( " getwalletinfo " , NullUniValue , ID_WALLETINFO ) ) ;
2020-03-27 19:12:38 -03:00
result . push_back ( JSONRPCRequestObj ( " getbalances " , NullUniValue , ID_BALANCES ) ) ;
2016-09-29 11:45:19 -03:00
return result ;
}
/** Collect values from the batch and form a simulated `getinfo` reply. */
UniValue ProcessReply ( const UniValue & batch_in ) override
{
UniValue result ( UniValue : : VOBJ ) ;
2020-04-12 15:46:16 -04:00
const std : : vector < UniValue > batch = JSONRPCProcessBatchReply ( batch_in ) ;
2020-03-27 19:12:38 -03:00
// Errors in getnetworkinfo() and getblockchaininfo() are fatal, pass them on;
// getwalletinfo() and getbalances() are allowed to fail if there is no wallet.
2016-09-29 11:45:19 -03:00
if ( ! batch [ ID_NETWORKINFO ] [ " error " ] . isNull ( ) ) {
return batch [ ID_NETWORKINFO ] ;
}
if ( ! batch [ ID_BLOCKCHAININFO ] [ " error " ] . isNull ( ) ) {
return batch [ ID_BLOCKCHAININFO ] ;
}
result . pushKV ( " version " , batch [ ID_NETWORKINFO ] [ " result " ] [ " version " ] ) ;
result . pushKV ( " blocks " , batch [ ID_BLOCKCHAININFO ] [ " result " ] [ " blocks " ] ) ;
2019-10-29 15:29:13 -03:00
result . pushKV ( " headers " , batch [ ID_BLOCKCHAININFO ] [ " result " ] [ " headers " ] ) ;
result . pushKV ( " verificationprogress " , batch [ ID_BLOCKCHAININFO ] [ " result " ] [ " verificationprogress " ] ) ;
2016-09-29 11:45:19 -03:00
result . pushKV ( " timeoffset " , batch [ ID_NETWORKINFO ] [ " result " ] [ " timeoffset " ] ) ;
result . pushKV ( " connections " , batch [ ID_NETWORKINFO ] [ " result " ] [ " connections " ] ) ;
result . pushKV ( " proxy " , batch [ ID_NETWORKINFO ] [ " result " ] [ " networks " ] [ 0 ] [ " proxy " ] ) ;
result . pushKV ( " difficulty " , batch [ ID_BLOCKCHAININFO ] [ " result " ] [ " difficulty " ] ) ;
2019-03-09 05:15:17 -03:00
result . pushKV ( " chain " , UniValue ( batch [ ID_BLOCKCHAININFO ] [ " result " ] [ " chain " ] ) ) ;
2019-11-04 16:39:34 -03:00
if ( ! batch [ ID_WALLETINFO ] [ " result " ] . isNull ( ) ) {
2016-09-29 11:45:19 -03:00
result . pushKV ( " keypoolsize " , batch [ ID_WALLETINFO ] [ " result " ] [ " keypoolsize " ] ) ;
if ( ! batch [ ID_WALLETINFO ] [ " result " ] [ " unlocked_until " ] . isNull ( ) ) {
result . pushKV ( " unlocked_until " , batch [ ID_WALLETINFO ] [ " result " ] [ " unlocked_until " ] ) ;
}
result . pushKV ( " paytxfee " , batch [ ID_WALLETINFO ] [ " result " ] [ " paytxfee " ] ) ;
}
2020-03-27 19:12:38 -03:00
if ( ! batch [ ID_BALANCES ] [ " result " ] . isNull ( ) ) {
result . pushKV ( " balance " , batch [ ID_BALANCES ] [ " result " ] [ " mine " ] [ " trusted " ] ) ;
}
2016-09-29 11:45:19 -03:00
result . pushKV ( " relayfee " , batch [ ID_NETWORKINFO ] [ " result " ] [ " relayfee " ] ) ;
result . pushKV ( " warnings " , batch [ ID_NETWORKINFO ] [ " result " ] [ " warnings " ] ) ;
return JSONRPCReplyObj ( result , NullUniValue , 1 ) ;
}
} ;
2020-07-27 02:20:26 -04:00
/** Process netinfo requests */
class NetinfoRequestHandler : public BaseRequestHandler
{
private :
2020-08-13 10:16:36 -04:00
bool IsAddrIPv6 ( const std : : string & addr ) const
{
return ! addr . empty ( ) & & addr . front ( ) = = ' [ ' ;
}
bool IsInboundOnion ( const std : : string & addr_local , int mapped_as ) const
{
return mapped_as = = 0 & & addr_local . find ( ONION ) ! = std : : string : : npos ;
}
bool IsOutboundOnion ( const std : : string & addr , int mapped_as ) const
{
const size_t addr_len { addr . size ( ) } ;
const size_t onion_pos { addr . rfind ( ONION ) } ;
return mapped_as = = 0 & & onion_pos ! = std : : string : : npos & & addr_len > ONION_LEN & &
( onion_pos = = addr_len - ONION_LEN | | onion_pos = = addr . find_last_of ( " : " ) - ONION_LEN ) ;
}
2020-07-27 02:20:26 -04:00
bool m_verbose { false } ; //!< Whether user requested verbose -netinfo report
2020-08-13 10:29:10 -04:00
std : : string ChainToString ( ) const
{
if ( gArgs . GetChainName ( ) = = CBaseChainParams : : TESTNET ) return " testnet " ;
if ( gArgs . GetChainName ( ) = = CBaseChainParams : : REGTEST ) return " regtest " ;
return " " ;
}
2020-07-27 02:20:26 -04:00
public :
const int ID_PEERINFO = 0 ;
const int ID_NETWORKINFO = 1 ;
UniValue PrepareRequest ( const std : : string & method , const std : : vector < std : : string > & args ) override
{
if ( ! args . empty ( ) ) {
const std : : string arg { ToLower ( args . at ( 0 ) ) } ;
m_verbose = ( arg = = " true " | | arg = = " t " ) ;
}
UniValue result ( UniValue : : VARR ) ;
result . push_back ( JSONRPCRequestObj ( " getpeerinfo " , NullUniValue , ID_PEERINFO ) ) ;
result . push_back ( JSONRPCRequestObj ( " getnetworkinfo " , NullUniValue , ID_NETWORKINFO ) ) ;
return result ;
}
UniValue ProcessReply ( const UniValue & batch_in ) override
{
const std : : vector < UniValue > batch { JSONRPCProcessBatchReply ( batch_in ) } ;
if ( ! batch [ ID_PEERINFO ] [ " error " ] . isNull ( ) ) return batch [ ID_PEERINFO ] ;
if ( ! batch [ ID_NETWORKINFO ] [ " error " ] . isNull ( ) ) return batch [ ID_NETWORKINFO ] ;
2020-08-13 10:19:27 -04:00
// Count peer connection totals.
int ipv4_i { 0 } , ipv6_i { 0 } , onion_i { 0 } , block_relay_i { 0 } ; // inbound conn counters
int ipv4_o { 0 } , ipv6_o { 0 } , onion_o { 0 } , block_relay_o { 0 } ; // outbound conn counters
const UniValue & getpeerinfo { batch [ ID_PEERINFO ] [ " result " ] } ;
for ( const UniValue & peer : getpeerinfo . getValues ( ) ) {
const std : : string addr { peer [ " addr " ] . get_str ( ) } ;
const std : : string addr_local { peer [ " addrlocal " ] . isNull ( ) ? " " : peer [ " addrlocal " ] . get_str ( ) } ;
const int mapped_as { peer [ " mapped_as " ] . isNull ( ) ? 0 : peer [ " mapped_as " ] . get_int ( ) } ;
const bool is_block_relay { ! peer [ " relaytxes " ] . get_bool ( ) } ;
const bool is_inbound { peer [ " inbound " ] . get_bool ( ) } ;
if ( is_inbound ) {
if ( IsAddrIPv6 ( addr ) ) {
+ + ipv6_i ;
} else if ( IsInboundOnion ( addr_local , mapped_as ) ) {
+ + onion_i ;
} else {
+ + ipv4_i ;
}
if ( is_block_relay ) + + block_relay_i ;
} else {
if ( IsAddrIPv6 ( addr ) ) {
+ + ipv6_o ;
} else if ( IsOutboundOnion ( addr , mapped_as ) ) {
+ + onion_o ;
} else {
+ + ipv4_o ;
}
if ( is_block_relay ) + + block_relay_o ;
}
}
2020-08-13 10:29:10 -04:00
// Generate report header.
const UniValue & networkinfo { batch [ ID_NETWORKINFO ] [ " result " ] } ;
std : : string result { strprintf ( " %s %s%s - %i%s \n \n " , PACKAGE_NAME , FormatFullVersion ( ) , ChainToString ( ) , networkinfo [ " protocolversion " ] . get_int ( ) , networkinfo [ " subversion " ] . get_str ( ) ) } ;
2020-07-27 02:20:26 -04:00
return JSONRPCReplyObj ( UniValue { result } , NullUniValue , 1 ) ;
}
} ;
2019-12-09 15:52:12 -03:00
/** Process RPC generatetoaddress request. */
class GenerateToAddressRequestHandler : public BaseRequestHandler
{
public :
UniValue PrepareRequest ( const std : : string & method , const std : : vector < std : : string > & args ) override
{
address_str = args . at ( 1 ) ;
UniValue params { RPCConvertValues ( " generatetoaddress " , args ) } ;
return JSONRPCRequestObj ( " generatetoaddress " , params , 1 ) ;
}
UniValue ProcessReply ( const UniValue & reply ) override
{
UniValue result ( UniValue : : VOBJ ) ;
result . pushKV ( " address " , address_str ) ;
result . pushKV ( " blocks " , reply . get_obj ( ) [ " result " ] ) ;
return JSONRPCReplyObj ( result , NullUniValue , 1 ) ;
}
protected :
std : : string address_str ;
} ;
2016-09-29 11:45:19 -03:00
/** Process default single requests */
class DefaultRequestHandler : public BaseRequestHandler {
public :
UniValue PrepareRequest ( const std : : string & method , const std : : vector < std : : string > & args ) override
{
UniValue params ;
if ( gArgs . GetBoolArg ( " -named " , DEFAULT_NAMED ) ) {
params = RPCConvertNamedValues ( method , args ) ;
} else {
params = RPCConvertValues ( method , args ) ;
}
return JSONRPCRequestObj ( method , params , 1 ) ;
}
UniValue ProcessReply ( const UniValue & reply ) override
{
return reply . get_obj ( ) ;
}
} ;
2020-04-10 16:34:43 -04:00
static UniValue CallRPC ( BaseRequestHandler * rh , const std : : string & strMethod , const std : : vector < std : : string > & args , const Optional < std : : string > & rpcwallet = { } )
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 03:53:17 -03:00
{
2017-07-12 16:59:09 -04:00
std : : string host ;
// In preference order, we choose the following for the port:
// 1. -rpcport
// 2. port in -rpcconnect (ie following : in ipv4 or ]: in ipv6)
// 3. default port for chain
int port = BaseParams ( ) . RPCPort ( ) ;
2017-08-01 15:17:40 -04:00
SplitHostPort ( gArgs . GetArg ( " -rpcconnect " , DEFAULT_RPCCONNECT ) , port , host ) ;
port = gArgs . GetArg ( " -rpcport " , port ) ;
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 03:53:17 -03:00
2016-12-20 08:46:11 -03:00
// Obtain event base
raii_event_base base = obtain_event_base ( ) ;
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 03:53:17 -03:00
// Synchronously look up hostname
2016-12-20 08:46:11 -03:00
raii_evhttp_connection evcon = obtain_evhttp_connection_base ( base . get ( ) , host , port ) ;
2019-10-13 19:19:47 -03:00
// Set connection timeout
{
const int timeout = gArgs . GetArg ( " -rpcclienttimeout " , DEFAULT_HTTP_CLIENT_TIMEOUT ) ;
if ( timeout > 0 ) {
evhttp_connection_set_timeout ( evcon . get ( ) , timeout ) ;
} else {
// Indefinite request timeouts are not possible in libevent-http, so we
// set the timeout to a very long time period instead.
constexpr int YEAR_IN_SECONDS = 31556952 ; // Average length of year in Gregorian calendar
evhttp_connection_set_timeout ( evcon . get ( ) , 5 * YEAR_IN_SECONDS ) ;
}
}
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 03:53:17 -03:00
HTTPReply response ;
2016-12-20 08:46:11 -03:00
raii_evhttp_request req = obtain_evhttp_request ( http_request_done , ( void * ) & response ) ;
2017-08-07 01:36:37 -04:00
if ( req = = nullptr )
2016-11-25 05:17:57 -03:00
throw std : : runtime_error ( " create http request failed " ) ;
2016-09-14 10:08:34 -03:00
# if LIBEVENT_VERSION_NUMBER >= 0x02010300
2016-12-20 08:46:11 -03:00
evhttp_request_set_error_cb ( req . get ( ) , http_error_cb ) ;
2016-09-14 10:08:34 -03:00
# endif
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 03:53:17 -03:00
// Get credentials
2015-07-07 09:53:48 -03:00
std : : string strRPCUserColonPass ;
2018-03-09 02:09:57 -03:00
bool failedToGetAuthCookie = false ;
2017-08-01 15:17:40 -04:00
if ( gArgs . GetArg ( " -rpcpassword " , " " ) = = " " ) {
2015-07-07 09:53:48 -03:00
// Try fall back to cookie-based authentication if no password is provided
if ( ! GetAuthCookie ( & strRPCUserColonPass ) ) {
2018-03-09 02:09:57 -03:00
failedToGetAuthCookie = true ;
2015-07-07 09:53:48 -03:00
}
} else {
2017-08-01 15:17:40 -04:00
strRPCUserColonPass = gArgs . GetArg ( " -rpcuser " , " " ) + " : " + gArgs . GetArg ( " -rpcpassword " , " " ) ;
2015-07-07 09:53:48 -03:00
}
2016-12-20 08:46:11 -03:00
struct evkeyvalq * output_headers = evhttp_request_get_output_headers ( req . get ( ) ) ;
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 03:53:17 -03:00
assert ( output_headers ) ;
evhttp_add_header ( output_headers , " Host " , host . c_str ( ) ) ;
evhttp_add_header ( output_headers , " Connection " , " close " ) ;
evhttp_add_header ( output_headers , " Authorization " , ( std : : string ( " Basic " ) + EncodeBase64 ( strRPCUserColonPass ) ) . c_str ( ) ) ;
// Attach request data
2016-09-29 11:45:19 -03:00
std : : string strRequest = rh - > PrepareRequest ( strMethod , args ) . write ( ) + " \n " ;
2016-12-20 08:46:11 -03:00
struct evbuffer * output_buffer = evhttp_request_get_output_buffer ( req . get ( ) ) ;
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 03:53:17 -03:00
assert ( output_buffer ) ;
evbuffer_add ( output_buffer , strRequest . data ( ) , strRequest . size ( ) ) ;
2017-07-13 11:06:27 -04:00
// check if we should use a special wallet endpoint
std : : string endpoint = " / " ;
2020-04-10 16:34:43 -04:00
if ( rpcwallet ) {
char * encodedURI = evhttp_uriencode ( rpcwallet - > data ( ) , rpcwallet - > size ( ) , false ) ;
2017-07-13 11:06:27 -04:00
if ( encodedURI ) {
2020-04-10 16:34:43 -04:00
endpoint = " /wallet/ " + std : : string ( encodedURI ) ;
2017-07-13 11:06:27 -04:00
free ( encodedURI ) ;
2020-04-10 16:34:43 -04:00
} else {
2017-07-13 11:06:27 -04:00
throw CConnectionFailed ( " uri-encode failed " ) ;
}
}
int r = evhttp_make_request ( evcon . get ( ) , req . get ( ) , EVHTTP_REQ_POST , endpoint . c_str ( ) ) ;
2016-12-20 08:46:11 -03:00
req . release ( ) ; // ownership moved to evcon in above call
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 03:53:17 -03:00
if ( r ! = 0 ) {
throw CConnectionFailed ( " send http request failed " ) ;
}
2014-05-26 05:38:44 -04:00
2016-12-20 08:46:11 -03:00
event_base_dispatch ( base . get ( ) ) ;
2014-05-26 05:38:44 -04:00
2018-03-09 02:09:57 -03:00
if ( response . status = = 0 ) {
std : : string responseErrorMessage ;
if ( response . error ! = - 1 ) {
responseErrorMessage = strprintf ( " (error code %d - \" %s \" ) " , response . error , http_errorstring ( response . error ) ) ;
}
throw CConnectionFailed ( strprintf ( " Could not connect to the server %s:%d%s \n \n Make sure the bitcoind server is running and that you are connecting to the correct RPC port. " , host , port , responseErrorMessage ) ) ;
} else if ( response . status = = HTTP_UNAUTHORIZED ) {
if ( failedToGetAuthCookie ) {
throw std : : runtime_error ( strprintf (
2018-05-29 12:49:44 -04:00
" Could not locate RPC credentials. No authentication cookie could be found, and RPC password is not set. See -rpcpassword and -stdinrpcpass. Configuration file: (%s) " ,
2019-10-28 09:30:20 -03:00
GetConfigFile ( gArgs . GetArg ( " -conf " , BITCOIN_CONF_FILENAME ) ) . string ( ) ) ) ;
2018-03-09 02:09:57 -03:00
} else {
throw std : : runtime_error ( " Authorization failed: Incorrect rpcuser or rpcpassword " ) ;
}
} else if ( response . status > = 400 & & response . status ! = HTTP_BAD_REQUEST & & response . status ! = HTTP_NOT_FOUND & & response . status ! = HTTP_INTERNAL_SERVER_ERROR )
2016-11-25 05:17:57 -03:00
throw std : : runtime_error ( strprintf ( " server returned HTTP error %d " , response . status ) ) ;
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 03:53:17 -03:00
else if ( response . body . empty ( ) )
2016-11-25 05:17:57 -03:00
throw std : : runtime_error ( " no response from server " ) ;
2014-05-26 05:38:44 -04:00
// Parse reply
2015-05-13 16:29:19 -03:00
UniValue valReply ( UniValue : : VSTR ) ;
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 03:53:17 -03:00
if ( ! valReply . read ( response . body ) )
2016-11-25 05:17:57 -03:00
throw std : : runtime_error ( " couldn't parse reply from server " ) ;
2016-09-29 11:45:19 -03:00
const UniValue reply = rh - > ProcessReply ( valReply ) ;
2014-05-26 05:38:44 -04:00
if ( reply . empty ( ) )
2016-11-25 05:17:57 -03:00
throw std : : runtime_error ( " expected reply to have result, error and id properties " ) ;
2014-05-26 05:38:44 -04:00
return reply ;
}
2020-04-12 15:01:29 -04:00
/**
* ConnectAndCallRPC wraps CallRPC with - rpcwait and an exception handler .
*
* @ param [ in ] rh Pointer to RequestHandler .
* @ param [ in ] strMethod Reference to const string method to forward to CallRPC .
2020-04-10 16:34:43 -04:00
* @ param [ in ] rpcwallet Reference to const optional string wallet name to forward to CallRPC .
2020-04-12 15:01:29 -04:00
* @ returns the RPC response as a UniValue object .
* @ throws a CConnectionFailed std : : runtime_error if connection failed or RPC server still in warmup .
*/
2020-04-10 16:34:43 -04:00
static UniValue ConnectAndCallRPC ( BaseRequestHandler * rh , const std : : string & strMethod , const std : : vector < std : : string > & args , const Optional < std : : string > & rpcwallet = { } )
2020-04-12 15:01:29 -04:00
{
UniValue response ( UniValue : : VOBJ ) ;
// Execute and handle connection failures with -rpcwait.
const bool fWait = gArgs . GetBoolArg ( " -rpcwait " , false ) ;
do {
try {
2020-04-10 16:34:43 -04:00
response = CallRPC ( rh , strMethod , args , rpcwallet ) ;
2020-04-12 15:01:29 -04:00
if ( fWait ) {
const UniValue & error = find_value ( response , " error " ) ;
if ( ! error . isNull ( ) & & error [ " code " ] . get_int ( ) = = RPC_IN_WARMUP ) {
throw CConnectionFailed ( " server in warmup " ) ;
}
}
break ; // Connection succeeded, no need to retry.
} catch ( const CConnectionFailed & ) {
if ( fWait ) {
UninterruptibleSleep ( std : : chrono : : milliseconds { 1000 } ) ;
} else {
throw ;
}
}
} while ( fWait ) ;
return response ;
}
2020-05-31 05:44:51 -04:00
/** Parse UniValue result to update the message to print to std::cout. */
static void ParseResult ( const UniValue & result , std : : string & strPrint )
{
if ( result . isNull ( ) ) return ;
strPrint = result . isStr ( ) ? result . get_str ( ) : result . write ( 2 ) ;
}
/** Parse UniValue error to update the message to print to std::cerr and the code to return. */
static void ParseError ( const UniValue & error , std : : string & strPrint , int & nRet )
{
if ( error . isObject ( ) ) {
const UniValue & err_code = find_value ( error , " code " ) ;
const UniValue & err_msg = find_value ( error , " message " ) ;
if ( ! err_code . isNull ( ) ) {
strPrint = " error code: " + err_code . getValStr ( ) + " \n " ;
}
if ( err_msg . isStr ( ) ) {
strPrint + = ( " error message: \n " + err_msg . get_str ( ) ) ;
}
if ( err_code . isNum ( ) & & err_code . get_int ( ) = = RPC_WALLET_NOT_SPECIFIED ) {
strPrint + = " \n Try adding \" -rpcwallet=<filename> \" option to bitcoin-cli command line. " ;
}
} else {
strPrint = " error: " + error . write ( ) ;
}
nRet = abs ( error [ " code " ] . get_int ( ) ) ;
}
2020-04-12 15:28:19 -04:00
/**
* GetWalletBalances calls listwallets ; if more than one wallet is loaded , it then
* fetches mine . trusted balances for each loaded wallet and pushes them to ` result ` .
*
* @ param result Reference to UniValue object the wallet names and balances are pushed to .
*/
static void GetWalletBalances ( UniValue & result )
{
2020-07-05 09:25:11 -04:00
DefaultRequestHandler rh ;
const UniValue listwallets = ConnectAndCallRPC ( & rh , " listwallets " , /* args=*/ { } ) ;
2020-04-12 15:28:19 -04:00
if ( ! find_value ( listwallets , " error " ) . isNull ( ) ) return ;
const UniValue & wallets = find_value ( listwallets , " result " ) ;
if ( wallets . size ( ) < = 1 ) return ;
UniValue balances ( UniValue : : VOBJ ) ;
for ( const UniValue & wallet : wallets . getValues ( ) ) {
const std : : string wallet_name = wallet . get_str ( ) ;
2020-07-05 09:25:11 -04:00
const UniValue getbalances = ConnectAndCallRPC ( & rh , " getbalances " , /* args=*/ { } , wallet_name ) ;
2020-04-12 15:28:19 -04:00
const UniValue & balance = find_value ( getbalances , " result " ) [ " mine " ] [ " trusted " ] ;
balances . pushKV ( wallet_name , balance ) ;
}
result . pushKV ( " balances " , balances ) ;
}
2020-06-01 05:57:12 -04:00
/**
* Call RPC getnewaddress .
* @ returns getnewaddress response as a UniValue object .
*/
static UniValue GetNewAddress ( )
{
2020-05-31 12:03:47 -04:00
Optional < std : : string > wallet_name { } ;
if ( gArgs . IsArgSet ( " -rpcwallet " ) ) wallet_name = gArgs . GetArg ( " -rpcwallet " , " " ) ;
2020-07-05 09:25:11 -04:00
DefaultRequestHandler rh ;
return ConnectAndCallRPC ( & rh , " getnewaddress " , /* args=*/ { } , wallet_name ) ;
2020-06-01 05:57:12 -04:00
}
2020-05-31 09:41:08 -04:00
/**
* Check bounds and set up args for RPC generatetoaddress params : nblocks , address , maxtries .
* @ param [ in ] address Reference to const string address to insert into the args .
* @ param args Reference to vector of string args to modify .
*/
static void SetGenerateToAddressArgs ( const std : : string & address , std : : vector < std : : string > & args )
{
if ( args . size ( ) > 2 ) throw std : : runtime_error ( " too many arguments (maximum 2 for nblocks and maxtries) " ) ;
if ( args . size ( ) = = 0 ) {
args . emplace_back ( DEFAULT_NBLOCKS ) ;
} else if ( args . at ( 0 ) = = " 0 " ) {
throw std : : runtime_error ( " the first argument (number of blocks to generate, default: " + DEFAULT_NBLOCKS + " ) must be an integer value greater than zero " ) ;
}
args . emplace ( args . begin ( ) + 1 , address ) ;
}
2018-05-02 12:14:48 -03:00
static int CommandLineRPC ( int argc , char * argv [ ] )
2014-05-26 05:38:44 -04:00
{
2016-11-25 05:17:57 -03:00
std : : string strPrint ;
2014-05-26 05:38:44 -04:00
int nRet = 0 ;
2014-06-25 21:09:36 -04:00
try {
2014-05-26 05:38:44 -04:00
// Skip switches
2014-06-25 21:09:36 -04:00
while ( argc > 1 & & IsSwitchChar ( argv [ 1 ] [ 0 ] ) ) {
2014-05-26 05:38:44 -04:00
argc - - ;
argv + + ;
}
2017-08-23 15:48:00 -03:00
std : : string rpcPass ;
if ( gArgs . GetBoolArg ( " -stdinrpcpass " , false ) ) {
2018-07-19 10:48:55 -04:00
NO_STDIN_ECHO ( ) ;
if ( ! StdinReady ( ) ) {
fputs ( " RPC password> " , stderr ) ;
fflush ( stderr ) ;
}
2017-08-24 14:35:06 -03:00
if ( ! std : : getline ( std : : cin , rpcPass ) ) {
2017-08-23 15:48:00 -03:00
throw std : : runtime_error ( " -stdinrpcpass specified but failed to read from standard input " ) ;
2017-08-24 14:35:06 -03:00
}
2019-02-14 02:51:28 -03:00
if ( StdinTerminal ( ) ) {
fputc ( ' \n ' , stdout ) ;
}
2017-08-23 15:48:00 -03:00
gArgs . ForceSetArg ( " -rpcpassword " , rpcPass ) ;
}
2016-02-17 11:03:38 -03:00
std : : vector < std : : string > args = std : : vector < std : : string > ( & argv [ 1 ] , & argv [ argc ] ) ;
2018-07-19 10:48:55 -04:00
if ( gArgs . GetBoolArg ( " -stdinwalletpassphrase " , false ) ) {
NO_STDIN_ECHO ( ) ;
std : : string walletPass ;
if ( args . size ( ) < 1 | | args [ 0 ] . substr ( 0 , 16 ) ! = " walletpassphrase " ) {
throw std : : runtime_error ( " -stdinwalletpassphrase is only applicable for walletpassphrase(change) " ) ;
}
if ( ! StdinReady ( ) ) {
fputs ( " Wallet passphrase> " , stderr ) ;
fflush ( stderr ) ;
}
if ( ! std : : getline ( std : : cin , walletPass ) ) {
throw std : : runtime_error ( " -stdinwalletpassphrase specified but failed to read from standard input " ) ;
}
2019-02-14 02:51:28 -03:00
if ( StdinTerminal ( ) ) {
fputc ( ' \n ' , stdout ) ;
}
2018-07-19 10:48:55 -04:00
args . insert ( args . begin ( ) + 1 , walletPass ) ;
}
2017-08-01 15:17:40 -04:00
if ( gArgs . GetBoolArg ( " -stdin " , false ) ) {
2016-02-17 11:03:38 -03:00
// Read one arg per line from stdin and append
std : : string line ;
2017-08-24 14:35:06 -03:00
while ( std : : getline ( std : : cin , line ) ) {
2016-02-17 11:03:38 -03:00
args . push_back ( line ) ;
2017-08-24 14:35:06 -03:00
}
2019-02-14 02:51:28 -03:00
if ( StdinTerminal ( ) ) {
fputc ( ' \n ' , stdout ) ;
}
2016-02-17 11:03:38 -03:00
}
2016-09-29 11:45:19 -03:00
std : : unique_ptr < BaseRequestHandler > rh ;
std : : string method ;
2020-05-03 05:10:24 -04:00
if ( gArgs . IsArgSet ( " -getinfo " ) ) {
2016-09-29 11:45:19 -03:00
rh . reset ( new GetinfoRequestHandler ( ) ) ;
2020-07-27 02:20:26 -04:00
} else if ( gArgs . GetBoolArg ( " -netinfo " , false ) ) {
rh . reset ( new NetinfoRequestHandler ( ) ) ;
2020-05-31 09:41:08 -04:00
} else if ( gArgs . GetBoolArg ( " -generate " , false ) ) {
const UniValue getnewaddress { GetNewAddress ( ) } ;
const UniValue & error { find_value ( getnewaddress , " error " ) } ;
if ( error . isNull ( ) ) {
SetGenerateToAddressArgs ( find_value ( getnewaddress , " result " ) . get_str ( ) , args ) ;
rh . reset ( new GenerateToAddressRequestHandler ( ) ) ;
} else {
ParseError ( error , strPrint , nRet ) ;
}
2016-11-22 10:56:29 -03:00
} else {
2016-09-29 11:45:19 -03:00
rh . reset ( new DefaultRequestHandler ( ) ) ;
if ( args . size ( ) < 1 ) {
throw std : : runtime_error ( " too few parameters (need at least command) " ) ;
}
method = args [ 0 ] ;
args . erase ( args . begin ( ) ) ; // Remove trailing method name from arguments vector
2016-11-22 10:56:29 -03:00
}
2020-05-31 05:44:51 -04:00
if ( nRet = = 0 ) {
// Perform RPC call
Optional < std : : string > wallet_name { } ;
if ( gArgs . IsArgSet ( " -rpcwallet " ) ) wallet_name = gArgs . GetArg ( " -rpcwallet " , " " ) ;
const UniValue reply = ConnectAndCallRPC ( rh . get ( ) , method , args , wallet_name ) ;
// Parse reply
UniValue result = find_value ( reply , " result " ) ;
const UniValue & error = find_value ( reply , " error " ) ;
if ( error . isNull ( ) ) {
if ( gArgs . IsArgSet ( " -getinfo " ) & & ! gArgs . IsArgSet ( " -rpcwallet " ) ) {
GetWalletBalances ( result ) ; // fetch multiwallet balances and append to result
2014-10-29 14:08:31 -03:00
}
2020-05-31 05:44:51 -04:00
ParseResult ( result , strPrint ) ;
2020-04-12 15:01:29 -04:00
} else {
2020-05-31 05:44:51 -04:00
ParseError ( error , strPrint , nRet ) ;
2014-10-29 14:08:31 -03:00
}
2020-04-12 15:01:29 -04:00
}
} catch ( const std : : exception & e ) {
2016-11-25 05:17:57 -03:00
strPrint = std : : string ( " error: " ) + e . what ( ) ;
2014-05-26 05:38:44 -04:00
nRet = EXIT_FAILURE ;
2020-04-12 15:01:29 -04:00
} catch ( . . . ) {
2017-08-07 01:36:37 -04:00
PrintExceptionContinue ( nullptr , " CommandLineRPC() " ) ;
2014-05-26 05:38:44 -04:00
throw ;
}
2014-06-25 21:09:36 -04:00
if ( strPrint ! = " " ) {
2019-10-28 09:30:20 -03:00
tfm : : format ( nRet = = 0 ? std : : cout : std : : cerr , " %s \n " , strPrint ) ;
2014-05-26 05:38:44 -04:00
}
return nRet ;
}
2018-08-05 12:38:25 -04:00
# ifdef WIN32
build: fix ASLR for bitcoin-cli on Windows
ASLR is not currently working for the bitcoin-cli.exe binary. This is
due to it not having a .reloc section, which is stripped by default by
the mingw-w64 ld we use for gitian builds. A good summary of issues with
ld and mingw-w64 is available in this thread:
https://sourceware.org/bugzilla/show_bug.cgi?id=19011.
All other Windows binaries that we distribute (bitcoind, bitcoin-qt,
bitcoin-wallet, bitcoin-tx and test_bitcoin) do not suffer this issue,
and currently having working ASLR. This is due to them exporting
(inadvertent or not) libsecp256k1 symbols, and, as a result, the .reloc
section is not stripped by ld.
This change is a temporary workaround, also the same one described here:
https://www.kb.cert.org/vuls/id/307144/, that causes main() to be
exported. Exporting a symbol will mean that the .reloc section is not
stripped, and ASLR will function correctly.
2020-04-18 22:05:29 -04:00
// Export main() and ensure working ASLR on Windows.
// Exporting a symbol will prevent the linker from stripping
// the .reloc section from the binary, which is a requirement
// for ASLR. This is a temporary workaround until a fixed
// version of binutils is used for releases.
__declspec ( dllexport ) int main ( int argc , char * argv [ ] )
{
2018-08-05 12:38:25 -04:00
util : : WinCmdLineArgs winArgs ;
std : : tie ( argc , argv ) = winArgs . get ( ) ;
build: fix ASLR for bitcoin-cli on Windows
ASLR is not currently working for the bitcoin-cli.exe binary. This is
due to it not having a .reloc section, which is stripped by default by
the mingw-w64 ld we use for gitian builds. A good summary of issues with
ld and mingw-w64 is available in this thread:
https://sourceware.org/bugzilla/show_bug.cgi?id=19011.
All other Windows binaries that we distribute (bitcoind, bitcoin-qt,
bitcoin-wallet, bitcoin-tx and test_bitcoin) do not suffer this issue,
and currently having working ASLR. This is due to them exporting
(inadvertent or not) libsecp256k1 symbols, and, as a result, the .reloc
section is not stripped by ld.
This change is a temporary workaround, also the same one described here:
https://www.kb.cert.org/vuls/id/307144/, that causes main() to be
exported. Exporting a symbol will mean that the .reloc section is not
stripped, and ASLR will function correctly.
2020-04-18 22:05:29 -04:00
# else
int main ( int argc , char * argv [ ] )
{
2018-08-05 12:38:25 -04:00
# endif
2014-05-13 06:15:00 -04:00
SetupEnvironment ( ) ;
2015-09-02 11:18:16 -03:00
if ( ! SetupNetworking ( ) ) {
2019-06-13 09:16:10 -04:00
tfm : : format ( std : : cerr , " Error: Initializing networking failed \n " ) ;
2016-05-02 13:48:04 -03:00
return EXIT_FAILURE ;
2015-09-02 11:18:16 -03:00
}
2018-06-04 14:55:00 -04:00
event_set_log_callback ( & libevent_log_cb ) ;
2014-05-13 06:15:00 -04:00
2014-06-25 21:09:36 -04:00
try {
2016-11-02 15:59:09 -03:00
int ret = AppInitRPC ( argc , argv ) ;
if ( ret ! = CONTINUE_EXECUTION )
return ret ;
2013-10-11 18:09:59 -03:00
}
2014-12-07 09:29:06 -03:00
catch ( const std : : exception & e ) {
2013-10-11 18:09:59 -03:00
PrintExceptionContinue ( & e , " AppInitRPC() " ) ;
2014-06-12 22:26:46 -04:00
return EXIT_FAILURE ;
2013-10-11 18:09:59 -03:00
} catch ( . . . ) {
2017-08-07 01:36:37 -04:00
PrintExceptionContinue ( nullptr , " AppInitRPC() " ) ;
2014-06-12 22:26:46 -04:00
return EXIT_FAILURE ;
2013-10-11 18:09:59 -03:00
}
2014-06-12 22:26:46 -04:00
int ret = EXIT_FAILURE ;
2014-06-25 21:09:36 -04:00
try {
2014-02-24 10:08:56 -03:00
ret = CommandLineRPC ( argc , argv ) ;
2013-10-11 18:09:59 -03:00
}
2014-12-07 09:29:06 -03:00
catch ( const std : : exception & e ) {
2013-10-11 18:09:59 -03:00
PrintExceptionContinue ( & e , " CommandLineRPC() " ) ;
} catch ( . . . ) {
2017-08-07 01:36:37 -04:00
PrintExceptionContinue ( nullptr , " CommandLineRPC() " ) ;
2013-10-11 18:09:59 -03:00
}
2014-02-24 10:08:56 -03:00
return ret ;
2013-10-11 18:09:59 -03:00
}