2014-03-04 00:07:58 +02:00
# pragma once
# include "console_handler.h"
2014-06-13 17:47:57 +03:00
# include "cryptonote_core/cryptonote_core.h"
2014-03-04 00:07:58 +02:00
# include "cryptonote_protocol/cryptonote_protocol_handler.h"
2014-06-17 23:46:41 +03:00
# include "p2p/net_node.h"
# include <functional>
2014-06-18 00:36:07 +03:00
# include <boost/algorithm/string.hpp>
2014-06-17 23:46:41 +03:00
namespace daemonize {
2014-03-04 00:07:58 +02:00
2014-06-17 23:46:41 +03:00
namespace p = std : : placeholders ;
using namespace epee ;
2014-03-04 00:07:58 +02:00
2014-06-17 23:46:41 +03:00
class t_command_server_backend
2014-03-04 00:07:58 +02:00
{
public :
2014-06-17 23:46:41 +03:00
typedef nodetool : : node_server < cryptonote : : t_cryptonote_protocol_handler < cryptonote : : core > > t_node_server ;
2014-03-04 00:07:58 +02:00
private :
2014-06-17 23:46:41 +03:00
t_node_server & m_srv ;
public :
t_command_server_backend ( t_node_server & srv ) :
m_srv ( srv )
{ }
2014-03-04 00:07:58 +02:00
bool print_pl ( const std : : vector < std : : string > & args )
{
m_srv . log_peerlist ( ) ;
return true ;
}
2014-06-17 23:46:41 +03:00
2014-03-04 00:07:58 +02:00
bool save ( const std : : vector < std : : string > & args )
{
m_srv . get_payload_object ( ) . get_core ( ) . get_blockchain_storage ( ) . store_blockchain ( ) ;
return true ;
}
2014-06-17 23:46:41 +03:00
2014-03-04 00:07:58 +02:00
bool show_hr ( const std : : vector < std : : string > & args )
{
2014-06-17 23:46:41 +03:00
if ( ! m_srv . get_payload_object ( ) . get_core ( ) . get_miner ( ) . is_mining ( ) )
{
2014-06-18 00:36:07 +03:00
std : : cout < < " Mining is not started. You need start mining before you can see hash rate. " < < std : : endl ;
2014-06-17 23:46:41 +03:00
} else
{
m_srv . get_payload_object ( ) . get_core ( ) . get_miner ( ) . do_print_hashrate ( true ) ;
}
2014-03-04 00:07:58 +02:00
return true ;
}
2014-06-17 23:46:41 +03:00
2014-03-04 00:07:58 +02:00
bool hide_hr ( const std : : vector < std : : string > & args )
{
m_srv . get_payload_object ( ) . get_core ( ) . get_miner ( ) . do_print_hashrate ( false ) ;
return true ;
}
2014-06-17 23:46:41 +03:00
2014-05-14 03:55:50 +03:00
bool diff ( const std : : vector < std : : string > & args )
{
2014-06-16 17:53:37 +03:00
cryptonote : : difficulty_type difficulty = m_srv . get_payload_object ( ) . get_core ( ) . get_blockchain_storage ( ) . get_difficulty_for_next_block ( ) ;
uint64_t height = m_srv . get_payload_object ( ) . get_core ( ) . get_blockchain_storage ( ) . get_current_blockchain_height ( ) ;
2014-05-14 03:55:50 +03:00
2014-06-18 00:36:07 +03:00
std : : cout < < " BH: " < < height < < " , DIFF: " < < difficulty
< < " , HR: " < < ( int ) difficulty / 60L < < " H/s " < < std : : endl ;
2014-05-14 03:55:50 +03:00
2014-06-16 17:53:37 +03:00
return true ;
}
2014-06-17 23:46:41 +03:00
2014-03-04 00:07:58 +02:00
bool print_bc_outs ( const std : : vector < std : : string > & args )
{
if ( args . size ( ) ! = 1 )
{
2014-06-18 00:36:07 +03:00
std : : cout < < " need file path as parameter " < < std : : endl ;
2014-03-04 00:07:58 +02:00
return true ;
}
m_srv . get_payload_object ( ) . get_core ( ) . print_blockchain_outs ( args [ 0 ] ) ;
return true ;
}
2014-06-17 23:46:41 +03:00
2014-03-04 00:07:58 +02:00
bool print_cn ( const std : : vector < std : : string > & args )
{
2014-03-20 13:46:11 +02:00
m_srv . get_payload_object ( ) . log_connections ( ) ;
2014-03-04 00:07:58 +02:00
return true ;
}
2014-06-17 23:46:41 +03:00
2014-03-04 00:07:58 +02:00
bool print_bc ( const std : : vector < std : : string > & args )
{
if ( ! args . size ( ) )
{
2014-06-18 00:36:07 +03:00
std : : cout < < " need block index parameter " < < std : : endl ;
2014-03-04 00:07:58 +02:00
return false ;
}
uint64_t start_index = 0 ;
2014-05-25 20:06:40 +03:00
uint64_t end_index = 0 ;
2014-03-04 00:07:58 +02:00
uint64_t end_block_parametr = m_srv . get_payload_object ( ) . get_core ( ) . get_current_blockchain_height ( ) ;
2014-06-13 17:48:24 +03:00
if ( ! epee : : string_tools : : get_xtype_from_string ( start_index , args [ 0 ] ) )
2014-03-04 00:07:58 +02:00
{
2014-06-18 00:36:07 +03:00
std : : cout < < " wrong starter block index parameter " < < std : : endl ;
2014-03-04 00:07:58 +02:00
return false ;
}
2014-06-13 17:48:24 +03:00
if ( args . size ( ) > 1 & & ! epee : : string_tools : : get_xtype_from_string ( end_index , args [ 1 ] ) )
2014-03-04 00:07:58 +02:00
{
2014-06-18 00:36:07 +03:00
std : : cout < < " wrong end block index parameter " < < std : : endl ;
2014-03-04 00:07:58 +02:00
return false ;
}
2014-05-25 20:06:40 +03:00
if ( end_index = = 0 )
{
end_index = end_block_parametr ;
}
if ( end_index > end_block_parametr )
{
2014-06-18 00:36:07 +03:00
std : : cout < < " end block index parameter shouldn't be greater than " < < end_block_parametr < < std : : endl ;
2014-05-25 20:06:40 +03:00
return false ;
}
if ( end_index < = start_index )
{
2014-06-18 00:36:07 +03:00
std : : cout < < " end block index should be greater than starter block index " < < std : : endl ;
2014-05-25 20:06:40 +03:00
return false ;
}
2014-03-04 00:07:58 +02:00
2014-05-25 20:06:40 +03:00
m_srv . get_payload_object ( ) . get_core ( ) . print_blockchain ( start_index , end_index ) ;
2014-03-04 00:07:58 +02:00
return true ;
}
2014-06-17 23:46:41 +03:00
2014-03-04 00:07:58 +02:00
bool print_bci ( const std : : vector < std : : string > & args )
{
m_srv . get_payload_object ( ) . get_core ( ) . print_blockchain_index ( ) ;
return true ;
}
2014-05-25 20:06:40 +03:00
bool set_log ( const std : : vector < std : : string > & args )
{
if ( args . size ( ) ! = 1 )
{
2014-06-18 00:36:07 +03:00
std : : cout < < " use: set_log <log_level_number_0-4> " < < std : : endl ;
2014-05-25 20:06:40 +03:00
return true ;
}
uint16_t l = 0 ;
2014-06-13 17:48:24 +03:00
if ( ! epee : : string_tools : : get_xtype_from_string ( l , args [ 0 ] ) )
2014-05-25 20:06:40 +03:00
{
2014-06-18 00:36:07 +03:00
std : : cout < < " wrong number format, use: set_log <log_level_number_0-4> " < < std : : endl ;
2014-05-25 20:06:40 +03:00
return true ;
}
if ( LOG_LEVEL_4 < l )
{
2014-06-18 00:36:07 +03:00
std : : cout < < " wrong number range, use: set_log <log_level_number_0-4> " < < std : : endl ;
2014-05-25 20:06:40 +03:00
return true ;
}
2014-06-13 17:48:24 +03:00
epee : : log_space : : log_singletone : : get_set_log_detalisation_level ( true , l ) ;
2014-05-25 20:06:40 +03:00
return true ;
}
2014-03-04 00:07:58 +02:00
template < typename T >
static bool print_as_json ( T & obj )
{
2014-06-18 00:36:07 +03:00
std : : cout < < cryptonote : : obj_to_json_str ( obj ) < < std : : endl ;
2014-03-04 00:07:58 +02:00
return true ;
}
2014-06-17 23:46:41 +03:00
2014-03-04 00:07:58 +02:00
bool print_block_by_height ( uint64_t height )
{
std : : list < cryptonote : : block > blocks ;
m_srv . get_payload_object ( ) . get_core ( ) . get_blocks ( height , 1 , blocks ) ;
if ( 1 = = blocks . size ( ) )
{
cryptonote : : block & block = blocks . front ( ) ;
2014-06-18 00:36:07 +03:00
std : : cout < < " block_id: " < < get_block_hash ( block ) < < std : : endl ;
2014-03-04 00:07:58 +02:00
print_as_json ( block ) ;
}
else
{
uint64_t current_height ;
crypto : : hash top_id ;
m_srv . get_payload_object ( ) . get_core ( ) . get_blockchain_top ( current_height , top_id ) ;
std : : cout < < " block wasn't found. Current block chain height: " < < current_height < < " , requested: " < < height < < std : : endl ;
return false ;
}
return true ;
}
2014-06-17 23:46:41 +03:00
2014-03-04 00:07:58 +02:00
bool print_block_by_hash ( const std : : string & arg )
{
crypto : : hash block_hash ;
if ( ! parse_hash256 ( arg , block_hash ) )
{
return false ;
}
std : : list < crypto : : hash > block_ids ;
block_ids . push_back ( block_hash ) ;
std : : list < cryptonote : : block > blocks ;
std : : list < crypto : : hash > missed_ids ;
m_srv . get_payload_object ( ) . get_core ( ) . get_blocks ( block_ids , blocks , missed_ids ) ;
if ( 1 = = blocks . size ( ) )
{
cryptonote : : block block = blocks . front ( ) ;
print_as_json ( block ) ;
}
else
{
std : : cout < < " block wasn't found: " < < arg < < std : : endl ;
return false ;
}
return true ;
}
2014-06-17 23:46:41 +03:00
2014-03-04 00:07:58 +02:00
bool print_block ( const std : : vector < std : : string > & args )
{
if ( args . empty ( ) )
{
std : : cout < < " expected: print_block (<block_hash> | <block_height>) " < < std : : endl ;
return true ;
}
const std : : string & arg = args . front ( ) ;
try
{
uint64_t height = boost : : lexical_cast < uint64_t > ( arg ) ;
print_block_by_height ( height ) ;
}
catch ( boost : : bad_lexical_cast & )
{
print_block_by_hash ( arg ) ;
}
return true ;
}
2014-06-17 23:46:41 +03:00
2014-03-04 00:07:58 +02:00
bool print_tx ( const std : : vector < std : : string > & args )
{
if ( args . empty ( ) )
{
std : : cout < < " expected: print_tx <transaction hash> " < < std : : endl ;
return true ;
}
const std : : string & str_hash = args . front ( ) ;
crypto : : hash tx_hash ;
if ( ! parse_hash256 ( str_hash , tx_hash ) )
{
return true ;
}
std : : vector < crypto : : hash > tx_ids ;
tx_ids . push_back ( tx_hash ) ;
std : : list < cryptonote : : transaction > txs ;
std : : list < crypto : : hash > missed_ids ;
m_srv . get_payload_object ( ) . get_core ( ) . get_transactions ( tx_ids , txs , missed_ids ) ;
if ( 1 = = txs . size ( ) )
{
cryptonote : : transaction tx = txs . front ( ) ;
print_as_json ( tx ) ;
}
else
{
std : : cout < < " transaction wasn't found: < " < < str_hash < < ' > ' < < std : : endl ;
}
return true ;
}
2014-06-17 23:46:41 +03:00
2014-03-04 00:07:58 +02:00
bool print_pool ( const std : : vector < std : : string > & args )
{
2014-06-18 00:36:07 +03:00
std : : cout < < " Pool state: " < < std : : endl < < m_srv . get_payload_object ( ) . get_core ( ) . print_pool ( false ) < < std : : endl ;
2014-03-04 00:07:58 +02:00
return true ;
}
2014-06-17 23:46:41 +03:00
2014-03-04 00:07:58 +02:00
bool print_pool_sh ( const std : : vector < std : : string > & args )
{
2014-06-18 00:36:07 +03:00
std : : cout < < " Pool state: " < < std : : endl < < m_srv . get_payload_object ( ) . get_core ( ) . print_pool ( true ) < < std : : endl ;
2014-03-04 00:07:58 +02:00
return true ;
2014-06-17 23:46:41 +03:00
}
2014-03-04 00:07:58 +02:00
bool start_mining ( const std : : vector < std : : string > & args )
{
if ( ! args . size ( ) )
{
2014-03-20 13:46:11 +02:00
std : : cout < < " Please, specify wallet address to mine for: start_mining <addr> [threads=1] " < < std : : endl ;
2014-03-04 00:07:58 +02:00
return true ;
}
cryptonote : : account_public_address adr ;
if ( ! cryptonote : : get_account_address_from_str ( adr , args . front ( ) ) )
{
std : : cout < < " target account address has wrong format " < < std : : endl ;
return true ;
}
2014-03-20 13:46:11 +02:00
size_t threads_count = 1 ;
2014-03-04 00:07:58 +02:00
if ( args . size ( ) > 1 )
{
2014-06-13 17:48:24 +03:00
bool ok = epee : : string_tools : : get_xtype_from_string ( threads_count , args [ 1 ] ) ;
2014-03-20 13:46:11 +02:00
threads_count = ( ok & & 0 < threads_count ) ? threads_count : 1 ;
2014-03-04 00:07:58 +02:00
}
2014-04-30 23:50:06 +03:00
boost : : thread : : attributes attrs ;
attrs . set_stack_size ( THREAD_STACK_SIZE ) ;
m_srv . get_payload_object ( ) . get_core ( ) . get_miner ( ) . start ( adr , threads_count , attrs ) ;
2014-03-04 00:07:58 +02:00
return true ;
}
2014-06-17 23:46:41 +03:00
2014-03-04 00:07:58 +02:00
bool stop_mining ( const std : : vector < std : : string > & args )
{
m_srv . get_payload_object ( ) . get_core ( ) . get_miner ( ) . stop ( ) ;
return true ;
}
} ;
2014-06-17 23:46:41 +03:00
class t_command_server {
private :
t_command_server_backend m_backend ;
command_handler m_handler ;
public :
t_command_server ( t_command_server_backend : : t_node_server & server ) :
m_backend ( server )
, m_handler ( )
{
m_handler . set_handler ( " help " , std : : bind ( & t_command_server : : help , this , p : : _1 ) , " Show this help " ) ;
m_handler . set_handler ( " print_pl " , std : : bind ( & t_command_server_backend : : print_pl , & m_backend , p : : _1 ) , " Print peer list " ) ;
m_handler . set_handler ( " print_cn " , std : : bind ( & t_command_server_backend : : print_cn , & m_backend , p : : _1 ) , " Print connections " ) ;
m_handler . set_handler ( " print_bc " , std : : bind ( & t_command_server_backend : : print_bc , & m_backend , p : : _1 ) , " Print blockchain info in a given blocks range, print_bc <begin_height> [<end_height>] " ) ;
//m_handler.set_handler("print_bci", std::bind(&t_command_server_backend::print_bci, &m_backend, p::_1));
//m_handler.set_handler("print_bc_outs", std::bind(&t_command_server_backend::print_bc_outs, &m_backend, p::_1));
m_handler . set_handler ( " print_block " , std : : bind ( & t_command_server_backend : : print_block , & m_backend , p : : _1 ) , " Print block, print_block <block_hash> | <block_height> " ) ;
m_handler . set_handler ( " print_tx " , std : : bind ( & t_command_server_backend : : print_tx , & m_backend , p : : _1 ) , " Print transaction, print_tx <transaction_hash> " ) ;
m_handler . set_handler ( " start_mining " , std : : bind ( & t_command_server_backend : : start_mining , & m_backend , p : : _1 ) , " Start mining for specified address, start_mining <addr> [threads=1] " ) ;
m_handler . set_handler ( " stop_mining " , std : : bind ( & t_command_server_backend : : stop_mining , & m_backend , p : : _1 ) , " Stop mining " ) ;
m_handler . set_handler ( " print_pool " , std : : bind ( & t_command_server_backend : : print_pool , & m_backend , p : : _1 ) , " Print transaction pool (long format) " ) ;
m_handler . set_handler ( " print_pool_sh " , std : : bind ( & t_command_server_backend : : print_pool_sh , & m_backend , p : : _1 ) , " Print transaction pool (short format) " ) ;
m_handler . set_handler ( " show_hr " , std : : bind ( & t_command_server_backend : : show_hr , & m_backend , p : : _1 ) , " Start showing hash rate " ) ;
m_handler . set_handler ( " hide_hr " , std : : bind ( & t_command_server_backend : : hide_hr , & m_backend , p : : _1 ) , " Stop showing hash rate " ) ;
m_handler . set_handler ( " save " , std : : bind ( & t_command_server_backend : : save , & m_backend , p : : _1 ) , " Save blockchain " ) ;
m_handler . set_handler ( " set_log " , std : : bind ( & t_command_server_backend : : set_log , & m_backend , p : : _1 ) , " set_log <level> - Change current log detalization level, <level> is a number 0-4 " ) ;
m_handler . set_handler ( " diff " , std : : bind ( & t_command_server_backend : : diff , & m_backend , p : : _1 ) , " Show difficulty " ) ;
}
bool process_command ( const std : : string & cmd )
{
return m_handler . process_command_str ( cmd ) ;
}
private :
bool help ( const std : : vector < std : : string > & args )
{
2014-06-18 00:36:07 +03:00
std : : cout < < get_commands_str ( ) < < std : : endl ;
2014-06-17 23:46:41 +03:00
return true ;
}
std : : string get_commands_str ( )
{
std : : stringstream ss ;
2014-06-18 00:36:07 +03:00
ss < < CRYPTONOTE_NAME < < " v " < < PROJECT_VERSION_LONG < < std : : endl ;
ss < < " Commands: " < < std : : endl ;
2014-06-17 23:46:41 +03:00
std : : string usage = m_handler . get_usage ( ) ;
boost : : replace_all ( usage , " \n " , " \n " ) ;
usage . insert ( 0 , " " ) ;
2014-06-18 00:36:07 +03:00
ss < < usage < < std : : endl ;
2014-06-17 23:46:41 +03:00
return ss . str ( ) ;
}
} ;
} // namespace daemonize