Electroneum
command_server.cpp
Go to the documentation of this file.
1 // Copyrights(c) 2017-2021, The Electroneum Project
2 // Copyrights(c) 2014-2019, The Monero Project
3 //
4 // All rights reserved.
5 //
6 // Redistribution and use in source and binary forms, with or without modification, are
7 // permitted provided that the following conditions are met:
8 //
9 // 1. Redistributions of source code must retain the above copyright notice, this list of
10 // conditions and the following disclaimer.
11 //
12 // 2. Redistributions in binary form must reproduce the above copyright notice, this list
13 // of conditions and the following disclaimer in the documentation and/or other
14 // materials provided with the distribution.
15 //
16 // 3. Neither the name of the copyright holder nor the names of its contributors may be
17 // used to endorse or promote products derived from this software without specific
18 // prior written permission.
19 //
20 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
21 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
22 // MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
23 // THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
25 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
27 // STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
28 // THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 
30 #include <boost/algorithm/string.hpp>
31 #include "cryptonote_config.h"
32 #include "version.h"
33 #include "string_tools.h"
34 #include "daemon/command_server.h"
35 
36 #undef ELECTRONEUM_DEFAULT_LOG_CATEGORY
37 #define ELECTRONEUM_DEFAULT_LOG_CATEGORY "daemon"
38 
39 namespace daemonize {
40 
41 namespace p = std::placeholders;
42 
44  uint32_t ip
45  , uint16_t port
46  , const boost::optional<tools::login>& login
47  , const epee::net_utils::ssl_options_t& ssl_options
48  , bool is_rpc
49  , cryptonote::core_rpc_server* rpc_server
50  )
51  : m_parser(ip, port, login, ssl_options, is_rpc, rpc_server)
52  , m_command_lookup()
53  , m_is_rpc(is_rpc)
54 {
55  m_command_lookup.set_handler(
56  "help"
57  , std::bind(&t_command_server::help, this, p::_1)
58  , "help [<command>]"
59  , "Show the help section or the documentation about a <command>."
60  );
61  m_command_lookup.set_handler(
62  "print_height"
63  , std::bind(&t_command_parser_executor::print_height, &m_parser, p::_1)
64  , "Print the local blockchain height."
65  );
66  m_command_lookup.set_handler(
67  "print_pl"
68  , std::bind(&t_command_parser_executor::print_peer_list, &m_parser, p::_1)
69  , "print_pl [white] [gray] [<limit>]"
70  , "Print the current peer list."
71  );
72  m_command_lookup.set_handler(
73  "print_pl_stats"
74  , std::bind(&t_command_parser_executor::print_peer_list_stats, &m_parser, p::_1)
75  , "Print the peer list statistics."
76  );
77  m_command_lookup.set_handler(
78  "print_cn"
79  , std::bind(&t_command_parser_executor::print_connections, &m_parser, p::_1)
80  , "Print the current connections."
81  );
82  m_command_lookup.set_handler(
83  "print_net_stats"
84  , std::bind(&t_command_parser_executor::print_net_stats, &m_parser, p::_1)
85  , "Print network statistics."
86  );
87  m_command_lookup.set_handler(
88  "print_bc"
89  , std::bind(&t_command_parser_executor::print_blockchain_info, &m_parser, p::_1)
90  , "print_bc <begin_height> [<end_height>]"
91  , "Print the blockchain info in a given blocks range."
92  );
93  m_command_lookup.set_handler(
94  "print_block"
95  , std::bind(&t_command_parser_executor::print_block, &m_parser, p::_1)
96  , "print_block <block_hash> | <block_height>"
97  , "Print a given block."
98  );
99  m_command_lookup.set_handler(
100  "print_tx"
101  , std::bind(&t_command_parser_executor::print_transaction, &m_parser, p::_1)
102  , "print_tx <transaction_hash> [+hex] [+json]"
103  , "Print a given transaction."
104  );
105  m_command_lookup.set_handler(
106  "is_key_image_spent"
107  , std::bind(&t_command_parser_executor::is_key_image_spent, &m_parser, p::_1)
108  , "is_key_image_spent <key_image>"
109  , "Print whether a given key image is in the spent key images set."
110  );
111  m_command_lookup.set_handler(
112  "start_mining"
113  , std::bind(&t_command_parser_executor::start_mining, &m_parser, p::_1)
114  , "start_mining <addr> [<threads>|auto] [do_background_mining] [ignore_battery]"
115  , "Start mining for specified address. Defaults to 1 thread and no background mining. Use \"auto\" to autodetect optimal number of threads."
116  );
117  m_command_lookup.set_handler(
118  "stop_mining"
119  , std::bind(&t_command_parser_executor::stop_mining, &m_parser, p::_1)
120  , "Stop mining."
121  );
122  m_command_lookup.set_handler(
123  "mining_status"
124  , std::bind(&t_command_parser_executor::mining_status, &m_parser, p::_1)
125  , "Show current mining status."
126  );
127  m_command_lookup.set_handler(
128  "print_pool"
129  , std::bind(&t_command_parser_executor::print_transaction_pool_long, &m_parser, p::_1)
130  , "Print the transaction pool using a long format."
131  );
132  m_command_lookup.set_handler(
133  "print_pool_sh"
134  , std::bind(&t_command_parser_executor::print_transaction_pool_short, &m_parser, p::_1)
135  , "Print transaction pool using a short format."
136  );
137  m_command_lookup.set_handler(
138  "print_pool_stats"
139  , std::bind(&t_command_parser_executor::print_transaction_pool_stats, &m_parser, p::_1)
140  , "Print the transaction pool's statistics."
141  );
142  m_command_lookup.set_handler(
143  "show_hr"
144  , std::bind(&t_command_parser_executor::show_hash_rate, &m_parser, p::_1)
145  , "Start showing the current hash rate."
146  );
147  m_command_lookup.set_handler(
148  "hide_hr"
149  , std::bind(&t_command_parser_executor::hide_hash_rate, &m_parser, p::_1)
150  , "Stop showing the hash rate."
151  );
152  m_command_lookup.set_handler(
153  "save"
154  , std::bind(&t_command_parser_executor::save_blockchain, &m_parser, p::_1)
155  , "Save the blockchain."
156  );
157  m_command_lookup.set_handler(
158  "set_log"
159  , std::bind(&t_command_parser_executor::set_log_level, &m_parser, p::_1)
160  , "set_log <level>|<{+,-,}categories>"
161  , "Change the current log level/categories where <level> is a number 0-4."
162  );
163  m_command_lookup.set_handler(
164  "diff"
165  , std::bind(&t_command_parser_executor::show_difficulty, &m_parser, p::_1)
166  , "Show the current difficulty."
167  );
168  m_command_lookup.set_handler(
169  "status"
170  , std::bind(&t_command_parser_executor::show_status, &m_parser, p::_1)
171  , "Show the current status."
172  );
173  m_command_lookup.set_handler(
174  "stop_daemon"
175  , std::bind(&t_command_parser_executor::stop_daemon, &m_parser, p::_1)
176  , "Stop the daemon."
177  );
178  m_command_lookup.set_handler(
179  "exit"
180  , std::bind(&t_command_parser_executor::stop_daemon, &m_parser, p::_1)
181  , "Stop the daemon."
182  );
183  m_command_lookup.set_handler(
184  "print_status"
185  , std::bind(&t_command_parser_executor::print_status, &m_parser, p::_1)
186  , "Print the current daemon status."
187  );
188  m_command_lookup.set_handler(
189  "limit"
190  , std::bind(&t_command_parser_executor::set_limit, &m_parser, p::_1)
191  , "limit [<kB/s>]"
192  , "Get or set the download and upload limit."
193  );
194  m_command_lookup.set_handler(
195  "limit_up"
196  , std::bind(&t_command_parser_executor::set_limit_up, &m_parser, p::_1)
197  , "limit_up [<kB/s>]"
198  , "Get or set the upload limit."
199  );
200  m_command_lookup.set_handler(
201  "limit_down"
202  , std::bind(&t_command_parser_executor::set_limit_down, &m_parser, p::_1)
203  , "limit_down [<kB/s>]"
204  , "Get or set the download limit."
205  );
206  m_command_lookup.set_handler(
207  "out_peers"
208  , std::bind(&t_command_parser_executor::out_peers, &m_parser, p::_1)
209  , "out_peers <max_number>"
210  , "Set the <max_number> of out peers."
211  );
212  m_command_lookup.set_handler(
213  "in_peers"
214  , std::bind(&t_command_parser_executor::in_peers, &m_parser, p::_1)
215  , "in_peers <max_number>"
216  , "Set the <max_number> of in peers."
217  );
218  m_command_lookup.set_handler(
219  "start_save_graph"
220  , std::bind(&t_command_parser_executor::start_save_graph, &m_parser, p::_1)
221  , "Start save data for dr electroneum"
222  );
223  m_command_lookup.set_handler(
224  "stop_save_graph"
225  , std::bind(&t_command_parser_executor::stop_save_graph, &m_parser, p::_1)
226  , "Stop save data for dr electroneum"
227  );
228  m_command_lookup.set_handler(
229  "hard_fork_info"
230  , std::bind(&t_command_parser_executor::hard_fork_info, &m_parser, p::_1)
231  , "Print the hard fork voting information."
232  );
233  m_command_lookup.set_handler(
234  "bans"
235  , std::bind(&t_command_parser_executor::show_bans, &m_parser, p::_1)
236  , "Show the currently banned IPs."
237  );
238  m_command_lookup.set_handler(
239  "ban"
240  , std::bind(&t_command_parser_executor::ban, &m_parser, p::_1)
241  , "ban <IP> [<seconds>]"
242  , "Ban a given <IP> for a given amount of <seconds>. Seconds = (-1) will result in a perm ban"
243  );
244  m_command_lookup.set_handler(
245  "unban"
246  , std::bind(&t_command_parser_executor::unban, &m_parser, p::_1)
247  , "unban <IP>"
248  , "Unban a given <IP>."
249  );
250  m_command_lookup.set_handler(
251  "flush_txpool"
252  , std::bind(&t_command_parser_executor::flush_txpool, &m_parser, p::_1)
253  , "flush_txpool [<txid>]"
254  , "Flush a transaction from the tx pool by its <txid>, or the whole tx pool."
255  );
256  m_command_lookup.set_handler(
257  "output_histogram"
258  , std::bind(&t_command_parser_executor::output_histogram, &m_parser, p::_1)
259  , "output_histogram [@<amount>] <min_count> [<max_count>]"
260  , "Print the output histogram of outputs."
261  );
262  m_command_lookup.set_handler(
263  "print_coinbase_tx_sum"
264  , std::bind(&t_command_parser_executor::print_coinbase_tx_sum, &m_parser, p::_1)
265  , "print_coinbase_tx_sum <start_height> [<block_count>]"
266  , "Print the sum of coinbase transactions."
267  );
268  m_command_lookup.set_handler(
269  "alt_chain_info"
270  , std::bind(&t_command_parser_executor::alt_chain_info, &m_parser, p::_1)
271  , "alt_chain_info [blockhash]"
272  , "Print the information about alternative chains."
273  );
274  m_command_lookup.set_handler(
275  "bc_dyn_stats"
276  , std::bind(&t_command_parser_executor::print_blockchain_dynamic_stats, &m_parser, p::_1)
277  , "bc_dyn_stats <last_block_count>"
278  , "Print the information about current blockchain dynamic state."
279  );
280  m_command_lookup.set_handler(
281  "update"
282  , std::bind(&t_command_parser_executor::update, &m_parser, p::_1)
283  , "update (check|download)"
284  , "Check if an update is available, optionally downloads it if there is. Updating is not yet implemented."
285  );
286  m_command_lookup.set_handler(
287  "relay_tx"
288  , std::bind(&t_command_parser_executor::relay_tx, &m_parser, p::_1)
289  , "relay_tx <txid>"
290  , "Relay a given transaction by its <txid>."
291  );
292  m_command_lookup.set_handler(
293  "sync_info"
294  , std::bind(&t_command_parser_executor::sync_info, &m_parser, p::_1)
295  , "Print information about the blockchain sync state."
296  );
297  m_command_lookup.set_handler(
298  "pop_blocks"
299  , std::bind(&t_command_parser_executor::pop_blocks, &m_parser, p::_1)
300  , "pop_blocks <nblocks>"
301  , "Remove blocks from end of blockchain"
302  );
303  m_command_lookup.set_handler(
304  "version"
305  , std::bind(&t_command_parser_executor::version, &m_parser, p::_1)
306  , "Print version information."
307  );
308  m_command_lookup.set_handler(
309  "prune_blockchain"
310  , std::bind(&t_command_parser_executor::prune_blockchain, &m_parser, p::_1)
311  , "Prune the blockchain."
312  );
313  m_command_lookup.set_handler(
314  "check_blockchain_pruning"
315  , std::bind(&t_command_parser_executor::check_blockchain_pruning, &m_parser, p::_1)
316  , "Check the blockchain pruning."
317  );
318  m_command_lookup.set_handler(
319  "set_validator_key"
320  , std::bind(&t_command_parser_executor::set_validator_key, &m_parser, p::_1)
321  , "Set validator private key to be used when signing mined blocks. <validator_key>"
322  );
323  m_command_lookup.set_handler(
324  "generate_ed25519_keypair"
325  , std::bind(&t_command_parser_executor::generate_ed25519_keypair, &m_parser, p::_1)
326  , "Generate ED25519-Donna keypair."
327  );
328  m_command_lookup.set_handler(
329  "sign_message"
330  , std::bind(&t_command_parser_executor::sign_message, &m_parser, p::_1)
331  , "Sign a message using ED25519-Donna private key. Usage: <private_key> <message>"
332  );
333 }
334 
336 {
337  return m_command_lookup.process_command_str(cmd);
338 }
339 
340 bool t_command_server::process_command_vec(const std::vector<std::string>& cmd)
341 {
342  bool result = m_command_lookup.process_command_vec(cmd);
343  if (!result)
344  {
345  help(std::vector<std::string>());
346  }
347  return result;
348 }
349 
350 bool t_command_server::start_handling(std::function<void(void)> exit_handler)
351 {
352  if (m_is_rpc) return false;
353 
354  m_command_lookup.start_handling("", get_commands_str(), exit_handler);
355 
356  return true;
357 }
358 
360 {
361  if (m_is_rpc) return;
362 
363  m_command_lookup.stop_handling();
364 }
365 
366 bool t_command_server::help(const std::vector<std::string>& args)
367 {
368  if(args.empty())
369  {
370  std::cout << get_commands_str() << std::endl;
371  }
372  else
373  {
374  std::cout << get_command_usage(args) << std::endl;
375  }
376  return true;
377 }
378 
379 std::string t_command_server::get_commands_str()
380 {
381  std::stringstream ss;
382  ss << "Electroneum '" << ELECTRONEUM_RELEASE_NAME << "' (v" << ELECTRONEUM_VERSION_FULL << ")" << std::endl;
383  ss << "Commands: " << std::endl;
384  std::string usage = m_command_lookup.get_usage();
385  boost::replace_all(usage, "\n", "\n ");
386  usage.insert(0, " ");
387  ss << usage << std::endl;
388  return ss.str();
389 }
390 
391  std::string t_command_server::get_command_usage(const std::vector<std::string> &args)
392  {
393  std::pair<std::string, std::string> documentation = m_command_lookup.get_documentation(args);
394  std::stringstream ss;
395  if(documentation.first.empty())
396  {
397  ss << "Unknown command: " << args.front() << std::endl;
398  }
399  else
400  {
401  std::string usage = documentation.second.empty() ? args.front() : documentation.first;
402  std::string description = documentation.second.empty() ? documentation.first : documentation.second;
403  usage.insert(0, " ");
404  ss << "Command usage: " << std::endl << usage << std::endl << std::endl;
405  boost::replace_all(description, "\n", "\n ");
406  description.insert(0, " ");
407  ss << "Command description: " << std::endl << description << std::endl;
408  }
409  return ss.str();
410  }
411 
412 } // namespace daemonize
bool show_bans(const std::vector< std::string > &args)
bool alt_chain_info(const std::vector< std::string > &args)
bool print_transaction_pool_long(const std::vector< std::string > &args)
bool version(const std::vector< std::string > &args)
bool print_peer_list(const std::vector< std::string > &args)
bool prune_blockchain(const std::vector< std::string > &args)
bool update(const std::vector< std::string > &args)
bool print_blockchain_info(const std::vector< std::string > &args)
bool generate_ed25519_keypair(const std::vector< std::string > &args)
bool set_validator_key(const std::vector< std::string > &args)
bool print_height(const std::vector< std::string > &args)
bool relay_tx(const std::vector< std::string > &args)
bool sync_info(const std::vector< std::string > &args)
bool print_peer_list_stats(const std::vector< std::string > &args)
bool stop_save_graph(const std::vector< std::string > &args)
bool set_limit_up(const std::vector< std::string > &args)
bool pop_blocks(const std::vector< std::string > &args)
bool ban(const std::vector< std::string > &args)
bool flush_txpool(const std::vector< std::string > &args)
bool out_peers(const std::vector< std::string > &args)
bool print_coinbase_tx_sum(const std::vector< std::string > &args)
bool check_blockchain_pruning(const std::vector< std::string > &args)
bool start_save_graph(const std::vector< std::string > &args)
bool show_difficulty(const std::vector< std::string > &args)
bool print_transaction_pool_short(const std::vector< std::string > &args)
bool output_histogram(const std::vector< std::string > &args)
bool print_transaction(const std::vector< std::string > &args)
bool is_key_image_spent(const std::vector< std::string > &args)
bool in_peers(const std::vector< std::string > &args)
bool hide_hash_rate(const std::vector< std::string > &args)
bool print_net_stats(const std::vector< std::string > &args)
bool print_blockchain_dynamic_stats(const std::vector< std::string > &args)
bool set_limit(const std::vector< std::string > &args)
bool mining_status(const std::vector< std::string > &args)
bool show_hash_rate(const std::vector< std::string > &args)
bool unban(const std::vector< std::string > &args)
bool print_connections(const std::vector< std::string > &args)
bool stop_daemon(const std::vector< std::string > &args)
bool stop_mining(const std::vector< std::string > &args)
bool sign_message(const std::vector< std::string > &args)
bool print_status(const std::vector< std::string > &args)
bool print_transaction_pool_stats(const std::vector< std::string > &args)
bool save_blockchain(const std::vector< std::string > &args)
bool show_status(const std::vector< std::string > &args)
bool set_log_level(const std::vector< std::string > &args)
bool set_limit_down(const std::vector< std::string > &args)
bool hard_fork_info(const std::vector< std::string > &args)
bool print_block(const std::vector< std::string > &args)
bool start_mining(const std::vector< std::string > &args)
bool process_command_vec(const std::vector< std::string > &cmd)
bool process_command_str(const std::string &cmd)
bool start_handling(std::function< void(void)> exit_handler=NULL)
t_command_server(uint32_t ip, uint16_t port, const boost::optional< tools::login > &login, const epee::net_utils::ssl_options_t &ssl_options, bool is_rpc=true, cryptonote::core_rpc_server *rpc_server=NULL)
bool process_command_str(const std::string &cmd)
std::pair< std::string, std::string > get_documentation(const std::vector< std::string > &cmd)
bool process_command_vec(const std::vector< std::string > &cmd)
void set_handler(const std::string &cmd, const callback &hndlr, const std::string &usage="", const std::string &description="")
bool start_handling(std::function< std::string(void)> prompt, const std::string &usage_string="", std::function< void(void)> exit_handler=NULL)
::std::string string
Definition: gtest-port.h:1097
boost::endian::big_uint16_t port
Definition: socks.cpp:60
boost::endian::big_uint32_t ip
Definition: socks.cpp:61
unsigned short uint16_t
Definition: stdint.h:125
unsigned int uint32_t
Definition: stdint.h:126
const char *const ELECTRONEUM_RELEASE_NAME
const char *const ELECTRONEUM_VERSION_FULL