This replaces the epee and data_loggers logging systems with
a single one, and also adds filename:line and explicit severity
levels. Categories may be defined, and logging severity set
by category (or set of categories). epee style 0-4 log level
maps to a sensible severity configuration. Log files now also
rotate when reaching 100 MB.
To select which logs to output, use the MONERO_LOGS environment
variable, with a comma separated list of categories (globs are
supported), with their requested severity level after a colon.
If a log matches more than one such setting, the last one in
the configuration string applies. A few examples:
This one is (mostly) silent, only outputting fatal errors:
MONERO_LOGS=*:FATAL
This one is very verbose:
MONERO_LOGS=*:TRACE
This one is totally silent (logwise):
MONERO_LOGS=""
This one outputs all errors and warnings, except for the
"verify" category, which prints just fatal errors (the verify
category is used for logs about incoming transactions and
blocks, and it is expected that some/many will fail to verify,
hence we don't want the spam):
MONERO_LOGS=*:WARNING,verify:FATAL
Log levels are, in decreasing order of priority:
FATAL, ERROR, WARNING, INFO, DEBUG, TRACE
Subcategories may be added using prefixes and globs. This
example will output net.p2p logs at the TRACE level, but all
other net* logs only at INFO:
MONERO_LOGS=*:ERROR,net*:INFO,net.p2p:TRACE
Logs which are intended for the user (which Monero was using
a lot through epee, but really isn't a nice way to go things)
should use the "global" category. There are a few helper macros
for using this category, eg: MGINFO("this shows up by default")
or MGINFO_RED("this is red"), to try to keep a similar look
and feel for now.
Existing epee log macros still exist, and map to the new log
levels, but since they're used as a "user facing" UI element
as much as a logging system, they often don't map well to log
severities (ie, a log level 0 log may be an error, or may be
something we want the user to see, such as an important info).
In those cases, I tried to use the new macros. In other cases,
I left the existing macros in. When modifying logs, it is
probably best to switch to the new macros with explicit levels.
The --log-level options and set_log commands now also accept
category settings, in addition to the epee style log levels.
t_safe lenall = all-pos; // length from here to end
t_safe lenall = all-pos; // length from here to end
t_safe len = std::min( chunksize_good , lenall); // take a smaller part
t_safe len = std::min( chunksize_good , lenall); // take a smaller part
ASRT(len<=chunksize_good);
CHECK_AND_ASSERT_MES(len<=chunksize_good, false, "len too large");
// pos=8; len=4; all=10; len=3;
// pos=8; len=4; all=10; len=3;
ASRT(! (len<0) ); // check before we cast away sign:
CHECK_AND_ASSERT_MES(! (len<0),false, "negative len"); // check before we cast away sign:
unsigned long long int len_unsigned = static_cast<long long int>( len );
unsigned long long int len_unsigned = static_cast<long long int>( len );
ASRT(len>0); // (redundand)
CHECK_AND_ASSERT_MES(len>0, false, "len not strictly positive"); // (redundant)
ASRT(len_unsigned < std::numeric_limits<size_t>::max()); // yeap we want strong < then max size, to be sure
CHECK_AND_ASSERT_MES(len_unsigned < std::numeric_limits<size_t>::max(), false, "Invalid len_unsigned"); // yeap we want strong < then max size, to be sure
_info_c("net/sleep", "Sleeping because QUEUE is FULL, in " << __FUNCTION__ << " for " << ms << " ms before packet_size="<<cb); // XXX debug sleep
MDEBUG("Sleeping because QUEUE is FULL, in " << __FUNCTION__ << " for " << ms << " ms before packet_size="<<cb); // XXX debug sleep
m_send_que_lock.unlock();
m_send_que_lock.unlock();
boost::this_thread::sleep(boost::posix_time::milliseconds( ms ) );
boost::this_thread::sleep(boost::posix_time::milliseconds( ms ) );
m_send_que_lock.lock();
m_send_que_lock.lock();
_dbg1("sleep for queue: " << ms);
_dbg1("sleep for queue: " << ms);
if (retry > retry_limit) {
if (retry > retry_limit) {
_erro("send que size is more than ABSTRACT_SERVER_SEND_QUE_MAX_COUNT(" << ABSTRACT_SERVER_SEND_QUE_MAX_COUNT << "), shutting down connection");
MWARNING("send que size is more than ABSTRACT_SERVER_SEND_QUE_MAX_COUNT(" << ABSTRACT_SERVER_SEND_QUE_MAX_COUNT << "), shutting down connection");
// _dbg1_c("net/sleep", "send que size is more than ABSTRACT_SERVER_SEND_QUE_MAX_COUNT(" << ABSTRACT_SERVER_SEND_QUE_MAX_COUNT << "), shutting down connection");
CHECK_AND_ASSERT_MES_NO_RET(0==boost::interprocess::ipcdetail::atomic_read32(&m_wait_count),"Failed to wait for operation completion. m_wait_count = "<<m_wait_count);
CHECK_AND_ASSERT_MES_NO_RET(0==boost::interprocess::ipcdetail::atomic_read32(&m_wait_count),"Failed to wait for operation completion. m_wait_count = "<<m_wait_count);
std::cerr<<OT_CODE_STAMP<<"WARNING: due to a problem in the debug/logging system itself ("<<msg<<") - we are switching back to fallback stream (e.g. cerr)"<<std::endl;
if(mStreamBrokenDebug==nullptr){
std::cerr<<OT_CODE_STAMP<<" ERROR: in addition, while reporting this problem, mStreamBrokenDebug stream is NULL: "<<mStreamBrokenDebug<<std::endl;
}else{
(*mStreamBrokenDebug)<<OT_CODE_STAMP<<"WARNING: due to debug stream problem ("<<msg<<") - switching back to fallback stream (e.g. cerr)"<<std::endl;
/// @author rfree (current maintainer in monero.cc project)
/// @brief various general utils taken from (and relate to) otshell project, including loggiang/debug
/* See other files here for the LICENCE that applies here. */
#include"ccolor.hpp"
#ifndef INCLUDE_OT_NEWCLI_UTILS
#define INCLUDE_OT_NEWCLI_UTILS
#include"lib_common1.hpp"
#ifdef __unix
#include<unistd.h>
#endif
#if defined(_WIN32)
#include"windows_stream.h"
#endif
#ifndef CFG_WITH_TERMCOLORS
//#error "You requested to turn off terminal colors (CFG_WITH_TERMCOLORS), however currently they are hardcoded (this option to turn them off is not yet implemented)."
#endif
///Macros related to automatic deduction of class name etc;
externcNullstreamg_nullstream;// a stream that does nothing (eats/discards data)
// ========== debug ==========
// _dbg_ignore is moved to global namespace (on purpose)
// TODO make _dbg_ignore thread-safe everywhere
externboost::recursive_mutexgLoggerGuard;// the mutex guarding logging/debugging code e.g. protecting streams, files, etc
std::atomic<int>&gLoggerGuardDepth_Get();// getter for the global singleton of counter (it guarantees initializing it to 0). This counter shows the current recursion (re-entrant) level of debug macros.
// TODO more debug of the debug system:
// detect lock() error e.g. recursive limit
// detect stream e.g. operator<< error
#define _debug_level(LEVEL,VAR) do { if (_dbg_ignore< LEVEL) { \
gCurrentLogger.write_stream(std::max(level,90),"")<<nOT::nUtils::get_current_time()<<''<<OT_CODE_STAMP<<''<<"(ERROR IN DEBUG)"<<gCurrentLogger.endline(); \
--nOT::nUtils::gLoggerGuardDepth_Get();throw; \
} \
--nOT::nUtils::gLoggerGuardDepth_Get(); \
}catch(...){if(part<8)gCurrentLogger.write_stream(100,"")<<"DEBUG-ERROR: problem in debug mechanism e.g. in locking."<<gCurrentLogger.endline();throw;} \
}}while(0)
// info for code below: oss object is normal stack variable, using it does not need lock protection
#define _debug_level_c(CHANNEL,LEVEL,VAR) do { if (_dbg_ignore< LEVEL) { \
_dbg_dbg("DONE will write to log LEVEL="<<LEVEL<<" to CHANNEL="<<CHANNEL<<" as_string="<<as_string); \
part=9; \
}catch(...){ \
gCurrentLogger.write_stream(std::max(level,90),CHANNEL)<<nOT::nUtils::get_current_time()<<''<<OT_CODE_STAMP<<''<<"(ERROR IN DEBUG)"<<gCurrentLogger.endline(); \
--nOT::nUtils::gLoggerGuardDepth_Get();throw; \
} \
--nOT::nUtils::gLoggerGuardDepth_Get(); \
}catch(...){if(part<8)gCurrentLogger.write_stream(100,CHANNEL)<<"DEBUG-ERROR: problem in debug mechanism e.g. in locking."<<gCurrentLogger.endline();throw;} \
}}while(0)
// Numerical values of the debug levels - are defined here as const ints. Full name (with namespace) given for clarity.
externconstint_debug_level_nr_dbg3;
externconstint_debug_level_nr_dbg2;
externconstint_debug_level_nr_dbg1;
externconstint_debug_level_nr_info;
externconstint_debug_level_nr_note;
externconstint_debug_level_nr_fact;
externconstint_debug_level_nr_mark;
externconstint_debug_level_nr_warn;
externconstint_debug_level_nr_erro;
#define _dbg3(VAR) _debug_level( nOT::nUtils::_debug_level_nr_dbg3,VAR) // details - most detailed
#define _dbg2(VAR) _debug_level( nOT::nUtils::_debug_level_nr_dbg2,VAR) // details - a bit more important
#define _dbg1(VAR) _debug_level( nOT::nUtils::_debug_level_nr_dbg1,VAR) // details - more important
#define _info(VAR) _debug_level( nOT::nUtils::_debug_level_nr_info,VAR) // information
#define _note(VAR) _debug_level( nOT::nUtils::_debug_level_nr_note,VAR) // more interesting information
#define _fact(VAR) _debug_level( nOT::nUtils::_debug_level_nr_fact,VAR) // interesting events that could be interesting even for user, for logical/business things
#define _dbg3_c(C,VAR) _debug_level_c(C, nOT::nUtils::_debug_level_nr_dbg3, VAR) // details - most detailed
#define _dbg2_c(C,VAR) _debug_level_c(C, nOT::nUtils::_debug_level_nr_dbg2, VAR) // details - a bit more important
#define _dbg1_c(C,VAR) _debug_level_c(C, nOT::nUtils::_debug_level_nr_dbg1, VAR) // details - more important
#define _info_c(C,VAR) _debug_level_c(C, nOT::nUtils::_debug_level_nr_info, VAR) // information
#define _note_c(C,VAR) _debug_level_c(C, nOT::nUtils::_debug_level_nr_note, VAR) // more interesting information
#define _fact_c(C,VAR) _debug_level_c(C, nOT::nUtils::_debug_level_nr_fact, VAR) // interesting events that could be interesting even for user, for logical/business things
constchar*DbgShortenCodeFileName(constchar*s);///< Returns a pointer to some part of the string that was given, skipping directory names, for log/debug
externnOT::nUtils::cLoggergCurrentLogger;///< The current main logger. Usually do not use it directly, instead use macros like _dbg1 etc
std::stringGetObjectName();///< Method to return name of current object; To use in debug; Can be shadowed in your classes. (Might be not used currently)
constexternint_dbg_ignore;///< the global _dbg_ignore, but local code (blocks, classes etc) you could shadow it in your code blocks,
// to override debug compile-time setting for given block/class, e.g. to disable debug in one of your methods or increase it there.
// Or to make it runtime by providing a class normal member and editing it in runtime
LOG_PRINT_GREEN("Blockchain initialized. last block: "<<m_db->height()-1<<", "<<epee::misc_utils::get_time_interval_string(timestamp_diff)<<" time ago, current difficulty: "<<get_difficulty_for_next_block(),LOG_LEVEL_0);
MINFO("Blockchain initialized. last block: "<<m_db->height()-1<<", "<<epee::misc_utils::get_time_interval_string(timestamp_diff)<<" time ago, current difficulty: "<<get_difficulty_for_next_block());
CHECK_AND_ASSERT_MES(b.miner_tx.unlock_time==height+CRYPTONOTE_MINED_MONEY_UNLOCK_WINDOW,false,"coinbase transaction transaction has the wrong unlock time="<<b.miner_tx.unlock_time<<", expected "<<height+CRYPTONOTE_MINED_MONEY_UNLOCK_WINDOW);
CHECK_AND_ASSERT_MES(b.miner_tx.unlock_time==height+CRYPTONOTE_MINED_MONEY_UNLOCK_WINDOW,false,"coinbase transaction transaction has the wrong unlock time="<<b.miner_tx.unlock_time<<", expected "<<height+CRYPTONOTE_MINED_MONEY_UNLOCK_WINDOW);
LOG_PRINT_L1("block size "<<cumulative_block_size<<" is bigger than allowed for this blockchain");
MERROR_VER("block size "<<cumulative_block_size<<" is bigger than allowed for this blockchain");
returnfalse;
returnfalse;
}
}
if(base_reward+fee<money_in_use)
if(base_reward+fee<money_in_use)
{
{
LOG_PRINT_L1("coinbase transaction spend too much money ("<<print_money(money_in_use)<<"). Block reward is "<<print_money(base_reward+fee)<<"("<<print_money(base_reward)<<"+"<<print_money(fee)<<")");
MERROR_VER("coinbase transaction spend too much money ("<<print_money(money_in_use)<<"). Block reward is "<<print_money(base_reward+fee)<<"("<<print_money(base_reward)<<"+"<<print_money(fee)<<")");
returnfalse;
returnfalse;
}
}
// From hard fork 2, we allow a miner to claim less block reward than is allowed, in case a miner wants less dust
// From hard fork 2, we allow a miner to claim less block reward than is allowed, in case a miner wants less dust
LOG_PRINT_L1("coinbase transaction doesn't use full amount of block reward: spent: "<<money_in_use<<", block reward "<<base_reward+fee<<"("<<base_reward<<"+"<<fee<<")");
MDEBUG("coinbase transaction doesn't use full amount of block reward: spent: "<<money_in_use<<", block reward "<<base_reward+fee<<"("<<base_reward<<"+"<<fee<<")");
returnfalse;
returnfalse;
}
}
}
}
@ -1139,7 +1144,7 @@ bool Blockchain::create_block_template(block& b, const account_public_address& m
//fuck, not lucky, -1 makes varint-counter size smaller, in that case we continue to grow with cumulative_size
//fuck, not lucky, -1 makes varint-counter size smaller, in that case we continue to grow with cumulative_size
LOG_PRINT_RED("Miner tx creation has no luck with delta_extra size = "<<delta<<" and "<<delta-1,LOG_LEVEL_2);
MDEBUG("Miner tx creation has no luck with delta_extra size = "<<delta<<" and "<<delta-1);
cumulative_size+=delta-1;
cumulative_size+=delta-1;
continue;
continue;
}
}
LOG_PRINT_GREEN("Setting extra for block: "<<b.miner_tx.extra.size()<<", try_count="<<try_count,LOG_LEVEL_1);
MDEBUG("Setting extra for block: "<<b.miner_tx.extra.size()<<", try_count="<<try_count);
}
}
}
}
CHECK_AND_ASSERT_MES(cumulative_size==txs_size+get_object_blobsize(b.miner_tx),false,"unexpected case: cumulative_size="<<cumulative_size<<" is not equal txs_cumulative_size="<<txs_size<<" + get_object_blobsize(b.miner_tx)="<<get_object_blobsize(b.miner_tx));
CHECK_AND_ASSERT_MES(cumulative_size==txs_size+get_object_blobsize(b.miner_tx),false,"unexpected case: cumulative_size="<<cumulative_size<<" is not equal txs_cumulative_size="<<txs_size<<" + get_object_blobsize(b.miner_tx)="<<get_object_blobsize(b.miner_tx));
LOG_PRINT_RED_L1("Block with id: "<<id<<std::endl<<" can't be accepted for alternative chain, block height: "<<block_height<<std::endl<<" blockchain height: "<<get_current_blockchain_height());
MERROR_VER("Block with id: "<<id<<std::endl<<" can't be accepted for alternative chain, block height: "<<block_height<<std::endl<<" blockchain height: "<<get_current_blockchain_height());
LOG_PRINT_RED_L1("Block with id: "<<id<<std::endl<<" for alternative chain, does not have enough proof of work: "<<proof_of_work<<std::endl<<" expected difficulty: "<<current_diff);
MERROR_VER("Block with id: "<<id<<std::endl<<" for alternative chain, does not have enough proof of work: "<<proof_of_work<<std::endl<<" expected difficulty: "<<current_diff);
bvc.m_verifivation_failed=true;
bvc.m_verifivation_failed=true;
returnfalse;
returnfalse;
}
}
if(!prevalidate_miner_transaction(b,bei.height))
if(!prevalidate_miner_transaction(b,bei.height))
{
{
LOG_PRINT_RED_L1("Block with id: "<<epee::string_tools::pod_to_hex(id)<<" (as alternative) has incorrect miner transaction.");
MERROR_VER("Block with id: "<<epee::string_tools::pod_to_hex(id)<<" (as alternative) has incorrect miner transaction.");
LOG_PRINT_GREEN("###### REORGANIZE on height: "<<alt_chain.front()->second.height<<" of "<<m_db->height()-1<<", checkpoint is found in alternative chain on height "<<bei.height,LOG_LEVEL_0);
MGINFO_GREEN("###### REORGANIZE on height: "<<alt_chain.front()->second.height<<" of "<<m_db->height()-1<<", checkpoint is found in alternative chain on height "<<bei.height);
elseif(main_chain_cumulative_difficulty<bei.cumulative_difficulty)//check if difficulty bigger then in main chain
elseif(main_chain_cumulative_difficulty<bei.cumulative_difficulty)//check if difficulty bigger then in main chain
{
{
//do reorganize!
//do reorganize!
LOG_PRINT_GREEN("###### REORGANIZE on height: "<<alt_chain.front()->second.height<<" of "<<m_db->height()-1<<" with cum_difficulty "<<m_db->get_block_cumulative_difficulty(m_db->height()-1)<<std::endl<<" alternative blockchain size: "<<alt_chain.size()<<" with cum_difficulty "<<bei.cumulative_difficulty,LOG_LEVEL_0);
MGINFO_GREEN("###### REORGANIZE on height: "<<alt_chain.front()->second.height<<" of "<<m_db->height()-1<<" with cum_difficulty "<<m_db->get_block_cumulative_difficulty(m_db->height()-1)<<std::endl<<" alternative blockchain size: "<<alt_chain.size()<<" with cum_difficulty "<<bei.cumulative_difficulty);
LOG_PRINT_BLUE("----- BLOCK ADDED AS ALTERNATIVE ON HEIGHT "<<bei.height<<std::endl<<"id:\t"<<id<<std::endl<<"PoW:\t"<<proof_of_work<<std::endl<<"difficulty:\t"<<current_diff,LOG_LEVEL_0);
MGINFO_BLUE("----- BLOCK ADDED AS ALTERNATIVE ON HEIGHT "<<bei.height<<std::endl<<"id:\t"<<id<<std::endl<<"PoW:\t"<<proof_of_work<<std::endl<<"difficulty:\t"<<current_diff);
LOG_PRINT_L1("Failed to check ring signature for tx "<<get_transaction_hash(tx)<<" vin key with k_image: "<<in_to_key.k_image<<" sig_index: "<<sig_index);
MERROR_VER("Failed to check ring signature for tx "<<get_transaction_hash(tx)<<" vin key with k_image: "<<in_to_key.k_image<<" sig_index: "<<sig_index);
if(pmax_used_block_height)// a default value of NULL is used when called from Blockchain::handle_block_to_main_chain()
if(pmax_used_block_height)// a default value of NULL is used when called from Blockchain::handle_block_to_main_chain()
LOG_PRINT_L1("Failed to check ring signature for tx "<<get_transaction_hash(tx)<<" vin key with k_image: "<<in_to_key.k_image<<" sig_index: "<<sig_index);
MERROR_VER("Failed to check ring signature for tx "<<get_transaction_hash(tx)<<" vin key with k_image: "<<in_to_key.k_image<<" sig_index: "<<sig_index);
if(pmax_used_block_height)// a default value of NULL is used when called from Blockchain::handle_block_to_main_chain()
if(pmax_used_block_height)// a default value of NULL is used when called from Blockchain::handle_block_to_main_chain()
LOG_PRINT_L1("Failed to get output keys for tx with amount = "<<print_money(txin.amount)<<" and count indexes "<<txin.key_offsets.size());
MERROR_VER("Failed to get output keys for tx with amount = "<<print_money(txin.amount)<<" and count indexes "<<txin.key_offsets.size());
returnfalse;
returnfalse;
}
}
if(txin.key_offsets.size()!=output_keys.size())
if(txin.key_offsets.size()!=output_keys.size())
{
{
LOG_PRINT_L1("Output keys for tx with amount = "<<txin.amount<<" and count indexes "<<txin.key_offsets.size()<<" returned wrong keys count "<<output_keys.size());
MERROR_VER("Output keys for tx with amount = "<<txin.amount<<" and count indexes "<<txin.key_offsets.size()<<" returned wrong keys count "<<output_keys.size());
LOG_PRINT_L1("Timestamp of block with id: "<<get_block_hash(b)<<", "<<b.timestamp<<", less than median of last "<<BLOCKCHAIN_TIMESTAMP_CHECK_WINDOW<<" blocks, "<<median_ts);
MERROR_VER("Timestamp of block with id: "<<get_block_hash(b)<<", "<<b.timestamp<<", less than median of last "<<BLOCKCHAIN_TIMESTAMP_CHECK_WINDOW<<" blocks, "<<median_ts);
returnfalse;
returnfalse;
}
}
@ -2946,7 +2950,7 @@ bool Blockchain::check_block_timestamp(const block& b) const
LOG_PRINT_L1("Block with id: "<<id<<std::endl<<"has wrong prev_id: "<<bl.prev_id<<std::endl<<"expected: "<<get_tail_id());
MERROR_VER("Block with id: "<<id<<std::endl<<"has wrong prev_id: "<<bl.prev_id<<std::endl<<"expected: "<<get_tail_id());
leave:
leave:
m_db->block_txn_stop();
m_db->block_txn_stop();
returnfalse;
returnfalse;
@ -3031,7 +3035,7 @@ leave:
// this is a cheap test
// this is a cheap test
if(!m_hardfork->check(bl))
if(!m_hardfork->check(bl))
{
{
LOG_PRINT_L1("Block with id: "<<id<<std::endl<<"has old version: "<<(unsigned)bl.major_version<<std::endl<<"current: "<<(unsigned)m_hardfork->get_current_version());
MERROR_VER("Block with id: "<<id<<std::endl<<"has old version: "<<(unsigned)bl.major_version<<std::endl<<"current: "<<(unsigned)m_hardfork->get_current_version());
bvc.m_verifivation_failed=true;
bvc.m_verifivation_failed=true;
gotoleave;
gotoleave;
}
}
@ -3043,7 +3047,7 @@ leave:
// of a set number of the most recent blocks.
// of a set number of the most recent blocks.
if(!check_block_timestamp(bl))
if(!check_block_timestamp(bl))
{
{
LOG_PRINT_L1("Block with id: "<<id<<std::endl<<"has invalid timestamp: "<<bl.timestamp);
MERROR_VER("Block with id: "<<id<<std::endl<<"has invalid timestamp: "<<bl.timestamp);
// validate proof_of_work versus difficulty target
// validate proof_of_work versus difficulty target
if(!check_hash(proof_of_work,current_diffic))
if(!check_hash(proof_of_work,current_diffic))
{
{
LOG_PRINT_L1("Block with id: "<<id<<std::endl<<"does not have enough proof of work: "<<proof_of_work<<std::endl<<"unexpected difficulty: "<<current_diffic);
MERROR_VER("Block with id: "<<id<<std::endl<<"does not have enough proof of work: "<<proof_of_work<<std::endl<<"unexpected difficulty: "<<current_diffic);
LOG_PRINT_RED_L1("tx is too large "<<get_object_blobsize(tx)<<", expected not bigger than "<<m_blockchain_storage.get_current_cumulative_blocksize_limit()-CRYPTONOTE_COINBASE_BLOB_RESERVED_SIZE);
MERROR_VER("tx is too large "<<get_object_blobsize(tx)<<", expected not bigger than "<<m_blockchain_storage.get_current_cumulative_blocksize_limit()-CRYPTONOTE_COINBASE_BLOB_RESERVED_SIZE);
returnfalse;
returnfalse;
}
}
//check if tx use different key images
//check if tx use different key images
if(!check_tx_inputs_keyimages_diff(tx))
if(!check_tx_inputs_keyimages_diff(tx))
{
{
LOG_PRINT_RED_L1("tx uses a single key image more than once");
MERROR_VER("tx uses a single key image more than once");
returnfalse;
returnfalse;
}
}
@ -610,24 +615,24 @@ namespace cryptonote
switch(rv.type){
switch(rv.type){
caserct::RCTTypeNull:
caserct::RCTTypeNull:
// coinbase should not come here, so we reject for all other types
// coinbase should not come here, so we reject for all other types
<<"The daemon will start synchronizing with the network. It may take up to several hours."<<ENDL
<<"The daemon will start synchronizing with the network. It may take up to several hours."<<ENDL
<<ENDL
<<ENDL
<<"You can set the level of process detailization* through \"set_log <level>\" command*, where <level> is between 0 (no details) and 4 (very verbose)."<<ENDL
<<"You can set the level of process detailization* through \"set_log <level|categories>\" command*, where <level> is between 0 (no details) and 4 (very verbose), or custom category based levels (eg, *:WARNING)"<<ENDL
<<ENDL
<<ENDL
<<"Use \"help\" command to see the list of available commands."<<ENDL
<<"Use \"help\" command to see the list of available commands."<<ENDL
LOG_PRINT_CCONTEXT_YELLOW("Sync data returned a new top block candidate: " << m_core.get_current_blockchain_height() << " -> " << hshd.current_height
MCLOG(is_inital ? el::Level::Info : el::Level::Debug, "global", context << "Sync data returned a new top block candidate: " << m_core.get_current_blockchain_height() << " -> " << hshd.current_height