2013-10-11 23:09:59 +02:00
// Copyright (c) 2009-2010 Satoshi Nakamoto
2023-08-16 19:27:31 +02:00
// Copyright (c) 2009-2020 The Bitcoin Core developers
2022-06-08 01:36:46 +02:00
// Copyright (c) 2014-2022 The Dash Core developers
2014-12-13 05:09:33 +01:00
// Distributed under the MIT software license, see the accompanying
2013-10-11 23:09:59 +02:00
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
2016-02-04 13:41:58 +01:00
# if defined(HAVE_CONFIG_H)
2022-08-02 18:34:58 +02:00
# include <config/bitcoin-config.h>
2016-02-04 13:41:58 +01:00
# endif
2020-03-19 23:46:56 +01:00
# include <chainparamsbase.h>
# include <clientversion.h>
2022-06-13 21:43:22 +02:00
# include <compat.h>
2020-03-19 23:46:56 +01:00
# include <rpc/client.h>
2023-04-16 21:53:03 +02:00
# include <rpc/mining.h>
2020-03-19 23:46:56 +01:00
# include <rpc/protocol.h>
2022-02-27 08:46:53 +01:00
# include <rpc/request.h>
2020-03-19 23:46:56 +01:00
# include <stacktraces.h>
2020-10-29 12:04:08 +01:00
# include <tinyformat.h>
2021-06-27 08:33:13 +02:00
# include <util/strencodings.h>
2022-03-24 05:13:51 +01:00
# include <util/system.h>
# include <util/translation.h>
2020-04-10 18:52:32 +02:00
# include <util/url.h>
2013-10-11 23:09:59 +02:00
2020-10-29 12:04:08 +01:00
# include <algorithm>
2022-12-25 09:25:19 +01:00
# include <cmath>
2022-03-24 05:13:51 +01:00
# include <functional>
2018-04-02 20:31:40 +02:00
# include <memory>
2022-10-15 22:11:49 +02: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
# include <stdio.h>
2020-05-27 13:15:53 +02:00
# include <string>
2018-10-08 03:47:03 +02:00
# include <tuple>
2013-04-13 07:13:08 +02: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 07:53:17 +01:00
# include <event2/buffer.h>
# include <event2/keyvalq_struct.h>
2020-03-19 23:46:56 +01:00
# include <support/events.h>
2013-04-13 07:13:08 +02:00
2015-09-04 16:11:34 +02:00
# include <univalue.h>
2019-10-02 18:36:01 +02:00
# include <compat/stdin.h>
2014-07-03 07:45:16 +02:00
2018-08-25 20:20:30 +02:00
const std : : function < std : : string ( const char * ) > G_TRANSLATION_FUN = nullptr ;
2020-04-10 18:52:32 +02:00
UrlDecodeFn * const URL_DECODE = urlDecode ;
2018-08-25 20:20:30 +02:00
2015-06-27 21:21:41 +02:00
static const char DEFAULT_RPCCONNECT [ ] = " 127.0.0.1 " ;
2015-09-18 15:45:38 +02:00
static const int DEFAULT_HTTP_CLIENT_TIMEOUT = 900 ;
2017-01-10 13:52:49 +01:00
static const bool DEFAULT_NAMED = false ;
2016-11-11 06:16:39 +01:00
static const int CONTINUE_EXECUTION = - 1 ;
2014-05-26 11:38:44 +02:00
2023-04-16 21:53:03 +02:00
/** Default number of blocks to generate for RPC generatetoaddress. */
static const std : : string DEFAULT_NBLOCKS = " 1 " ;
2022-05-21 10:27:30 +02:00
static void SetupCliArgs ( ArgsManager & argsman )
2014-05-26 11:38:44 +02:00
{
2022-05-21 10:27:30 +02:00
SetupHelpOptions ( argsman ) ;
2022-05-21 10:12:13 +02:00
2017-05-09 09:29:12 +02:00
const auto defaultBaseParams = CreateBaseChainParams ( CBaseChainParams : : MAIN ) ;
const auto testnetBaseParams = CreateBaseChainParams ( CBaseChainParams : : TESTNET ) ;
2018-09-04 12:45:48 +02:00
const auto regtestBaseParams = CreateBaseChainParams ( CBaseChainParams : : REGTEST ) ;
2021-03-19 16:00:24 +01:00
2022-05-21 10:27:30 +02: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 ) ;
2023-04-16 21:53:03 +02:00
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: dash-cli -generate 4 1000 " , DEFAULT_NBLOCKS , DEFAULT_MAX_TRIES ) , ArgsManager : : ALLOW_ANY , OptionsCategory : : OPTIONS ) ;
2022-05-21 10:27:30 +02:00
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 ) ;
Merge #20829: doc: add -netinfo help
6f2c4fd0775a9c45eacc4bab8f138528852fdf44 netinfo: add user help documentation (Jon Atack)
Pull request description:
This is the help doc commit of #20764 without the rest of the PR or anything new since the 0.21.0 branch-off in order to target giving users a -netinfo help doc for 0.21.
- to test the new help
```
$ ./src/bitcoin-cli -netinfo help
```
- to see the updated short help
```
$ ./src/bitcoin-cli -help | grep -A4 netinfo
```
<details><summary><code>-netinfo</code> help doc</summary><p>
```
$ ./src/bitcoin-cli -netinfo help
-netinfo level "help"
Returns a network peer connections dashboard with information from the remote server.
Under the hood, -netinfo fetches the data by calling getpeerinfo and getnetworkinfo.
An optional integer argument from 0 to 4 can be passed for different peers listings.
Pass "help" to see this detailed help documentation.
If more than one argument is passed, only the first one is read and parsed.
Suggestion: use with the Linux watch(1) command for a live dashboard; see example below.
Arguments:
1. level (integer 0-4, optional) Specify the info level of the peers dashboard (default 0):
0 - Connection counts and local addresses
1 - Like 0 but with a peers listing (without address or version columns)
2 - Like 1 but with an address column
3 - Like 1 but with a version column
4 - Like 1 but with both address and version columns
2. help (string "help", optional) Print this help documentation instead of the dashboard.
Result:
* The peers listing in levels 1-4 displays all of the peers sorted by direction and minimum ping time:
Column Description
------ -----------
<-> Direction
"in" - inbound connections are those initiated by the peer
"out" - outbound connections are those initiated by us
type Type of peer connection
"full" - full relay, the default
"block" - block relay; like full relay but does not relay transactions or addresses
net Network the peer connected through ("ipv4", "ipv6", "onion", "i2p", or "cjdns")
mping Minimum observed ping time, in milliseconds (ms)
ping Last observed ping time, in milliseconds (ms)
send Time since last message sent to the peer, in seconds
recv Time since last message received from the peer, in seconds
txn Time since last novel transaction received from the peer and accepted into our mempool, in minutes
blk Time since last novel block passing initial validity checks received from the peer, in minutes
age Duration of connection to the peer, in minutes
asmap Mapped AS (Autonomous System) number in the BGP route to the peer, used for diversifying
peer selection (only displayed if the -asmap config option is set)
id Peer index, in increasing order of peer connections since node startup
address IP address and port of the peer
version Peer version and subversion concatenated, e.g. "70016/Satoshi:21.0.0/"
* The connection counts table displays the number of peers by direction, network, and the totals
for each, as well as a column for block relay peers.
* The local addresses table lists each local address broadcast by the node, the port, and the score.
Examples:
Connection counts and local addresses only
> bitcoin-cli -netinfo
Compact peers listing
> bitcoin-cli -netinfo 1
Full dashboard
> bitcoin-cli -netinfo 4
Full live dashboard, adjust --interval or --no-title as needed (Linux)
> watch --interval 1 --no-title ./src/bitcoin-cli -netinfo 4
See this help
> bitcoin-cli -netinfo help
```
</p></details>
ACKs for top commit:
laanwj:
ACK 6f2c4fd0775a9c45eacc4bab8f138528852fdf44
Tree-SHA512: dd49b1ce65546dacfb8ba9f9d57de0eae55560fd05533cf26c0b5d6ec65bf1de789c3287e90a0e2f47707532fab2fe62919a4192a7ffd58ac8eec18293e9aaeb
2021-01-06 16:10:39 +01:00
argsman . AddArg ( " -netinfo " , " Get network peer connection information from the remote server. An optional integer argument from 0 to 4 can be passed for different peers listings (default: 0). Pass \" help \" for detailed help documentation. " , ArgsManager : : ALLOW_ANY , OptionsCategory : : OPTIONS ) ;
2022-05-21 10:27:30 +02: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 dashd). This changes the RPC endpoint used, e.g. http://127.0.0.1:9998/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 ) ;
SetupChainParamsBaseOptions ( argsman ) ;
2014-05-26 11:38:44 +02:00
}
2018-06-07 08:58:06 +02:00
/** libevent event log callback */
static void libevent_log_cb ( int severity , const char * msg )
{
// Ignore everything other than errors
if ( severity > = EVENT_LOG_ERR ) {
throw std : : runtime_error ( strprintf ( " libevent error: %s " , msg ) ) ;
}
}
2013-10-11 23:09:59 +02:00
//////////////////////////////////////////////////////////////////////////////
//
// Start
//
2014-10-29 18:08:31 +01: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-11 06:16:39 +01: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 23:09:59 +02:00
{
//
// Parameters
//
2022-05-21 10:27:30 +02:00
SetupCliArgs ( gArgs ) ;
2018-05-30 19:42:58 +02:00
std : : string error ;
if ( ! gArgs . ParseParameters ( argc , argv , error ) ) {
2022-03-21 18:28:10 +01:00
tfm : : format ( std : : cerr , " Error parsing command line arguments: %s \n " , error ) ;
2018-05-30 19:42:58 +02:00
return EXIT_FAILURE ;
}
2019-07-02 06:16:11 +02:00
if ( gArgs . IsArgSet ( " -printcrashinfo " ) ) {
std : : cout < < GetCrashInfoStrFromSerializedStr ( gArgs . GetArg ( " -printcrashinfo " , " " ) ) < < std : : endl ;
return true ;
}
2018-04-03 17:51:48 +02:00
if ( argc < 2 | | HelpRequested ( gArgs ) | | gArgs . IsArgSet ( " -version " ) ) {
2018-08-07 10:19:09 +02:00
std : : string strUsage = PACKAGE_NAME " RPC client version " + FormatFullVersion ( ) + " \n " ;
2019-06-24 18:44:27 +02:00
if ( ! gArgs . IsArgSet ( " -version " ) ) {
2018-08-07 10:19:09 +02:00
strUsage + = " \n "
" Usage: dash-cli [options] <command> [params] Send command to " PACKAGE_NAME " \n "
" or: dash-cli [options] -named <command> [name=value]... Send command to " PACKAGE_NAME " (with named arguments) \n "
" or: dash-cli [options] help List commands \n "
" or: dash-cli [options] help <command> Get help for a command \n " ;
2021-03-19 16:00:24 +01:00
strUsage + = " \n " + gArgs . GetHelpMessage ( ) ;
2014-11-22 19:56:25 +01:00
}
2022-03-21 18:28:10 +01:00
tfm : : format ( std : : cout , " %s " , strUsage ) ;
2016-11-11 06:16:39 +01:00
if ( argc < 2 ) {
2021-10-24 12:51:47 +02:00
tfm : : format ( std : : cerr , " Error: too few parameters \n " ) ;
2016-11-11 06:16:39 +01:00
return EXIT_FAILURE ;
}
return EXIT_SUCCESS ;
2014-11-22 19:56:25 +01:00
}
2019-04-29 21:46:34 +02:00
if ( ! CheckDataDirOption ( ) ) {
2022-03-21 18:28:10 +01:00
tfm : : format ( std : : cerr , " Error: Specified data directory \" %s \" does not exist. \n " , gArgs . GetArg ( " -datadir " , " " ) ) ;
2016-11-11 06:16:39 +01:00
return EXIT_FAILURE ;
2013-10-11 23:09:59 +02:00
}
2018-05-30 19:42:58 +02:00
if ( ! gArgs . ReadConfigFiles ( error , true ) ) {
2022-03-21 18:28:10 +01:00
tfm : : format ( std : : cerr , " Error reading configuration file: %s \n " , error ) ;
2016-11-11 06:16:39 +01:00
return EXIT_FAILURE ;
2014-04-07 10:10:01 +02:00
}
2019-09-10 11:42:52 +02:00
// Check for -chain, -testnet or -regtest parameter (BaseParams() calls are only valid after this clause)
2015-05-25 09:00:17 +02:00
try {
2020-04-29 12:16:37 +02:00
SelectBaseParams ( gArgs . GetChainName ( ) ) ;
2015-10-27 17:39:42 +01:00
} catch ( const std : : exception & e ) {
2021-10-24 12:51:47 +02:00
tfm : : format ( std : : cerr , " Error: %s \n " , e . what ( ) ) ;
2016-11-11 06:16:39 +01:00
return EXIT_FAILURE ;
2013-11-28 17:28:27 +01:00
}
2016-11-11 06:16:39 +01:00
return CONTINUE_EXECUTION ;
2013-10-11 23:09:59 +02: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 07:53:17 +01:00
/** Reply structure for request_done to fill in */
struct HTTPReply
2014-05-26 11:38:44 +02:00
{
2016-09-26 14:52:56 +02: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 07:53:17 +01:00
int status ;
2016-09-26 14:52:56 +02: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 07:53:17 +01:00
std : : string body ;
} ;
2020-05-27 13:15:53 +02:00
static std : : string http_errorstring ( int code )
2016-09-26 14:52:56 +02: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 07:53:17 +01:00
static void http_request_done ( struct evhttp_request * req , void * ctx )
{
HTTPReply * reply = static_cast < HTTPReply * > ( ctx ) ;
2019-08-06 05:08:33 +02:00
if ( req = = nullptr ) {
/* If req is nullptr, it means an error occurred while connecting: the
2016-09-26 14:52:56 +02: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 07:53:17 +01:00
*/
reply - > status = 0 ;
return ;
}
2013-10-11 23:09:59 +02: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 07:53:17 +01:00
reply - > status = evhttp_request_get_response_code ( req ) ;
2014-05-26 11:38:44 +02: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 07:53:17 +01:00
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 ) ;
}
}
2014-05-26 11:38:44 +02:00
2016-09-26 14:52:56 +02: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
2017-09-28 08:33:12 +02: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 :
2018-02-06 18:05:11 +01:00
virtual ~ BaseRequestHandler ( ) { }
2017-09-28 08:33:12 +02: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 ;
2023-04-16 09:18:51 +02:00
const int ID_BALANCES = 3 ;
2017-09-28 08:33:12 +02:00
/** Create a simulated `getinfo` request. */
UniValue PrepareRequest ( const std : : string & method , const std : : vector < std : : string > & args ) override
{
2017-11-18 12:05:27 +01:00
if ( ! args . empty ( ) ) {
throw std : : runtime_error ( " -getinfo takes no arguments " ) ;
}
2017-09-28 08:33:12 +02: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 ) ) ;
2023-04-16 09:18:51 +02:00
result . push_back ( JSONRPCRequestObj ( " getbalances " , NullUniValue , ID_BALANCES ) ) ;
2017-09-28 08:33:12 +02: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 ) ;
2023-04-17 10:28:19 +02:00
const std : : vector < UniValue > batch = JSONRPCProcessBatchReply ( batch_in ) ;
2023-04-16 09:18:51 +02:00
// Errors in getnetworkinfo() and getblockchaininfo() are fatal, pass them on;
// getwalletinfo() and getbalances() are allowed to fail if there is no wallet.
2017-09-28 08:33:12 +02: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-30 12:38:25 +01:00
result . pushKV ( " headers " , batch [ ID_BLOCKCHAININFO ] [ " result " ] [ " headers " ] ) ;
result . pushKV ( " verificationprogress " , batch [ ID_BLOCKCHAININFO ] [ " result " ] [ " verificationprogress " ] ) ;
2017-09-28 08:33:12 +02: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-11 15:26:38 +01:00
result . pushKV ( " chain " , UniValue ( batch [ ID_BLOCKCHAININFO ] [ " result " ] [ " chain " ] ) ) ;
Merge #17368: cli: fix -getinfo output when compiled with no wallet
3d05d332693ec860626fc77e6ba50dec94e4e83c cli: fix -getinfo output when compiled with no wallet (fanquake)
Pull request description:
master (33b155f28732487854cf0ca29ca17c50f8c6872e):
```bash
src/bitcoin-cli -getinfo
{
"version": 199900,
"protocolversion": 70015,
"blocks": 602348,
"headers": 602348,
"verificationprogress": 0.9999995592310106,
"timeoffset": 0,
"connections": 10,
"proxy": "",
"difficulty": 13691480038694.45,
"chain": "main",
"walletversion": null,
"balance": null,
"keypoololdest": null,
"keypoolsize": null,
"paytxfee": null,
"relayfee": 0.00001000,
"warnings": "This is a pre-release test build - use at your own risk - do not use for mining or merchant applications"
}
```
This PR (3d05d332693ec860626fc77e6ba50dec94e4e83c):
```bash
{
"version": 199900,
"protocolversion": 70015,
"blocks": 602348,
"headers": 602348,
"verificationprogress": 0.9999996313568186,
"timeoffset": 0,
"connections": 10,
"proxy": "",
"difficulty": 13691480038694.45,
"chain": "main",
"relayfee": 0.00001000,
"warnings": "This is a pre-release test build - use at your own risk - do not use for mining or merchant applications"
}
```
ACKs for top commit:
MarcoFalke:
ouch ACK 3d05d332693ec860626fc77e6ba50dec94e4e83c
laanwj:
ACK 3d05d332693ec860626fc77e6ba50dec94e4e83c
darosior:
ACK 3d05d332693ec860626fc77e6ba50dec94e4e83c
Tree-SHA512: 055424e122a082cbfea410da287d9ceb7ed405fd68d53e2f5bef62beea80bc374a7d00366de0479d23faecb7f063b232aca52e9fdbdb97c58ddf46e7749136a9
2019-11-06 11:07:07 +01:00
if ( ! batch [ ID_WALLETINFO ] [ " result " ] . isNull ( ) ) {
2021-03-17 23:36:11 +01:00
result . pushKV ( " coinjoin_balance " , batch [ ID_WALLETINFO ] [ " result " ] [ " coinjoin_balance " ] ) ;
2017-09-28 08:33:12 +02: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 " ] ) ;
}
2023-04-16 09:18:51 +02:00
if ( ! batch [ ID_BALANCES ] [ " result " ] . isNull ( ) ) {
result . pushKV ( " balance " , batch [ ID_BALANCES ] [ " result " ] [ " mine " ] [ " trusted " ] ) ;
}
2017-09-28 08:33:12 +02:00
result . pushKV ( " relayfee " , batch [ ID_NETWORKINFO ] [ " result " ] [ " relayfee " ] ) ;
result . pushKV ( " warnings " , batch [ ID_NETWORKINFO ] [ " result " ] [ " warnings " ] ) ;
return JSONRPCReplyObj ( result , NullUniValue , 1 ) ;
}
} ;
2023-04-17 10:36:33 +02:00
/** Process netinfo requests */
class NetinfoRequestHandler : public BaseRequestHandler
{
private :
2023-04-16 07:18:06 +02:00
static constexpr int8_t UNKNOWN_NETWORK { - 1 } ;
2020-10-29 12:04:08 +01:00
static constexpr uint8_t m_networks_size { 3 } ;
2023-04-16 07:18:06 +02:00
const std : : array < std : : string , m_networks_size > m_networks { { " ipv4 " , " ipv6 " , " onion " } } ;
std : : array < std : : array < uint16_t , m_networks_size + 2 > , 3 > m_counts { { { } } } ; //!< Peer counts by (in/out/total, networks/total/block-relay)
int8_t NetworkStringToId ( const std : : string & str ) const
2023-04-17 10:36:33 +02:00
{
2020-10-29 12:04:08 +01:00
for ( uint8_t i = 0 ; i < m_networks_size ; + + i ) {
2023-04-16 07:18:06 +02:00
if ( str = = m_networks . at ( i ) ) return i ;
}
return UNKNOWN_NETWORK ;
2023-04-17 10:36:33 +02:00
}
Merge #20829: doc: add -netinfo help
6f2c4fd0775a9c45eacc4bab8f138528852fdf44 netinfo: add user help documentation (Jon Atack)
Pull request description:
This is the help doc commit of #20764 without the rest of the PR or anything new since the 0.21.0 branch-off in order to target giving users a -netinfo help doc for 0.21.
- to test the new help
```
$ ./src/bitcoin-cli -netinfo help
```
- to see the updated short help
```
$ ./src/bitcoin-cli -help | grep -A4 netinfo
```
<details><summary><code>-netinfo</code> help doc</summary><p>
```
$ ./src/bitcoin-cli -netinfo help
-netinfo level "help"
Returns a network peer connections dashboard with information from the remote server.
Under the hood, -netinfo fetches the data by calling getpeerinfo and getnetworkinfo.
An optional integer argument from 0 to 4 can be passed for different peers listings.
Pass "help" to see this detailed help documentation.
If more than one argument is passed, only the first one is read and parsed.
Suggestion: use with the Linux watch(1) command for a live dashboard; see example below.
Arguments:
1. level (integer 0-4, optional) Specify the info level of the peers dashboard (default 0):
0 - Connection counts and local addresses
1 - Like 0 but with a peers listing (without address or version columns)
2 - Like 1 but with an address column
3 - Like 1 but with a version column
4 - Like 1 but with both address and version columns
2. help (string "help", optional) Print this help documentation instead of the dashboard.
Result:
* The peers listing in levels 1-4 displays all of the peers sorted by direction and minimum ping time:
Column Description
------ -----------
<-> Direction
"in" - inbound connections are those initiated by the peer
"out" - outbound connections are those initiated by us
type Type of peer connection
"full" - full relay, the default
"block" - block relay; like full relay but does not relay transactions or addresses
net Network the peer connected through ("ipv4", "ipv6", "onion", "i2p", or "cjdns")
mping Minimum observed ping time, in milliseconds (ms)
ping Last observed ping time, in milliseconds (ms)
send Time since last message sent to the peer, in seconds
recv Time since last message received from the peer, in seconds
txn Time since last novel transaction received from the peer and accepted into our mempool, in minutes
blk Time since last novel block passing initial validity checks received from the peer, in minutes
age Duration of connection to the peer, in minutes
asmap Mapped AS (Autonomous System) number in the BGP route to the peer, used for diversifying
peer selection (only displayed if the -asmap config option is set)
id Peer index, in increasing order of peer connections since node startup
address IP address and port of the peer
version Peer version and subversion concatenated, e.g. "70016/Satoshi:21.0.0/"
* The connection counts table displays the number of peers by direction, network, and the totals
for each, as well as a column for block relay peers.
* The local addresses table lists each local address broadcast by the node, the port, and the score.
Examples:
Connection counts and local addresses only
> bitcoin-cli -netinfo
Compact peers listing
> bitcoin-cli -netinfo 1
Full dashboard
> bitcoin-cli -netinfo 4
Full live dashboard, adjust --interval or --no-title as needed (Linux)
> watch --interval 1 --no-title ./src/bitcoin-cli -netinfo 4
See this help
> bitcoin-cli -netinfo help
```
</p></details>
ACKs for top commit:
laanwj:
ACK 6f2c4fd0775a9c45eacc4bab8f138528852fdf44
Tree-SHA512: dd49b1ce65546dacfb8ba9f9d57de0eae55560fd05533cf26c0b5d6ec65bf1de789c3287e90a0e2f47707532fab2fe62919a4192a7ffd58ac8eec18293e9aaeb
2021-01-06 16:10:39 +01:00
uint8_t m_details_level { 0 } ; //!< Optional user-supplied arg to set dashboard details level
bool m_is_help_requested { false } ; //!< Optional user-supplied arg to print help documentation
2023-04-17 10:36:33 +02:00
bool DetailsRequested ( ) const { return m_details_level > 0 & & m_details_level < 5 ; }
bool IsAddressSelected ( ) const { return m_details_level = = 2 | | m_details_level = = 4 ; }
bool IsVersionSelected ( ) const { return m_details_level = = 3 | | m_details_level = = 4 ; }
2023-04-16 07:18:06 +02:00
bool m_is_asmap_on { false } ;
size_t m_max_addr_length { 0 } ;
2020-10-29 12:04:08 +01:00
size_t m_max_age_length { 4 } ;
2023-04-16 07:18:06 +02:00
size_t m_max_id_length { 2 } ;
2023-04-17 10:36:33 +02:00
struct Peer {
2020-10-29 12:04:08 +01:00
std : : string addr ;
std : : string sub_version ;
std : : string network ;
std : : string age ;
double min_ping ;
double ping ;
2023-04-17 10:36:33 +02:00
int64_t last_blck ;
int64_t last_recv ;
int64_t last_send ;
int64_t last_trxn ;
2020-10-29 12:04:08 +01:00
int id ;
int mapped_as ;
int version ;
2023-04-17 10:36:33 +02:00
bool is_block_relay ;
bool is_outbound ;
bool operator < ( const Peer & rhs ) const { return std : : tie ( is_outbound , min_ping ) < std : : tie ( rhs . is_outbound , rhs . min_ping ) ; }
} ;
2023-04-16 07:18:06 +02:00
std : : vector < Peer > m_peers ;
2023-04-17 10:36:33 +02:00
std : : string ChainToString ( ) const
{
if ( gArgs . GetChainName ( ) = = CBaseChainParams : : TESTNET ) return " testnet " ;
2020-10-29 12:04:08 +01:00
if ( gArgs . GetChainName ( ) = = CBaseChainParams : : DEVNET ) return " devnet " ;
2023-04-17 10:36:33 +02:00
if ( gArgs . GetChainName ( ) = = CBaseChainParams : : REGTEST ) return " regtest " ;
return " " ;
}
2020-10-29 12:04:08 +01:00
std : : string PingTimeToString ( double seconds ) const
{
if ( seconds < 0 ) return " " ;
const double milliseconds { round ( 1000 * seconds ) } ;
return milliseconds > 999999 ? " - " : ToString ( milliseconds ) ;
}
Merge #20829: doc: add -netinfo help
6f2c4fd0775a9c45eacc4bab8f138528852fdf44 netinfo: add user help documentation (Jon Atack)
Pull request description:
This is the help doc commit of #20764 without the rest of the PR or anything new since the 0.21.0 branch-off in order to target giving users a -netinfo help doc for 0.21.
- to test the new help
```
$ ./src/bitcoin-cli -netinfo help
```
- to see the updated short help
```
$ ./src/bitcoin-cli -help | grep -A4 netinfo
```
<details><summary><code>-netinfo</code> help doc</summary><p>
```
$ ./src/bitcoin-cli -netinfo help
-netinfo level "help"
Returns a network peer connections dashboard with information from the remote server.
Under the hood, -netinfo fetches the data by calling getpeerinfo and getnetworkinfo.
An optional integer argument from 0 to 4 can be passed for different peers listings.
Pass "help" to see this detailed help documentation.
If more than one argument is passed, only the first one is read and parsed.
Suggestion: use with the Linux watch(1) command for a live dashboard; see example below.
Arguments:
1. level (integer 0-4, optional) Specify the info level of the peers dashboard (default 0):
0 - Connection counts and local addresses
1 - Like 0 but with a peers listing (without address or version columns)
2 - Like 1 but with an address column
3 - Like 1 but with a version column
4 - Like 1 but with both address and version columns
2. help (string "help", optional) Print this help documentation instead of the dashboard.
Result:
* The peers listing in levels 1-4 displays all of the peers sorted by direction and minimum ping time:
Column Description
------ -----------
<-> Direction
"in" - inbound connections are those initiated by the peer
"out" - outbound connections are those initiated by us
type Type of peer connection
"full" - full relay, the default
"block" - block relay; like full relay but does not relay transactions or addresses
net Network the peer connected through ("ipv4", "ipv6", "onion", "i2p", or "cjdns")
mping Minimum observed ping time, in milliseconds (ms)
ping Last observed ping time, in milliseconds (ms)
send Time since last message sent to the peer, in seconds
recv Time since last message received from the peer, in seconds
txn Time since last novel transaction received from the peer and accepted into our mempool, in minutes
blk Time since last novel block passing initial validity checks received from the peer, in minutes
age Duration of connection to the peer, in minutes
asmap Mapped AS (Autonomous System) number in the BGP route to the peer, used for diversifying
peer selection (only displayed if the -asmap config option is set)
id Peer index, in increasing order of peer connections since node startup
address IP address and port of the peer
version Peer version and subversion concatenated, e.g. "70016/Satoshi:21.0.0/"
* The connection counts table displays the number of peers by direction, network, and the totals
for each, as well as a column for block relay peers.
* The local addresses table lists each local address broadcast by the node, the port, and the score.
Examples:
Connection counts and local addresses only
> bitcoin-cli -netinfo
Compact peers listing
> bitcoin-cli -netinfo 1
Full dashboard
> bitcoin-cli -netinfo 4
Full live dashboard, adjust --interval or --no-title as needed (Linux)
> watch --interval 1 --no-title ./src/bitcoin-cli -netinfo 4
See this help
> bitcoin-cli -netinfo help
```
</p></details>
ACKs for top commit:
laanwj:
ACK 6f2c4fd0775a9c45eacc4bab8f138528852fdf44
Tree-SHA512: dd49b1ce65546dacfb8ba9f9d57de0eae55560fd05533cf26c0b5d6ec65bf1de789c3287e90a0e2f47707532fab2fe62919a4192a7ffd58ac8eec18293e9aaeb
2021-01-06 16:10:39 +01:00
const UniValue NetinfoHelp ( )
{
return std : : string {
" -netinfo level| \" help \" \n \n "
" Returns a network peer connections dashboard with information from the remote server. \n "
" Under the hood, -netinfo fetches the data by calling getpeerinfo and getnetworkinfo. \n "
" An optional integer argument from 0 to 4 can be passed for different peers listings. \n "
" Pass \" help \" to see this detailed help documentation. \n "
" If more than one argument is passed, only the first one is read and parsed. \n "
" Suggestion: use with the Linux watch(1) command for a live dashboard; see example below. \n \n "
" Arguments: \n "
" 1. level (integer 0-4, optional) Specify the info level of the peers dashboard (default 0): \n "
" 0 - Connection counts and local addresses \n "
" 1 - Like 0 but with a peers listing (without address or version columns) \n "
" 2 - Like 1 but with an address column \n "
" 3 - Like 1 but with a version column \n "
" 4 - Like 1 but with both address and version columns \n "
" 2. help (string \" help \" , optional) Print this help documentation instead of the dashboard. \n \n "
" Result: \n \n "
" * The peers listing in levels 1-4 displays all of the peers sorted by direction and minimum ping time: \n \n "
" Column Description \n "
" ------ ----------- \n "
" <-> Direction \n "
" \" in \" - inbound connections are those initiated by the peer \n "
" \" out \" - outbound connections are those initiated by us \n "
" type Type of peer connection \n "
" \" full \" - full relay, the default \n "
" \" block \" - block relay; like full relay but does not relay transactions or addresses \n "
" net Network the peer connected through ( \" ipv4 \" , \" ipv6 \" , \" onion \" , \" i2p \" , or \" cjdns \" ) \n "
" mping Minimum observed ping time, in milliseconds (ms) \n "
" ping Last observed ping time, in milliseconds (ms) \n "
" send Time since last message sent to the peer, in seconds \n "
" recv Time since last message received from the peer, in seconds \n "
" txn Time since last novel transaction received from the peer and accepted into our mempool, in minutes \n "
" blk Time since last novel block passing initial validity checks received from the peer, in minutes \n "
" age Duration of connection to the peer, in minutes \n "
" asmap Mapped AS (Autonomous System) number in the BGP route to the peer, used for diversifying \n "
" peer selection (only displayed if the -asmap config option is set) \n "
" id Peer index, in increasing order of peer connections since node startup \n "
" address IP address and port of the peer \n "
" version Peer version and subversion concatenated, e.g. \" 70016/Satoshi:21.0.0/ \" \n \n "
" * The connection counts table displays the number of peers by direction, network, and the totals \n "
" for each, as well as a column for block relay peers. \n \n "
" * The local addresses table lists each local address broadcast by the node, the port, and the score. \n \n "
" Examples: \n \n "
" Connection counts and local addresses only \n "
" > dash-cli -netinfo \n \n "
" Compact peers listing \n "
" > dash-cli -netinfo 1 \n \n "
" Full dashboard \n "
" > dash-cli -netinfo 4 \n \n "
" Full live dashboard, adjust --interval or --no-title as needed (Linux) \n "
" > watch --interval 1 --no-title dash-cli -netinfo 4 \n \n "
" See this help \n "
" > dash-cli -netinfo help \n " } ;
}
2023-04-16 07:18:06 +02:00
const int64_t m_time_now { GetSystemTimeInSeconds ( ) } ;
2023-04-17 10:36:33 +02:00
public :
2023-04-16 07:18:06 +02:00
static constexpr int ID_PEERINFO = 0 ;
static constexpr int ID_NETWORKINFO = 1 ;
2023-04-17 10:36:33 +02:00
UniValue PrepareRequest ( const std : : string & method , const std : : vector < std : : string > & args ) override
{
if ( ! args . empty ( ) ) {
uint8_t n { 0 } ;
if ( ParseUInt8 ( args . at ( 0 ) , & n ) ) {
m_details_level = n ;
Merge #20829: doc: add -netinfo help
6f2c4fd0775a9c45eacc4bab8f138528852fdf44 netinfo: add user help documentation (Jon Atack)
Pull request description:
This is the help doc commit of #20764 without the rest of the PR or anything new since the 0.21.0 branch-off in order to target giving users a -netinfo help doc for 0.21.
- to test the new help
```
$ ./src/bitcoin-cli -netinfo help
```
- to see the updated short help
```
$ ./src/bitcoin-cli -help | grep -A4 netinfo
```
<details><summary><code>-netinfo</code> help doc</summary><p>
```
$ ./src/bitcoin-cli -netinfo help
-netinfo level "help"
Returns a network peer connections dashboard with information from the remote server.
Under the hood, -netinfo fetches the data by calling getpeerinfo and getnetworkinfo.
An optional integer argument from 0 to 4 can be passed for different peers listings.
Pass "help" to see this detailed help documentation.
If more than one argument is passed, only the first one is read and parsed.
Suggestion: use with the Linux watch(1) command for a live dashboard; see example below.
Arguments:
1. level (integer 0-4, optional) Specify the info level of the peers dashboard (default 0):
0 - Connection counts and local addresses
1 - Like 0 but with a peers listing (without address or version columns)
2 - Like 1 but with an address column
3 - Like 1 but with a version column
4 - Like 1 but with both address and version columns
2. help (string "help", optional) Print this help documentation instead of the dashboard.
Result:
* The peers listing in levels 1-4 displays all of the peers sorted by direction and minimum ping time:
Column Description
------ -----------
<-> Direction
"in" - inbound connections are those initiated by the peer
"out" - outbound connections are those initiated by us
type Type of peer connection
"full" - full relay, the default
"block" - block relay; like full relay but does not relay transactions or addresses
net Network the peer connected through ("ipv4", "ipv6", "onion", "i2p", or "cjdns")
mping Minimum observed ping time, in milliseconds (ms)
ping Last observed ping time, in milliseconds (ms)
send Time since last message sent to the peer, in seconds
recv Time since last message received from the peer, in seconds
txn Time since last novel transaction received from the peer and accepted into our mempool, in minutes
blk Time since last novel block passing initial validity checks received from the peer, in minutes
age Duration of connection to the peer, in minutes
asmap Mapped AS (Autonomous System) number in the BGP route to the peer, used for diversifying
peer selection (only displayed if the -asmap config option is set)
id Peer index, in increasing order of peer connections since node startup
address IP address and port of the peer
version Peer version and subversion concatenated, e.g. "70016/Satoshi:21.0.0/"
* The connection counts table displays the number of peers by direction, network, and the totals
for each, as well as a column for block relay peers.
* The local addresses table lists each local address broadcast by the node, the port, and the score.
Examples:
Connection counts and local addresses only
> bitcoin-cli -netinfo
Compact peers listing
> bitcoin-cli -netinfo 1
Full dashboard
> bitcoin-cli -netinfo 4
Full live dashboard, adjust --interval or --no-title as needed (Linux)
> watch --interval 1 --no-title ./src/bitcoin-cli -netinfo 4
See this help
> bitcoin-cli -netinfo help
```
</p></details>
ACKs for top commit:
laanwj:
ACK 6f2c4fd0775a9c45eacc4bab8f138528852fdf44
Tree-SHA512: dd49b1ce65546dacfb8ba9f9d57de0eae55560fd05533cf26c0b5d6ec65bf1de789c3287e90a0e2f47707532fab2fe62919a4192a7ffd58ac8eec18293e9aaeb
2021-01-06 16:10:39 +01:00
} else if ( args . at ( 0 ) = = " help " ) {
m_is_help_requested = true ;
} else {
throw std : : runtime_error ( strprintf ( " invalid -netinfo argument: %s " , args . at ( 0 ) ) ) ;
2023-04-17 10:36:33 +02:00
}
}
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
{
Merge #20829: doc: add -netinfo help
6f2c4fd0775a9c45eacc4bab8f138528852fdf44 netinfo: add user help documentation (Jon Atack)
Pull request description:
This is the help doc commit of #20764 without the rest of the PR or anything new since the 0.21.0 branch-off in order to target giving users a -netinfo help doc for 0.21.
- to test the new help
```
$ ./src/bitcoin-cli -netinfo help
```
- to see the updated short help
```
$ ./src/bitcoin-cli -help | grep -A4 netinfo
```
<details><summary><code>-netinfo</code> help doc</summary><p>
```
$ ./src/bitcoin-cli -netinfo help
-netinfo level "help"
Returns a network peer connections dashboard with information from the remote server.
Under the hood, -netinfo fetches the data by calling getpeerinfo and getnetworkinfo.
An optional integer argument from 0 to 4 can be passed for different peers listings.
Pass "help" to see this detailed help documentation.
If more than one argument is passed, only the first one is read and parsed.
Suggestion: use with the Linux watch(1) command for a live dashboard; see example below.
Arguments:
1. level (integer 0-4, optional) Specify the info level of the peers dashboard (default 0):
0 - Connection counts and local addresses
1 - Like 0 but with a peers listing (without address or version columns)
2 - Like 1 but with an address column
3 - Like 1 but with a version column
4 - Like 1 but with both address and version columns
2. help (string "help", optional) Print this help documentation instead of the dashboard.
Result:
* The peers listing in levels 1-4 displays all of the peers sorted by direction and minimum ping time:
Column Description
------ -----------
<-> Direction
"in" - inbound connections are those initiated by the peer
"out" - outbound connections are those initiated by us
type Type of peer connection
"full" - full relay, the default
"block" - block relay; like full relay but does not relay transactions or addresses
net Network the peer connected through ("ipv4", "ipv6", "onion", "i2p", or "cjdns")
mping Minimum observed ping time, in milliseconds (ms)
ping Last observed ping time, in milliseconds (ms)
send Time since last message sent to the peer, in seconds
recv Time since last message received from the peer, in seconds
txn Time since last novel transaction received from the peer and accepted into our mempool, in minutes
blk Time since last novel block passing initial validity checks received from the peer, in minutes
age Duration of connection to the peer, in minutes
asmap Mapped AS (Autonomous System) number in the BGP route to the peer, used for diversifying
peer selection (only displayed if the -asmap config option is set)
id Peer index, in increasing order of peer connections since node startup
address IP address and port of the peer
version Peer version and subversion concatenated, e.g. "70016/Satoshi:21.0.0/"
* The connection counts table displays the number of peers by direction, network, and the totals
for each, as well as a column for block relay peers.
* The local addresses table lists each local address broadcast by the node, the port, and the score.
Examples:
Connection counts and local addresses only
> bitcoin-cli -netinfo
Compact peers listing
> bitcoin-cli -netinfo 1
Full dashboard
> bitcoin-cli -netinfo 4
Full live dashboard, adjust --interval or --no-title as needed (Linux)
> watch --interval 1 --no-title ./src/bitcoin-cli -netinfo 4
See this help
> bitcoin-cli -netinfo help
```
</p></details>
ACKs for top commit:
laanwj:
ACK 6f2c4fd0775a9c45eacc4bab8f138528852fdf44
Tree-SHA512: dd49b1ce65546dacfb8ba9f9d57de0eae55560fd05533cf26c0b5d6ec65bf1de789c3287e90a0e2f47707532fab2fe62919a4192a7ffd58ac8eec18293e9aaeb
2021-01-06 16:10:39 +01:00
if ( m_is_help_requested ) {
return JSONRPCReplyObj ( NetinfoHelp ( ) , NullUniValue , 1 ) ;
}
2023-04-17 10:36:33 +02:00
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 ] ;
const UniValue & networkinfo { batch [ ID_NETWORKINFO ] [ " result " ] } ;
if ( networkinfo [ " version " ] . get_int ( ) < 200000 ) {
throw std : : runtime_error ( " -netinfo requires dashd server to be running v20.0 and up " ) ;
}
// Count peer connection totals, and if DetailsRequested(), store peer data in a vector of structs.
2023-04-16 07:18:06 +02:00
for ( const UniValue & peer : batch [ ID_PEERINFO ] [ " result " ] . getValues ( ) ) {
const std : : string network { peer [ " network " ] . get_str ( ) } ;
const int8_t network_id { NetworkStringToId ( network ) } ;
if ( network_id = = UNKNOWN_NETWORK ) continue ;
const bool is_outbound { ! peer [ " inbound " ] . get_bool ( ) } ;
2023-04-17 10:36:33 +02:00
const bool is_block_relay { ! peer [ " relaytxes " ] . get_bool ( ) } ;
2023-04-16 07:18:06 +02:00
+ + m_counts . at ( is_outbound ) . at ( network_id ) ; // in/out by network
+ + m_counts . at ( is_outbound ) . at ( m_networks_size ) ; // in/out overall
+ + m_counts . at ( 2 ) . at ( network_id ) ; // total by network
+ + m_counts . at ( 2 ) . at ( m_networks_size ) ; // total overall
if ( is_block_relay ) {
+ + m_counts . at ( is_outbound ) . at ( m_networks_size + 1 ) ; // in/out block-relay
+ + m_counts . at ( 2 ) . at ( m_networks_size + 1 ) ; // total block-relay
2023-04-17 10:36:33 +02:00
}
if ( DetailsRequested ( ) ) {
// Push data for this peer to the peers vector.
const int peer_id { peer [ " id " ] . get_int ( ) } ;
2023-04-16 07:18:06 +02:00
const int mapped_as { peer [ " mapped_as " ] . isNull ( ) ? 0 : peer [ " mapped_as " ] . get_int ( ) } ;
2023-04-17 10:36:33 +02:00
const int version { peer [ " version " ] . get_int ( ) } ;
const int64_t conn_time { peer [ " conntime " ] . get_int64 ( ) } ;
const int64_t last_blck { peer [ " last_block " ] . get_int64 ( ) } ;
const int64_t last_recv { peer [ " lastrecv " ] . get_int64 ( ) } ;
const int64_t last_send { peer [ " lastsend " ] . get_int64 ( ) } ;
const int64_t last_trxn { peer [ " last_transaction " ] . get_int64 ( ) } ;
const double min_ping { peer [ " minping " ] . isNull ( ) ? - 1 : peer [ " minping " ] . get_real ( ) } ;
const double ping { peer [ " pingtime " ] . isNull ( ) ? - 1 : peer [ " pingtime " ] . get_real ( ) } ;
2023-04-16 07:18:06 +02:00
const std : : string addr { peer [ " addr " ] . get_str ( ) } ;
2020-10-29 12:04:08 +01:00
const std : : string age { conn_time = = 0 ? " " : ToString ( ( m_time_now - conn_time ) / 60 ) } ;
2023-04-16 07:18:06 +02:00
const std : : string sub_version { peer [ " subver " ] . get_str ( ) } ;
2020-10-29 12:04:08 +01:00
m_peers . push_back ( { addr , sub_version , network , age , min_ping , ping , last_blck , last_recv , last_send , last_trxn , peer_id , mapped_as , version , is_block_relay , is_outbound } ) ;
2023-04-16 07:18:06 +02:00
m_max_addr_length = std : : max ( addr . length ( ) + 1 , m_max_addr_length ) ;
2020-10-29 12:04:08 +01:00
m_max_age_length = std : : max ( age . length ( ) , m_max_age_length ) ;
m_max_id_length = std : : max ( ToString ( peer_id ) . length ( ) , m_max_id_length ) ;
2023-04-16 07:18:06 +02:00
m_is_asmap_on | = ( mapped_as ! = 0 ) ;
2023-04-17 10:36:33 +02:00
}
}
// Generate report header.
2021-09-06 09:16:28 +02:00
std : : string result { strprintf ( " %s client %s%s - server %i%s \n \n " , PACKAGE_NAME , FormatFullVersion ( ) , ChainToString ( ) , networkinfo [ " protocolversion " ] . get_int ( ) , networkinfo [ " subversion " ] . get_str ( ) ) } ;
2023-04-17 10:36:33 +02:00
// Report detailed peer connections list sorted by direction and minimum ping time.
2023-04-16 07:18:06 +02:00
if ( DetailsRequested ( ) & & ! m_peers . empty ( ) ) {
std : : sort ( m_peers . begin ( ) , m_peers . end ( ) ) ;
2020-10-29 12:04:08 +01:00
result + = strprintf ( " <-> relay net mping ping send recv txn blk %*s " , m_max_age_length , " age " ) ;
2023-04-16 07:18:06 +02:00
if ( m_is_asmap_on ) result + = " asmap " ;
result + = strprintf ( " %*s %-*s%s \n " , m_max_id_length , " id " , IsAddressSelected ( ) ? m_max_addr_length : 0 , IsAddressSelected ( ) ? " address " : " " , IsVersionSelected ( ) ? " version " : " " ) ;
for ( const Peer & peer : m_peers ) {
2023-04-17 10:36:33 +02:00
std : : string version { ToString ( peer . version ) + peer . sub_version } ;
result + = strprintf (
2020-10-29 12:04:08 +01:00
" %3s %5s %5s%7s%7s%5s%5s%5s%5s %*s%*i %*s %-*s%s \n " ,
2023-04-17 10:36:33 +02:00
peer . is_outbound ? " out " : " in " ,
peer . is_block_relay ? " block " : " full " ,
2023-04-16 07:18:06 +02:00
peer . network ,
2020-10-29 12:04:08 +01:00
PingTimeToString ( peer . min_ping ) ,
PingTimeToString ( peer . ping ) ,
2023-04-16 07:18:06 +02:00
peer . last_send = = 0 ? " " : ToString ( m_time_now - peer . last_send ) ,
peer . last_recv = = 0 ? " " : ToString ( m_time_now - peer . last_recv ) ,
peer . last_trxn = = 0 ? " " : ToString ( ( m_time_now - peer . last_trxn ) / 60 ) ,
peer . last_blck = = 0 ? " " : ToString ( ( m_time_now - peer . last_blck ) / 60 ) ,
2020-10-29 12:04:08 +01:00
m_max_age_length , // variable spacing
peer . age ,
2023-04-16 07:18:06 +02:00
m_is_asmap_on ? 7 : 0 , // variable spacing
m_is_asmap_on & & peer . mapped_as ! = 0 ? ToString ( peer . mapped_as ) : " " ,
m_max_id_length , // variable spacing
2023-04-17 10:36:33 +02:00
peer . id ,
2023-04-16 07:18:06 +02:00
IsAddressSelected ( ) ? m_max_addr_length : 0 , // variable spacing
2023-04-17 10:36:33 +02:00
IsAddressSelected ( ) ? peer . addr : " " ,
IsVersionSelected ( ) & & version ! = " 0 " ? version : " " ) ;
}
2020-10-29 12:04:08 +01:00
result + = strprintf ( " ms ms sec sec min min %*s \n \n " , m_max_age_length , " min " ) ;
2023-04-17 10:36:33 +02:00
}
// Report peer connection totals by type.
result + = " ipv4 ipv6 onion total block-relay \n " ;
2023-04-16 07:18:06 +02:00
const std : : array < std : : string , 3 > rows { { " in " , " out " , " total " } } ;
2020-10-29 12:04:08 +01:00
for ( uint8_t i = 0 ; i < m_networks_size ; + + i ) {
2023-04-16 07:18:06 +02:00
result + = strprintf ( " %-5s %5i %5i %5i %5i %5i \n " , rows . at ( i ) , m_counts . at ( i ) . at ( 0 ) , m_counts . at ( i ) . at ( 1 ) , m_counts . at ( i ) . at ( 2 ) , m_counts . at ( i ) . at ( m_networks_size ) , m_counts . at ( i ) . at ( m_networks_size + 1 ) ) ;
}
2023-04-17 10:36:33 +02:00
// Report local addresses, ports, and scores.
result + = " \n Local addresses " ;
2020-10-29 12:04:08 +01:00
const std : : vector < UniValue > & local_addrs { networkinfo [ " localaddresses " ] . getValues ( ) } ;
2023-04-17 10:36:33 +02:00
if ( local_addrs . empty ( ) ) {
result + = " : n/a \n " ;
} else {
2020-10-29 12:04:08 +01:00
size_t max_addr_size { 0 } ;
for ( const UniValue & addr : local_addrs ) {
max_addr_size = std : : max ( addr [ " address " ] . get_str ( ) . length ( ) + 1 , max_addr_size ) ;
}
for ( const UniValue & addr : local_addrs ) {
result + = strprintf ( " \n %-*s port %6i score %6i " , max_addr_size , addr [ " address " ] . get_str ( ) , addr [ " port " ] . get_int ( ) , addr [ " score " ] . get_int ( ) ) ;
2023-04-17 10:36:33 +02:00
}
}
return JSONRPCReplyObj ( UniValue { result } , NullUniValue , 1 ) ;
}
} ;
2023-04-16 21:53:03 +02: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 ;
} ;
2017-09-28 08:33:12 +02: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 ( ) ;
}
} ;
2023-04-17 10:28:19 +02:00
static UniValue CallRPC ( BaseRequestHandler * rh , const std : : string & strMethod , const std : : vector < std : : string > & args , const std : : 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 07:53:17 +01:00
{
2017-07-15 22:16:56 +02: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
2021-03-01 21:35:28 +01:00
uint16_t port { BaseParams ( ) . RPCPort ( ) } ;
2017-07-15 22:16:56 +02:00
SplitHostPort ( gArgs . GetArg ( " -rpcconnect " , DEFAULT_RPCCONNECT ) , port , host ) ;
2021-03-01 21:35:28 +01:00
port = static_cast < uint16_t > ( 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 07:53:17 +01:00
2017-01-05 11:10:40 +01: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 07:53:17 +01:00
// Synchronously look up hostname
2017-01-05 11:10:40 +01:00
raii_evhttp_connection evcon = obtain_evhttp_connection_base ( base . get ( ) , host , port ) ;
2019-10-16 16:00:39 +02: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 07:53:17 +01:00
HTTPReply response ;
2017-01-05 11:10:40 +01:00
raii_evhttp_request req = obtain_evhttp_request ( http_request_done , ( void * ) & response ) ;
2019-08-06 05:08:33 +02:00
if ( req = = nullptr )
2016-11-25 11:33:05 +01:00
throw std : : runtime_error ( " create http request failed " ) ;
2016-09-26 14:52:56 +02:00
# if LIBEVENT_VERSION_NUMBER >= 0x02010300
2017-01-05 11:10:40 +01:00
evhttp_request_set_error_cb ( req . get ( ) , http_error_cb ) ;
2016-09-26 14:52:56 +02: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 07:53:17 +01:00
// Get credentials
2015-07-07 14:53:48 +02:00
std : : string strRPCUserColonPass ;
2018-03-20 09:36:14 +01:00
bool failedToGetAuthCookie = false ;
2019-06-24 18:44:27 +02:00
if ( gArgs . GetArg ( " -rpcpassword " , " " ) = = " " ) {
2015-07-07 14:53:48 +02:00
// Try fall back to cookie-based authentication if no password is provided
if ( ! GetAuthCookie ( & strRPCUserColonPass ) ) {
2018-03-20 09:36:14 +01:00
failedToGetAuthCookie = true ;
2015-07-07 14:53:48 +02:00
}
} else {
2019-06-24 18:44:27 +02:00
strRPCUserColonPass = gArgs . GetArg ( " -rpcuser " , " " ) + " : " + gArgs . GetArg ( " -rpcpassword " , " " ) ;
2015-07-07 14:53:48 +02:00
}
2014-05-26 11:38:44 +02:00
2017-01-05 11:10:40 +01: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 07:53:17 +01:00
assert ( output_headers ) ;
evhttp_add_header ( output_headers , " Host " , host . c_str ( ) ) ;
evhttp_add_header ( output_headers , " Connection " , " close " ) ;
2020-10-02 09:06:18 +02:00
evhttp_add_header ( output_headers , " Content-Type " , " application/json " ) ;
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
evhttp_add_header ( output_headers , " Authorization " , ( std : : string ( " Basic " ) + EncodeBase64 ( strRPCUserColonPass ) ) . c_str ( ) ) ;
// Attach request data
2017-09-28 08:33:12 +02:00
std : : string strRequest = rh - > PrepareRequest ( strMethod , args ) . write ( ) + " \n " ;
2017-01-05 11:10:40 +01: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 07:53:17 +01:00
assert ( output_buffer ) ;
evbuffer_add ( output_buffer , strRequest . data ( ) , strRequest . size ( ) ) ;
2017-07-18 17:15:46 +02:00
// check if we should use a special wallet endpoint
std : : string endpoint = " / " ;
2023-04-17 10:28:19 +02:00
if ( rpcwallet ) {
char * encodedURI = evhttp_uriencode ( rpcwallet - > data ( ) , rpcwallet - > size ( ) , false ) ;
2017-07-18 17:15:46 +02:00
if ( encodedURI ) {
2023-04-17 10:28:19 +02:00
endpoint = " /wallet/ " + std : : string ( encodedURI ) ;
2017-07-18 17:15:46 +02:00
free ( encodedURI ) ;
2023-04-17 10:28:19 +02:00
} else {
2017-07-18 17:15:46 +02:00
throw CConnectionFailed ( " uri-encode failed " ) ;
}
}
int r = evhttp_make_request ( evcon . get ( ) , req . get ( ) , EVHTTP_REQ_POST , endpoint . c_str ( ) ) ;
2017-01-05 11:10:40 +01: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 07:53:17 +01:00
if ( r ! = 0 ) {
throw CConnectionFailed ( " send http request failed " ) ;
}
2014-05-26 11:38:44 +02:00
2017-01-05 11:10:40 +01:00
event_base_dispatch ( base . get ( ) ) ;
2014-05-26 11:38:44 +02:00
2018-03-20 09:36:14 +01: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 dashd 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 (
2021-03-19 18:23:58 +01: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) " ,
2022-03-21 18:28:10 +01:00
GetConfigFile ( gArgs . GetArg ( " -conf " , BITCOIN_CONF_FILENAME ) ) . string ( ) ) ) ;
2018-03-20 09:36:14 +01:00
} else {
throw std : : runtime_error ( " Authorization failed: Incorrect rpcuser or rpcpassword " ) ;
}
2021-03-19 20:52:10 +01:00
} else if ( response . status = = HTTP_SERVICE_UNAVAILABLE ) {
throw std : : runtime_error ( strprintf ( " Server response: %s " , response . body ) ) ;
2018-03-20 09:36:14 +01:00
} else if ( response . status > = 400 & & response . status ! = HTTP_BAD_REQUEST & & response . status ! = HTTP_NOT_FOUND & & response . status ! = HTTP_INTERNAL_SERVER_ERROR )
2016-11-25 11:33:05 +01: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 07:53:17 +01:00
else if ( response . body . empty ( ) )
2016-11-25 11:33:05 +01:00
throw std : : runtime_error ( " no response from server " ) ;
2014-05-26 11:38:44 +02:00
// Parse reply
2015-05-13 21:29:19 +02: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 07:53:17 +01:00
if ( ! valReply . read ( response . body ) )
2016-11-25 11:33:05 +01:00
throw std : : runtime_error ( " couldn't parse reply from server " ) ;
2017-09-28 08:33:12 +02:00
const UniValue reply = rh - > ProcessReply ( valReply ) ;
2014-05-26 11:38:44 +02:00
if ( reply . empty ( ) )
2016-11-25 11:33:05 +01:00
throw std : : runtime_error ( " expected reply to have result, error and id properties " ) ;
2014-05-26 11:38:44 +02:00
return reply ;
}
2023-04-17 10:28:19 +02: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 .
* @ param [ in ] rpcwallet Reference to const optional string wallet name to forward to CallRPC .
* @ returns the RPC response as a UniValue object .
* @ throws a CConnectionFailed std : : runtime_error if connection failed or RPC server still in warmup .
*/
static UniValue ConnectAndCallRPC ( BaseRequestHandler * rh , const std : : string & strMethod , const std : : vector < std : : string > & args , const std : : optional < std : : string > & rpcwallet = { } )
{
UniValue response ( UniValue : : VOBJ ) ;
// Execute and handle connection failures with -rpcwait.
const bool fWait = gArgs . GetBoolArg ( " -rpcwait " , false ) ;
do {
try {
response = CallRPC ( rh , strMethod , args , rpcwallet ) ;
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 ;
}
2023-04-16 21:53:03 +02: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 dash-cli command line. " ;
}
} else {
strPrint = " error: " + error . write ( ) ;
}
nRet = abs ( error [ " code " ] . get_int ( ) ) ;
}
2023-04-17 10:28:19 +02: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-10 22:41:28 +02:00
DefaultRequestHandler rh ;
const UniValue listwallets = ConnectAndCallRPC ( & rh , " listwallets " , /* args=*/ { } ) ;
2023-04-17 10:28:19 +02: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-10 22:41:28 +02:00
const UniValue getbalances = ConnectAndCallRPC ( & rh , " getbalances " , /* args=*/ { } , wallet_name ) ;
2023-04-17 10:28:19 +02:00
const UniValue & balance = find_value ( getbalances , " result " ) [ " mine " ] [ " trusted " ] ;
balances . pushKV ( wallet_name , balance ) ;
}
result . pushKV ( " balances " , balances ) ;
}
2023-04-16 21:53:03 +02:00
/**
* Call RPC getnewaddress .
* @ returns getnewaddress response as a UniValue object .
*/
static UniValue GetNewAddress ( )
{
std : : optional < std : : string > wallet_name { } ;
if ( gArgs . IsArgSet ( " -rpcwallet " ) ) wallet_name = gArgs . GetArg ( " -rpcwallet " , " " ) ;
2020-07-10 22:41:28 +02:00
DefaultRequestHandler rh ;
return ConnectAndCallRPC ( & rh , " getnewaddress " , /* args=*/ { } , wallet_name ) ;
2023-04-16 21:53:03 +02: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-04 22:42:39 +02:00
static int CommandLineRPC ( int argc , char * argv [ ] )
2014-05-26 11:38:44 +02:00
{
2016-11-25 11:33:05 +01:00
std : : string strPrint ;
2014-05-26 11:38:44 +02:00
int nRet = 0 ;
2014-06-26 03:09:36 +02:00
try {
2014-05-26 11:38:44 +02:00
// Skip switches
2014-06-26 03:09:36 +02:00
while ( argc > 1 & & IsSwitchChar ( argv [ 1 ] [ 0 ] ) ) {
2014-05-26 11:38:44 +02:00
argc - - ;
argv + + ;
}
2017-08-24 08:35:42 +02:00
std : : string rpcPass ;
if ( gArgs . GetBoolArg ( " -stdinrpcpass " , false ) ) {
2019-10-02 18:36:01 +02:00
NO_STDIN_ECHO ( ) ;
if ( ! StdinReady ( ) ) {
fputs ( " RPC password> " , stderr ) ;
fflush ( stderr ) ;
}
2017-09-07 01:43:16 +02:00
if ( ! std : : getline ( std : : cin , rpcPass ) ) {
2017-08-24 08:35:42 +02:00
throw std : : runtime_error ( " -stdinrpcpass specified but failed to read from standard input " ) ;
2017-09-07 01:43:16 +02:00
}
2019-10-02 18:36:01 +02:00
if ( StdinTerminal ( ) ) {
fputc ( ' \n ' , stdout ) ;
}
2017-08-24 08:35:42 +02:00
gArgs . ForceSetArg ( " -rpcpassword " , rpcPass ) ;
}
2016-02-24 11:33:08 +01:00
std : : vector < std : : string > args = std : : vector < std : : string > ( & argv [ 1 ] , & argv [ argc ] ) ;
2019-10-02 18:36:01 +02: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 " ) ;
}
if ( StdinTerminal ( ) ) {
fputc ( ' \n ' , stdout ) ;
}
args . insert ( args . begin ( ) + 1 , walletPass ) ;
}
2019-06-24 18:44:27 +02:00
if ( gArgs . GetBoolArg ( " -stdin " , false ) ) {
2016-02-24 11:33:08 +01:00
// Read one arg per line from stdin and append
std : : string line ;
2017-09-07 01:43:16 +02:00
while ( std : : getline ( std : : cin , line ) ) {
2016-02-24 11:33:08 +01:00
args . push_back ( line ) ;
2017-09-07 01:43:16 +02:00
}
2019-10-02 18:36:01 +02:00
if ( StdinTerminal ( ) ) {
fputc ( ' \n ' , stdout ) ;
}
2016-02-24 11:33:08 +01:00
}
2017-09-28 08:33:12 +02:00
std : : unique_ptr < BaseRequestHandler > rh ;
std : : string method ;
2023-04-17 10:28:19 +02:00
if ( gArgs . IsArgSet ( " -getinfo " ) ) {
2017-09-28 08:33:12 +02:00
rh . reset ( new GetinfoRequestHandler ( ) ) ;
2023-04-17 10:36:33 +02:00
} else if ( gArgs . GetBoolArg ( " -netinfo " , false ) ) {
rh . reset ( new NetinfoRequestHandler ( ) ) ;
2023-04-16 21:53:03 +02: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 ) ;
}
2017-01-10 13:52:49 +01:00
} else {
2017-09-28 08:33:12 +02: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
2017-01-10 13:52:49 +01:00
}
2023-04-16 21:53:03 +02:00
if ( nRet = = 0 ) {
// Perform RPC call
std : : 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 18:08:31 +01:00
}
2023-04-16 21:53:03 +02:00
ParseResult ( result , strPrint ) ;
2023-04-17 10:28:19 +02:00
} else {
2023-04-16 21:53:03 +02:00
ParseError ( error , strPrint , nRet ) ;
2023-04-17 10:28:19 +02:00
}
}
} catch ( const std : : exception & e ) {
2016-11-25 11:33:05 +01:00
strPrint = std : : string ( " error: " ) + e . what ( ) ;
2014-05-26 11:38:44 +02:00
nRet = EXIT_FAILURE ;
2023-04-17 10:28:19 +02:00
} catch ( . . . ) {
2019-02-21 19:37:16 +01:00
PrintExceptionContinue ( std : : current_exception ( ) , " CommandLineRPC() " ) ;
2014-05-26 11:38:44 +02:00
throw ;
}
2014-06-26 03:09:36 +02:00
if ( strPrint ! = " " ) {
2022-03-21 18:28:10 +01:00
tfm : : format ( nRet = = 0 ? std : : cout : std : : cerr , " %s \n " , strPrint ) ;
2014-05-26 11:38:44 +02:00
}
return nRet ;
2013-10-11 23:09:59 +02:00
}
2022-06-13 21:43:22 +02:00
MAIN_FUNCTION
2013-10-11 23:09:59 +02:00
{
2019-02-21 19:37:16 +01:00
RegisterPrettyTerminateHander ( ) ;
RegisterPrettySignalHandlers ( ) ;
2018-10-08 03:47:03 +02:00
# ifdef WIN32
util : : WinCmdLineArgs winArgs ;
std : : tie ( argc , argv ) = winArgs . get ( ) ;
# endif
2014-05-13 12:15:00 +02:00
SetupEnvironment ( ) ;
2015-09-02 16:18:16 +02:00
if ( ! SetupNetworking ( ) ) {
2021-10-24 12:51:47 +02:00
tfm : : format ( std : : cerr , " Error: Initializing networking failed \n " ) ;
2017-09-15 15:12:07 +02:00
return EXIT_FAILURE ;
2015-09-02 16:18:16 +02:00
}
2018-06-07 08:58:06 +02:00
event_set_log_callback ( & libevent_log_cb ) ;
2014-05-13 12:15:00 +02:00
2014-06-26 03:09:36 +02:00
try {
2016-11-11 06:16:39 +01:00
int ret = AppInitRPC ( argc , argv ) ;
if ( ret ! = CONTINUE_EXECUTION )
return ret ;
2013-10-11 23:09:59 +02:00
} catch ( . . . ) {
2019-02-21 19:37:16 +01:00
PrintExceptionContinue ( std : : current_exception ( ) , " AppInitRPC() " ) ;
2014-06-13 04:26:46 +02:00
return EXIT_FAILURE ;
2013-10-11 23:09:59 +02:00
}
2014-06-13 04:26:46 +02:00
int ret = EXIT_FAILURE ;
2014-06-26 03:09:36 +02:00
try {
2014-02-24 14:08:56 +01:00
ret = CommandLineRPC ( argc , argv ) ;
2013-10-11 23:09:59 +02:00
} catch ( . . . ) {
2019-02-21 19:37:16 +01:00
PrintExceptionContinue ( std : : current_exception ( ) , " CommandLineRPC() " ) ;
2013-10-11 23:09:59 +02:00
}
2014-02-24 14:08:56 +01:00
return ret ;
2013-10-11 23:09:59 +02:00
}